Last active
January 19, 2018 09:27
-
-
Save Jerakin/4b68b9e7209cb0c0b6c6722f708624cd to your computer and use it in GitHub Desktop.
Script to export custom animation curves from maya to be used in defold
This file contains 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
""" | |
MAYA 2016 Version | |
Hack for making custom animations in Defold, animate in Maya then export the animation as a curve. | |
The script will save every frame as a point on the curve, so try to use as few keys in maya as possible. | |
Set the "animate to" to 1 and the time to how ever long you want the animation to be. Something like below | |
go.animate("go", "position.x", go.PLAYBACK_LOOP_PINGPONG, 1, vmath.vector(transform_x), 5.0) | |
go.animate("go", "position.y", go.PLAYBACK_LOOP_PINGPONG, 1, vmath.vector(transform_y), 5.0) | |
""" | |
from PySide.QtCore import * | |
from PySide.QtGui import * | |
from shiboken import wrapInstance | |
from maya import OpenMayaUI as omui | |
import pymel.core as pm | |
class ExportWindow(QtWidgets.QWidget): | |
def __init__(self, *args, **kwargs): | |
super(ExportWindow, self).__init__(*args, **kwargs) | |
self.setParent(mayaMainWindow) | |
self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.WindowStaysOnTopHint) | |
self.setObjectName('ExportWindowUI_uniqueId') | |
self.initUI() | |
self.keyframe_rb.setChecked(True) | |
self.timeslider_rb.setChecked(True) | |
self.export_b.clicked.connect(self.export) | |
def initUI(self): | |
self.resize(148, 177) | |
self.windowLayout = QtWidgets.QVBoxLayout(self) | |
self.windowLayout.setContentsMargins(1, 1, 1, 1) | |
self.mainLayout = QtWidgets.QVBoxLayout() | |
self.typeWidget = QtWidgets.QWidget(self) | |
self.typeLayout = QtWidgets.QVBoxLayout(self.typeWidget) | |
self.typeLayout.setContentsMargins(1, 1, 1, 1) | |
self.curve_rb = QtWidgets.QRadioButton(self.typeWidget) | |
self.keyframe_rb = QtWidgets.QRadioButton(self.typeWidget) | |
self.typeLayout.addWidget(self.keyframe_rb) | |
self.typeLayout.addWidget(self.curve_rb) | |
self.mainLayout.addWidget(self.typeWidget) | |
self.line = QtWidgets.QFrame(self) | |
self.line.setFrameShape(QtWidgets.QFrame.HLine) | |
self.line.setFrameShadow(QtWidgets.QFrame.Sunken) | |
self.mainLayout.addWidget(self.line) | |
self.rangeWidget = QtWidgets.QWidget(self) | |
self.rangeLayout = QtWidgets.QVBoxLayout(self.rangeWidget) | |
self.rangeLayout.setContentsMargins(1, 1, 1, 1) | |
self.timeslider_rb = QtWidgets.QRadioButton(self.rangeWidget) | |
self.rangeLayout.addWidget(self.timeslider_rb) | |
self.customrange_rb = QtWidgets.QRadioButton(self.rangeWidget) | |
self.rangeLayout.addWidget(self.customrange_rb) | |
self.mainLayout.addWidget(self.rangeWidget) | |
self.framenumberLayout = QtWidgets.QHBoxLayout() | |
self.framenumberLayout.setSpacing(15) | |
self.minframe_le = QtWidgets.QLineEdit(self) | |
self.framenumberLayout.addWidget(self.minframe_le) | |
self.maxframe_le = QtWidgets.QLineEdit(self) | |
self.framenumberLayout.addWidget(self.maxframe_le) | |
self.mainLayout.addLayout(self.framenumberLayout) | |
self.windowLayout.addLayout(self.mainLayout) | |
self.line_2 = QtWidgets.QFrame(self) | |
self.line_2.setFrameShape(QtWidgets.QFrame.HLine) | |
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) | |
self.windowLayout.addWidget(self.line_2) | |
self.export_b = QtWidgets.QPushButton(self) | |
self.windowLayout.addWidget(self.export_b) | |
self.textBrowser = QtWidgets.QTextBrowser(self) | |
self.textBrowser.setLineWrapMode(QtWidgets.QTextEdit.NoWrap) | |
self.windowLayout.addWidget(self.textBrowser) | |
self.setWindowTitle("Export") | |
self.curve_rb.setText("Curve") | |
self.keyframe_rb.setText("Key Frames") | |
self.timeslider_rb.setText("Time slider") | |
self.customrange_rb.setText("Custom range") | |
self.export_b.setText("Export") | |
def export(self): | |
if self.customrange_rb.isChecked(): | |
start = int(self.minframe_le.text()) | |
end = int(self.maxframe_le.text()) | |
else: | |
start = pm.playbackOptions(minTime=True, query=True) | |
end = pm.playbackOptions(maxTime=True, query=True) | |
if self.keyframe_rb.isChecked(): | |
data = defold_format(get_key_frame_data(start, end)) | |
else: | |
data = defold_format(get_curve_data(start, end)) | |
self.textBrowser.setText(data) | |
def _anim_keys(ob, start, end): | |
animation_data = {"translate": {"x": [], "y": [], "z": []}, "scale": {"x": [], "y": [], "z": []}} | |
for frame in xrange(int(end - start + 1)): | |
pm.currentTime(start + frame) | |
trans = ob.getTranslation() | |
scale = ob.getScale() | |
animation_data["translate"]["x"].append(round(trans[0], 4)) | |
animation_data["translate"]["y"].append(round(trans[1], 4)) | |
animation_data["translate"]["z"].append(round(trans[2], 4)) | |
animation_data["scale"]["x"].append(round(scale[0], 4)) | |
animation_data["scale"]["y"].append(round(scale[1], 4)) | |
animation_data["scale"]["z"].append(round(scale[2], 4)) | |
return animation_data | |
def get_key_frame_data(start, end): | |
animation_data = {} | |
sel = pm.selected() | |
for ob in sel: | |
animation_data[ob] = _anim_keys(ob, start, end) | |
return animation_data | |
def get_curve_data(start, end): | |
anim_data = {} | |
for sel in pm.selected(): | |
curve_data = {"translate": {"x": [], "y": [], "z": []}} | |
points = end - start + 1 | |
increment = 1 / points | |
for p in xrange(int(points)): | |
trans = pm.pointOnCurve(sel, pr=increment * p) | |
curve_data["translate"]["x"].append(round(trans[0], 4)) | |
curve_data["translate"]["y"].append(round(trans[1], 4)) | |
curve_data["translate"]["z"].append(round(trans[2], 4)) | |
anim_data[sel] = curve_data | |
return anim_data | |
def defold_format(data): | |
string = "" | |
for d in data: | |
string += "-- {}\n".format(d) | |
if "translate" in data[d]: | |
t_x = "local transform_x = {" + str(clean_data(data[d]["translate"]["x"]))[1:-1] + "}" | |
t_y = "local transform_y = {" + str(clean_data(data[d]["translate"]["y"]))[1:-1] + "}" | |
t_z = "local transform_z = {" + str(clean_data(data[d]["translate"]["z"]))[1:-1] + "}" | |
string += "{}\n{}\n{}\n\n".format(t_x, t_y, t_z) | |
if "scale" in data[d]: | |
s_x = "local scale_x = {" + str(clean_data(data[d]["scale"]["x"]))[1:-1] + "}" | |
s_y = "local scale_y = {" + str(clean_data(data[d]["scale"]["y"]))[1:-1] + "}" | |
s_z = "local scale_z = {" + str(clean_data(data[d]["scale"]["z"]))[1:-1] + "}" | |
string += "{}\n{}\n{}\n\n\n".format(s_x, s_y, s_z) | |
return string | |
def clean_data(d): | |
if len(set(d)) == 1: | |
return list(set(d)) | |
return d | |
mayaMainWindowPtr = omui.MQtUtil.mainWindow() | |
mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QtWidgets.QWidget) | |
ui = ExportWindow() | |
ui.show() |
This file contains 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
""" | |
Hack for making custom animations in Defold, animate in Maya then export the animation as a curve. | |
The script will save every frame as a point on the curve, so try to use as few keys in maya as possible. | |
Set the "animate to" to 1 and the time to how ever long you want the animation to be. Something like below | |
go.animate("go", "position.x", go.PLAYBACK_LOOP_PINGPONG, 1, vmath.vector(transform_x), 5.0) | |
go.animate("go", "position.y", go.PLAYBACK_LOOP_PINGPONG, 1, vmath.vector(transform_y), 5.0) | |
""" | |
from PySide2.QtCore import * | |
from PySide2.QtGui import * | |
from PySide2.QtWidgets import * | |
from shiboken2 import wrapInstance | |
from maya import OpenMayaUI as omui | |
import pymel.core as pm | |
class ExportWindow(QWidget): | |
def __init__(self, *args, **kwargs): | |
super(ExportWindow, self).__init__(*args, **kwargs) | |
self.setParent(mayaMainWindow) | |
self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint) | |
self.setObjectName('ExportWindowUI_uniqueId') | |
self.initUI() | |
self.keyframe_rb.setChecked(True) | |
self.timeslider_rb.setChecked(True) | |
self.export_b.clicked.connect(self.export) | |
def initUI(self): | |
self.resize(148, 177) | |
self.windowLayout = QVBoxLayout(self) | |
self.windowLayout.setContentsMargins(1, 1, 1, 1) | |
self.mainLayout = QVBoxLayout() | |
self.typeWidget = QWidget(self) | |
self.typeLayout = QVBoxLayout(self.typeWidget) | |
self.typeLayout.setContentsMargins(1, 1, 1, 1) | |
self.curve_rb = QRadioButton(self.typeWidget) | |
self.keyframe_rb = QRadioButton(self.typeWidget) | |
self.typeLayout.addWidget(self.keyframe_rb) | |
self.typeLayout.addWidget(self.curve_rb) | |
self.mainLayout.addWidget(self.typeWidget) | |
self.line = QFrame(self) | |
self.line.setFrameShape(QFrame.HLine) | |
self.line.setFrameShadow(QFrame.Sunken) | |
self.mainLayout.addWidget(self.line) | |
self.rangeWidget = QWidget(self) | |
self.rangeLayout = QVBoxLayout(self.rangeWidget) | |
self.rangeLayout.setContentsMargins(1, 1, 1, 1) | |
self.timeslider_rb = QRadioButton(self.rangeWidget) | |
self.rangeLayout.addWidget(self.timeslider_rb) | |
self.customrange_rb = QRadioButton(self.rangeWidget) | |
self.rangeLayout.addWidget(self.customrange_rb) | |
self.mainLayout.addWidget(self.rangeWidget) | |
self.framenumberLayout = QHBoxLayout() | |
self.framenumberLayout.setSpacing(15) | |
self.minframe_le = QLineEdit(self) | |
self.framenumberLayout.addWidget(self.minframe_le) | |
self.maxframe_le = QLineEdit(self) | |
self.framenumberLayout.addWidget(self.maxframe_le) | |
self.mainLayout.addLayout(self.framenumberLayout) | |
self.windowLayout.addLayout(self.mainLayout) | |
self.line_2 = QFrame(self) | |
self.line_2.setFrameShape(QFrame.HLine) | |
self.line_2.setFrameShadow(QFrame.Sunken) | |
self.windowLayout.addWidget(self.line_2) | |
self.line_3 = QFrame(self) | |
self.line_3.setFrameShape(QFrame.HLine) | |
self.line_3.setFrameShadow(QFrame.Sunken) | |
self.normalize = QCheckBox() | |
self.normalize.setText("Normalize Animation") | |
self.windowLayout.addWidget(self.normalize) | |
self.windowLayout.addWidget(self.line_3) | |
self.export_b = QPushButton(self) | |
self.windowLayout.addWidget(self.export_b) | |
self.textBrowser = QTextEdit(self) | |
self.textBrowser.setWordWrapMode(QTextOption.WordWrap) | |
self.windowLayout.addWidget(self.textBrowser) | |
self.setWindowTitle("Export") | |
self.curve_rb.setText("Curve") | |
self.keyframe_rb.setText("Key Frames") | |
self.timeslider_rb.setText("Time slider") | |
self.customrange_rb.setText("Custom range") | |
self.export_b.setText("Export") | |
def export(self): | |
if self.customrange_rb.isChecked(): | |
start = int(self.minframe_le.text()) | |
end = int(self.maxframe_le.text()) | |
else: | |
start = pm.playbackOptions(minTime=True, query=True) | |
end = pm.playbackOptions(maxTime=True, query=True) | |
if self.keyframe_rb.isChecked(): | |
data = get_key_frame_data(start, end) | |
else: | |
data = get_curve_data(start, end) | |
if self.normalize.isChecked(): | |
data = normalize_data(data) | |
self.textBrowser.setText(defold_format(data)) | |
def normalize_data(anim_data): | |
normalized_scale_value = 1 | |
for k in anim_data: | |
data = anim_data[k] | |
max_value = max(max(data["translate"]["x"]), max(data["translate"]["y"]), max(data["translate"]["z"])) | |
_scale = normalized_scale_value / max_value | |
if _scale < normalized_scale_value: | |
normalized_scale_value = _scale | |
print("scale", normalized_scale_value) | |
for k in anim_data: | |
data = anim_data[k] | |
x_l = [] | |
y_l = [] | |
z_l = [] | |
for x in data["translate"]["x"]: | |
x_l.append(x * normalized_scale_value) | |
for y in data["translate"]["y"]: | |
y_l.append(y * normalized_scale_value) | |
for z in data["translate"]["z"]: | |
z_l.append(z * normalized_scale_value) | |
data["translate"]["x"] = x_l | |
data["translate"]["y"] = y_l | |
data["translate"]["z"] = z_l | |
return anim_data | |
def _anim_keys(ob, start, end): | |
animation_data = {"translate": {"x": [], "y": [], "z": []}, "scale": {"x": [], "y": [], "z": []}} | |
for frame in xrange(int(end - start + 1)): | |
pm.currentTime(start + frame) | |
trans = ob.getTranslation() | |
scale = ob.getScale() | |
animation_data["translate"]["x"].append(round(trans[0], 4)) | |
animation_data["translate"]["y"].append(round(trans[1], 4)) | |
animation_data["translate"]["z"].append(round(trans[2], 4)) | |
animation_data["scale"]["x"].append(round(scale[0], 4)) | |
animation_data["scale"]["y"].append(round(scale[1], 4)) | |
animation_data["scale"]["z"].append(round(scale[2], 4)) | |
return animation_data | |
def get_key_frame_data(start, end): | |
animation_data = {} | |
sel = pm.selected() | |
for ob in sel: | |
animation_data[ob] = _anim_keys(ob, start, end) | |
return animation_data | |
def get_curve_data(start, end): | |
anim_data = {} | |
for sel in pm.selected(): | |
curve_data = {"translate": {"x": [], "y": [], "z": []}} | |
points = end - start + 1 | |
increment = 1 / points | |
for p in xrange(int(points)): | |
trans = pm.pointOnCurve(sel, pr=increment * p) | |
curve_data["translate"]["x"].append(round(trans[0], 4)) | |
curve_data["translate"]["y"].append(round(trans[1], 4)) | |
curve_data["translate"]["z"].append(round(trans[2], 4)) | |
anim_data[sel] = curve_data | |
return anim_data | |
def defold_format(data): | |
string = "" | |
for d in data: | |
string += "-- {}\n".format(d) | |
if "translate" in data[d]: | |
t_x = "local transform_x = {" + str(clean_data(data[d]["translate"]["x"]))[1:-1] + "}" | |
t_y = "local transform_y = {" + str(clean_data(data[d]["translate"]["y"]))[1:-1] + "}" | |
t_z = "local transform_z = {" + str(clean_data(data[d]["translate"]["z"]))[1:-1] + "}" | |
string += "{}\n{}\n{}\n\n".format(t_x, t_y, t_z) | |
if "scale" in data[d]: | |
s_x = "local scale_x = {" + str(clean_data(data[d]["scale"]["x"]))[1:-1] + "}" | |
s_y = "local scale_y = {" + str(clean_data(data[d]["scale"]["y"]))[1:-1] + "}" | |
s_z = "local scale_z = {" + str(clean_data(data[d]["scale"]["z"]))[1:-1] + "}" | |
string += "{}\n{}\n{}\n\n\n".format(s_x, s_y, s_z) | |
return string | |
def clean_data(d): | |
if len(set(d)) == 1: | |
return list(set(d)) | |
return d | |
mayaMainWindowPtr = omui.MQtUtil.mainWindow() | |
mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QWidget) | |
ui = ExportWindow() | |
ui.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment