From 47d67997b48c77f46a9551ce9503c1283dcc7756 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Tue, 7 Jul 2015 15:59:28 -0400 Subject: [PATCH] Implement layer transform animation --- korman/exporter/animation.py | 65 ++++++++++++++++++++++++++++++++++++ korman/exporter/material.py | 9 +++++ 2 files changed, 74 insertions(+) diff --git a/korman/exporter/animation.py b/korman/exporter/animation.py index 70e524c..64b4afe 100644 --- a/korman/exporter/animation.py +++ b/korman/exporter/animation.py @@ -40,6 +40,32 @@ class AnimationConverter: tm.Z = self.make_scale_controller(fcurves, default_xform) return tm + def make_matrix44_controller(self, pos_fcurves, scale_fcurves, default_pos, default_scale): + pos_keyframes, pos_bez = self._process_keyframes(pos_fcurves) + scale_keyframes, scale_bez = self._process_keyframes(scale_fcurves) + + # Matrix keyframes cannot do bezier schtuff + if pos_bez or scale_bez: + self._exporter().report.warn("This animation cannot use bezier keyframes--forcing linear", indent=3) + + # Let's pair up the pos and scale schtuff based on frame numbers. I realize that we're creating + # a lot of temporary objects, but until I see profiling results that this is terrible, I prefer + # to have code that makes sense. + keyframes = [] + for pos, scale in zip(pos_keyframes, scale_keyframes): + if pos.frame_num == scale.frame_num: + keyframes.append((pos, scale)) + elif pos.frame_num < scale.frame_num: + keyframes.append((pos, None)) + keyframes.append((None, scale)) + elif pos.frame_num > scale.frame_num: + keyframes.append((None, scale)) + keyframes.append((pos, None)) + + # Now we make the controller + ctrl = self._make_matrix44_controller(pos_fcurves, scale_fcurves, keyframes, default_pos, default_scale) + return ctrl + def make_pos_controller(self, fcurves, default_xform): pos_curves = [i for i in fcurves if i.data_path == "location" and i.keyframe_points] keyframes, bez_chans = self._process_keyframes(pos_curves) @@ -84,6 +110,45 @@ class AnimationConverter: ctrl = self._make_scalar_leaf_controller(keyframes, bezier) return ctrl + def _make_matrix44_controller(self, pos_fcurves, scale_fcurves, keyframes, default_pos, default_scale): + ctrl = plLeafController() + keyframe_type = hsKeyFrame.kMatrix44KeyFrame + exported_frames = [] + pcurves = { i.array_index: i for i in pos_fcurves } + scurves = { i.array_index: i for i in scale_fcurves } + + def eval_fcurve(fcurves, keyframe, i, default_xform): + try: + return fcurves[i].evaluate(keyframe.frame_num_blender) + except KeyError: + return default_xform[i] + + for pos_key, scale_key in keyframes: + valid_key = pos_key if pos_key is not None else scale_key + exported = hsMatrix44Key() + exported.frame = valid_key.frame_num + exported.frameTime = valid_key.frame_time + exported.type = keyframe_type + + if pos_key is not None: + pos_value = [pos_key.values[i] if i in pos_key.values else eval_fcurve(pcurves, pos_key, i, default_pos) for i in range(3)] + else: + pos_value = [eval_fcurve(pcurves, valid_key, i, default_pos) for i in range(3)] + if scale_key is not None: + scale_value = [scale_key.values[i] if i in scale_key.values else eval_fcurve(scurves, scale_key, i, default_scale) for i in range(3)] + else: + scale_value = [eval_fcurve(scurves, valid_key, i, default_scale) for i in range(3)] + pos_value = hsVector3(*pos_value) + scale_value = hsVector3(*scale_value) + + value = hsMatrix44() + value.setTranslate(pos_value) + value.setScale(scale_value) + exported.value = value + exported_frames.append(exported) + ctrl.keys = (exported_frames, keyframe_type) + return ctrl + def _make_point3_controller(self, fcurves, keyframes, bezier, default_xform): ctrl = plLeafController() subctrls = ("X", "Y", "Z") diff --git a/korman/exporter/material.py b/korman/exporter/material.py index 6e443dc..f9c9ea9 100644 --- a/korman/exporter/material.py +++ b/korman/exporter/material.py @@ -178,6 +178,7 @@ class MaterialConverter: } self._animation_exporters = { "opacityCtl": self._export_layer_opacity_animation, + "transformCtl": self._export_layer_transform_animation, } def export_material(self, bo, bm): @@ -338,6 +339,14 @@ class MaterialConverter: ctrl = self._exporter().animation.make_scalar_leaf_controller(opacity_fcurve) return ctrl + def _export_layer_transform_animation(self, bm, tex_slot, fcurves): + pos_fcurves = (i for i in fcurves if i.data_path.find("offset") != -1) + scale_fcurves = (i for i in fcurves if i.data_path.find("scale") != -1) + + # Plasma uses the controller to generate a matrix44... so we have to produce a leaf controller + ctrl = self._exporter().animation.make_matrix44_controller(pos_fcurves, scale_fcurves, tex_slot.offset, tex_slot.scale) + return ctrl + def _export_texture_type_environment_map(self, bo, hsgmat, layer, slot): """Exports a Blender EnvironmentMapTexture to a plLayer"""