Last active
March 28, 2025 15:28
-
-
Save joaen/23aa408c54bc6bc94d08f9ab0423ac81 to your computer and use it in GitHub Desktop.
Simple tool to load and save animation poses in Autodesk Maya using .json files.
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
'''' | |
Name: pose_tool.py | |
Description: Simple tool to load and save poses in Autodesk Maya using .json files. | |
Author: Joar Engberg 2022 | |
''' | |
import json | |
import sys | |
import maya.cmds as cmds | |
import maya.OpenMayaUI as omui | |
from collections import OrderedDict | |
from shiboken2 import wrapInstance | |
from PySide2 import QtCore, QtGui, QtWidgets | |
def maya_main_window(): | |
# Return the Maya main window as QMainWindow | |
main_window = omui.MQtUtil.mainWindow() | |
if sys.version_info.major >= 3: | |
return wrapInstance(int(main_window), QtWidgets.QWidget) | |
else: | |
return wrapInstance(long(main_window), QtWidgets.QWidget) # type: ignore | |
class PoseToolWindow(QtWidgets.QDialog): | |
pose_folder_path = None | |
def __init__(self): | |
super(PoseToolWindow, self).__init__(maya_main_window()) | |
self.setWindowTitle("Simple Pose Tool") | |
self.setWindowIcon(QtGui.QIcon(":character.svg")) | |
self.setWindowFlags(self.windowFlags() ^ QtCore.Qt.WindowContextHelpButtonHint) | |
self.resize(200, 80) | |
self.create_ui_widgets() | |
self.create_ui_layout() | |
self.create_ui_connections() | |
if cmds.about(macOS=True): | |
self.setWindowFlags(QtCore.Qt.Tool) | |
def create_ui_widgets(self): | |
self.text_label = QtWidgets.QLabel("Save/load pose from/to selected controllers or joints:") | |
self.save_button = QtWidgets.QPushButton("Save pose ...") | |
self.load_button = QtWidgets.QPushButton("Load pose ...") | |
def create_ui_layout(self): | |
main_layout = QtWidgets.QVBoxLayout(self) | |
main_layout.setContentsMargins(10, 10, 10, 10) | |
main_layout.addWidget(self.text_label) | |
main_layout.addWidget(self.save_button) | |
main_layout.addWidget(self.load_button) | |
main_layout.addStretch() | |
def create_ui_connections(self): | |
self.save_button.clicked.connect(self.save_pose_dialog) | |
self.load_button.clicked.connect(self.load_pose_dialog) | |
def pose_folder_dialog(self): | |
folder_path = QtWidgets.QFileDialog.getExistingDirectory(self, "Select pose folder path", "") | |
if folder_path: | |
self.pose_filepath_line.setText(folder_path) | |
self.pose_folder_path = folder_path | |
self.refresh_pose_widgets() | |
def save_pose_dialog(self): | |
file_path = QtWidgets.QFileDialog.getSaveFileName(self, "Save pose file", self.pose_folder_path, "Pose file (*.json);;All files (*.*)") | |
if file_path[0]: | |
self.save_pose(file_path[0]) | |
print("Saved pose: "+file_path[0]) | |
def load_pose_dialog(self): | |
file_path = QtWidgets.QFileDialog.getOpenFileName(self, "Save pose file", self.pose_folder_path, "Pose file (*.json);;All files (*.*)") | |
if file_path[0]: | |
self.load_pose(file_path[0]) | |
print("Loaded pose: "+file_path[0]) | |
def save_pose(self, pose_path): | |
controllers = cmds.ls(sl=True) | |
controller_dict = OrderedDict() | |
attr_dict = OrderedDict() | |
for ctrl in controllers: | |
keyable_attr_list = cmds.listAttr(ctrl, keyable=True, unlocked=True) | |
for attr in keyable_attr_list: | |
attr_value = cmds.getAttr(ctrl+"."+attr) | |
attr_dict[attr] = attr_value | |
controller_dict[ctrl] = attr_dict | |
attr_dict = {} | |
save_path = pose_path | |
with open(save_path,"w") as jsonFile: | |
json.dump(controller_dict, jsonFile, indent=4) | |
def load_pose(self, file_path): | |
pose_data = json.load(open(file_path)) | |
self.active_controls = [] | |
for ctrl, input in pose_data.iteritems(): | |
for attr, value in input.iteritems(): | |
cmds.setAttr(ctrl+"."+attr, value) | |
self.active_controls.append(ctrl) | |
def start(): | |
global pose_tool_ui | |
try: | |
pose_tool_ui.close() | |
pose_tool_ui.deleteLater() | |
except: | |
pass | |
pose_tool_ui = PoseToolWindow() | |
pose_tool_ui.show() | |
if __name__ == "__main__": | |
start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment