diff --git a/bakeAllAnim_v01.py b/bakeAllAnim_v01.py
index 82baba6..7062bd6 100644
--- a/bakeAllAnim_v01.py
+++ b/bakeAllAnim_v01.py
@@ -22,18 +22,14 @@
import sys
import os
-# PyMXS variable setup
-_rt = pymxs.runtime
-_at = pymxs.attime
-_animate = pymxs.animate
-
# --------------------
# UI Class
# --------------------
-class bakeAnimUI(QtW.QDialog):
- def __init__(self, ui_file, runtime, parent=MaxPlus.GetQMaxMainWindow()):
+class BakeAnimUI(QtW.QDialog):
+
+ def __init__(self, ui_file, pymxs, parent=MaxPlus.GetQMaxMainWindow()):
"""
The Initialization of the main UI class
:param ui_file: The path to the .UI file from QDesigner
@@ -41,14 +37,14 @@ def __init__(self, ui_file, runtime, parent=MaxPlus.GetQMaxMainWindow()):
:param parent: The main Max Window
"""
# Init QtW.QDialog
- super(bakeAnimUI, self).__init__(parent)
+ super(BakeAnimUI, self).__init__(parent)
# ---------------------------------------------------
# Variables
# ---------------------------------------------------
self._ui_file_string = ui_file
- self._rt = runtime
+ self._pymxs = pymxs
self._parent = parent
# ---------------------------------------------------
@@ -81,32 +77,114 @@ def __init__(self, ui_file, runtime, parent=MaxPlus.GetQMaxMainWindow()):
# Widget Setup
# ---------------------------------------------------
+ # Frame Range
+ self._spn_start = self.findChild(QtW.QSpinBox, 'spn_start')
+ self._spn_end = self.findChild(QtW.QSpinBox, 'spn_end')
+ self._spn_nth = self.findChild(QtW.QSpinBox, 'spn_nth')
+ self._btn_range = self.findChild(QtW.QPushButton, 'btn_updateRange')
+ self._chk_pad = self.findChild(QtW.QCheckBox, 'chk_pad')
+
+ # Track Selection
+ self._box_tracks = self.findChild(QtW.QWidget, 'box_tracks')
+ self._btn_tracks = self.findChild(QtW.QPushButton, 'btn_updateTracks')
+
+ # Bake
+ self._btn_bake = self.findChild(QtW.QPushButton, 'btn_getBaked')
+ self._bar_progress = self.findChild(QtW.QProgressBar, 'bar_progress')
+ self._lbl_status = self.findChild(QtW.QLabel, 'lbl_status')
+
+ # ---------------------------------------------------
+ # Function Connections
+ # ---------------------------------------------------
+ # This section is sparse because we don't worry about fetching and validating other settings until we bake.
+
+ # Frame Range
+ self._btn_range.pressed.connect(self._update_range)
+
+ # Track Selection
+ self._btn_tracks.pressed.connect(self._update_tracks)
+
+ # Bake
+ self._btn_bake.pressed.connect(self._bake)
+
+ # ---------------------------------------------------
+ # Parameter Setup
+ # ---------------------------------------------------
+
+ self._options = {'start': 0,
+ 'end': 100,
+ 'nth': 1,
+ 'pad': False}
+
# ---------------------------------------------------
# End of Init
+ # ---------------------------------------------------
+ # Private Methods
+ # ---------------------------------------------------
-# ===========================
-# Logic
-# ===========================
+ def _update_range(self):
+ _rt = self._pymxs.runtime
+ self._spn_start.setValue(_rt.animationRange.start)
+ self._spn_end.setValue(_rt.animationRange.end)
-def get_keyed_subtracks(track, list=[]):
- """
- Crawl through track heirarchy, building a list of animated tracks.
- :param track: The track to start crawling from - also used when called recursively
- :param list: The list of animated tracks, should start blank.
- :return: A list of all animated track objects below the initial track.
- """
- # Only add this track to the list if it's a SubAnim, has a controller, and has been animated
- if _rt.iskindof(track, _rt.SubAnim) and _rt.iscontroller(track.controller) and track.isanimated:
- if track not in list:
- list.append(track)
- # Always call self recursively on all children of this track
- # Note: SubAnim list is 1-indexed. Thanks, Autodesk.
- for i in range(1, track.numsubs + 1):
- list = get_keyed_subtracks(_rt.getSubAnim(track, i), list)
+ def _update_tracks(self):
+ """
+ Updates the Track Selection box with a list of unique track names
+ """
+ _rt = self._pymxs.runtime
+ tracks = []
+ layout = self._box_tracks.layout()
+
+ # Get track list from current selection
+ for obj in _rt.getCurrentSelection():
+ tracks = self._get_keyed_subtracks(obj, tracks)
+
+ # Clear the UI track list, repopulate with tracks we found
+ for i in range(layout.count()):
+ item = layout.takeAt(0)
+ widget = item.widget()
+ if widget:
+ widget.deleteLater()
+
+ index = 0
+ for track in tracks:
+ layout.addWidget(QtW.QCheckBox(track.name))
+ widget = layout.itemAt(index).widget()
+ widget.setChecked(True)
+ index += 1
+
+ layout.addStretch()
+
+
+ def _bake(self):
+ print "Bake"
+
+
+ def _get_keyed_subtracks(self, track, list=[]):
+ """
+ Crawl through track heirarchy, building a list of animated tracks. Exclude Position and Rotation parent tracks.
+ :param track: The track to start crawling from - also used when called recursively
+ :param list: The list of animated tracks, should start blank.
+ :return: A list of all (unique) animated track objects below the initial track.
+ """
+ _rt = self._pymxs.runtime
+
+ ignore = ['Transform', 'Position', 'Rotation']
+
+ # Only add this track to the list if it's a SubAnim, has a controller, and has been animated
+ if _rt.iskindof(track, _rt.SubAnim) and _rt.iscontroller(track.controller) and track.isanimated:
+ if track not in list and track.name not in ignore:
+ list.append(track)
+
+ # Always call self recursively on all children of this track
+ # Note: SubAnim list is 1-indexed. Thanks, Autodesk.
+ for i in range(1, track.numsubs + 1):
+ list = self._get_keyed_subtracks(_rt.getSubAnim(track, i), list)
+
+ return list
- return list
def bake_anim(obj, start, end, n):
tracks = get_keyed_subtracks(obj)
@@ -136,17 +214,6 @@ def bake_anim(obj, start, end, n):
print "Baked %s" % track.name
-# start = _rt.animationRange.start
-# end = _rt.animationRange.end
-# n = 3
-#
-# print "Start: %d\rEnd: %d\rN: %d" % (start, end, n)
-#
-# for obj in _rt.getCurrentSelection():
-# print "-------------------\rChecking %s..." % obj.name
-# bake_anim(obj, start, end, n)
-
-
# --------------------
# Dialog Setup
# --------------------
@@ -154,7 +221,7 @@ def bake_anim(obj, start, end, n):
# Path to UI file
_uif = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) + "\\bakeAllAnim_v01.ui"
_app = MaxPlus.GetQMaxMainWindow()
-ui = bakeAnimUI(_uif, _rt, _app)
+ui = BakeAnimUI(_uif, pymxs, _app)
# Punch it
ui.show()
diff --git a/bakeAllAnim_v01.ui b/bakeAllAnim_v01.ui
index 3649781..7fa27ad 100644
--- a/bakeAllAnim_v01.ui
+++ b/bakeAllAnim_v01.ui
@@ -7,7 +7,7 @@
0
0
227
- 381
+ 409
@@ -24,7 +24,7 @@
10
-
-
+
Frame Range
@@ -45,7 +45,7 @@
6
-
-
+
-
@@ -54,13 +54,16 @@
-
-
+
0
0
+
+ Set higher than 1 to only bake every nth frame. eg, 1, 3, 5, 7... or 1, 5, 10, 15...
+
999
@@ -83,7 +86,10 @@
-
-
+
+
+ If checked, and Nth Frame is set, we'll make sure to put a key on the End frame
+
Pad Range?
@@ -92,7 +98,7 @@
-
-
+
0
@@ -104,7 +110,10 @@
-
-
+
+
+ The frame to start baking from. Note that <b>all animation</b> on the selected tracks will be cleared, not just in this range.
+
9999
@@ -131,13 +140,16 @@
-
-
+
0
0
+
+ The frame to bake to. Note that <b>all animation</b> on the selected tracks will be cleared, not just in this range.
+
false
@@ -155,7 +167,10 @@
-
-
+
+
+ Matches the animation range to the 3ds Max time slider.
+
Get Range from Scene
@@ -165,7 +180,7 @@
-
-
+
Track Selection
@@ -189,7 +204,7 @@
0
-
-
+
0
@@ -199,9 +214,12 @@
0
- 100
+ 150
+
+ Tracks selected here will be baked.
+
QFrame::Box
@@ -211,21 +229,40 @@
true
-
+
0
0
203
- 158
+ 146
-
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
-
-
+
+
+ Update the Track Selection list with all animated tracks in the current selection.
+
Get Tracks from Selection
@@ -235,12 +272,76 @@
-
-
+
+
+ Bake selected tracks.
+
Get Baked
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 5
+
+
+
+
+ 0
+ 0
+
+
+
+ 100
+
+
+ 0
+
+
+ false
+
+
+ Qt::Horizontal
+
+
+ false
+
+
+
+ -
+
+
+
+ 8
+ 75
+ true
+ true
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ Status Update
+
+
+ Qt::AutoText
+
+
+