This commit is contained in:
2025-11-30 22:42:19 +08:00
parent de46c4b073
commit 618e2abae5
11 changed files with 1238 additions and 3749 deletions

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,144 @@
# IKFK Switch Tool
## 概述
IKFK Switch Tool 是一个用于在Maya中实现IK和FK动画之间无缝切换的工具。该工具从原始MEL脚本转换为Python版本提供更好的跨版本兼容性。
## 版本信息
- **版本**: V1.0
- **兼容性**: Maya 2018+
- **语言**: Python
- **原始版本**: MEL (ikfk_switch.mel)
## 功能特性
### 主要功能
1. **无缝切换**: 在IK和FK动画之间进行无缝切换保持动画连续性
2. **自动匹配**: 切换时自动匹配控制器位置和旋转
3. **关键帧设置**: 自动在切换点设置关键帧
4. **预设支持**: 内置ADV绑定预设支持快速设置
### UI功能
- **FK控制器加载**: 加载FK骨骼和控制器
- FK Joint Root/Mid/End
- FK Ctrl Root/Mid/End
- **IK控制器加载**: 加载IK骨骼和控制器
- IK Joint Root/Mid/End
- IK Ctrl Root (IK手柄)
- IK Ctrl Pole (极向量控制器)
- **切换控制器**: 设置切换属性
- Switch Ctrl (切换控制器)
- Switch Attr (切换属性名称)
### 辅助功能
- **ADV Build**: 快速为ADV绑定设置IKFK切换
- **Empty**: 清空所有输入字段
- **BiliBili**: 打开教程链接
## 使用方法
### 基本使用流程
1. **加载FK控制器**
- 选择FK骨骼根节点点击"< FK Joint Root"
- 选择FK骨骼中间节点点击"< FK Joint Mid"
- 选择FK骨骼末端节点点击"< FK Joint End"
- 重复以上步骤加载FK控制器
2. **加载IK控制器**
- 选择IK骨骼节点点击相应按钮
- 选择IK控制器和极向量控制器
3. **设置切换控制器**
- 选择用于切换的控制器,点击"< Switch Ctrl"
- 在通道盒中选择切换属性,点击"< Switch Attr"
4. **构建切换系统**
- 点击"<<< Build Seamless Switching >>>"按钮
- 系统会自动创建必要的属性和脚本节点
5. **使用切换功能**
- 在切换控制器上找到"IKFK_Seamless"属性
- 切换该属性值IK=0, FK=1即可实现无缝切换
### ADV绑定快速设置
如果使用ADV绑定系统可以使用预设功能
1. 展开"Edit"面板
2. 点击"<<< ADV Build >>>"
3. 系统会自动为左右手臂和腿部设置IKFK切换
## 技术实现
### 核心组件
1. **IKFKSwitchUI类**: UI界面管理
- 创建和管理UI窗口
- 处理用户输入
- 调用切换逻辑
2. **seamless_switching函数**: 核心切换逻辑
- 创建数据存储locator
- 添加必要属性
- 建立属性连接
- 创建脚本节点
3. **create_switching_script函数**: 创建全局切换脚本
- 使用MEL脚本实现切换逻辑
- 处理约束和关键帧
4. **create_script_job函数**: 创建脚本任务
- 监听属性变化
- 自动触发切换
### 兼容性设计
- 使用`maya.cmds``maya.mel`模块,确保跨版本兼容
- 避免使用版本特定的API
- 使用f-string格式化Python 3.6+
- 异常处理确保稳定性
## 工具架集成
该工具已集成到Nexus Animation工具架
- **图标**: ikfk_switch.png
- **位置**: 动画工具架末尾
- **调用**: `import animation_tools.ikfx_switch; animation_tools.ikfx_switch.show()`
## 文件位置
### Maya 2023
- 脚本: `scripts/animation_tools/ikfx_switch.py`
- 图标: `icons/ikfk_switch.png`
- 工具架: `shelves/shelf_Nexus_Animation.mel`
### Maya 2025
- 脚本: `scripts/animation_tools/ikfx_switch.py`
- 图标: `icons/ikfk_switch.png`
- 工具架: `shelves/shelf_Nexus_Animation.mel`
## 注意事项
1. **属性要求**: 切换属性必须有最小值和最大值设置
2. **命名规范**: 建议使用清晰的命名规范以便识别
3. **关键帧**: 切换会在当前帧和前一帧设置关键帧
4. **选择保持**: 切换后会恢复原始选择
## 故障排除
### 常见问题
1. **切换不工作**
- 检查所有必需的对象是否存在
- 确认切换属性已正确设置
- 查看脚本编辑器的错误信息
2. **位置不匹配**
- 确保FK和IK骨骼层级正确
- 检查约束设置
- 验证控制器方向
3. **属性加载失败**
- 确保在通道盒中选择了属性
- 检查属性是否可关键帧化

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,466 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
IKFK Switch Tool V1.0
Seamless switching between IK and FK animation for Maya rigs
Compatible with Maya 2018+
"""
import maya.cmds as cmds
import maya.mel as mel
class IKFKSwitchUI(object):
"""IKFK Switch UI Class"""
WINDOW_NAME = "IKFK_Switch_UI"
WINDOW_TITLE = "IKFK V1.0"
WINDOW_WIDTH = 300
WINDOW_HEIGHT = 578
def __init__(self):
"""Initialize UI"""
self.target_fields = {}
self.target_values = {
'target_01': '',
'target_02': '',
'target_03': '',
'target_04': '',
'target_05': '',
'target_06': '',
'target_07': '',
'target_08': '',
'target_09': '',
'target_10': '',
'target_11': '',
'target_12': '',
'target_13': ''
}
def create_ui(self):
"""Create the main UI window"""
# Delete existing window if it exists
if cmds.window(self.WINDOW_NAME, exists=True):
cmds.deleteUI(self.WINDOW_NAME)
# Create window
cmds.window(
self.WINDOW_NAME,
title=self.WINDOW_TITLE,
widthHeight=(self.WINDOW_WIDTH, self.WINDOW_HEIGHT),
sizeable=True
)
# Main layout
main_layout = cmds.columnLayout(rowSpacing=1, adjustableColumn=True)
# Edit frame
edit_frame = cmds.frameLayout(
label="Edit",
collapsable=True,
collapse=True,
collapseCommand=lambda: cmds.window(self.WINDOW_NAME, edit=True, height=self.WINDOW_HEIGHT)
)
cmds.columnLayout(rowSpacing=2, adjustableColumn=True)
cmds.button(label="<<< ADV Build >>>", command=lambda x: self.adv_build())
cmds.button(label="<<< Empty >>>", command=lambda x: self.empty_fields())
cmds.setParent('..')
cmds.setParent('..')
# FK Controls frame
fk_frame = cmds.frameLayout(label="Load FK Ctrl")
cmds.columnLayout(rowSpacing=2, adjustableColumn=True)
self._create_text_field_row('target_01', '< FK Joint Root')
self._create_text_field_row('target_02', '< FK Joint Mid')
self._create_text_field_row('target_03', '< FK Joint End')
cmds.separator(style='in', height=5)
self._create_text_field_row('target_04', '< FK Ctrl Root')
self._create_text_field_row('target_05', '< FK Ctrl Mid')
self._create_text_field_row('target_06', '< FK Ctrl End')
cmds.setParent('..')
cmds.setParent('..')
# IK Controls frame
ik_frame = cmds.frameLayout(label="Load IK Ctrl")
cmds.columnLayout(rowSpacing=2, adjustableColumn=True)
self._create_text_field_row('target_07', '< IK Joint Root')
self._create_text_field_row('target_08', '< IK Joint Mid')
self._create_text_field_row('target_09', '< IK Joint End')
cmds.separator(style='in', height=5)
self._create_text_field_row('target_10', '< IK Ctrl Root')
self._create_text_field_row('target_11', '< IK Ctrl Pole')
cmds.setParent('..')
cmds.setParent('..')
# Switch Control frame
switch_frame = cmds.frameLayout(label="Load Switch Ctrl")
cmds.columnLayout(rowSpacing=2, adjustableColumn=True)
self._create_text_field_row('target_12', '< Switch Ctrl')
# Special row for attribute selection
cmds.rowLayout(numberOfColumns=2, adjustableColumn=1, columnWidth2=(45, 60))
self.target_fields['target_13'] = cmds.textField(text='')
cmds.button(width=120, label='< Switch Attr', command=lambda x: self.load_attr())
cmds.setParent('..')
cmds.setParent('..')
cmds.setParent('..')
# Execute button
cmds.separator(style='in', height=5)
cmds.button(height=32, label="<<< Build Seamless Switching >>>", command=lambda x: self.execute())
# Show window
cmds.window(self.WINDOW_NAME, edit=True, height=self.WINDOW_HEIGHT)
cmds.showWindow(self.WINDOW_NAME)
def _create_text_field_row(self, target_name, button_label):
"""Create a text field row with button"""
cmds.rowLayout(numberOfColumns=2, adjustableColumn=1, columnWidth2=(45, 60))
self.target_fields[target_name] = cmds.textField(text=self.target_values[target_name])
cmds.button(
width=120,
label=button_label,
command=lambda x: self.set_text_field(target_name)
)
cmds.setParent('..')
def set_text_field(self, target_name):
"""Set text field from selection"""
selection = cmds.ls(selection=True)
if selection:
obj_name = selection[0]
cmds.textField(self.target_fields[target_name], edit=True, text=obj_name)
self.target_values[target_name] = obj_name
def load_attr(self):
"""Load attribute from channel box selection"""
try:
# Get selected attributes from channel box
attrs = cmds.channelBox('mainChannelBox', query=True, selectedMainAttributes=True)
if not attrs:
cmds.error("Select an attribute...")
return
attr_name = attrs[0]
cmds.textField(self.target_fields['target_13'], edit=True, text=attr_name)
self.target_values['target_13'] = attr_name
except Exception as e:
cmds.warning(f"Failed to load attribute: {e}")
def execute(self):
"""Execute the seamless switching setup"""
# Get values from text fields
fk_joint_root = cmds.textField(self.target_fields['target_01'], query=True, text=True)
fk_joint_mid = cmds.textField(self.target_fields['target_02'], query=True, text=True)
fk_joint_end = cmds.textField(self.target_fields['target_03'], query=True, text=True)
fk_ctrl_root = cmds.textField(self.target_fields['target_04'], query=True, text=True)
fk_ctrl_mid = cmds.textField(self.target_fields['target_05'], query=True, text=True)
fk_ctrl_end = cmds.textField(self.target_fields['target_06'], query=True, text=True)
ik_joint_root = cmds.textField(self.target_fields['target_07'], query=True, text=True)
ik_joint_mid = cmds.textField(self.target_fields['target_08'], query=True, text=True)
ik_joint_end = cmds.textField(self.target_fields['target_09'], query=True, text=True)
ik_ctrl_root = cmds.textField(self.target_fields['target_10'], query=True, text=True)
ik_ctrl_pole = cmds.textField(self.target_fields['target_11'], query=True, text=True)
switch_ctrl = cmds.textField(self.target_fields['target_12'], query=True, text=True)
switch_attr = cmds.textField(self.target_fields['target_13'], query=True, text=True)
# Call the seamless switching function
seamless_switching(
fk_joint_root, fk_joint_mid, fk_joint_end,
fk_ctrl_root, fk_ctrl_mid, fk_ctrl_end,
ik_joint_root, ik_joint_mid, ik_joint_end,
ik_ctrl_root, ik_ctrl_pole,
switch_ctrl, switch_attr
)
def adv_build(self):
"""Build ADV rig presets"""
# Right arm
seamless_switching(
"FKXShoulder_R", "FKXElbow_R", "FKXWrist_R",
"FKShoulder_R", "FKElbow_R", "FKWrist_R",
"IKXShoulder_R", "IKXElbow_R", "IKXWrist_R",
"IKArm_R", "PoleArm_R",
"FKIKArm_R", "FKIKBlend"
)
# Left arm
seamless_switching(
"FKXShoulder_L", "FKXElbow_L", "FKXWrist_L",
"FKShoulder_L", "FKElbow_L", "FKWrist_L",
"IKXShoulder_L", "IKXElbow_L", "IKXWrist_L",
"IKArm_L", "PoleArm_L",
"FKIKArm_L", "FKIKBlend"
)
# Right leg
seamless_switching(
"FKXHip_R", "FKXKnee_R", "FKXAnkle_R",
"FKHip_R", "FKKnee_R", "FKAnkle_R",
"IKXHip_R", "IKXKnee_R", "IKXAnkle_R",
"IKLeg_R", "PoleLeg_R",
"FKIKLeg_R", "FKIKBlend"
)
# Left leg
seamless_switching(
"FKXHip_L", "FKXKnee_L", "FKXAnkle_L",
"FKHip_L", "FKKnee_L", "FKAnkle_L",
"IKXHip_L", "IKXKnee_L", "IKXAnkle_L",
"IKLeg_L", "PoleLeg_L",
"FKIKLeg_L", "FKIKBlend"
)
def empty_fields(self):
"""Clear all text fields"""
for target_name in self.target_values.keys():
self.target_values[target_name] = ''
if target_name in self.target_fields:
cmds.textField(self.target_fields[target_name], edit=True, text='')
def seamless_switching(
fk_joint_root, fk_joint_mid, fk_joint_end,
fk_ctrl_root, fk_ctrl_mid, fk_ctrl_end,
ik_joint_root, ik_joint_mid, ik_joint_end,
ik_ctrl_root, ik_ctrl_pole,
switch_ctrl, switch_attr
):
"""
Setup seamless IKFK switching
Args:
fk_joint_root: FK joint root
fk_joint_mid: FK joint mid
fk_joint_end: FK joint end
fk_ctrl_root: FK control root
fk_ctrl_mid: FK control mid
fk_ctrl_end: FK control end
ik_joint_root: IK joint root
ik_joint_mid: IK joint mid
ik_joint_end: IK joint end
ik_ctrl_root: IK control root
ik_ctrl_pole: IK pole vector control
switch_ctrl: Switch control
switch_attr: Switch attribute name
"""
# Create locator for storing data
locator_name = f"{switch_ctrl}_Switch_Locator"
if not cmds.objExists(locator_name):
locator_shape = cmds.createNode('locator', name=locator_name)
locator_transform = cmds.listRelatives(locator_shape, parent=True)[0]
cmds.parent(locator_shape, switch_ctrl, shape=True, add=True)
cmds.delete(locator_transform)
cmds.setAttr(f"{locator_name}.visibility", 0)
# Add IKFK_Seamless attribute if it doesn't exist
if not cmds.objExists(f"{switch_ctrl}.IKFK_Seamless"):
cmds.addAttr(switch_ctrl, longName="IKFK_Seamless", attributeType="enum", enumName="IK:FK:", keyable=False)
cmds.setAttr(f"{switch_ctrl}.IKFK_Seamless", channelBox=True)
# Add Location attribute to all objects
objs = [
fk_joint_root, fk_joint_mid, fk_joint_end,
fk_ctrl_root, fk_ctrl_mid, fk_ctrl_end,
ik_joint_root, ik_joint_mid, ik_joint_end,
ik_ctrl_root, ik_ctrl_pole, switch_ctrl
]
for obj in objs:
if not cmds.objExists(f"{obj}.Location"):
cmds.addAttr(obj, longName="Location", dataType="string", keyable=True)
# Add attributes to locator and connect
attrs_data = {
"IKFK_Seamless_Switching": locator_name,
"FK_Joint_Root": fk_joint_root,
"FK_Joint_Mid": fk_joint_mid,
"FK_Joint_End": fk_joint_end,
"FK_Ctrl_Root": fk_ctrl_root,
"FK_Ctrl_Mid": fk_ctrl_mid,
"FK_Ctrl_End": fk_ctrl_end,
"IK_Joint_Root": ik_joint_root,
"IK_Joint_Mid": ik_joint_mid,
"IK_Joint_End": ik_joint_end,
"IK_Ctrl_Root": ik_ctrl_root,
"IK_Ctrl_Pole": ik_ctrl_pole,
"Switch_Ctrl": switch_ctrl,
"Switch_Attr": switch_attr
}
for attr_name, attr_value in attrs_data.items():
if not cmds.objExists(f"{locator_name}.{attr_name}"):
cmds.addAttr(locator_name, longName=attr_name, dataType="string", keyable=True)
cmds.setAttr(f"{locator_name}.{attr_name}", attr_value, type="string")
# Connect to Location attribute (except for special attributes)
if attr_name not in ["IKFK_Seamless_Switching", "Switch_Attr"]:
target_obj = attr_value
if cmds.objExists(f"{target_obj}.Location"):
if not cmds.isConnected(f"{locator_name}.{attr_name}", f"{target_obj}.Location"):
cmds.connectAttr(f"{locator_name}.{attr_name}", f"{target_obj}.Location", force=True)
# Create switching script
create_switching_script()
# Create script job for this control
create_script_job(switch_ctrl, locator_name)
print(f"IKFK Seamless Switching setup completed for {switch_ctrl}")
def create_switching_script():
"""Create the global switching script"""
script_node_name = "SG_IKFK_Switching_Script"
# MEL script for switching logic
mel_script = '''
global proc sg_switching (string $Switch)
{
int $state_tmp;
if (!`optionVar -ex $Switch`){
$state_tmp = 0;
}
$state_tmp = `optionVar -q $Switch`;
string $tmp[] = `listConnections ($Switch+".Switch_Ctrl")`;
string $Switch_Ctrl = $tmp[0];
int $state=`getAttr ($Switch_Ctrl+".IKFK_Seamless")`;
if($state_tmp == $state)
{
return;
}
string $sel[] = `ls -sl`;
string $tmp01[] = `listConnections ($Switch+".FK_Joint_Root")`;
string $tmp02[] = `listConnections ($Switch+".FK_Joint_Mid")`;
string $tmp03[] = `listConnections ($Switch+".FK_Joint_End")`;
string $tmp04[] = `listConnections ($Switch+".FK_Ctrl_Root")`;
string $tmp05[] = `listConnections ($Switch+".FK_Ctrl_Mid")`;
string $tmp06[] = `listConnections ($Switch+".FK_Ctrl_End")`;
string $tmp07[] = `listConnections ($Switch+".IK_Joint_Root")`;
string $tmp08[] = `listConnections ($Switch+".IK_Joint_Mid")`;
string $tmp09[] = `listConnections ($Switch+".IK_Joint_End")`;
string $tmp10[] = `listConnections ($Switch+".IK_Ctrl_Root")`;
string $tmp11[] = `listConnections ($Switch+".IK_Ctrl_Pole")`;
string $FK_Joint_Root = $tmp01[0];
string $FK_Joint_Mid = $tmp02[0];
string $FK_Joint_End = $tmp03[0];
string $FK_Ctrl_Root = $tmp04[0];
string $FK_Ctrl_Mid = $tmp05[0];
string $FK_Ctrl_End = $tmp06[0];
string $IK_Joint_Root = $tmp07[0];
string $IK_Joint_Mid = $tmp08[0];
string $IK_Joint_End = $tmp09[0];
string $IK_Ctrl_Root = $tmp10[0];
string $IK_Ctrl_Pole = $tmp11[0];
string $Switch_Attr = `getAttr ($Switch+".Switch_Attr")`;
int $min = `addAttr -q -min ($Switch_Ctrl+"."+$Switch_Attr)`;
int $max = `addAttr -q -max ($Switch_Ctrl+"."+$Switch_Attr)`;
int $time=`currentTime -q`;
setKeyframe $FK_Ctrl_Root;
setKeyframe $FK_Ctrl_Mid;
setKeyframe $FK_Ctrl_End;
setKeyframe $IK_Ctrl_Root;
setKeyframe $IK_Ctrl_Pole;
if($state==0){
string $tempGroup_A = `group -em`;
string $tempGroup_B = `group -em`;
delete `parentConstraint -weight 1 $IK_Joint_End $tempGroup_A`;
delete `parentConstraint -weight 1 $IK_Joint_End $tempGroup_B`;
delete `orientConstraint -offset 0 0 0 -weight 1 $IK_Ctrl_Root $tempGroup_B`;
parent $tempGroup_B $tempGroup_A;
delete `parentConstraint -weight 1 $FK_Joint_End $tempGroup_A`;
string $con_A[] = `parentConstraint -weight 1 $tempGroup_B $IK_Ctrl_Root`;
setKeyframe $IK_Ctrl_Root;
delete $con_A;
string $con_B[] = `pointConstraint -offset 0 0 0 -weight 1 $FK_Joint_Mid $IK_Ctrl_Pole`;
setKeyframe $IK_Ctrl_Pole;
delete $con_B;
setAttr ($Switch_Ctrl+"."+$Switch_Attr) $min;
setKeyframe -t ($time-1) -at $Switch_Attr $Switch_Ctrl;
setAttr ($Switch_Ctrl+"."+$Switch_Attr) $max;
setKeyframe -t $time -at $Switch_Attr $Switch_Ctrl;
delete $tempGroup_A;
}
if($state==1){
string $con_A[] = `parentConstraint -weight 1 $IK_Joint_Root $FK_Ctrl_Root`;
setKeyframe $FK_Ctrl_Root;
delete $con_A;
string $con_B[] = `parentConstraint -weight 1 $IK_Joint_Mid $FK_Ctrl_Mid`;
setKeyframe $FK_Ctrl_Mid;
delete $con_B;
string $con_C[] = `parentConstraint -weight 1 $IK_Joint_End $FK_Ctrl_End`;
setKeyframe $FK_Ctrl_End;
delete $con_C;
setAttr ($Switch_Ctrl+"."+$Switch_Attr) $max;
setKeyframe -t ($time-1) -at $Switch_Attr $Switch_Ctrl;
setAttr ($Switch_Ctrl+"."+$Switch_Attr) $min;
setKeyframe -t $time -at $Switch_Attr $Switch_Ctrl;
}
optionVar -iv $Switch $state;
select -r $sel;
}
'''
if not cmds.objExists(script_node_name):
cmds.scriptNode(beforeScript=mel_script, name=script_node_name)
else:
cmds.scriptNode(script_node_name, edit=True, beforeScript=mel_script)
cmds.setAttr(f"{script_node_name}.scriptType", 1)
cmds.scriptNode(script_node_name, executeBefore=True)
def create_script_job(switch_ctrl, locator_name):
"""Create script job for automatic switching"""
script_node_name = f"{switch_ctrl}_Switching_Script"
# MEL script for script job creation
mel_script = f'''
string $Locator_all[]=`ls -typ "locator"`;
for($Locator in $Locator_all){{
if(`objExists ($Locator+".IKFK_Seamless_Switching")`){{
string $tmp=`getAttr ($Locator+".IKFK_Seamless_Switching")`;
if($tmp=="{locator_name}"){{
string $Switch[]=`listConnections ($Locator+".Switch_Ctrl")`;
scriptJob -ac ($Switch[0]+".IKFK_Seamless") ("sg_switching "+$Locator) -kws;
}}
}}
}}
'''
if not cmds.objExists(script_node_name):
cmds.scriptNode(beforeScript=mel_script, name=script_node_name)
else:
cmds.scriptNode(script_node_name, edit=True, beforeScript=mel_script)
cmds.setAttr(f"{script_node_name}.scriptType", 1)
cmds.scriptNode(script_node_name, executeBefore=True)
def show():
"""Main entry point to show the UI"""
ui = IKFKSwitchUI()
ui.create_ui()
# For backwards compatibility
def start():
"""Alternative entry point"""
show()
if __name__ == "__main__":
show()

View File

@@ -49,27 +49,27 @@ global proc shelf_Nexus_Animation () {
-manage 1
-visible 1
-preventOverride 0
-annotation "IK/FK Switcher - Build temporary IK/FK setup on any rig"
-annotation "IKFK Switch - Seamless switching between IK and FK animation"
-enableBackground 0
-backgroundColor 0 0 0
-highlightColor 0.321569 0.521569 0.65098
-align "center"
-label "IK/FK"
-label "IKFK"
-labelOffset 0
-rotation 0
-flipX 0
-flipY 0
-useAlpha 1
-font "plainLabelFont"
-imageOverlayLabel "IK/FK"
-imageOverlayLabel "IKFK"
-overlayLabelColor 0.8 0.8 0.8
-overlayLabelBackColor 0 0 0 0.5
-image "ik_fk_switcher.png"
-image1 "ik_fk_switcher.png"
-image "ikfk_switch.png"
-image1 "ikfk_switch.png"
-style "iconOnly"
-marginWidth 0
-marginHeight 1
-command "import animation_tools.ik_fk_switcher\nanimation_tools.ik_fk_switcher.user_interface()"
-command "import animation_tools.ikfx_switch\nanimation_tools.ikfx_switch.show()"
-sourceType "python"
-commandRepeatable 1
-flat 1
@@ -249,5 +249,4 @@ global proc shelf_Nexus_Animation () {
-commandRepeatable 1
-flat 1
;
}