Home Website Youtube GitHub

Space Switch using script

Hello, I was wondering if there is a way to use mgear module to do space switching externally. I found the following function in anim_utils

def changeSpace(model, uiHost, combo_attr, cnsIndex, ctl_names):
    """Change the space of a control

    i.e: A control with ik reference array

    Args:
        model (PyNode): Rig top node
        uiHost (str): uiHost Name with the switch attr
        combo_attr (str): Combo attribute name
        cnsIndex (int): Combo index to change
        ctl_names ([str]]): Name of the target controls
    """
    nameSpace = getNamespace(model)
    return changeSpace_with_namespace(
        nameSpace, uiHost, combo_attr, cnsIndex, ctl_names
    )

I am trying to figure out how to call the script externally and get all the parameters right. After debugging through dagMenu script and getting the parameters, I extracted following needed parts from the script.

root = "chr.is_rig"
uiHost = pm.PyNode("chr:armUI_l0_ctl")
switch_control = uiHost
switch_attr = "clavicle_L0_rotRef"
switch_idx = 0
search_token = switch_attr.split("_")[-1].split("ref")[0].split("Ref")[0]
attr_split_name = switch_attr.split("_")
# creates a map for non logical components controls
control_map = {"elbow": "mid", "rot": "orbit", "knee": "mid"}

print("switch_control", switch_control)
print("switch_idx", switch_idx)
print("uiHost", uiHost)
print("switch_control", switch_control)
print("switch_attr", switch_attr)
if len(attr_split_name) <= 2:
    attr_name = attr_split_name[0]
else:
    attr_name = "_".join(attr_split_name[:-1])
# search criteria to find all the components sharing the name
criteria = attr_name + "_id*_ctl_cnx"
print("attr_name", attr_name)
print("criteria", criteria)
component_ctl = (pm.listAttr(switch_control, ud=True, string=criteria) or [])

target_control_list = []
for comp_ctl_list in component_ctl:

    # first search for tokens match in all controls. If not token is found
    # we will use all controls for the switch
    # this token match is a filter for components like arms or legs
    for ctl in uiHost.attr(comp_ctl_list).listConnections():
        if ctl.ctl_role.get() == search_token:
            target_control = ctl.stripNamespace()
            break
        elif (search_token in control_map.keys()
              and ctl.ctl_role.get() == control_map[search_token]):
            target_control = ctl.stripNamespace()
            break

    if target_control:
        target_control_list.append(target_control)
    else:
        # token didn't match with any target control. We will add all
        # found controls for the match.
        # This is needed for regular ik match in Control_01
        for ctl in uiHost.attr(comp_ctl_list).listConnections():
            target_control_list.append(ctl.stripNamespace())
print(target_control_list[0])
changeSpace(root, switch_control, switch_attr, switch_idx, target_control_list)

How ever I get error for changeSpace_with_namespace in anim_utils

sWM.append(ctl.getMatrix(worldSpace=True))
# AttributeError: 'NoneType' object has no attribute 'getMatrix' # 
# Error: line 1: 'NoneType' object has no attribute 'getMatrix'

Does anyone know what might be causing this issue?

In that last block, you show the single line:
sWM.append(ctl.getMatrix(worldSpace=True))

In your script, ctl is a variable in a for loop.

So if you run that line calling ctl outside of a loop, it isn’t cast to anything, so it will just return None. That might be the problem.

Or if you are calling ctl in a loop, you might have to check each iteration of the loop to make sure it’s actually returning a valid attribute, and if not, skip with continue. (The simplest way to do that is print(ctl) and see what it says.)

1 Like

Thanks for the reply.
That is not part of the my script and is part of mgear script from anim utils. I can check, may be I might have modified it accidentally.

I mean that error leads me to the default file and is not part of my script.
Overall, what I am trying to do in the end is space transfer using a space recorder. My animation team has requested that the rig be baked to its default spaces when the animation is done so it is easier for others to start.
I can toggle spaces through attributes but it will only cause snapping therefore I am trying do it this way.