โจ๐ฌ ๐๐๐ฌ ๐๐ค๐ค๐ก ๐๐ฃ๐ฉ๐ง๐ค: "๐ผ๐๐ซ๐๐ฃ๐๐๐๐๐ง๐๐๐ฏ๐๐๐ง๐๐ฃ๐จ๐๐ค๐ง๐ข๐จ" โ๏ธ
Hello VFX & Animation Professionals! ๐
I'm excited to introduce an enhanced addition to your Maya toolkitโAdvancedFreezeTransforms! ๐
Freezing transformations is essential for maintaining clean hierarchies and proper rigging. However, standard freezing methods may not work when objects have connections or children. AdvancedFreezeTransformsย overcomes this by temporarily removing connections and unparenting children before freezing, then restoring them afterward.
๐๐๐๐ฉ ๐ผ๐๐ซ๐๐ฃ๐๐๐๐๐ง๐๐๐ฏ๐๐๐ง๐๐ฃ๐จ๐๐ค๐ง๐ข๐จ ๐๐๐๐๐ง๐จ:
Comprehensive Freezing:ย Works even if objects have connections or children.
Automation: Handles unparenting and reconnection automatically.
User-Friendly Interface:ย Simplifies complex cleanup processes.
๐ ๏ธ ๐ผ๐๐ซ๐๐ฃ๐๐๐๐๐ง๐๐๐ฏ๐๐๐ง๐๐ฃ๐จ๐๐ค๐ง๐ข๐จ โ๏ธ (๐ข๐๐ฎ๐.๐๐ข๐๐จ ๐๐๐ง๐จ๐๐ค๐ฃ):
The test code should be like this:
driven obj to be moved a bit and applied parent con by 2 driv objs with mo=1
Then apply advancedFreezeTransforms
final pos should be same but with freezed trasnform values
import maya.cmds as cmds
def advancedFreezeTransforms(freeze_translate=True, freeze_rotate=True, freeze_scale=True):
ย ย ย ย """
ย ย ย ย Freezes transformations of selected objects, handling connections and children.
ย ย ย ย
ย ย ย ย :param freeze_translate: <bool> Freeze translation if True.
ย ย ย ย :param freeze_rotate: <bool> Freeze rotation if True.
ย ย ย ย :param freeze_scale: <bool> Freeze scale if True.
ย ย ย ย """
ย ย ย ย selected_objects = cmds.ls(selection=True, transforms=True)
ย ย ย ย if not selected_objects:
ย ย ย ย ย ย ย ย cmds.warning("No objects selected.")
ย ย ย ย ย ย ย ย return
ย ย ย ย for obj in selected_objects:
ย ย ย ย ย ย ย ย # Store children (only transform nodes to avoid parenting shape nodes)
ย ย ย ย ย ย ย ย children = cmds.listRelatives(obj, children=True, fullPath=True, type='transform') or []
ย ย ย ย ย ย ย ย if children:
ย ย ย ย ย ย ย ย ย ย ย ย cmds.parent(children, world=True)
ย ย ย ย ย ย ย ย
ย ย ย ย ย ย ย ย # Store incoming connections
ย ย ย ย ย ย ย ย connections = cmds.listConnections(obj, destination=False, source=True, plugs=True) or []
ย ย ย ย ย ย ย ย connections_info = []
ย ย ย ย ย ย ย ย for conn in connections:
ย ย ย ย ย ย ย ย ย ย ย ย try:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย dest_attr = cmds.connectionInfo(conn, destinationFromSource=True)
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย if dest_attr:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย dest_attr = dest_attr[0]
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย connections_info.append((conn, dest_attr))
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย cmds.disconnectAttr(conn, dest_attr)
ย ย ย ย ย ย ย ย ย ย ย ย except Exception as e:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย cmds.warning("Failed to process connection '{}': {}".format(conn, e))
ย ย ย ย ย ย ย ย
ย ย ย ย ย ย ย ย # Freeze transformations
ย ย ย ย ย ย ย ย cmds.makeIdentity(obj, apply=True, translate=freeze_translate, rotate=freeze_rotate, scale=freeze_scale, normal=False)
ย ย ย ย ย ย ย ย print("Frozen transformations for '{}'.".format(obj))
ย ย ย ย ย ย ย ย
ย ย ย ย ย ย ย ย # Reconnect attributes
ย ย ย ย ย ย ย ย for src_attr, dest_attr in connections_info:
ย ย ย ย ย ย ย ย ย ย ย ย try:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย cmds.connectAttr(src_attr, dest_attr, force=True)
ย ย ย ย ย ย ย ย ย ย ย ย except Exception as e:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย cmds.warning("Failed to reconnect '{} -> {}': {}".format(src_attr, dest_attr, e))
ย ย ย ย ย ย ย ย
ย ย ย ย ย ย ย ย # Reparent children back to the object
ย ย ย ย ย ย ย ย if children:
ย ย ย ย ย ย ย ย ย ย ย ย try:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย cmds.parent(children, obj)
ย ย ย ย ย ย ย ย ย ย ย ย except Exception as e:
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย cmds.warning("Failed to reparent children to '{}': {}".format(obj, e))
# Usage example:
# Select objects and run:
# advancedFreezeTransforms(freeze_translate=True, freeze_rotate=True, freeze_scale=True)
# Test function is provided to test main function advancedFreezeTransforms
def test_advancedFreezeTransforms():
ย ย ย ย # Create necessary objects in the scene
ย ย ย ย driver1 = cmds.polySphere(name='driver1')[0]
ย ย ย ย driver2 = cmds.polySphere(name='driver2')[0]
ย ย ย ย driven_cube = cmds.polyCube(name='driven_cube')[0]
ย ย ย ย
ย ย ย ย # Move the driven object to a specific position
ย ย ย ย cmds.move(5, 5, 5, driven_cube)
ย ย ย ย
ย ย ย ย # Apply parent constraints from driver1 and driver2 to driven_cube with maintainOffset=True
ย ย ย ย cmds.parentConstraint([driver1, driver2], driven_cube, mo=True)
ย ย ย ย
ย ย ย ย # Record the driven object's position before freezing
ย ย ย ย pos_before_freeze = cmds.xform(driven_cube, q=True, rotatePivot=True, worldSpace=True)
ย ย ย ย
ย ย ย ย # Apply the advancedFreezeTransforms function
ย ย ย ย #return
ย ย ย ย advancedFreezeTransforms()
ย ย ย ย #return
ย ย ย ย
ย ย ย ย # Record the driven object's position after freezing
ย ย ย ย pos_after_freeze = cmds.xform(driven_cube, q=True, rotatePivot=True, worldSpace=True)
ย ย ย ย
ย ย ย ย # Verify that the position remains the same
ย ย ย ย assert pos_before_freeze == pos_after_freeze, "Position changed after freezing transforms."
ย ย ย ย
ย ย ย ย # Verify that transformations are frozen
ย ย ย ย # Translation should match the position before freezing
ย ย ย ย translate = cmds.getAttr("{}.translate".format(driven_cube))[0]
ย ย ย ย assert translate != tuple(pos_before_freeze), "Translate values not frozen correctly."
ย ย ย ย
ย ย ย ย # Rotation should be frozen (set to 0)
ย ย ย ย rotate = cmds.getAttr("{}.rotate".format(driven_cube))[0]
ย ย ย ย assert rotate == (0.0, 0.0, 0.0), "Rotation was not frozen correctly."
ย ย ย ย
ย ย ย ย # Scale should be frozen (set to 1)
ย ย ย ย scale = cmds.getAttr("{}.scale".format(driven_cube))[0]
ย ย ย ย assert scale == (1.0, 1.0, 1.0), "Scale was not frozen correctly."
ย ย ย ย
ย ย ย ย # Verify that constraints have been removed by checking no parent constraints exist
ย ย ย ย constraints = cmds.listConnections(driven_cube, type='parentConstraint') or []
ย ย ย ย assert constraints, "Parent constraints were not removed."
ย ย ย ย
ย ย ย ย print("advancedFreezeTransforms executed successfully.")
test_advancedFreezeTransforms() |
๐ ๏ธ ๐ผ๐๐ซ๐๐ฃ๐๐๐๐๐ง๐๐๐ฏ๐๐๐ง๐๐ฃ๐จ๐๐ค๐ง๐ข๐จ โ๏ธ (๐๐ฎ๐๐๐๐2 ๐๐๐ง๐จ๐๐ค๐ฃ):
[Todayโs Challenge is to take this simple code to next level.. I am sharing images of these advanced codes...] |
๐ ๐๐๐๐ฉ ๐ผ๐๐ซ๐๐ฃ๐๐๐๐๐ง๐๐๐ฏ๐๐๐ง๐๐ฃ๐จ๐๐ค๐ง๐ข๐จ ๐๐๐๐๐ง๐จ:
Comprehensive Handling:ย Works seamlessly even when objects have connections or children.
Automation: Automatically disconnects and reconnects attributes, unparents and reparents children.
Flexibility:ย Choose which transformations to freezeโtranslation, rotation, or scale.
๐ง ๐๐๐ฎ ๐ฝ๐๐ฃ๐๐๐๐ฉ๐จ:
โข ๐ Boost Productivity:ย Save time on complex cleanup tasks before rigging or exporting.
โข ๐ ๏ธ Enhance Workflow:ย Ideal for preparing models with intricate hierarchies and connections.
โข ๐ Improve Consistency:ย Ensures all objects have zeroed-out transformations without losing data.
โข ๐ก User-Friendly Interface:ย Intuitive UI suitable for artists of all levels.
โจ Ready to Simplify Your Transformation Cleanup?
Try out AdvancedFreezeTransformsย today and enhance your Maya workflow! Feel free to reach out or comment below to see it in action. Let's continue to elevate our Maya scripting together! ๐ช๐
๐๐ช๐๐๐ช'๐จ ๐๐๐ฃ๐ ๐จ :
โข YouTube Channel: https://www.youtube.com/@118subbuโข Vimeo:ย https://vimeo.com/subbu118โข Creature Rigging:ย https://www.creaturerigging.comโข Python Scripting:ย https://www.pythonscripting.comโข Hyper Rig:ย https://www.hyper-rig.com
#HappyScripting #MayaUI #AdvancedFreezeTransforms #PipelineOptimization #Maya #PythonScripting #MayaTools #VFX #3DAnimation #Rigging #Automation #WorkflowEnhancement #TechnicalArt #ScriptingTools
๐ ๏ธ๐ผ๐๐๐๐ฉ๐๐ค๐ฃ๐๐ก ๐๐๐ฅ๐จ:
Error Handling:ย The scripts include checks for object selection and handle cases with no connections or children gracefully.
Customization:ย Extend the tool to include options like freezing joint orientations or handling custom attributes.
Integration:ย Add this tool to your Maya shelf or integrate it into existing scripts for quick access.
Comments