[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2690] contrib/py/scripts/addons/ animation_motion_trail.py: Moving from upload to contrib.

Bart Crouch bartius.crouch at gmail.com
Thu Dec 1 09:50:08 CET 2011


Revision: 2690
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2690
Author:   crouch
Date:     2011-12-01 08:49:59 +0000 (Thu, 01 Dec 2011)
Log Message:
-----------
Moving from upload to contrib.

Added Paths:
-----------
    contrib/py/scripts/addons/animation_motion_trail.py

Added: contrib/py/scripts/addons/animation_motion_trail.py
===================================================================
--- contrib/py/scripts/addons/animation_motion_trail.py	                        (rev 0)
+++ contrib/py/scripts/addons/animation_motion_trail.py	2011-12-01 08:49:59 UTC (rev 2690)
@@ -0,0 +1,1736 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+
+bl_info = {
+    'name': "Motion Trail",
+    'author': "Bart Crouch",
+    'version': (3, 1, 0),
+    'blender': (2, 6, 0),
+    'api': 42181,
+    'location': "View3D > Toolbar > Motion Trail tab",
+    'warning': "",
+    'description': "Display and edit motion trails in the 3d-view",
+    'wiki_url': "http://wiki.blender.org/index.php/Extensions:2.5/"\
+        "Py/Scripts/Animation/Motion_Trail",
+    'tracker_url': "http://projects.blender.org/tracker/index.php?"\
+        "func=detail&aid=26374",
+    'category': 'Animation'}
+
+
+import bgl
+import blf
+import bpy
+from bpy_extras import view3d_utils
+import math
+import mathutils
+
+
+# fake fcurve class, used if no fcurve is found for a path
+class fake_fcurve():
+    def __init__(self, object, index, rotation=False, scale=False):
+        # location
+        if not rotation and not scale:
+            self.loc = object.location[index]
+        # scale
+        elif scale:
+            self.loc = object.scale[index]
+        # rotation
+        elif rotation == 'QUATERNION':
+            self.loc = object.rotation_quaternion[index]
+        elif rotation == 'AXIS_ANGLE':
+            self.loc = object.rotation_axis_angle[index]
+        else:
+            self.loc = object.rotation_euler[index]
+        self.keyframe_points = []
+    
+    def evaluate(self, frame):
+        return(self.loc)
+    
+    def range(self):
+        return([])
+
+
+# get location curves of the given object
+def get_curves(object, child=False):
+    if object.animation_data and object.animation_data.action:
+        action = object.animation_data.action
+        if child:
+            # posebone
+            curves = [fc for fc in action.fcurves if len(fc.data_path)>=14 \
+            and fc.data_path[-9:]=='.location' and \
+            child.name in fc.data_path.split("\"")]
+        else:
+            # normal object
+            curves = [fc for fc in action.fcurves if \
+            fc.data_path == 'location']
+    elif object.animation_data and object.animation_data.use_nla:
+        curves = []
+        strips = []
+        for track in object.animation_data.nla_tracks:
+            not_handled = [s for s in track.strips]
+            while not_handled:
+                current_strip = not_handled.pop(-1)
+                if current_strip.action:
+                    strips.append(current_strip)
+                if current_strip.strips:
+                    # meta strip
+                    not_handled += [s for s in current_strip.strips]
+        
+        for strip in strips:
+            if child:
+                # posebone
+                curves = [fc for fc in strip.action.fcurves if \
+                len(fc.data_path)>=14 and fc.data_path[-9:]=='.location' \
+                and child.name in fc.data_path.split("\"")]
+            else:
+                # normal object
+                curves = [fc for fc in strip.action.fcurves if \
+                fc.data_path == 'location']
+            if curves:
+                # use first strip with location fcurves
+                break
+    else:
+        # should not happen?
+        curves = []
+    
+    # ensure we have three curves per object
+    fcx = None
+    fcy = None
+    fcz = None
+    for fc in curves:
+        if fc.array_index == 0:
+            fcx = fc
+        elif fc.array_index == 1:
+            fcy = fc
+        elif fc.array_index == 2:
+            fcz = fc
+    if fcx == None:
+        fcx = fake_fcurve(object, 0)
+    if fcy == None:
+        fcy = fake_fcurve(object, 1)
+    if fcz == None:
+        fcz = fake_fcurve(object, 2)
+
+    return([fcx, fcy, fcz])
+
+
+# turn screen coordinates (x,y) into world coordinates vector
+def screen_to_world(context, x, y):
+    depth_vector = view3d_utils.region_2d_to_vector_3d(\
+        context.region, context.region_data, [x,y])
+    vector = view3d_utils.region_2d_to_location_3d(\
+        context.region, context.region_data, [x,y], depth_vector)
+    
+    return(vector)
+
+
+# turn 3d world coordinates vector into screen coordinate integers (x,y)
+def world_to_screen(context, vector):
+    prj = context.region_data.perspective_matrix * \
+        mathutils.Vector((vector[0], vector[1], vector[2], 1.0))
+    width_half = context.region.width / 2.0
+    height_half = context.region.height / 2.0
+
+    x = int(width_half + width_half * (prj.x / prj.w))
+    y = int(height_half + height_half * (prj.y / prj.w))
+    
+    # correction for corner cases in perspective mode
+    if prj.w < 0:
+        if x < 0:
+            x = context.region.width * 2
+        else:
+            x = context.region.width * -2
+        if y < 0:
+            y = context.region.height * 2
+        else:
+            y = context.region.height * -2
+    
+    return(x, y)
+
+
+# calculate location of display_ob in worldspace
+def get_location(frame, display_ob, offset_ob, curves):
+    if offset_ob:
+        bpy.context.scene.frame_set(frame)
+        display_mat = getattr(display_ob, "matrix", False)
+        if not display_mat:
+            # posebones have "matrix", objects have "matrix_world"
+            display_mat = display_ob.matrix_world
+        if offset_ob:
+            loc = display_mat.to_translation() + \
+                offset_ob.matrix_world.to_translation()
+        else:
+            loc = display_mat.to_translation()
+    else:
+        fcx, fcy, fcz = curves
+        locx = fcx.evaluate(frame)
+        locy = fcy.evaluate(frame)
+        locz = fcz.evaluate(frame)
+        loc = mathutils.Vector([locx, locy, locz])
+    
+    return(loc)
+
+
+# get position of keyframes and handles at the start of dragging
+def get_original_animation_data(context, keyframes):
+    keyframes_ori = {}
+    handles_ori = {}
+    
+    if context.active_object and context.active_object.mode == 'POSE':
+        armature_ob = context.active_object
+        objects = [[armature_ob, pb, armature_ob] for pb in \
+            context.selected_pose_bones]
+    else:
+        objects = [[ob, False, False] for ob in context.selected_objects]
+    
+    for action_ob, child, offset_ob in objects:
+        if not action_ob.animation_data:
+            continue
+        curves = get_curves(action_ob, child)
+        if len(curves) == 0:
+            continue
+        fcx, fcy, fcz = curves
+        if child:
+            display_ob = child
+        else:
+            display_ob = action_ob
+        
+        # get keyframe positions
+        frame_old = context.scene.frame_current
+        keyframes_ori[display_ob.name] = {}
+        for frame in keyframes[display_ob.name]:
+            loc = get_location(frame, display_ob, offset_ob, curves)
+            keyframes_ori[display_ob.name][frame] = [frame, loc]
+        
+        # get handle positions
+        handles_ori[display_ob.name] = {}
+        for frame in keyframes[display_ob.name]:
+            handles_ori[display_ob.name][frame] = {}
+            left_x = [frame, fcx.evaluate(frame)]
+            right_x = [frame, fcx.evaluate(frame)]
+            for kf in fcx.keyframe_points:
+                if kf.co[0] == frame:
+                    left_x = kf.handle_left[:]
+                    right_x = kf.handle_right[:]
+                    break
+            left_y = [frame, fcy.evaluate(frame)]
+            right_y = [frame, fcy.evaluate(frame)]
+            for kf in fcy.keyframe_points:
+                if kf.co[0] == frame:
+                    left_y = kf.handle_left[:]
+                    right_y = kf.handle_right[:]
+                    break
+            left_z = [frame, fcz.evaluate(frame)]
+            right_z = [frame, fcz.evaluate(frame)]
+            for kf in fcz.keyframe_points:
+                if kf.co[0] == frame:
+                    left_z = kf.handle_left[:]
+                    right_z = kf.handle_right[:]
+                    break
+            handles_ori[display_ob.name][frame]["left"] = [left_x, left_y,
+                left_z]
+            handles_ori[display_ob.name][frame]["right"] = [right_x, right_y,
+                right_z]
+        
+        if context.scene.frame_current != frame_old:
+            context.scene.frame_set(frame_old)
+    
+    return(keyframes_ori, handles_ori)
+
+
+# callback function that calculates positions of all things that need be drawn
+def calc_callback(self, context):
+    if context.active_object and context.active_object.mode == 'POSE':
+        armature_ob = context.active_object
+        objects = [[armature_ob, pb, armature_ob] for pb in \
+            context.selected_pose_bones]
+    else:
+        objects = [[ob, False, False] for ob in context.selected_objects]
+    if objects == self.displayed:
+        selection_change = False
+    else:
+        selection_change = True
+    
+    if self.lock and not selection_change and \
+    context.region_data.perspective_matrix == self.perspective and not \
+    context.window_manager.motion_trail.force_update:
+        return
+    
+    # dictionaries with key: objectname
+    self.paths = {} # value: list of lists with x, y, colour
+    self.keyframes = {} # value: dict with frame as key and [x,y] as value
+    self.handles = {} # value: dict of dicts
+    self.timebeads = {} # value: dict with frame as key and [x,y] as value

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list