Add looping detection to animation exporter
authorMikko Rasa <tdb@tdb.fi>
Sun, 16 Jun 2019 08:52:27 +0000 (11:52 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 16 Jun 2019 08:52:27 +0000 (11:52 +0300)
Since Blender's actions do not have a looping property, detect looping by
comparing the first and last keyframes of each curve.

blender/io_mspgl/__init__.py
blender/io_mspgl/animation.py
blender/io_mspgl/export_animation.py

index f0cb6579266c6ecdf1850676c36689934137eabe..3ce60c4c0a91864b9001eaeda21b95eba942be75 100644 (file)
@@ -98,6 +98,7 @@ class ExportMspGLAnimation(bpy.types.Operator, ExportMspGLBase):
 
        export_all = bpy.props.BoolProperty(name="Export all animations", description="Export all animations present on the selected objects' NLA tracks")
        collection = bpy.props.BoolProperty(name="As a collection", description="Export the animations as a single collection file", default=True)
+       looping_threshold = bpy.props.FloatProperty(name="Looping threshold", description="Tolerance for curve beginning and end values for looping", min=0.0, soft_max=1.0, precision=4, default=0.001)
 
        def check(self, context):
                result = False
@@ -122,6 +123,7 @@ class ExportMspGLAnimation(bpy.types.Operator, ExportMspGLBase):
                col.prop(self, "export_all")
                if self.export_all:
                        col.prop(self, "collection")
+               col.prop(self, "looping_threshold")
 
 class ExportMspGLScene(bpy.types.Operator, ExportMspGLBase):
        bl_idname = "export_scene.mspgl_scene"
index ffce11f596fc8099b2e48e39d8401beca84f45d2..59f34b4d7c532e35e0a852493b81120a1a9fff61 100644 (file)
@@ -1,3 +1,4 @@
+import math
 import mathutils
 
 class Curve:
@@ -34,6 +35,7 @@ class Animation:
                self._action = action
                self.curves = [Curve(c) for c in action.fcurves]
                self.fps = 1
+               self.looping = False
 
                for c in self.curves:
                        for i in range(0, len(c.knots)-1, 3):
@@ -77,6 +79,24 @@ class Animation:
        def __getattr__(self, attr):
                return getattr(self._curve, attr)
 
+       def check_looping(self, threshold):
+               self.looping = True
+               for c in self.curves:
+                       first_y = c.knots[0][1]
+                       last_y = c.knots[-1][1]
+                       d = abs(last_y-first_y)
+
+                       if c.data_path=="rotation_euler":
+                               while d>math.pi/2:
+                                       d -= math.pi
+                               while d<-math.pi/2:
+                                       d += math.pi
+
+                       print("Difference for {} {} is {}".format(c.data_path, c.array_index, d))
+                       if d>threshold:
+                               self.looping = False
+                               break
+
        def change_fps(self, fps):
                scale = self.fps/fps
                self.fps = fps
@@ -89,8 +109,9 @@ class Animation:
                        k.time *= scale
 
 
-def create_animation_from_action(context, action):
+def create_animation_from_action(context, action, *, looping_threshold=0.001):
        anim = Animation(action)
        render = context.scene.render
+       anim.check_looping(looping_threshold)
        anim.change_fps(render.fps/render.fps_base)
        return anim
index e2c7733df69be358cd5e54029675a2caebc5361d..0d72edb4d5eed4894e1df575e8a5b396213ab158 100644 (file)
@@ -5,6 +5,7 @@ class AnimationExporter:
        def __init__(self):
                self.export_all = False
                self.collection = True
+               self.looping_threshold = 0.001
 
        def export_to_file(self, context, out_fn):
                if self.export_all:
@@ -55,7 +56,7 @@ class AnimationExporter:
 
        def export_animation(self, context, action):
                from .animation import create_animation_from_action
-               anim = create_animation_from_action(context, action)
+               anim = create_animation_from_action(context, action, looping_threshold=self.looping_threshold)
 
                from .datafile import Resource, Statement
                resource = Resource(action.name+".anim")
@@ -100,5 +101,7 @@ class AnimationExporter:
 
                        resource.statements.append(st)
 
+               resource.statements.append(Statement("looping", anim.looping))
+
                return resource