# of this source code package. # from maya import cmds from ngSkinTools.utils import Utils, MessageException from ngSkinTools.ui.basetab import BaseTab from ngSkinTools.ui.intensityslider import IntensitySlider from ngSkinTools.doclink import SkinToolsDocs from ngSkinTools.ui.uiWrappers import IntField, FloatField, CheckBoxField from ngSkinTools.ui.softSelectionRow import SoftSelectionRow from ngSkinTools.log import getLogger log = getLogger("tabSkinRelax") class TabSkinRelax(BaseTab): ''' Defines a UI function set for Weights Relax operations. ''' # prefix for environment variables for this tab VAR_RELAX_PREFIX = 'ngSkinToolsRelaxTab_' def __init__(self): BaseTab.__init__(self)
class BaseTab(object): ''' base class for ui group (tab) classes ''' VAR_GROUP_COLLAPSE = 'ngSkinTools_group%s_collapse' log = getLogger("BaseToolWindow") def __init__(self): # create container for all controls. # using fake class instead of dictionary to simplify usage code self.controls = Controls() self.controls.groups = [] self.parentWindow = None self.title = 'Untitled' def getTitle(self): ''' return title of this gui set. override for functionality ''' return self.title def setTitle(self, title): self.title = title def getGroupVariable(self, group): title = cmds.frameLayout(group, q=True, label=True) title = title.replace(" ", "") return self.VAR_GROUP_COLLAPSE % title @staticmethod def createScrollLayout(parent): return cmds.scrollLayout(parent=parent, childResizable=True) def createUIGroup(self, layout, title, defaultCollapsed=False): ''' creates collapsable UI group ''' cmds.setParent(layout) group = uiWrappers.frameLayout( label=title, marginWidth=Constants.MARGIN_SPACING_HORIZONTAL, marginHeight=Constants.MARGIN_SPACING_VERTICAL, collapsable=True, expandCommand=self.saveOptions, collapseCommand=self.saveOptions) self.lastCreatedGroup = group self.controls.groups.append(group) cmds.frameLayout(group, e=True, collapse=Options.loadOption( self.getGroupVariable(group), 1 if defaultCollapsed else 0)) return cmds.columnLayout(adjustableColumn=1, rowSpacing=Constants.MARGIN_SPACING_VERTICAL) def createUI(self, parent): ''' override this method to implement gui creation ''' cmds.setParent(parent) self.baseLayout = cmds.columnLayout( rowSpacing=Constants.MARGIN_SPACING_VERTICAL, adjustableColumn=1) def saveOptions(self, *args): ''' save gui options for this tab. this can be directly supplied as a handler to control's "change value" events ''' for group in self.controls.groups: Options.saveOption(self.getGroupVariable(group), cmds.frameLayout(group, q=True, collapse=True)) @staticmethod def createHelpButton(helpLink): import os.path as path imageName = path.join(path.dirname(__file__), 'icons', 'help.png') return cmds.symbolButton('?', image=imageName, height=Constants.BUTTON_HEIGHT, width=Constants.BUTTON_WIDTH_SMALL, annotation='Open manual at: ' + helpLink.title, command=lambda *args: helpLink.open()) @staticmethod def createTitledRow(parent, title, innerContentConstructor=None, adjustable=True): return titledRow.create( parent, title, innerContentConstructor=innerContentConstructor, adjustable=adjustable) @staticmethod def createFixedTitledRow(parent, title): return titledRow.createFixed(parent, title) @staticmethod def layoutButtonForm(buttonForm, buttons): ''' horizontally spaces buttons in a form with a grid size of 100 ''' for index, button in enumerate(buttons): spaceWidth = 100 / len(buttons) cmds.formLayout(buttonForm, e=True, attachForm=[(button, 'top', 0), (button, 'bottom', 0)], attachPosition=[ (button, 'right', Constants.MARGIN_SPACING_HORIZONTAL / 2, spaceWidth * (index + 1)), (button, 'left', Constants.MARGIN_SPACING_HORIZONTAL / 2, spaceWidth * index) ]) def createCommandLayout(self, commandIterator, helpLink): ''' creates a layout that has a help button and command buttons at the bottom of the page, with a scroll layout created for the rest of the page; inside scroll layout, column layout is created for adding rows of interface commandIterator should be an iterator or a list of tuples with: * button label * button handler - either BaseAction action, or an executable object ''' return CommandLayout(helpLink, commandIterator)
from maya import cmds from ngSkinTools.ui.basetab import BaseTab from ngSkinTools.ui.editMirrorInfluencesWindow import EditMirrorInfluencesWindow from ngSkinTools.ui.uiWrappers import FloatField, CheckBoxField, DropDownField from ngSkinTools.doclink import SkinToolsDocs from ngSkinTools.ui.layerDataModel import LayerDataModel from ngSkinTools.ui.events import LayerEvents, MayaEvents from ngSkinTools.log import getLogger from ngSkinTools.orderedDict import OrderedDict from ngSkinTools.ui.components.influencePrefixSuffixSelector import InfluencePrefixSuffixSelector from ngSkinTools.ui.components import titledRow, uiGroup from ngSkinTools.mllInterface import MllInterface, MirrorDirection from ngSkinTools import selectionState from ngSkinTools.influenceMapping import InfluenceMapping log = getLogger("mirror UI") class TabMirror(BaseTab): TOOL_PAINT = 'ngSkinToolsLayerPaintCtx' # prefix for environment variables for this tab VAR_PREFIX = 'ngSkinToolsMirrorTab_' def __init__(self): BaseTab.__init__(self) def executeMirror(self): self.influenceMappingConfiguration.updateSelectionsInfluenceMapping() mirrorDirection = MirrorDirection.DIRECTION_POSITIVETONEGATIVE
# of this source code package. # from maya import cmds from ngSkinTools import selectionState from ngSkinTools.doclink import SkinToolsDocs from ngSkinTools.influenceMapping import InfluenceMapping from ngSkinTools.log import getLogger from ngSkinTools.mllInterface import MllInterface from ngSkinTools.ui.basetab import CommandLayout from ngSkinTools.ui.basetoolwindow import BaseToolWindow from ngSkinTools.ui.components import uiGroup from ngSkinTools.ui.components.influencesManualMapping import InfluencesManualMapping from ngSkinTools.ui.components.influencesMappingPreview import InfluencesMappingPreview log = getLogger('editMirrorInfluencesWindow') class EditMirrorInfluencesWindow(BaseToolWindow): def __init__(self, windowName): BaseToolWindow.__init__(self, windowName) self.useUserPrefSize = False self.windowTitle = 'Edit Mirror Influences' self.sizeable = True self.defaultHeight = 400 self.defaultWidth = 450 self.influenceMappingPreview = InfluencesMappingPreview() self.influencesManualMapping = InfluencesManualMapping() self.buildMapper = None
# http://www.ngskintools.com # # -------------------------------------------------------------------------- # # The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # from maya import cmds from ngSkinTools.log import getLogger log = getLogger("LayerUtils") class NamedPaintTarget: MASK = "mask" DUAL_QUATERNION = "dq" class LayerUtils: @staticmethod def iterCustomNodes(): for nodeType in ['ngSkinLayerData', 'ngSkinLayerDisplay']: items = cmds.ls(type=nodeType) if items is not None: for i in items: yield i
def __init__(self, mesh=None): self.log = log.getLogger("MllInterface") self.setCurrentMesh(mesh)
class BaseToolWindow(object): log = getLogger("BaseToolWindow") windowInstances = {} def __init__(self,windowName): self.updateAvailable = False self.windowTitle = '' self.windowName = windowName self.sizeable = False self.menuBar = True self.defaultWidth = 300 self.defaultHeight = 300 self.useUserPrefSize = True BaseToolWindow.windowInstances[self.windowName]=self @staticmethod def closeAll(): for _, window in BaseToolWindow.windowInstances.items(): window.closeWindow() @staticmethod def getWindowInstance(windowName,windowClass=None): if BaseToolWindow.windowInstances.has_key(windowName): return BaseToolWindow.windowInstances[windowName] if windowClass is None: return None return BaseToolWindow.rebuildWindow(windowName, windowClass) @staticmethod def rebuildWindow(windowName,windowClass): BaseToolWindow.destroyWindow(windowName); instance = windowClass(windowName) instance.createWindow() return instance def createWindow(self): self.log.debug("creating window "+self.windowName) if self.windowExists(self.windowName): raise Exception("window %s already opened" % self.windowName) if not self.useUserPrefSize: try: cmds.windowPref(self.windowName,remove=True) cmds.windowPref(self.windowName,width=self.defaultWidth,height=self.defaultHeight) except: pass cmds.window(self.windowName, title=self.windowTitle, maximizeButton=False, minimizeButton=False, width=self.defaultWidth, height=self.defaultHeight, sizeable=self.sizeable, menuBar=self.menuBar) scriptJobs.scriptJob(uiDeleted=[self.windowName,self.onWindowDeleted]) HeadlessDataHost.HANDLE.addReference(self) def onWindowDeleted(self): if not HeadlessDataHost.HANDLE.removeReference(self): return BaseToolWindow.windowInstances.pop(self.windowName) def showWindow(self): if self.windowExists(self.windowName): cmds.showWindow(self.windowName) def closeWindow(self): if self.windowExists(self.windowName): self.onWindowDeleted() cmds.window(self.windowName,e=True,visible=False) @staticmethod def windowExists(windowName): return cmds.window(windowName, exists=True) @staticmethod def destroyWindow(windowName): if BaseToolWindow.windowExists(windowName): instance = BaseToolWindow.getWindowInstance(windowName) if instance is not None: instance.onWindowDeleted(); cmds.deleteUI(windowName, window=True) @staticmethod def closeAllWindows(): for i in BaseToolWindow.windowInstances.values(): i.closeWindow()
# -------------------------------------------------------------------------- # # The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # from maya import cmds from ngSkinTools.ui.uiWrappers import FormLayout from ngSkinTools.ui.constants import Constants from ngSkinTools.log import getLogger log = getLogger("base dialog") class Button: def __init__(self, title, buttonId): self.title = title self.buttonId = buttonId def __str__(self): return self.buttonId class BaseDialog: currentDialog = None BUTTON_OK = Button("Ok", "ok")
For usage details, see unit test examples. ''' import re from itertools import izip import math from maya import OpenMaya as om from ngSkinTools.log import getLogger def isChildOf(a, b): return b.startswith(a + "|") log = getLogger("influenceMapping") class NameMatchingRule: def __init__(self): self.prefixRegexp = None self.mirrorMode = False self.prefixes = None self.ignoreNamespaces = True self.reversePathCache = {} def reversePath(self, path): cachedResult = self.reversePathCache.get(path) if cachedResult is not None: return cachedResult
from maya import OpenMaya as om from maya import cmds from maya import mel from ngSkinTools.log import getLogger from functools import wraps class MessageException(Exception): def __init__(self, message): self.message = message def __str__(self, *args, **kwargs): return self.message log = getLogger("utils") def confirmDialog(**kwargs): ''' used to be a pre-2011 Maya compatibility wrapper of cmds.confirmDialog. Keeping for now ''' return cmds.confirmDialog(**kwargs) def displayError(message): ''' displays error in script editor and in a dialog box '''
# A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # import os from maya import cmds from ngSkinTools.license import fileFormat from ngSkinTools.log import getLogger from ngSkinTools.ui.events import Signal from ngSkinTools.ui.options import PersistentValueModel from ngSkinTools.utils import Utils savedLicensePath = PersistentValueModel("ngSkinToolsOption_licensePath") log = getLogger("license") class LicenseType: RLM = "rlm-ez" NGSTKEY = "ngstKey" class Status: ''' given licensePath, track license status. works both with ngstKey licenses and RLM licenses ''' def __init__(self): ''' :param str licensePath:
# # -------------------------------------------------------------------------- # # The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # from ngSkinTools.utils import MessageException from ngSkinTools.log import getLogger from ngSkinTools.layerUtils import NamedPaintTarget log = getLogger("WeightsClipboard") class WeightsClipboard: def __init__(self, mllInterface): ''' :param MllInterface mllInterface: ''' self.copiedWeights = None self.mll = mllInterface self.layer = None self.influence = None def withCurrentLayerAndInfluence(self): ''' :rtype: WeightsClipboard
from maya import cmds from ngSkinTools import selectionState from ngSkinTools.selectionState import selectionInfo from ngSkinTools.ui.uiWrappers import FormLayout, TextEdit, RadioButtonField from ngSkinTools.ui.constants import Constants from ngSkinTools.layerUtils import NamedPaintTarget from ngSkinTools.ui.layerDataModel import LayerDataModel from ngSkinTools.ui.events import LayerEvents, Signal, MayaEvents from ngSkinTools.utils import Utils from ngSkinTools.ui.options import Options, PersistentValueModel from ngSkinTools.log import getLogger from ngSkinTools.InfluenceNameTransforms import InfluenceNameTransform from ngSkinTools.InfluenceNameFilter import InfluenceNameFilter from ngSkinTools.ui import uiWrappers log = getLogger("layerListsUI") class IdToNameEntry(object): def __init__(self, itemId=None, name=None, displayName=None, suffix=None): assert isinstance(itemId, basestring) if displayName is None: displayName = name self.id = itemId self.name = name self.displayName = displayName self.suffix = suffix self.parent = None
# # -------------------------------------------------------------------------- # # The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # from maya import cmds from ngSkinTools.log import getLogger log = getLogger("events") class Signal: ''' Signal class collects observers, interested in some particular event,and handles signaling them all when some event occurs. Both handling and signaling happens outside of signal's own code ''' all = [] def __init__(self,name): if name is None: raise Exception("need name for debug purposes later") self.name = name self.reset()
# # The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # from ngSkinTools.mllInterface import MllInterface from ngSkinTools.utils import MessageException from ngSkinTools.log import getLogger from maya import cmds from ngSkinTools.skinClusterFn import SkinClusterFn log = getLogger("ImportInfluences") class ImportInfluences(object): def __init__(self): self.sourceSkinCluster = None self.destinationSkinCluster = None def __detectSkinCluster(self,mesh): mll = MllInterface() mll.setCurrentMesh(mesh) try: _,skinCluster = mll.getTargetInfo() except TypeError: raise MessageException("cannot find skin cluster attached to %s" % mesh)
# The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # from ngSkinTools import selectionState from ngSkinTools.ui.layerDataModel import LayerDataModel from ngSkinTools.utils import Utils from ngSkinTools.ui.events import MayaEvents, scriptJobs from ngSkinTools.doclink import SkinToolsDocs from ngSkinTools.log import getLogger log = getLogger("HeadlessDataHost") class RefCountedHandle: ''' reference counted handle to a dynamically allocated instance; creates reference after first addReference() call, and destroys it when last reference is removed via removeReference() ''' def __init__(self, instantiator): self.instantiator = instantiator self.instance = None self.references = set() def getCurrentInstance(self):
from ngSkinTools.ui.components import titledRow from ngSkinTools.ui.mainwindow import MainWindow from ngSkinTools.utils import Utils from ngSkinTools.ui.events import LayerEvents, MayaEvents from ngSkinTools.ui.layerDataModel import LayerDataModel from ngSkinTools.ui.uiWrappers import RadioButtonField, DropDownField,\ CheckBoxField from ngSkinTools.doclink import SkinToolsDocs from ngSkinTools.ui.options import PersistentValueModel from ngSkinTools.ui.uiCompounds import FloatSliderField from ngSkinTools.ui.SelectHelper import SelectHelper from ngSkinTools.mllInterface import PaintMode, MllInterface from ngSkinTools.paint import ngLayerPaintCtxInitialize from ngSkinTools.log import getLogger log = getLogger("tabPaint") class TabPaint(BaseTab): TOOL_PAINT = 'ngSkinToolsLayerPaintCtx' VAR_PREFIX = 'ngSkinToolsPaintTab_' def __init__(self): BaseTab.__init__(self) self.parentWindow = None # type: MainWindow self.controls.brushShapeButtons = [] self.intensityReplace = PersistentValueModel(self.VAR_PREFIX +
from ngSkinTools.doclink import SkinToolsDocs from ngSkinTools.ui.components import uiGroup from ngSkinTools.ui.components.influencesManualMapping import InfluencesManualMapping from ngSkinTools.ui.components.influencesMappingPreview import InfluencesMappingPreview from ngSkinTools.ui.events import LayerEvents, MayaEvents from ngSkinTools.ui.uiWrappers import FloatField, StoredTextEdit,\ DropDownField, CheckBoxField, RadioButtonField from ngSkinTools.ui.layerDataModel import LayerDataModel from ngSkinTools.ui.constants import Constants from ngSkinTools.utils import Utils from ngSkinTools.log import getLogger from ngSkinTools.influenceMapping import InfluenceMapping from ngSkinTools.mllInterface import MllInterface from ngSkinTools.orderedDict import OrderedDict log = getLogger("initTransferWindow") class CopyWeightsModel(object): vertexTransferModes = OrderedDict(( ("Closest point on surface", "closestPoint"), ("UV space", "uvSpace"), ("By Vertex ID", "vertexId"), )) def __init__(self): self.parent = None self.sourceModel = None self.sourceMesh = None self.targetMesh = None
class LayerDataModel: log = getLogger("layerDataModel") # holds instance of singleton object __instance = None @staticmethod def getInstance(): ''' returns singleton instance of LayerDataModel :rtype: LayerDataModel ''' return LayerDataModel.__instance @classmethod def bindAll(cls): cls.__instance = LayerDataModel() MayaEvents.undoRedoExecuted.addHandler( cls.__instance.updateLayerAvailability) MayaEvents.nodeSelectionChanged.addHandler( cls.__instance.updateLayerAvailability) cls.__instance.updateLayerAvailability() def __init__(self): self.layerDataAvailable = None self.mll = MllInterface() self.clipboard = WeightsClipboard(self.mll) def setLayerListsUI(self, ui): self.layerListsUI = ui def getLayerListsUI(self): ''' :rtype: LayerListsUI ''' from ngSkinTools.ui import mainwindow mainWindow = mainwindow.MainWindow.getInstance() if mainWindow is None: return None return mainWindow.getLayersUI() def getSelectedLayer(self): listsUi = self.getLayerListsUI() if listsUi is None: return None return listsUi.getLayersList().getSelectedID() def getSelectedLayers(self): listsUi = self.getLayerListsUI() if listsUi is None: return [] return listsUi.getSelectedLayers() def getSelectedInfluenceIds(self): listsUi = self.getLayerListsUI() if listsUi is None: return [] return listsUi.getSelectedInfluenceIds() def updateLayerAvailability(self): ''' checks if availability of skin layers changed with the current scene selection ''' self.log.info("updating layer availability") oldValue = self.layerDataAvailable self.layerDataAvailable = self.mll.getLayersAvailable() if self.layerDataAvailable != oldValue: LayerEvents.layerAvailabilityChanged.emit() @Utils.undoable def addLayer(self, name): def guessParent(): currentLayer = self.mll.getCurrentLayer() if currentLayer is None: return None # guess layer's new parent parentsByLayerId = dict([ (layerId, parentId) for layerId, _, parentId in self.mll.listLayers() if currentLayer in (layerId, parentId) ]) # current layer is a parent? if currentLayer in parentsByLayerId.values(): return currentLayer # current layer has parent if currentLayer in parentsByLayerId.keys(): return parentsByLayerId[currentLayer] layerId = self.mll.createLayer(name) self.mll.setLayerParent(layerId, guessParent()) if layerId is None: return None LayerEvents.layerListModified.emit() self.setCurrentLayer(layerId) return layerId def removeLayer(self, layerId): self.mll.deleteLayer(layerId) LayerEvents.layerListModified.emit() LayerEvents.currentLayerChanged.emit() def setCurrentLayer(self, layerId): self.mll.setCurrentLayer(layerId) LayerEvents.currentLayerChanged.emit() def getCurrentLayer(self): return self.mll.getCurrentLayer() def attachLayerData(self): self.mll.initLayers() with self.mll.batchUpdateContext(): self.addLayer('Base Weights') self.updateLayerAvailability() selectionState.selectionInfo.dropCache() def cleanCustomNodes(self): ''' removes all custom nodes from current scene ''' # just in case we were in the middle of painting cmds.setToolTo('selectSuperContext') LayerUtils.deleteCustomNodes() # notify the rest of the world self.updateLayerAvailability() selectionState.selectionInfo.dropCache() def getLayerName(self, layerId): return mel.eval('ngSkinLayer -id {0} -q -name'.format(int(layerId))) def setLayerName(self, layerId, name): self.mll.setLayerName(layerId, name) LayerEvents.nameChanged.emit() def getLayerOpacity(self, layerId): return mel.eval('ngSkinLayer -id {0} -q -opacity'.format(layerId)) def getLayerEnabled(self, layerId): return mel.eval('ngSkinLayer -id {0} -q -enabled'.format(layerId)) def setLayerEnabled(self, layerId, enabled): cmds.ngSkinLayer(e=True, id=layerId, enabled=1 if enabled else 0) def toggleLayerEnabled(self, layerId): self.setLayerEnabled(layerId, not self.getLayerEnabled(layerId)) def getLayersCandidateFromSelection(self): ''' for given selection, returns mesh and skin cluster node names where skinLayer data is (or can be) attached. ''' return self.mll.getTargetInfo() def getLayersAvailable(self): self.updateLayerAvailability() return self.layerDataAvailable def isDqMode(self): ''' returns True if current skin cluster is operating in dual quaternion mode ''' target = self.mll.getTargetInfo() if not target: return False skinCluster = target[1] return cmds.skinCluster(skinCluster, q=True, skinMethod=True) == 2
class TransferWeightsTab(BaseTab): log = getLogger("Transfer Weights Tab") VAR_PREFIX = 'ngSkinToolsTransferTab_' axisValues = ('X', 'Y', 'Z') def __init__(self): BaseTab.__init__(self) self.dataModel = CopyWeightsModel() self.dataModel.parent = self self.currentSelection = None self.influenceMappingPreview = InfluencesMappingPreview() self.influencesManualMapping = InfluencesManualMapping() def createUI(self, parent): buttons = [('Done', self.execContinue, ''), ('Cancel', self.closeWindow, '')] self.cmdLayout = self.createCommandLayout( buttons, SkinToolsDocs.INITWEIGHTTRANSFER_INTERFACE) self.createTransferOptionsGroup() self.createInfluenceMappingGroup() LayerEvents.layerAvailabilityChanged.addHandler( self.updateLayoutEnabled, self.cmdLayout.outerLayout) MayaEvents.nodeSelectionChanged.addHandler(self.updateUIValues, self.cmdLayout.outerLayout) self.updateLayoutEnabled() self.updateUIValues() self.updatePreferedValues() def releaseUI(self): LayerEvents.layerAvailabilityChanged.removeHandler( self.updateLayoutEnabled) MayaEvents.nodeSelectionChanged.removeHandler(self.updateUIValues) def updatePreferedValues(self): self.influencesManualMapping.manualOverrides = {} def updateUIValues(self): # when selection changes between update UI calls, overwrite UI with preferred values in the mesh selection = cmds.ls(sl=True) if selection != self.currentSelection: self.updatePreferedValues() self.currentSelection = selection self.previewInfluenceMapping() def createTransferOptionsGroup(self): group = self.createUIGroup(self.cmdLayout.innerLayout, 'Transfer Options') self.createTitledRow(parent=group, title="Vertex Transfer Mode") self.controls.transferMode = DropDownField(self.VAR_PREFIX + 'vertexTransferMode') for opt in CopyWeightsModel.vertexTransferModes.keys(): self.controls.transferMode.addOption(opt) self.createTitledRow(parent=group, title=None) self.controls.keepExistingLayers = CheckBoxField( self.VAR_PREFIX + 'KeepExistingLayers', label="Keep existing layers", annotation= 'when unselected, will delete existing layers in destination', defaultValue=1) def createInfluenceMappingGroup(self): group = self.createUIGroup(self.cmdLayout.innerLayout, 'Influence Mapping') self.createFixedTitledRow(group, 'Infl. Distance Error') self.controls.influenceDistanceError = FloatField( self.VAR_PREFIX + 'distanceError', minValue=0, maxValue=None, step=0.01, defaultValue=0.001, annotation= 'Defines maximum inaccuracy between left and right influence positions' ) self.controls.influenceDistanceError.changeCommand.addHandler( self.previewInfluenceMapping, group) self.createTitledRow(parent=group, title="Namespaces") self.controls.ignoreNamespaces = CheckBoxField( self.VAR_PREFIX + 'IgnoreNamespaces', label="Ignore", annotation='ignore influence namespaces when matching by name', defaultValue=1) self.controls.ignoreNamespaces.changeCommand.addHandler( self.previewInfluenceMapping, ownerUI=group) self.influenceMappingPreview.mirrorMode = False self.influenceMappingPreview.createUI(parent=group) self.influenceMappingPreview.onDelete.addHandler( self.influencesManualMapping.removeSelectedManualMappings, group) manualGroup = uiGroup.create(self.cmdLayout.innerLayout, 'Manual influence mapping') self.influencesManualMapping.mirrorMode = False self.influencesManualMapping.createUI(parent=manualGroup) self.influencesManualMapping.getSelectedInfluences = lambda: self.influenceMappingPreview.currentInfluencesSelection self.influencesManualMapping.manualOverridesChanged.addHandler( self.previewInfluenceMapping, group) cmds.setParent(group) def closeWindow(self, *args): self.parentWindow.closeWindow() def buildInfluenceMappingEngine(self): ''' :rtype: InfluenceMapping ''' result = self.dataModel.buildInfluenceMappingEngine(self.controls) result.manualOverrides = self.influencesManualMapping.manualOverrides return result def previewInfluenceMapping(self): if not self.dataModel.isEnabled(): return engine = self.buildInfluenceMappingEngine() engine.calculate() self.influenceMappingPreview.mapper = engine self.influenceMappingPreview.constructInfluenceList() def execContinue(self, *args): self.previewInfluenceMapping() self.dataModel.execute() self.closeWindow() def updateLayoutEnabled(self): ''' updates UI enabled/disabled flag based on layer data availability ''' enabled = self.dataModel.isEnabled() cmds.layout(self.cmdLayout.innerLayout, e=True, enable=enabled) cmds.layout(self.cmdLayout.buttonForm, e=True, enable=enabled)
from __future__ import with_statement from maya import cmds, mel from ngSkinTools import utils from ngSkinTools.ui.events import Signal, LayerEvents, MayaEvents from ngSkinTools.ui.layerDataModel import LayerDataModel from ngSkinTools.ui.dlgLayerProperties import LayerPropertiesDialog from ngSkinTools.ui.basedialog import BaseDialog from ngSkinTools.utils import Utils, MessageException from ngSkinTools.ui.basetoolwindow import BaseToolWindow from ngSkinTools.log import getLogger from ngSkinTools.ui.options import deleteCustomOptions from ngSkinTools.mllInterface import MllInterface, MirrorDirection from ngSkinTools.ui import tabMirror log = getLogger("actions") class BaseAction(object): def __init__(self, ownerUI): self.ownerUI = ownerUI self.onExecuted = Signal("action executed") self.updateControls = [] def addUpdateControl(self, control, menu=False): self.updateControls.append((control, menu)) def isEnabled(self): ''' override this method to provide enabled/disabled state of this action '''
# The coded instructions, statements, computer programs, and/or related # material (collectively the "Data") in these files are subject to the terms # and conditions defined by EULA. # # A copy of EULA can be found in file 'LICENSE.txt', which is part # of this source code package. # ''' Cached information about current selection ''' from ngSkinTools.log import getLogger from ngSkinTools.mllInterface import MllInterface from ngSkinTools.stateStore import CachedValue from ngSkinTools.ui.events import Signal, LayerEvents, MayaEvents log = getLogger('selectionState') mll = MllInterface() # container for mirror related state mirrorInfo = CachedValue('mirrorInfo', lambda: { 'axis': mll.getMirrorAxis(), }) # container for primary selection data selectionInfo = CachedValue( 'selectionInfo', lambda: { 'target': mll.getTargetInfo(), 'layersAvailable': mll.getLayersAvailable(), })