Last active
February 20, 2024 20:32
-
-
Save gregoiredehame/a7224fb04a9090ac1f24c772dd6b693c to your computer and use it in GitHub Desktop.
native maya push matrix collider
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import maya.cmds as cmds | |
| import maya.mel as mel | |
| import maya.api.OpenMaya as om2 | |
| if __name__ == '__main__': | |
| from kata import core as kcore | |
| from kata import rig as krig | |
| else: | |
| from .. import core as kcore | |
| from .. import rig as krig | |
| def create(node:str=None, targets:str=None, **kwargs) -> str: | |
| """function that will create a push matrix connection. | |
| this is based on maya muscles node, but will clean up nodes connections. | |
| compared to default maya muscle, we are going to use target node world matrix attribute instead of creating a new transform. | |
| if target have only one children, the matrix connections will be made on children, otherwise will create a new transform. | |
| usually, we want to use this tool for lower lips and upper lips connections. | |
| /!\ maya muscles shape nodes will be parented under the node's transforms. | |
| Args: | |
| node: (str): - string node of the collider mesh / nurbs surface | |
| targets: (str, list): - string or list of node(s) to use as push matrix | |
| maya muscles nodes explained: | |
| Riham Toulan: (collar rig): - https://www.rihamtoulan.com/blog/2018/3/24/faking-collisions-with-joints-based-setup-8snd2 | |
| Perry Leijten: (skirt rig): - https://www.perryleijten.com/en/works/skirtColliderRD | |
| """ | |
| if not node or not isinstance(node, str) or not cmds.objExists(node): | |
| raise AttributeError('unable to create push matrix rig. no node given and/or given node might not be a <str> existing object.') | |
| if not kcore.mesh.is_mesh(node) and not kcore.surface.is_surface(node): | |
| raise AttributeError('unable to create push matrix rig on "%s". type needs to be a <mesh> or a <nurbsSurface>. current <%s> does not work.'% (node, kcore.utilities.get_type(node))) | |
| kcore.plugin.load('MayaMuscle.mll') | |
| muscle = cmds.ls(cmds.listHistory(node), type="cMuscleObject") | |
| if muscle: | |
| muscle = muscle[0] | |
| cmds.setAttr("%s.stickyStrength"% muscle, 0) | |
| cmds.setAttr("%s.slidingStrength"% muscle, 1) | |
| cmds.setAttr("%s.reverseNormals"% muscle, 0) | |
| cmds.setAttr("%s.relative"% muscle, 0) | |
| cmds.setAttr("%s.lockStickyWt"% muscle, 0) | |
| cmds.setAttr("%s.lockSlidingWt"% muscle, 0) | |
| cmds.setAttr("%s.affectSticky"% muscle, 0) | |
| cmds.setAttr("%s.affectSliding"% muscle, 0) | |
| cmds.setAttr("%s.userScaleX"% muscle, 0) | |
| cmds.setAttr("%s.userScaleY"% muscle, 0) | |
| cmds.setAttr("%s.userScaleZ"% muscle, 0) | |
| cmds.setAttr("%s.draw"% muscle, 1) | |
| cmds.setAttr("%s.shaded"% muscle, 0) | |
| cmds.setAttr("%s.highlight"% muscle, 0) | |
| cmds.setAttr("%s.highlightShaded"% muscle, 0) | |
| if not kcore.attributes.is_exists(node, "collisionWidth"): | |
| cmds.addAttr(node, longName="collisionWidth", niceName="Collision Width", attributeType="float", keyable=True, min=0, max=1, defaultValue=0) | |
| cmds.connectAttr("%s.collisionWidth"% node, "%s.fat"% muscle) | |
| kcore.attributes.animable(node, "collisionWidth") | |
| if not kcore.attributes.is_exists(node, "collisionLod"): | |
| cmds.addAttr(node, longName="collisionLod", niceName="Collision LOD", attributeType="enum", enumName="Full:Medium:Low", defaultValue=2) | |
| kcore.attributes.animable(node, "collisionLod") | |
| else: | |
| cmds.select(node) | |
| mel.eval("cMuscle_makeMuscle(0)") | |
| return create(node, targets) | |
| for target in kcore.utilities.as_list(targets): | |
| childrens = cmds.listRelatives(target, children=True, type="transform") or [] | |
| reconnection = True if len(childrens) == 1 else None | |
| cmds.select(target) | |
| mel.eval("cMuscle_rigKeepOutSel();") | |
| cmds.select(node, cmds.listConnections("%s.msgKeepOutXForm"% target, source=True)[0]) | |
| mel.eval("cMuscle_keepOutAddRemMuscle(1);") | |
| keep_out = cmds.listConnections("%s.msgKeepOutXForm"% target, source=True)[0] | |
| keep_out_shape = cmds.listRelatives(keep_out, shapes=True)[0] | |
| keep_out_transform = cmds.listConnections("%s.msgKeepOutDriven"% target, source=True)[0] | |
| cmds.parent(keep_out_shape, node, relative=True, shape=True) | |
| cmds.setAttr("%s.draw"% keep_out_shape, 0) | |
| cmds.connectAttr("%s.collisionLod"% node, "%s.quality"% keep_out_shape) | |
| cmds.connectAttr("%s.worldMatrix[0]"% target, "%s.worldMatrixAim"% keep_out_shape, force=True) | |
| if reconnection: | |
| try: | |
| cmds.connectAttr("%s.outTranslateLocal"% keep_out_shape, "%s.translate"% childrens[0]) | |
| for children in cmds.listRelatives(keep_out_transform, children=True, type="transform") or []: | |
| cmds.parent(children, target) | |
| cmds.delete(keep_out_transform) | |
| except: | |
| cmds.parent(keep_out_transform, target) | |
| else: | |
| cmds.parent(keep_out_transform, target) | |
| for attribute in ("msgKeepOut", "msgKeepOutDriven", "msgKeepOutXForm"): | |
| [cmds.disconnectAttr(connection, "%s.%s"% (target, attribute)) for connection in cmds.listConnections("%s.%s"% (target, attribute), source=True, plugs=True) or []] | |
| cmds.deleteAttr("%s.%s"% (target, attribute)) | |
| if not kcore.attributes.is_exists(target, "enableCollision"): | |
| cmds.addAttr(target, longName="enableCollision", niceName="Collision", attributeType="bool", keyable=True, defaultValue=True) | |
| kcore.attributes.animable(target, "enableCollision") | |
| cmds.connectAttr("%s.enableCollision"% target, "%s.enable"% keep_out_shape) | |
| for vector in ("X", "Y", "Z"): | |
| if not kcore.attributes.is_exists(target, "inDirection%s"% vector): | |
| cmds.addAttr(target, longName="inDirection%s"% vector, niceName="Collision Vector %s"% vector, attributeType="float", keyable=True, min=0, max=1, defaultValue=1 if vector == "Y" else 0) | |
| kcore.attributes.animable(target, "inDirection%s"% vector) | |
| cmds.connectAttr("%s.inDirection%s"% (target, vector), "%s.inDirection%s"% (keep_out_shape, vector)) | |
| cmds.delete(keep_out) | |
| return node | |
| if __name__ == '__main__': | |
| create(node="nurbsSphere1", targets=["locator1", "locator2", "locator3"]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

e70fdf7802167e3a1e44b685ad2e80fd.mp4