Exemple #1
0
	def exportSystemTemplate(self):
		if self._currentObject is None:
			QMessageBox.warning(self, 'Warning', 'Must have a current object selection')
			return

		if blurdev is None:
			pref = QSettings("Blur", "Simplex3")
			defaultPath = str(toPyObject(pref.value('systemExport', os.path.join(os.path.expanduser('~')))))
			path = self.fileDialog("Export Template", defaultPath, ["smpx", "json"], save=True)
			if not path:
				return
			pref.setValue('systemExport', os.path.dirname(path))
			pref.sync()
		else:
			# Blur Prefs
			pref = blurdev.prefs.find('tools/simplex3')
			defaultPath = pref.restoreProperty('systemExport', os.path.join(os.path.expanduser('~')))
			path = self.fileDialog("Export Template", defaultPath, ["smpx", "json"], save=True)
			if not path:
				return
			pref.recordProperty('systemExport', os.path.dirname(path))
			pref.save()

		if path.endswith('.smpx'):
			pBar = QProgressDialog("Exporting smpx File", "Cancel", 0, 100, self)
			pBar.show()
			self.simplex.exportAbc(path, pBar)
			pBar.close()
		elif path.endswith('.json'):
			dump = self.simplex.dump()
			with open(path, 'w') as f:
				f.write(dump)
Exemple #2
0
def updateRestShapeInterface(window):
    sel = cmds.ls(sl=True)
    if not sel:
        QMessageBox.warning(window, "Nothing Selected", "Nothing Selected")
        return
    sel = sel[0]
    mesh = window.simplex.DCC.mesh

    # TODO, Check vert number and blendshape input connections
    selVerts = cmds.polyEvaluate(sel, vertex=1)
    meshVerts = cmds.polyEvaluate(mesh, vertex=1)

    if selVerts != meshVerts:
        msg = "Selected object {0} has {1} verts\nBase Object has {2} verts".format(
            sel, selVerts, meshVerts)
        QMessageBox.warning(window, "Vert Mismatch", msg)
        return

    # TODO Check for live connections
    bs = window.simplex.DCC.shapeNode
    cnx = cmds.listConnections(bs, plugs=1, destination=0, type='mesh')
    if cnx:
        cnxs = ', '.join([i.split('.')[0] for i in cnx])
        cnxs = textwrap.fill(cnxs)
        msg = [
            "Some shapes have a live input connection:", cnxs, "",
            "These shapes will not get the update.", "Continue anyway?"
        ]
        msg = '\n'.join(msg)
        btns = QMessageBox.Ok | QMessageBox.Cancel
        bret = QMessageBox.question(window, "Live Connections", msg, btns)
        if not bret & QMessageBox.Ok:
            return

    updateRestShape(mesh, sel)
Exemple #3
0
    def renameFalloff(self):
        if not self.simplex.falloffs:
            return
        idx = self.uiShapeFalloffCBOX.currentIndex()
        if idx < 0:
            return
        fo = self.simplex.falloffs[idx]
        foNames = [f.name for f in self.simplex.falloffs]
        foNames.pop(idx)

        newName, good = QInputDialog.getText(
            self,
            "Rename Falloff",
            "Enter a new name for the Falloff",
            text=fo.name)
        if not good:
            return

        if not NAME_CHECK.match(newName):
            message = 'Falloff name can only contain letters and numbers, and cannot start with a number'
            QMessageBox.warning(self, 'Warning', message)
            return

        nn = getNextName(newName, foNames)
        fo.name = nn
Exemple #4
0
	def newComboGroup(self):
		if self.simplex is None:
			return
		newName, good = QInputDialog.getText(self, "New Group", "Enter a name for the new group", text="Group")
		if not good:
			return
		if not NAME_CHECK.match(newName):
			message = 'Group name can only contain letters and numbers, and cannot start with a number'
			QMessageBox.warning(self, 'Warning', message)
			return
		Group.createGroup(str(newName), self.simplex, groupType=Combo)
		self.uiComboTREE.model().sourceModel().invalidateFilter()
Exemple #5
0
def exportSplitInterface(window):
	if np is None:
		QMessageBox.warning(window, "No Numpy", "Numpy is not available here, an it is required to split a system")
		return
	path, _filter = QtCompat.QFileDialog.getSaveFileName(window, "Export Split", "", "Simplex (*.smpx)")

	if not path:
		return

	pBar = QProgressDialog("Exporting Split smpx File", "Cancel", 0, 100, window)
	pBar.show()
	split = window.simplex.split(pBar)
	split.exportAbc(path, pBar)
	pBar.close()
Exemple #6
0
	def setShapeName(self):
		progPairs = self.uiSliderTREE.getSelectedItems(ProgPair)
		if len(progPairs) != 1:
			message = 'You can set exactly one shape name at a time this way'
			QMessageBox.warning(self, 'Warning', message)
			return

		newName = self.uiShapeNameTXT.text()
		if not NAME_CHECK.match(newName):
			message = 'Slider name can only contain letters and numbers, and cannot start with a number'
			QMessageBox.warning(self, 'Warning', message)
			return
		progPairs[0].shape.name = newName
		self.uiSliderTREE.viewport().update()
Exemple #7
0
	def sliderTreeDelete(self):
		idxs = self.uiSliderTREE.getSelectedIndexes()
		roots = coerceIndexToRoots(idxs)
		if not roots:
			QMessageBox.warning(self, 'Warning', 'Nothing Selected')
			return
		roots = makeUnique([i.model().itemFromIndex(i) for i in roots])
		for r in roots:
			if isinstance(r, Simplex):
				QMessageBox.warning(self, 'Warning', 'Cannot delete a simplex system this way (for now)')
				return

		for r in roots:
			r.delete()
		self.uiSliderTREE.model().invalidateFilter()
def generateShapeIncrementalsContext(indexes, window):
	idx = indexes[0] # Only on the click index
	slider = idx.model().itemFromIndex(idx)
	if len(slider.prog.pairs) > 2:
		QMessageBox.warning(window, "Warning", "Slider already has incrementals")
		return

	increments, good = QInputDialog.getInt(window, "Increments", "Number of Increments", 4, 1, 100)
	if not good:
		return

	rest = None
	target = None
	maxval = -1.0

	for pp in slider.prog.pairs:
		if pp.shape.isRest:
			rest = pp.shape
		elif abs(pp.value) > maxval:
			target = pp.shape

	target.name = target.name + "_100"

	startObj = slider.extractShape(rest, live=False)
	endObj = slider.extractShape(target)
	shapeDup = cmds.duplicate(endObj, name="shapeDup")[0]

	bs = cmds.blendShape(startObj, shapeDup)

	incs = []
	for i in range(1, increments):
		val = float(increments - i) / increments
		percent = int(float(i) * 100 / increments)
		cmds.blendShape(bs, edit=True, weight=((0, val)))

		nne = endObj.replace("_100_", "_{0}_".format(percent))
		nn = nne.replace("_Extract", "")
		inc = cmds.duplicate(shapeDup, name=nne)
		incs.append((percent, nn, nne))

	for perc, inc, ince in incs:
		pp = slider.createShape(shapeName=inc, tVal=perc/100.0)
		pp.shape.connectShape(mesh=ince, live=True)

	window.uiSliderTREE.model().invalidateFilter()

	cmds.delete((shapeDup, startObj))
	cmds.select(endObj)
Exemple #9
0
    def newGroup(self):
        if self.simplex is None:
            return
        newName, good = QInputDialog.getText(self,
                                             "New Group",
                                             "Enter a name for the new group",
                                             text="Group")
        if not good:
            return
        if not NAME_CHECK.match(newName):
            message = 'Group name can only contain letters and numbers, and cannot start with a number'
            QMessageBox.warning(self, 'Warning', message)
            return

        items = self.uiTraversalTREE.getSelectedItems(Slider)
        Group.createGroup(str(newName), self.simplex, items)
Exemple #10
0
	def newSlider(self):
		if self.simplex is None:
			return
		# get the new slider name
		newName, good = QInputDialog.getText(self, "New Slider", "Enter a name for the new slider", text="Slider")
		if not good:
			return

		if not NAME_CHECK.match(newName):
			message = 'Slider name can only contain letters and numbers, and cannot start with a number'
			QMessageBox.warning(self, 'Warning', message)
			return

		idxs = self.uiSliderTREE.getSelectedIndexes()
		groups = coerceIndexToParentType(idxs, Group)
		group = groups[0].model().itemFromIndex(groups[0]) if groups else None

		Slider.createSlider(str(newName), self.simplex, group=group)
Exemple #11
0
	def renameSystem(self):
		if self.simplex is None:
			return
		nn, good = QInputDialog.getText(self, "New System Name", "Enter a name for the System", text=self.simplex.name)
		if not good:
			return

		if not NAME_CHECK.match(nn):
			message = 'System name can only contain letters and numbers, and cannot start with a number'
			QMessageBox.warning(self, 'Warning', message)
			return

		sysNames = [str(self.uiCurrentSystemCBOX.itemText(i)) for i in range(self.uiCurrentSystemCBOX.count())]
		nn = getNextName(nn, sysNames)
		self.simplex.name = nn

		idx = self.uiCurrentSystemCBOX.currentIndex()
		self.uiCurrentSystemCBOX.setItemText(idx, nn)

		self.currentSystemChanged(idx)
Exemple #12
0
	def newSystem(self):
		if self._currentObject is None:
			QMessageBox.warning(self, 'Warning', 'Must have a current object selection')
			return

		newName, good = QInputDialog.getText(self, "New System", "Enter a name for the new system")
		if not good:
			return

		newName = str(newName)
		if not NAME_CHECK.match(newName):
			message = 'System name can only contain letters and numbers, and cannot start with a number'
			QMessageBox.warning(self, 'Warning', message)
			return

		newSystem = Simplex.buildEmptySystem(self._currentObject, newName, sliderMul=self._sliderMul)
		with signalsBlocked(self.uiCurrentSystemCBOX):
			self.uiCurrentSystemCBOX.addItem(newName)
			self.uiCurrentSystemCBOX.setCurrentIndex(self.uiCurrentSystemCBOX.count()-1)
			self.setSystem(newSystem)
Exemple #13
0
    def newFalloff(self):
        if not self.simplex.falloffs:
            return
        foNames = [f.name for f in self.simplex.falloffs]
        tempName = getNextName("NewFalloff", foNames)

        newName, good = QInputDialog.getText(
            self,
            "Rename Falloff",
            "Enter a new name for the Falloff",
            text=tempName)
        if not good:
            return

        if not NAME_CHECK.match(newName):
            message = 'Falloff name can only contain letters and numbers, and cannot start with a number'
            QMessageBox.warning(self, 'Warning', message)
            return

        nn = getNextName(newName, foNames)
        Falloff.createPlanar(nn, self.simplex, 'X', 1.0, 0.66, 0.33, -1.0)
Exemple #14
0
    def newTrav(self):
        sliders = self.parent().uiSliderTREE.getSelectedItems(Slider)
        combos = self.parent().uiComboTREE.getSelectedItems(Combo)
        items = sliders + combos

        if len(items) != 2:
            message = 'Must have exactly 2 other controller selected'
            QMessageBox.warning(self, 'Warning', message)
            return None

        # the progressor will have more shapes in the prog
        val0 = items[0].prog.getValues()
        val1 = items[1].prog.getValues()
        pos0count = len([i for i in val0 if i > 0])
        neg0count = len([i for i in val0 if i < 0])
        pos1count = len([i for i in val1 if i > 0])
        neg1count = len([i for i in val1 if i < 0])

        # Find the prog item
        vals = [pos0count, neg0count, pos1count, neg1count]
        mIdx = vals.index(max(vals))
        iidx = 0 if mIdx < 2 else 1
        progItem = items[iidx]
        multItem = items[iidx - 1]

        progFlip = (mIdx % 2) == 1
        multFlip = False

        name = Traversal.buildTraversalName(progItem, multItem, progFlip,
                                            multFlip)
        return Traversal.createTraversal(name,
                                         self.simplex,
                                         multItem,
                                         progItem,
                                         multFlip,
                                         progFlip,
                                         count=vals[mIdx])
Exemple #15
0
	def importObjFolder(self, folder):
		''' Import all objs from a user selected folder '''
		if not os.path.isdir(folder):
			QMessageBox.warning(self, 'Warning', 'Folder does not exist')
			return

		paths = os.listdir(folder)
		paths = [i for i in paths if i.endswith('.obj')]
		if not paths:
			QMessageBox.warning(self, 'Warning', 'Folder does not contain any .obj files')
			return

		shapeDict = {shape.name: shape for shape in self.simplex.shapes}

		inPairs = {}
		for path in paths:
			shapeName = os.path.splitext(os.path.basename(path))[0]
			shape = shapeDict.get(shapeName)
			if shape is not None:
				inPairs[shapeName] = path
			else:
				sfx = "_Extract"
				if shapeName.endswith(sfx):
					shapeName = shapeName[:-len(sfx)]
					shape = shapeDict.get(shapeName)
					if shape is not None:
						inPairs[shapeName] = path

		sliderMasters, comboMasters = {}, {}
		for masters in [self.simplex.sliders, self.simplex.combos]:
			for master in masters:
				for pp in master.prog.pairs:
					shape = shapeDict.get(pp.shape.name)
					if shape is not None:
						if shape.name in inPairs:
							if isinstance(master, Slider):
								sliderMasters[shape.name] = master
							if isinstance(master, Combo):
								comboMasters[shape.name] = master

		comboDepth = {}
		for k, v in comboMasters.iteritems():
			depth = len(v.pairs)
			comboDepth.setdefault(depth, {})[k] = v

		pBar = QProgressDialog("Loading from Mesh", "Cancel", 0, len(comboMasters) + len(sliderMasters), self)
		pBar.show()

		for shapeName, slider in sliderMasters.iteritems():
			pBar.setValue(pBar.value() + 1)
			pBar.setLabelText("Loading Obj :\n{0}".format(shapeName))
			QApplication.processEvents()
			if pBar.wasCanceled():
				return

			path = inPairs[shapeName]
			mesh = self.simplex.DCC.importObj(os.path.join(folder, path))

			shape = shapeDict[shapeName]
			self.simplex.DCC.connectShape(shape, mesh=mesh, live=False, delete=True)

		for depth in sorted(comboDepth.keys()):
			for shapeName, combo in comboDepth[depth].iteritems():
				pBar.setValue(pBar.value() + 1)
				pBar.setLabelText("Loading Obj :\n{0}".format(shapeName))
				QApplication.processEvents()
				if pBar.wasCanceled():
					return

				path = inPairs[shapeName]
				mesh = self.simplex.DCC.importObj(os.path.join(folder, path))
				shape = shapeDict[shapeName]
				self.simplex.DCC.connectComboShape(combo, shape, mesh=mesh, live=False, delete=True)

		pBar.close()