Skip to content

Instantly share code, notes, and snippets.

@Pakmanv
Created May 2, 2025 23:53
Show Gist options
  • Select an option

  • Save Pakmanv/edb98935e0f061a325ae40232419334f to your computer and use it in GitHub Desktop.

Select an option

Save Pakmanv/edb98935e0f061a325ae40232419334f to your computer and use it in GitHub Desktop.
vvjointalignx
import maya.cmds as cmds
# Global list to store all created joints
created_joints_list = []
# Function to get the hierarchy of the selected joints
def get_joint_hierarchy(joint, indent_level=0):
"""
Recursively get the joint hierarchy with indentation for children.
:param joint: The joint to start from.
:param indent_level: The level of indentation (for children).
:return: A list of strings representing the hierarchy.
"""
hierarchy = []
hierarchy.append(" " * indent_level + joint)
children = cmds.listRelatives(joint, children=True, type="joint") or []
for child in children:
hierarchy.extend(get_joint_hierarchy(child, indent_level + 1))
return hierarchy
# Function to update the UI with the current joint selection
def update_joint_hierarchy_ui(*args):
cmds.textScrollList("jointHierarchyList", edit=True, removeAll=True)
selection = cmds.ls(selection=True, type="joint")
if not selection:
cmds.textScrollList("jointHierarchyList", edit=True, append="No joints selected!")
cmds.text("jointHierarchyCount", edit=True, label="Entries: 0")
return
for joint in selection:
joint_hierarchy = get_joint_hierarchy(joint)
for line in joint_hierarchy:
cmds.textScrollList("jointHierarchyList", edit=True, append=line)
entry_count = cmds.textScrollList("jointHierarchyList", query=True, numberOfItems=True)
cmds.text("jointHierarchyCount", edit=True, label=f"Entries: {entry_count}")
# Function to create joints at the pivot of objects in the first list
def create_joints_from_first_list(*args):
global created_joints_list
cmds.textScrollList("thirdList", edit=True, removeAll=True)
first_list_items = cmds.textScrollList("jointHierarchyList", query=True, allItems=True)
if not first_list_items:
cmds.warning("No items in the first list to create joints from!")
return
if not cmds.objExists("assetname"):
locator = cmds.spaceLocator(name="assetname")[0]
else:
locator = "assetname"
if not cmds.objExists("locator_group"):
locator_group = cmds.group(empty=True, name="locator_group")
else:
locator_group = "locator_group"
for item in first_list_items:
item_name = item.strip()
if not cmds.objExists(item_name):
cmds.warning(f"Object '{item_name}' does not exist in the scene. Skipping...")
continue
pivot_position = cmds.xform(item_name, query=True, worldSpace=True, rotatePivot=True)
joint_matrix = cmds.xform(item_name, query=True, worldSpace=True, matrix=True)
joint_locator = cmds.spaceLocator(name=f"{item_name}_locator")[0]
cmds.xform(joint_locator, translation=pivot_position, worldSpace=True)
cmds.xform(joint_locator, matrix=joint_matrix, worldSpace=True)
cmds.setAttr(f"{joint_locator}.overrideEnabled", 1)
cmds.setAttr(f"{joint_locator}.overrideColor", 17)
cmds.parent(joint_locator, locator_group)
cmds.select(clear=True)
joint = cmds.joint(position=pivot_position)
cmds.delete(cmds.orientConstraint(joint_locator, joint))
rotation = cmds.getAttr(f"{joint}.rotate")[0]
cmds.setAttr(f"{joint}.jointOrientX", rotation[0])
cmds.setAttr(f"{joint}.jointOrientY", rotation[1])
cmds.setAttr(f"{joint}.jointOrientZ", rotation[2])
cmds.setAttr(f"{joint}.rotateX", 0)
cmds.setAttr(f"{joint}.rotateY", 0)
cmds.setAttr(f"{joint}.rotateZ", 0)
cmds.setAttr(f"{joint}.radius", 100)
cmds.setAttr(f"{joint}.overrideEnabled", 1)
cmds.setAttr(f"{joint}.overrideColor", 30)
base_name = f"{item_name}_joint"
joint_name = base_name
version = 1
while cmds.objExists(joint_name):
joint_name = f"{base_name}{version}"
version += 1
joint = cmds.rename(joint, joint_name)
created_joints_list.append(joint)
cmds.parent(joint, locator)
update_created_joints_ui()
update_third_list()
# Function to update the created joints list in the UI
def update_created_joints_ui(*args):
global created_joints_list
cmds.textScrollList("createdJointsList", edit=True, removeAll=True)
for joint in created_joints_list:
cmds.textScrollList("createdJointsList", edit=True, append=joint)
entry_count = cmds.textScrollList("createdJointsList", query=True, numberOfItems=True)
cmds.text("createdJointsCount", edit=True, label=f"Entries: {entry_count}")
# Function to update the third list (new hierarchy)
def update_third_list(*args):
cmds.textScrollList("thirdList", edit=True, removeAll=True)
new_joints = cmds.listRelatives("assetname", children=True, type="joint") or []
if not new_joints:
cmds.textScrollList("thirdList", edit=True, append="No joints under 'assetname' locator.")
return
for joint in new_joints:
joint_hierarchy = get_joint_hierarchy(joint)
for line in joint_hierarchy:
cmds.textScrollList("thirdList", edit=True, append=line)
entry_count = cmds.textScrollList("thirdList", query=True, numberOfItems=True)
cmds.text("thirdCount", edit=True, label=f"Entries: {entry_count}")
# Function to select objects from the lists
def select_from_list(list_name, *args):
selected_items = cmds.textScrollList(list_name, query=True, selectItem=True) or []
if selected_items:
cmds.select(selected_items)
# Function to reconstruct the hierarchy of created joints
def reconstruct_hierarchy(*args):
first_list_items = cmds.textScrollList("jointHierarchyList", query=True, allItems=True) or []
first_list_items = [item.strip() for item in first_list_items]
new_joints = cmds.listRelatives("assetname", children=True, type="joint") or []
for item in first_list_items:
joint_name = f"{item}_joint"
if joint_name in new_joints:
parent_item = cmds.listRelatives(item, parent=True) or []
if parent_item:
parent_joint = f"{parent_item[0]}_joint"
if parent_joint in new_joints:
cmds.parent(joint_name, parent_joint)
update_third_list()
# Function to compare naming differences between List One and List Three
def compare_naming_differences():
first_list_items = cmds.textScrollList("jointHierarchyList", query=True, allItems=True) or []
third_list_items = cmds.textScrollList("thirdList", query=True, allItems=True) or []
first_list_names = [item.strip() for item in first_list_items]
third_list_names = [item.strip().replace("_joint", "") for item in third_list_items]
naming_differences = []
for name in first_list_names:
if name not in third_list_names:
naming_differences.append(f"'{name}' in List One but not in List Three")
for name in third_list_names:
if name not in first_list_names:
naming_differences.append(f"'{name}' in List Three but not in List One")
return naming_differences
# Function to compare hierarchies side by side
def compare_hierarchies():
first_list_items = cmds.textScrollList("jointHierarchyList", query=True, allItems=True) or []
third_list_items = cmds.textScrollList("thirdList", query=True, allItems=True) or []
first_list_hierarchy = "\n".join(first_list_items)
third_list_hierarchy = "\n".join(third_list_items)
return first_list_hierarchy, third_list_hierarchy
# Function to rename items in the lists
def conform_joints(*args):
cmds.textScrollList("fourthList", edit=True, removeAll=True)
first_list_items = cmds.textScrollList("jointHierarchyList", query=True, allItems=True) or []
naming_conflicts = []
for item in first_list_items:
item_name = item.strip()
if cmds.objExists(item_name):
new_name = f"{item_name}_old"
version = 1
while cmds.objExists(new_name):
new_name = f"{item_name}_old{version}"
version += 1
if version > 1:
naming_conflicts.append(f"Renamed '{item_name}' to '{new_name}' due to conflict.")
cmds.rename(item_name, new_name)
third_list_items = cmds.textScrollList("thirdList", query=True, allItems=True) or []
for item in third_list_items:
item_name = item.strip()
if cmds.objExists(item_name):
new_name = item_name.replace("_joint", "")
version = 1
while cmds.objExists(new_name):
new_name = f"{new_name}{version}"
version += 1
if version > 1:
naming_conflicts.append(f"Renamed '{item_name}' to '{new_name}' due to conflict.")
cmds.rename(item_name, new_name)
rotation_issues = []
tolerance = 0.001
for joint in cmds.listRelatives("assetname", children=True, type="joint") or []:
rotation = cmds.getAttr(f"{joint}.rotate")[0]
if any(abs(val) > tolerance for val in rotation):
rotation_issues.append(f"Joint '{joint}' has non-zero rotation: {rotation}")
naming_differences = compare_naming_differences()
first_list_hierarchy, third_list_hierarchy = compare_hierarchies()
if naming_conflicts:
cmds.textScrollList("fourthList", edit=True, append="Naming Conflicts:")
for conflict in naming_conflicts:
cmds.textScrollList("fourthList", edit=True, append=conflict)
if rotation_issues:
cmds.textScrollList("fourthList", edit=True, append="Rotation Issues:")
for issue in rotation_issues:
cmds.textScrollList("fourthList", edit=True, append=issue)
else:
cmds.textScrollList("fourthList", edit=True, append="Joint placements completed and fucken solid. Refresh all.")
if naming_differences:
cmds.textScrollList("fourthList", edit=True, append="Naming Differences:")
for difference in naming_differences:
cmds.textScrollList("fourthList", edit=True, append=difference)
cmds.textScrollList("fourthList", edit=True, append="Hierarchy Comparison:")
cmds.textScrollList("fourthList", edit=True, append="List One Hierarchy:")
cmds.textScrollList("fourthList", edit=True, append=first_list_hierarchy)
cmds.textScrollList("fourthList", edit=True, append="List Three Hierarchy:")
cmds.textScrollList("fourthList", edit=True, append=third_list_hierarchy)
cmds.textScrollList("fourthList", edit=True, append="Disclaimer:")
cmds.textScrollList("fourthList", edit=True, append="If the rig is broken, it's not my fault. I'm just matching what you inputted and cleaning your shit.")
if cmds.objExists("locator_group"):
cmds.delete("locator_group")
cmds.textScrollList("jointHierarchyList", edit=True, removeAll=True)
cmds.text("jointHierarchyCount", edit=True, label="Entries: 0")
update_joint_hierarchy_ui()
update_third_list()
# Function to refresh the UI
def refresh_ui(*args):
cmds.textScrollList("jointHierarchyList", edit=True, removeAll=True)
cmds.textScrollList("createdJointsList", edit=True, removeAll=True)
cmds.textScrollList("thirdList", edit=True, removeAll=True)
cmds.textScrollList("fourthList", edit=True, removeAll=True)
cmds.text("jointHierarchyCount", edit=True, label="Entries: 0")
cmds.text("createdJointsCount", edit=True, label="Entries: 0")
cmds.text("thirdCount", edit=True, label="Entries: 0")
cmds.text("fourthCount", edit=True, label="Entries: 0")
# Function to create the UI
def create_vv_joint_align_ui():
if cmds.window("vvJointAlignWindow", exists=True):
cmds.deleteUI("vvJointAlignWindow")
cmds.window("vvJointAlignWindow", title="VV JointAlignX", widthHeight=(1250, 1000))
cmds.formLayout("mainFormLayout")
hierarchy_label = cmds.text(label="Selection Hierarchy", align="left", parent="mainFormLayout")
joint_hierarchy_count = cmds.text("jointHierarchyCount", label="Entries: 0", align="left", parent="mainFormLayout")
joint_list = cmds.textScrollList("jointHierarchyList", allowMultiSelection=True, height=800, width=300, parent="mainFormLayout")
created_joints_label = cmds.text(label="Created Joints", align="left", parent="mainFormLayout")
created_joints_count = cmds.text("createdJointsCount", label="Entries: 0", align="left", parent="mainFormLayout")
created_joints_list_ui = cmds.textScrollList("createdJointsList", allowMultiSelection=True, height=800, width=300, parent="mainFormLayout")
third_label = cmds.text(label="New Hierarchy", align="left", parent="mainFormLayout")
third_count = cmds.text("thirdCount", label="Entries: 0", align="left", parent="mainFormLayout")
third_list = cmds.textScrollList("thirdList", allowMultiSelection=True, height=800, width=300, parent="mainFormLayout")
fourth_label = cmds.text(label="Additional Info", align="left", parent="mainFormLayout")
fourth_count = cmds.text("fourthCount", label="Entries: 0", align="left", parent="mainFormLayout")
fourth_list = cmds.textScrollList("fourthList", allowMultiSelection=True, height=800, width=400, parent="mainFormLayout")
bottom_window = cmds.scrollField("bottomWindow", wordWrap=True, height=100, width=1200, parent="mainFormLayout")
update_button = cmds.button(label="Update Selection", command=update_joint_hierarchy_ui, parent="mainFormLayout")
create_joints_button = cmds.button(label="Create Joints", command=create_joints_from_first_list, parent="mainFormLayout")
reconstruct_button = cmds.button(label="Reconstruct Hierarchy", command=reconstruct_hierarchy, parent="mainFormLayout")
conform_button = cmds.button(label="Conform", command=conform_joints, parent="mainFormLayout")
refresh_button = cmds.button(label="Refresh All", command=refresh_ui, parent="mainFormLayout")
cmds.formLayout(
"mainFormLayout",
edit=True,
attachForm=[
(hierarchy_label, "top", 5), (hierarchy_label, "left", 5),
(joint_hierarchy_count, "top", 30), (joint_hierarchy_count, "left", 5),
(joint_list, "top", 60), (joint_list, "left", 5),
(created_joints_label, "top", 5), (created_joints_label, "left", 315),
(created_joints_count, "top", 30), (created_joints_count, "left", 315),
(created_joints_list_ui, "top", 60), (created_joints_list_ui, "left", 315),
(third_label, "top", 5), (third_label, "left", 625),
(third_count, "top", 30), (third_count, "left", 625),
(third_list, "top", 60), (third_list, "left", 625),
(fourth_label, "top", 5), (fourth_label, "left", 935),
(fourth_count, "top", 30), (fourth_count, "left", 935),
(fourth_list, "top", 60), (fourth_list, "left", 935),
(bottom_window, "left", 5), (bottom_window, "right", 5), (bottom_window, "bottom", 40),
(update_button, "left", 5), (update_button, "bottom", 5),
(create_joints_button, "left", 315), (create_joints_button, "bottom", 5),
(reconstruct_button, "left", 625), (reconstruct_button, "bottom", 5),
(conform_button, "left", 935), (conform_button, "bottom", 5),
(refresh_button, "left", 5), (refresh_button, "bottom", 35),
],
attachControl=[
(joint_list, "bottom", 5, update_button),
(created_joints_list_ui, "bottom", 5, create_joints_button),
(third_list, "bottom", 5, reconstruct_button),
(fourth_list, "bottom", 5, refresh_button),
(bottom_window, "top", 5, fourth_list),
],
)
cmds.textScrollList("jointHierarchyList", edit=True, selectCommand=lambda *args: select_from_list("jointHierarchyList"))
cmds.textScrollList("createdJointsList", edit=True, selectCommand=lambda *args: select_from_list("createdJointsList"))
cmds.textScrollList("thirdList", edit=True, selectCommand=lambda *args: select_from_list("thirdList"))
cmds.textScrollList("fourthList", edit=True, selectCommand=lambda *args: select_from_list("fourthList"))
cmds.showWindow("vvJointAlignWindow")
# Run the function to create the UI
create_vv_joint_align_ui()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment