568 lines
18 KiB
Python
568 lines
18 KiB
Python
'''
|
|
This module contains additional adapters which define how some objects
|
|
have to be additionally adapted for later use.
|
|
|
|
Adapter objects can be connected into chains. If so, object is being adapted by
|
|
first adapter in chain. Once first adapter finish adapting, it calls next
|
|
adapter in chain to do its adapting, and so on.
|
|
'''
|
|
|
|
from maya import cmds
|
|
|
|
|
|
class AdditionalAdapter:
|
|
'''
|
|
Base AdditionalAdapter class.
|
|
|
|
All adapters have to inherent this class and redefine method adapt().
|
|
Attributes:
|
|
nextAdapter (AdditionalAdapter): Next adapter in adapting chain.
|
|
'''
|
|
|
|
def __init__(self):
|
|
self.nextAdapter = None
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Changes given data in a way to adapt it for later use depending on context.
|
|
|
|
This method has to be overridden.
|
|
When method finish with adapting objects, it calls next adapter in chain.
|
|
@param object: Object which has to be adapted.
|
|
'''
|
|
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
# ----------------------------
|
|
# Joint additional adapters
|
|
# ----------------------------
|
|
class MayaJointsDataScaleAA(AdditionalAdapter):
|
|
'''
|
|
Maya joint data additional adapter.
|
|
|
|
This adapter changes joints scale.
|
|
@see trilateral.api.maya.MayaJoint
|
|
@see trilateral.api.maya.MayaJointDataHolder
|
|
'''
|
|
|
|
def __init__(self, scale, pivot):
|
|
AdditionalAdapter.__init__(self)
|
|
self._scale = scale
|
|
self._pivot = pivot
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt Maya joints scale based on scale coefficient and pivot.
|
|
|
|
@param object: Maya joints object. (trilateral.api.maya.MayaJointDataHolder)
|
|
'''
|
|
|
|
# adapt
|
|
if self._scale != 1.0:
|
|
object.scale(self._scale, self._pivot)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
class MayaJointsDataOrientAA(AdditionalAdapter):
|
|
'''
|
|
Maya joint data additional adapter.
|
|
|
|
This adapter changes joints orient.
|
|
@see trilateral.api.maya.MayaJoint
|
|
@see trilateral.api.maya.MayaJointDataHolder
|
|
'''
|
|
|
|
def __init__(self, orient, translate):
|
|
AdditionalAdapter.__init__(self)
|
|
self._orient = orient
|
|
self._translate = translate
|
|
|
|
def adapt(self, joints):
|
|
'''
|
|
Adapt Maya joints orientation based on given orient.
|
|
|
|
@param object: Maya joints object. (trilateral.api.maya.MayaJointDataHolder)
|
|
'''
|
|
|
|
# adapt
|
|
for mayaJoint in joints:
|
|
# create joints
|
|
cmds.select(clear=True)
|
|
jointNode = cmds.joint(name="temp_root_jnt")
|
|
jointNode.jointOrient.set(mayaJoint.jointOrient.get())
|
|
jointNode.translate.set(mayaJoint.translate.get())
|
|
jointNode.rotate.set(mayaJoint.rotate.get())
|
|
jointNode.scale.set(mayaJoint.scale.get())
|
|
|
|
# rotate
|
|
locator = cmds.spaceLocator()
|
|
jointNode.setParent(locator)
|
|
if self._orient[0] != 0.0 or self._orient[1] != 0.0 or self._orient[2] != 0.0:
|
|
locator.rotate.set(self._orient)
|
|
|
|
if self._translate[0] != 0.0 or self._translate[1] != 0.0 or self._translate[2] != 0.0:
|
|
locator.translate.set(self._translate)
|
|
|
|
jointNode.setParent(None)
|
|
cmds.delete(locator)
|
|
|
|
# save changes
|
|
mayaJoint.translate.set(jointNode.translate.get())
|
|
mayaJoint.rotate.set(jointNode.rotate.get())
|
|
mayaJoint.scale.set(jointNode.scale.get())
|
|
mayaJoint.jointOrient.set(jointNode.jointOrient.get())
|
|
cmds.delete(jointNode)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
# ----------------------------
|
|
# Mesh additional adapters
|
|
# ----------------------------
|
|
class MeshScaleAA(AdditionalAdapter):
|
|
'''
|
|
Mesh additional adapter.
|
|
|
|
This adapter changes mesh scale.
|
|
'''
|
|
|
|
def __init__(self, scale, pivot):
|
|
AdditionalAdapter.__init__(self)
|
|
self._scale = scale
|
|
self._pivot = pivot
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt Mesh scale based on scale coefficient and pivot.
|
|
|
|
This method leave clean channels (translations and rotations at 0.0,
|
|
scale at 1.0).
|
|
@param object: Maya mesh node. (Mesh)
|
|
'''
|
|
|
|
# adapt
|
|
locator = cmds.spaceLocator()
|
|
locator.translate.set(self._pivot)
|
|
object.setParent(locator)
|
|
locator.scale.set([self._scale, self._scale, self._scale])
|
|
object.setParent(None)
|
|
cmds.delete(locator)
|
|
cmds.makeIdentity(object, apply=True, t=True, r=True, s=True, n=True)
|
|
cmds.polyNormalPerVertex(object, unFreezeNormal=True)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
class MeshOrientAA(AdditionalAdapter):
|
|
'''
|
|
Mesh additional adapter.
|
|
|
|
This adapter changes mesh orientation.
|
|
'''
|
|
|
|
def __init__(self, orient, translate):
|
|
AdditionalAdapter.__init__(self)
|
|
self._orient = orient
|
|
self._translate = translate
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt Mesh orientation based on given orient.
|
|
|
|
This method leave clean channels (translations and rotations at 0.0,
|
|
scale at 1.0).
|
|
@param object: Maya mesh node. (Mesh)
|
|
'''
|
|
|
|
# adapt
|
|
if self._orient[0] != 0.0 or self._orient[1] != 0.0 or self._orient[2] != 0.0:
|
|
cmds.xform(object, ro=self._orient, relative=True)
|
|
|
|
if self._translate[0] != 0.0 or self._translate[1] != 0.0 or self._translate[2] != 0.0:
|
|
cmds.xform(object, translation=self._translate, relative=True)
|
|
|
|
cmds.makeIdentity(object, apply=True, t=True, r=True, s=True, n=True)
|
|
cmds.polyNormalPerVertex(object, unFreezeNormal=True)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
# ----------------------------
|
|
# GUI additional adapters
|
|
# ----------------------------
|
|
class GuiScaleAA(AdditionalAdapter):
|
|
'''
|
|
Gui additional adapter.
|
|
|
|
This adapter changes scale.
|
|
'''
|
|
|
|
def __init__(self, scale, pivot):
|
|
AdditionalAdapter.__init__(self)
|
|
self._scale = scale
|
|
self._pivot = pivot
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt 2D gui scale based on scale coefficient and pivot.
|
|
|
|
This method does not leave clean channels (translations and rotations
|
|
can be different than 0.0, and scale different than 1.0).
|
|
|
|
@param object: List of root gui Maya nodes. (DagNode[])
|
|
|
|
Algorithm:
|
|
1. Creates helper locator.
|
|
2. Parent all root nodes under helper locator.
|
|
3. Moves and scales helper locator.
|
|
4. Unparent all root nodes.
|
|
5. Delete helper locator.
|
|
'''
|
|
|
|
# adapt
|
|
for rootNode in object:
|
|
locator = cmds.spaceLocator()
|
|
locator.translate.set(self._pivot)
|
|
parent = rootNode.getParent()
|
|
rootNode.setParent(locator)
|
|
locator.scale.set([self._scale, self._scale, self._scale])
|
|
rootNode.setParent(parent)
|
|
cmds.delete(locator)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
class GuiOrientAA(AdditionalAdapter):
|
|
'''
|
|
Gui additional adapter.
|
|
|
|
This adapter changes 2D GUI orientation.
|
|
'''
|
|
|
|
def __init__(self, orient):
|
|
AdditionalAdapter.__init__(self)
|
|
self._orient = orient
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt 2D gui orientation based on given orient.
|
|
|
|
This method does not leave clean channels (translations and rotations
|
|
can be different than 0.0, and scale different than 1.0).
|
|
|
|
@param object: List of root gui Maya nodes. (DagNode[])
|
|
|
|
Algorithm:
|
|
1. Creates helper locator.
|
|
2. Parent all root nodes under helper locator.
|
|
3. Rotates helper locator.
|
|
4. Unparent all root nodes.
|
|
5. Delete helper locator.
|
|
'''
|
|
|
|
# adapt
|
|
for rootNode in object:
|
|
locator = cmds.spaceLocator()
|
|
parent = rootNode.getParent()
|
|
rootNode.setParent(locator)
|
|
locator.rotate.set(self._orient)
|
|
rootNode.setParent(parent)
|
|
cmds.delete(locator)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
# ----------------------------
|
|
# Controls additional adapters
|
|
# ----------------------------
|
|
class ControlsScaleAA(AdditionalAdapter):
|
|
'''
|
|
Analog controls additional adapter.
|
|
|
|
This adapter changes scale.
|
|
'''
|
|
|
|
def __init__(self, scale, pivot):
|
|
AdditionalAdapter.__init__(self)
|
|
self._scale = scale
|
|
self._pivot = pivot
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt analog controls (or controls in general) scale based on scale
|
|
coefficient and pivot.
|
|
This method leave clean channels (translations and rotations at 0.0,
|
|
scale at 1.0).
|
|
|
|
@param object: List of root analog control Maya nodes. (DagNode[])
|
|
|
|
Algorithm:
|
|
1. Make list of all nodes sorted from parent to children.
|
|
2. Scale all objects:
|
|
- take each root node,
|
|
- create locator, move locator to pivot position, parent root node
|
|
under it,
|
|
- scale locator for scale coefficient,
|
|
- unparent root node,
|
|
- delete locator.
|
|
3. Unlock channels:
|
|
- for all nodes, save data which channels (translate, rotate, scale)
|
|
are locked,
|
|
- for all nodes unlock all channels,
|
|
4. Clean controls channels. For each node:
|
|
- disconnect node from parent and children,
|
|
- save node translate and rotate data,
|
|
- move node to 0, 0, 0,
|
|
- freeze transformations,
|
|
- return node to its previous position using saved translate
|
|
and rotate data,
|
|
- connect node with its previous parent and children.
|
|
5. Lock channels which were locked using saved data.
|
|
'''
|
|
|
|
# adapt
|
|
# get all nodes and scale them all
|
|
nodes = []
|
|
for rootNode in object:
|
|
nodes.extend(cmds.listRelatives(rootNode, allDescendents=True, type="transform"))
|
|
locator = cmds.spaceLocator()
|
|
locator.translate.set(self._pivot)
|
|
parent = rootNode.getParent()
|
|
rootNode.setParent(locator)
|
|
locator.scale.set([self._scale, self._scale, self._scale])
|
|
rootNode.setParent(parent)
|
|
cmds.delete(locator)
|
|
nodes.extend(object)
|
|
nodes.reverse()
|
|
|
|
# unlock translate, rotate, scale on all nodes
|
|
lockedDict = {}
|
|
for node in nodes:
|
|
locks = [node.translateX.isLocked(), node.translateY.isLocked(), node.translateZ.isLocked(),
|
|
node.rotateX.isLocked(), node.rotateY.isLocked(), node.rotateZ.isLocked(),
|
|
node.scaleX.isLocked(), node.scaleY.isLocked(), node.scaleZ.isLocked()]
|
|
lockedDict[node.longName()] = locks
|
|
node.translateX.setLocked(False)
|
|
node.translateY.setLocked(False)
|
|
node.translateZ.setLocked(False)
|
|
node.rotateX.setLocked(False)
|
|
node.rotateY.setLocked(False)
|
|
node.rotateZ.setLocked(False)
|
|
node.scaleX.setLocked(False)
|
|
node.scaleY.setLocked(False)
|
|
node.scaleZ.setLocked(False)
|
|
|
|
# clean transformations
|
|
for node in nodes:
|
|
# save data
|
|
parent = node.getParent()
|
|
children = node.getChildren(type="transform")
|
|
if parent:
|
|
node.setParent(None)
|
|
for child in children:
|
|
child.setParent(None)
|
|
translateValues = node.translate.get()
|
|
rotateValues = node.rotate.get()
|
|
|
|
# freeze
|
|
node.translate.set([0, 0, 0])
|
|
cmds.makeIdentity(node, apply=True, t=True, r=True, s=True, n=True)
|
|
if node.hasAttr("localScale"):
|
|
node.localScale.set([self._scale, self._scale, self._scale])
|
|
|
|
# parent and return previous state
|
|
node.translate.set(translateValues)
|
|
node.rotate.set(rotateValues)
|
|
if parent:
|
|
node.setParent(parent)
|
|
for child in children:
|
|
child.setParent(node)
|
|
|
|
# lock translate, rotate, scale on all nodes
|
|
for node in nodes:
|
|
locks = lockedDict[node.longName()]
|
|
node.translateX.setLocked(locks[0])
|
|
node.translateY.setLocked(locks[1])
|
|
node.translateZ.setLocked(locks[2])
|
|
node.rotateX.setLocked(locks[3])
|
|
node.rotateY.setLocked(locks[4])
|
|
node.rotateZ.setLocked(locks[5])
|
|
node.scaleX.setLocked(locks[6])
|
|
node.scaleY.setLocked(locks[7])
|
|
node.scaleZ.setLocked(locks[8])
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
class ControlsOrientAA(AdditionalAdapter):
|
|
'''
|
|
Gui additional adapter.
|
|
|
|
This adapter changes controls orientation.
|
|
'''
|
|
|
|
def __init__(self, orient):
|
|
AdditionalAdapter.__init__(self)
|
|
self._orient = orient
|
|
|
|
def adapt(self, object):
|
|
'''
|
|
Adapt analog controls (or controls in general) orientation based on
|
|
given orient.
|
|
|
|
This method does not leave clean channels (translations and rotations
|
|
can be different than 0.0, and scale different than 1.0).
|
|
|
|
@param object: List of root analog control Maya nodes. (DagNode[])
|
|
|
|
Algorithm:
|
|
1. Creates helper locator.
|
|
2. Parent all root nodes under helper locator.
|
|
3. Rotates helper locator.
|
|
4. Unparent all root nodes.
|
|
5. Delete helper locator.
|
|
'''
|
|
|
|
# adapt
|
|
for rootNode in object:
|
|
locator = cmds.spaceLocator()
|
|
parent = rootNode.getParent()
|
|
rootNode.setParent(locator)
|
|
locator.rotate.set(self._orient)
|
|
rootNode.setParent(parent)
|
|
cmds.delete(locator)
|
|
|
|
# call next in chain
|
|
if self.nextAdapter:
|
|
self.nextAdapter.adapt(object)
|
|
|
|
|
|
# ----------------------------
|
|
# Addition adapter builders
|
|
# ----------------------------
|
|
class AdditionalAdapterBuilder:
|
|
'''
|
|
This class contains static methods for building addition adapter chains
|
|
depending on its usage.
|
|
|
|
@see AdditionalAdapter
|
|
'''
|
|
|
|
@staticmethod
|
|
def buildMayaJointsDataAA(scale, pivot, orient, translate):
|
|
'''
|
|
Builds additional adapters chain for Maya joint data adaptation.
|
|
|
|
@param scale: Scale factor (float)
|
|
@param pivor: Scale pivot position. ([float, float, float])
|
|
@param orient: Orientation rotations. ([float, float, float])
|
|
'''
|
|
|
|
firstAA = None
|
|
lastAA = None
|
|
if scale != 1.0:
|
|
aa = MayaJointsDataScaleAA(scale, pivot)
|
|
firstAA = aa
|
|
lastAA = aa
|
|
if orient[0] != 0.0 or orient[1] != 0.0 or orient[2] != 0.0 or translate[0] != 0.0 or translate[1] != 0.0 or translate[2] != 0.0:
|
|
aa = MayaJointsDataOrientAA(orient, translate)
|
|
if lastAA:
|
|
lastAA.nextAdapter = aa
|
|
else:
|
|
firstAA = aa
|
|
lastAA = aa
|
|
return firstAA
|
|
|
|
@staticmethod
|
|
def buildMeshAA(scale, pivot, orient, translate):
|
|
'''
|
|
Builds additional adapters chain for mesh adaptation.
|
|
|
|
@param scale: Scale factor (float)
|
|
@param pivot: Scale pivot position. ([float, float, float])
|
|
@param orient: Orientation rotations. ([float, float, float])
|
|
@param translate: Translate position. ([float, float, float])
|
|
'''
|
|
|
|
firstAA = None
|
|
lastAA = None
|
|
if scale != 1.0:
|
|
aa = MeshScaleAA(scale, pivot)
|
|
firstAA = aa
|
|
lastAA = aa
|
|
if orient[0] != 0.0 or orient[1] != 0.0 or orient[2] != 0.0 or translate[0] != 0.0 or translate[1] != 0.0 or translate[2] != 0.0:
|
|
aa = MeshOrientAA(orient, translate)
|
|
if lastAA:
|
|
lastAA.nextAdapter = aa
|
|
else:
|
|
firstAA = aa
|
|
lastAA = aa
|
|
return firstAA
|
|
|
|
@staticmethod
|
|
def buildGuiAA(scale, pivot, orient):
|
|
'''
|
|
Builds additional adapters chain for 2D GUI adaptation.
|
|
|
|
@param scale: Scale factor (float)
|
|
@param pivor: Scale pivot position. ([float, float, float])
|
|
@param orient: Orientation rotations. ([float, float, float])
|
|
'''
|
|
|
|
firstAA = None
|
|
lastAA = None
|
|
if scale != 1.0:
|
|
aa = GuiScaleAA(scale, pivot)
|
|
firstAA = aa
|
|
lastAA = aa
|
|
if orient[0] != 0.0 or orient[1] != 0.0 or orient[2] != 0.0:
|
|
aa = GuiOrientAA(orient)
|
|
if lastAA:
|
|
lastAA.nextAdapter = aa
|
|
else:
|
|
firstAA = aa
|
|
lastAA = aa
|
|
return firstAA
|
|
|
|
@staticmethod
|
|
def buildControlsAA(scale, pivot, orient):
|
|
'''
|
|
Builds additional adapters chain for controls adaptation.
|
|
|
|
@param scale: Scale factor (float)
|
|
@param pivor: Scale pivot position. ([float, float, float])
|
|
@param orient: Orientation rotations. ([float, float, float])
|
|
'''
|
|
|
|
firstAA = None
|
|
lastAA = None
|
|
if scale != 1.0:
|
|
aa = ControlsScaleAA(scale, pivot)
|
|
firstAA = aa
|
|
lastAA = aa
|
|
if orient[0] != 0.0 or orient[1] != 0.0 or orient[2] != 0.0:
|
|
aa = ControlsOrientAA(orient)
|
|
if lastAA:
|
|
lastAA.nextAdapter = aa
|
|
else:
|
|
firstAA = aa
|
|
lastAA = aa
|
|
return firstAA
|