Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/ui/properties_animviz.py160
-rw-r--r--release/scripts/ui/properties_data_armature.py50
-rw-r--r--source/blender/blenkernel/BKE_anim.h4
-rw-r--r--source/blender/blenkernel/intern/anim.c62
-rw-r--r--source/blender/blenkernel/intern/armature.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c17
-rw-r--r--source/blender/editors/armature/poseobject.c230
-rw-r--r--source/blender/editors/include/ED_object.h4
-rw-r--r--source/blender/editors/object/object_edit.c112
-rw-r--r--source/blender/editors/object/object_intern.h2
-rw-r--r--source/blender/editors/object/object_ops.c2
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c3
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c195
-rw-r--r--source/blender/editors/space_view3d/drawobject.c16
14 files changed, 389 insertions, 476 deletions
diff --git a/release/scripts/ui/properties_animviz.py b/release/scripts/ui/properties_animviz.py
new file mode 100644
index 00000000000..2085030a29c
--- /dev/null
+++ b/release/scripts/ui/properties_animviz.py
@@ -0,0 +1,160 @@
+# ##### 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+
+narrowui = 180
+
+################################################
+# Generic Panels (Independent of DataType)
+
+class MotionPathButtonsPanel(bpy.types.Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_label = "Motion Paths"
+
+ def draw_settings(self, context, avs, wide_ui, bones=False):
+ layout = self.layout
+
+ mps = avs.motion_paths
+
+ if wide_ui:
+ layout.prop(mps, "type", expand=True)
+ else:
+ layout.prop(mps, "type", text="")
+
+ split = layout.split()
+
+ col = split.column()
+ sub = col.column(align=True)
+ if (mps.type == 'CURRENT_FRAME'):
+ sub.prop(mps, "before_current", text="Before")
+ sub.prop(mps, "after_current", text="After")
+ elif (mps.type == 'RANGE'):
+ sub.prop(mps, "start_frame", text="Start")
+ sub.prop(mps, "end_frame", text="End")
+
+ sub.prop(mps, "frame_step", text="Step")
+ if bones:
+ col.row().prop(mps, "bake_location", expand=True)
+
+ if wide_ui:
+ col = split.column()
+ col.label(text="Display:")
+ col.prop(mps, "show_frame_numbers", text="Frame Numbers")
+ col.prop(mps, "highlight_keyframes", text="Keyframes")
+ col.prop(mps, "show_keyframe_numbers", text="Keyframe Numbers")
+
+# FIXME: this panel still needs to be ported so that it will work correctly with animviz
+class OnionSkinButtonsPanel(bpy.types.Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_label = "Onion Skinning"
+
+ def draw(self, context):
+ layout = self.layout
+
+ arm = context.armature
+ wide_ui = context.region.width > narrowui
+
+ if wide_ui:
+ layout.prop(arm, "ghost_type", expand=True)
+ else:
+ layout.prop(arm, "ghost_type", text="")
+
+ split = layout.split()
+
+ col = split.column()
+
+ sub = col.column(align=True)
+ if arm.ghost_type == 'RANGE':
+ sub.prop(arm, "ghost_start_frame", text="Start")
+ sub.prop(arm, "ghost_end_frame", text="End")
+ sub.prop(arm, "ghost_size", text="Step")
+ elif arm.ghost_type == 'CURRENT_FRAME':
+ sub.prop(arm, "ghost_step", text="Range")
+ sub.prop(arm, "ghost_size", text="Step")
+
+ if wide_ui:
+ col = split.column()
+ col.label(text="Display:")
+ col.prop(arm, "ghost_only_selected", text="Selected Only")
+
+################################################
+# Specific Panels for DataTypes
+
+class OBJECT_PT_motion_paths(MotionPathButtonsPanel):
+ #bl_label = "Object Motion Paths"
+ bl_context = "object"
+
+ def poll(self, context):
+ return (context.object)
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ wide_ui = context.region.width > narrowui
+
+ self.draw_settings(context, ob.animation_visualisation, wide_ui)
+
+ layout.separator()
+
+ split = layout.split()
+
+ col = split.column()
+ col.operator("object.paths_calculate", text="Calculate Paths")
+
+ if wide_ui:
+ col = split.column()
+ col.operator("object.paths_clear", text="Clear Paths")
+
+class DATA_PT_motion_paths(MotionPathButtonsPanel):
+ #bl_label = "Bone Motion Paths"
+ bl_context = "data"
+
+ def poll(self, context):
+ # XXX: include posemode check?
+ return (context.object) and (context.armature)
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ wide_ui = context.region.width > narrowui
+
+ self.draw_settings(context, ob.pose.animation_visualisation, wide_ui, bones=True)
+
+ layout.separator()
+
+ split = layout.split()
+
+ col = split.column()
+ col.operator("pose.paths_calculate", text="Calculate Paths")
+
+ if wide_ui:
+ col = split.column()
+ col.operator("pose.paths_clear", text="Clear Paths")
+
+
+
+#bpy.types.register(OBJECT_PT_onion_skinning)
+#bpy.types.register(DATA_PT_onion_skinning)
+bpy.types.register(OBJECT_PT_motion_paths)
+bpy.types.register(DATA_PT_motion_paths)
diff --git a/release/scripts/ui/properties_data_armature.py b/release/scripts/ui/properties_data_armature.py
index bded38ee3cc..0b33825279b 100644
--- a/release/scripts/ui/properties_data_armature.py
+++ b/release/scripts/ui/properties_data_armature.py
@@ -162,54 +162,7 @@ class DATA_PT_bone_groups(DataButtonsPanel):
#row.operator("object.bone_group_select", text="Select")
#row.operator("object.bone_group_deselect", text="Deselect")
-
-class DATA_PT_paths(DataButtonsPanel):
- bl_label = "Paths"
-
- def draw(self, context):
- layout = self.layout
-
- arm = context.armature
- wide_ui = context.region.width > narrowui
-
- if wide_ui:
- layout.prop(arm, "paths_type", expand=True)
- else:
- layout.prop(arm, "paths_type", text="")
-
- split = layout.split()
-
- col = split.column()
- sub = col.column(align=True)
- if (arm.paths_type == 'CURRENT_FRAME'):
- sub.prop(arm, "path_before_current", text="Before")
- sub.prop(arm, "path_after_current", text="After")
- elif (arm.paths_type == 'RANGE'):
- sub.prop(arm, "path_start_frame", text="Start")
- sub.prop(arm, "path_end_frame", text="End")
-
- sub.prop(arm, "path_size", text="Step")
- col.row().prop(arm, "paths_location", expand=True)
-
- if wide_ui:
- col = split.column()
- col.label(text="Display:")
- col.prop(arm, "paths_show_frame_numbers", text="Frame Numbers")
- col.prop(arm, "paths_highlight_keyframes", text="Keyframes")
- col.prop(arm, "paths_show_keyframe_numbers", text="Keyframe Numbers")
-
- layout.separator()
-
- split = layout.split()
-
- col = split.column()
- col.operator("pose.paths_calculate", text="Calculate Paths")
-
- if wide_ui:
- col = split.column()
- col.operator("pose.paths_clear", text="Clear Paths")
-
-
+# TODO: this panel will soon be depreceated too
class DATA_PT_ghost(DataButtonsPanel):
bl_label = "Ghost"
@@ -302,7 +255,6 @@ bpy.types.register(DATA_PT_context_arm)
bpy.types.register(DATA_PT_skeleton)
bpy.types.register(DATA_PT_display)
bpy.types.register(DATA_PT_bone_groups)
-bpy.types.register(DATA_PT_paths)
bpy.types.register(DATA_PT_ghost)
bpy.types.register(DATA_PT_iksolver_itasc)
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 4862f4e5c46..c664469527e 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -53,7 +53,9 @@ void animviz_free_motionpath_cache(struct bMotionPath *mpath);
void animviz_free_motionpath(struct bMotionPath *mpath);
struct bMotionPath *animviz_verify_motionpaths(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan);
-void animviz_calc_motionpaths(struct Scene *scene, struct Object *ob);
+
+void animviz_get_object_motionpaths(Object *ob, ListBase *targets);
+void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
/* ---------------------------------------------------- */
/* Curve Paths */
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 507fc520a85..6d95df3ca84 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -154,7 +154,7 @@ void animviz_free_motionpath(bMotionPath *mpath)
/* ------------------- */
-/* Setup motion paths for the given data
+/* Setup motion paths for the given data
* - scene: current scene (for frame ranges, etc.)
* - ob: object to add paths for (must be provided)
* - pchan: posechannel to add paths for (optional; if not provided, object-paths are assumed)
@@ -226,8 +226,10 @@ typedef struct MPathTarget {
/* ........ */
-/* get list of motion paths to be baked (assumes the list is ready to be used) */
-static void motionpaths_get_bake_targets(Object *ob, ListBase *targets)
+/* get list of motion paths to be baked for the given object
+ * - assumes the given list is ready to be used
+ */
+void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
{
MPathTarget *mpt;
@@ -260,6 +262,8 @@ static void motionpaths_get_bake_targets(Object *ob, ListBase *targets)
}
}
+/* ........ */
+
/* perform baking for the targets on the current frame */
static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
{
@@ -270,8 +274,10 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
bMotionPath *mpath= mpt->mpath;
bMotionPathVert *mpv;
- /* current frame must be within the range the cache works for */
- if (IN_RANGE(CFRA, mpath->start_frame, mpath->end_frame) == 0)
+ /* current frame must be within the range the cache works for
+ * - is inclusive of the first frame, but not the last otherwise we get buffer overruns
+ */
+ if ((CFRA < mpath->start_frame) || (CFRA >= mpath->end_frame))
continue;
/* get the relevant cache vert to write to */
@@ -297,36 +303,30 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
}
}
-/* ........ */
-
/* Perform baking of the given object's and/or its bones' transforms to motion paths
* - scene: current scene
* - ob: object whose flagged motionpaths should get calculated
* - recalc: whether we need to
*/
// TODO: include reports pointer?
-void animviz_calc_motionpaths(Scene *scene, Object *ob)
+void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
{
- ListBase targets = {NULL, NULL};
MPathTarget *mpt;
int sfra, efra;
int cfra;
- /* sanity checks */
- if (ob == NULL)
- return;
-
- /* get motion paths to affect */
- motionpaths_get_bake_targets(ob, &targets);
-
- if (targets.first == NULL)
+ /* sanity check */
+ if (ELEM(NULL, targets, targets->first))
return;
/* set frame values */
cfra = CFRA;
sfra = efra = cfra;
- for (mpt= targets.first; mpt; mpt= mpt->next) {
+ // TODO: this method could be improved...
+ // 1) max range for standard baking
+ // 2) minimum range for recalc baking (i.e. between keyfames, but how?)
+ for (mpt= targets->first; mpt; mpt= mpt->next) {
/* try to increase area to do (only as much as needed) */
sfra= MIN2(sfra, mpt->mpath->start_frame);
efra= MAX2(efra, mpt->mpath->end_frame);
@@ -340,23 +340,29 @@ void animviz_calc_motionpaths(Scene *scene, Object *ob)
* that doesn't force complete update, but for now, this is the
* most accurate way!
*/
- scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive?
+ scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving
/* perform baking for targets */
- motionpaths_calc_bake_targets(scene, &targets);
+ motionpaths_calc_bake_targets(scene, targets);
}
/* reset original environment */
CFRA= cfra;
- scene_update_for_newframe(scene, ob->lay); // XXX is the layer flag too restrictive?
-
- // TODO: make an API call for this too?
- ob->avs.recalc &= ~ANIMVIZ_RECALC_PATHS;
- if (ob->pose)
- ob->pose->avs.recalc &= ~ANIMVIZ_RECALC_PATHS;
+ scene_update_for_newframe(scene, scene->lay); // XXX this is the best way we can get anything moving
- /* free temp data */
- BLI_freelistN(&targets);
+ /* clear recalc flags from targets */
+ for (mpt= targets->first; mpt; mpt= mpt->next) {
+ bAnimVizSettings *avs;
+
+ /* get pointer to animviz settings for each target */
+ if (mpt->pchan)
+ avs= &mpt->ob->pose->avs;
+ else
+ avs= &mpt->ob->avs;
+
+ /* clear the flag requesting recalculation of targets */
+ avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
+ }
}
/* ******************************************************************** */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index e4079eac31b..3a7d79b8e00 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1602,7 +1602,13 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
int counter=0;
/* only done here */
- if(ob->pose==NULL) ob->pose= MEM_callocN(sizeof(bPose), "new pose");
+ if(ob->pose==NULL) {
+ /* create new pose */
+ ob->pose= MEM_callocN(sizeof(bPose), "new pose");
+
+ /* set default settings for animviz */
+ animviz_settings_init(&ob->pose->avs);
+ }
pose= ob->pose;
/* clear */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 8975dcd4c67..96b2b793267 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -10381,9 +10381,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
avs->ghost_sf= arm->ghostsf;
avs->ghost_ef= arm->ghostef;
+ if ((avs->ghost_sf == avs->ghost_ef) && (avs->ghost_sf == 0)) {
+ avs->ghost_sf= 1;
+ avs->ghost_ef= 100;
+ }
/* type */
- avs->ghost_type= arm->ghosttype;
+ if (arm->ghostep == 0)
+ avs->ghost_type= GHOST_TYPE_NONE;
+ else
+ avs->ghost_type= arm->ghosttype + 1;
/* stepsize */
avs->ghost_step= arm->ghostsize;
@@ -10394,9 +10401,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* ranges */
avs->path_bc= arm->pathbc;
avs->path_ac= arm->pathac;
+ if ((avs->path_bc == avs->path_ac) && (avs->path_bc == 0))
+ avs->path_bc= avs->path_ac= 10;
avs->path_sf= arm->pathsf;
avs->path_ef= arm->pathef;
+ if ((avs->path_sf == avs->path_ef) && (avs->path_sf == 0)) {
+ avs->path_sf= 1;
+ avs->path_ef= 250;
+ }
/* flags */
if (arm->pathflag & ARM_PATH_FNUMS)
@@ -10419,6 +10432,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
if (avs->path_step == 0)
avs->path_step= 1;
}
+ else
+ animviz_settings_init(&ob->pose->avs);
}
}
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index d26238150ca..ee6e87292fa 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -51,6 +51,7 @@
#include "DNA_view3d_types.h"
#include "DNA_userdef_types.h"
+#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -200,6 +201,7 @@ int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
}
/* ********************************************** */
+/* Motion Paths */
/* For the object with pose/action: update paths for those that have got them
* This should selectively update paths that exist...
@@ -208,120 +210,25 @@ int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
*/
void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
{
- bArmature *arm;
- bPoseChannel *pchan;
- Base *base;
- float *fp;
- int cfra;
- int sfra, efra;
-
- /* sanity checks */
- if ELEM(NULL, ob, ob->pose)
- return;
- arm= ob->data;
-
- /* set frame values */
- cfra = CFRA;
- sfra = efra = cfra;
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
- if (pchan->path) {
- /* if the pathsf and pathef aren't initialised, abort! */
- // XXX can now have negative frames, so this check needs improvement
- if (ELEM(0, pchan->pathsf, pchan->pathef))
- return;
-
- /* try to increase area to do (only as much as needed) */
- sfra= MIN2(sfra, pchan->pathsf);
- efra= MAX2(efra, pchan->pathef);
- }
- }
- }
- if (efra <= sfra) return;
-
- /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */
- if ((ob->recalc & OB_RECALC)==0) {
- ob->recalc |= OB_RECALC;
- DAG_id_update_flags(&ob->id);
- }
- else
- DAG_id_update_flags(&ob->id);
-
- /* calculate path over requested range */
- for (CFRA=sfra; CFRA<=efra; CFRA++) {
- /* do all updates */
- for (base= FIRSTBASE; base; base= base->next) {
- if (base->object->recalc) {
- int temp= base->object->recalc;
-
- if (base->object->adt)
- BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
-
- /* update object */
- object_handle_update(scene, base->object);
- base->object->recalc= temp;
- }
- }
-
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
- if (pchan->path) {
- /* only update if:
- * - in range of this pchan's existing path
- * - ... insert evil filtering/optimising conditions here...
- */
- if (IN_RANGE(CFRA, pchan->pathsf, pchan->pathef)) {
- fp= pchan->path+3*(CFRA-sfra);
-
- if (arm->pathflag & ARM_PATH_HEADS) {
- VECCOPY(fp, pchan->pose_head);
- }
- else {
- VECCOPY(fp, pchan->pose_tail);
- }
-
- mul_m4_v3(ob->obmat, fp);
- }
- }
- }
- }
- }
+ ListBase targets = {NULL, NULL};
- /* reset flags */
- CFRA= cfra;
- ob->pose->flag &= ~POSE_RECALCPATHS;
+ /* set flag to force recalc, then grab the relevant bones to target */
+ ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
+ animviz_get_object_motionpaths(ob, &targets);
- /* flush one final time - to restore to the original state */
- for (base= FIRSTBASE; base; base= base->next) {
- if (base->object->recalc) {
- int temp= base->object->recalc;
-
- if (base->object->adt)
- BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
-
- object_handle_update(scene, base->object);
- base->object->recalc= temp;
- }
- }
+ /* recalculate paths, then free */
+ animviz_calc_motionpaths(scene, &targets);
+ BLI_freelistN(&targets);
}
-/* --------- */
-
/* For the object with pose/action: create path curves for selected bones
* This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
*/
static int pose_calculate_paths_exec (bContext *C, wmOperator *op)
{
- wmWindow *win= CTX_wm_window(C);
ScrArea *sa= CTX_wm_area(C);
Scene *scene= CTX_data_scene(C);
Object *ob;
- bArmature *arm;
- bPoseChannel *pchan;
- Base *base;
- float *fp;
- int cfra;
- int sfra, efra;
/* since this call may also be used from the buttons window, we need to check for where to get the object */
if (sa->spacetype == SPACE_BUTS)
@@ -329,109 +236,20 @@ static int pose_calculate_paths_exec (bContext *C, wmOperator *op)
else
ob= CTX_data_active_object(C);
- /* only continue if there's an object */
- if ELEM(NULL, ob, ob->pose)
- return OPERATOR_CANCELLED;
- arm= ob->data;
-
- /* version patch for older files here (do_versions patch too complicated) */
- if ((arm->pathsf == 0) || (arm->pathef == 0)) {
- arm->pathsf = SFRA;
- arm->pathef = EFRA;
- }
- if (arm->pathsize == 0) {
- arm->pathsize = 1;
- }
-
- /* get frame values to use */
- cfra= CFRA;
- sfra = arm->pathsf;
- efra = arm->pathef;
-
- if (efra <= sfra) {
- BKE_report(op->reports, RPT_ERROR, "Can't calculate paths when pathlen <= 0");
+ if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
- }
- /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */
- if ((ob->recalc & OB_RECALC)==0) {
- ob->recalc |= OB_RECALC;
- DAG_id_update_flags(&ob->id);
- }
- else
- DAG_id_update_flags(&ob->id);
-
- /* alloc the path cache arrays */
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
- if (arm->layer & pchan->bone->layer) {
- pchan->pathlen= efra-sfra+1;
- pchan->pathsf= sfra;
- pchan->pathef= efra+1;
- if (pchan->path)
- MEM_freeN(pchan->path);
- pchan->path= MEM_callocN(3*pchan->pathlen*sizeof(float), "pchan path");
- }
- }
- }
-
- /* step through frame range sampling the values */
- for (CFRA=sfra; CFRA<=efra; CFRA++) {
- /* for each frame we calculate, update time-cursor... (may be too slow) */
- WM_timecursor(win, CFRA);
-
- /* do all updates */
- for (base= FIRSTBASE; base; base= base->next) {
- if (base->object->recalc) {
- int temp= base->object->recalc;
-
- if (base->object->adt)
- BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
-
- object_handle_update(scene, base->object);
- base->object->recalc= temp;
- }
- }
-
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
- if (arm->layer & pchan->bone->layer) {
- if (pchan->path) {
- fp= pchan->path+3*(CFRA-sfra);
-
- if (arm->pathflag & ARM_PATH_HEADS) {
- VECCOPY(fp, pchan->pose_head);
- }
- else {
- VECCOPY(fp, pchan->pose_tail);
- }
-
- mul_m4_v3(ob->obmat, fp);
- }
- }
- }
- }
+ /* set up path data for bones being calculated */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
+ {
+ /* verify makes sure that the selected bone has a bone with the appropriate settings */
+ animviz_verify_motionpaths(scene, ob, pchan);
}
+ CTX_DATA_END;
- /* restore original cursor */
- WM_cursor_restore(win);
-
- /* reset current frame, and clear flags */
- CFRA= cfra;
- ob->pose->flag &= ~POSE_RECALCPATHS;
-
- /* flush one final time - to restore to the original state */
- for (base= FIRSTBASE; base; base= base->next) {
- if (base->object->recalc) {
- int temp= base->object->recalc;
-
- if (base->object->adt)
- BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
-
- object_handle_update(scene, base->object);
- base->object->recalc= temp;
- }
- }
+ /* calculate the bones that now have motionpaths... */
+ // TODO: only make for the selected bones?
+ ED_pose_recalculate_paths(C, scene, ob);
/* notifiers for updates */
WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
@@ -464,12 +282,12 @@ void ED_pose_clear_paths(Object *ob)
if ELEM(NULL, ob, ob->pose)
return;
- /* free the path blocks */
+ /* free the motionpath blocks */
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
- if (pchan->path) {
- MEM_freeN(pchan->path);
- pchan->path= NULL;
+ if (pchan->mpath) {
+ animviz_free_motionpath(pchan->mpath);
+ pchan->mpath= NULL;
}
}
}
@@ -491,7 +309,7 @@ static int pose_clear_paths_exec (bContext *C, wmOperator *op)
if ELEM(NULL, ob, ob->pose)
return OPERATOR_CANCELLED;
- /* for now, just call the API function for this (which is shared with backend functions) */
+ /* use the backend function for this */
ED_pose_clear_paths(ob);
/* notifiers for updates */
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 91b297b7581..aa6914ab0ad 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -95,6 +95,10 @@ void ED_object_single_users(struct Scene *scene, int full);
int object_is_libdata(struct Object *ob);
int object_data_is_libdata(struct Object *ob);
+/* object motion paths */
+void ED_objects_clear_paths(struct bContext *C, struct Scene *scene);
+void ED_objects_recalculate_paths(struct bContext *C, struct Scene *scene);
+
/* constraints */
struct ListBase *get_active_constraints(struct Object *ob);
struct ListBase *get_constraint_lb(struct Object *ob, struct bConstraint *con, struct bPoseChannel **pchan_r);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 54fa3f51eb6..e2d714fac0d 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1610,6 +1610,118 @@ void copy_attr_menu(Scene *scene, View3D *v3d)
copy_attr(scene, v3d, event);
}
+/* ********************************************** */
+/* Motion Paths */
+
+/* For the object with pose/action: update paths for those that have got them
+ * This should selectively update paths that exist...
+ *
+ * To be called from various tools that do incremental updates
+ */
+void ED_objects_recalculate_paths(bContext *C, Scene *scene)
+{
+ ListBase targets = {NULL, NULL};
+
+ /* loop over objects in scene */
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
+ {
+ /* set flag to force recalc, then grab the relevant bones to target */
+ ob->avs.recalc |= ANIMVIZ_RECALC_PATHS;
+ animviz_get_object_motionpaths(ob, &targets);
+ }
+ CTX_DATA_END;
+
+ /* recalculate paths, then free */
+ animviz_calc_motionpaths(scene, &targets);
+ BLI_freelistN(&targets);
+}
+
+/* For the object with pose/action: create path curves for selected bones
+ * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
+ */
+static int object_calculate_paths_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ /* set up path data for bones being calculated */
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
+ {
+ /* verify makes sure that the selected bone has a bone with the appropriate settings */
+ animviz_verify_motionpaths(scene, ob, NULL);
+ }
+ CTX_DATA_END;
+
+ /* calculate the bones that now have motionpaths... */
+ // TODO: only make for the selected bones?
+ ED_objects_recalculate_paths(C, scene);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_paths_calculate (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Calculate Object Paths";
+ ot->idname= "OBJECT_OT_paths_calculate";
+ ot->description= "Calculate paths for the selected bones.";
+
+ /* api callbacks */
+ ot->exec= object_calculate_paths_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* --------- */
+
+/* for the object with pose/action: clear path curves for selected bones only */
+void ED_objects_clear_paths(bContext *C, Scene *scene)
+{
+ /* loop over objects in scene */
+ CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects)
+ {
+ if (ob->mpath) {
+ animviz_free_motionpath(ob->mpath);
+ ob->mpath= NULL;
+ }
+ }
+ CTX_DATA_END;
+}
+
+/* operator callback for this */
+static int object_clear_paths_exec (bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+
+ /* use the backend function for this */
+ ED_objects_clear_paths(C, scene);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_paths_clear (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Clear Object Paths";
+ ot->idname= "OBJECT_OT_paths_clear";
+ ot->description= "Clear path caches for selected bones.";
+
+ /* api callbacks */
+ ot->exec= object_clear_paths_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
/********************** Smooth/Flat *********************/
static int shade_smooth_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index cfb4cda2460..a11ead1fe9d 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -79,6 +79,8 @@ void OBJECT_OT_restrictview_clear(struct wmOperatorType *ot);
void OBJECT_OT_proxy_make(struct wmOperatorType *ot);
void OBJECT_OT_shade_smooth(struct wmOperatorType *ot);
void OBJECT_OT_shade_flat(struct wmOperatorType *ot);
+void OBJECT_OT_paths_calculate(struct wmOperatorType *ot);
+void OBJECT_OT_paths_clear(struct wmOperatorType *ot);
/* object_select.c */
void OBJECT_OT_select_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 8b29e2ca2ae..80992887e97 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -81,6 +81,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_restrictview_set);
WM_operatortype_append(OBJECT_OT_shade_smooth);
WM_operatortype_append(OBJECT_OT_shade_flat);
+ WM_operatortype_append(OBJECT_OT_paths_calculate);
+ WM_operatortype_append(OBJECT_OT_paths_clear);
WM_operatortype_append(OBJECT_OT_parent_set);
WM_operatortype_append(OBJECT_OT_parent_no_inverse_set);
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index b8184a60cee..c57fad96a94 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -104,6 +104,7 @@ void draw_motion_paths_init(Scene *scene, View3D *v3d, ARegion *ar)
* - assumes that the viewport has already been initialised properly
* i.e. draw_motion_paths_init() has been called
*/
+// FIXME: the text is still drawn in the wrong space - it includes the current transforms of the object still...
void draw_motion_path_instance(Scene *scene, View3D *v3d, ARegion *ar,
Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath)
{
@@ -273,7 +274,7 @@ void draw_motion_path_instance(Scene *scene, View3D *v3d, ARegion *ar,
glPointSize(1.0f);
/* Draw frame numbers of keyframes */
- if (avs->path_viewflag & (MOTIONPATH_VIEW_FNUMS|MOTIONPATH_VIEW_KFNOS)) {
+ if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
float mframe= (float)(sfra + i);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index c59c5cddb3f..bfdeaef1834 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -2118,200 +2118,21 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
*/
static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob)
{
- RegionView3D *rv3d= ar->regiondata;
- AnimData *adt= BKE_animdata_from_id(&ob->id);
+ bAnimVizSettings *avs= &ob->pose->avs;
bArmature *arm= ob->data;
bPoseChannel *pchan;
- ActKeyColumn *ak;
- DLRBT_Tree keys;
- float *fp, *fp_start;
- int a, stepsize;
- int sfra, efra, len;
- if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
-
- /* version patch here - cannot access frame info from file reading */
- if (arm->pathsize == 0) arm->pathsize= 1;
- stepsize = arm->pathsize;
+ /* setup drawing environment for paths */
+ draw_motion_paths_init(scene, v3d, ar);
+ /* draw paths where they exist and they releated bone is visible */
for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if (pchan->bone->layer & arm->layer) {
- if (pchan->path) {
- /* version patch here - cannot access frame info from file reading */
- if ((pchan->pathsf == 0) || (pchan->pathef == 0)) {
- pchan->pathsf= SFRA;
- pchan->pathef= EFRA;
- }
-
- /* get frame ranges */
- if (arm->pathflag & ARM_PATH_ACFRA) {
- int sind;
-
- /* With "Around Current", we only choose frames from around
- * the current frame to draw. However, this range is still
- * restricted by the limits of the original path.
- */
- sfra= CFRA - arm->pathbc;
- efra= CFRA + arm->pathac;
- if (sfra < pchan->pathsf) sfra= pchan->pathsf;
- if (efra > pchan->pathef) efra= pchan->pathef;
-
- len= efra - sfra;
-
- sind= sfra - pchan->pathsf;
- fp_start= (pchan->path + (3*sind));
- }
- else {
- sfra= pchan->pathsf;
- efra = sfra + pchan->pathlen;
- len = pchan->pathlen;
- fp_start = pchan->path;
- }
-
- /* draw curve-line of path */
- glShadeModel(GL_SMOOTH);
-
- glBegin(GL_LINE_STRIP);
- for (a=0, fp=fp_start; a<len; a++, fp+=3) {
- float intensity; /* how faint */
-
- /* set color
- * - more intense for active/selected bones, less intense for unselected bones
- * - black for before current frame, green for current frame, blue for after current frame
- * - intensity decreases as distance from current frame increases
- */
- #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min)
- if ((a+sfra) < CFRA) {
- /* black - before cfra */
- if (pchan->bone->flag & BONE_SELECTED) {
- // intensity= 0.5f;
- intensity = SET_INTENSITY(sfra, a, CFRA, 0.25f, 0.75f);
- }
- else {
- //intensity= 0.8f;
- intensity = SET_INTENSITY(sfra, a, CFRA, 0.68f, 0.92f);
- }
- UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity);
- }
- else if ((a+sfra) > CFRA) {
- /* blue - after cfra */
- if (pchan->bone->flag & BONE_SELECTED) {
- //intensity = 0.5f;
- intensity = SET_INTENSITY(CFRA, a, efra, 0.25f, 0.75f);
- }
- else {
- //intensity = 0.8f;
- intensity = SET_INTENSITY(CFRA, a, efra, 0.68f, 0.92f);
- }
- UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity);
- }
- else {
- /* green - on cfra */
- if (pchan->bone->flag & BONE_SELECTED) {
- intensity= 0.5f;
- }
- else {
- intensity= 0.99f;
- }
- UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
- }
-
- /* draw a vertex with this color */
- glVertex3fv(fp);
- }
-
- glEnd();
- glShadeModel(GL_FLAT);
-
- glPointSize(1.0);
-
- /* draw little black point at each frame
- * NOTE: this is not really visible/noticable
- */
- glBegin(GL_POINTS);
- for (a=0, fp=fp_start; a<len; a++, fp+=3)
- glVertex3fv(fp);
- glEnd();
-
- /* Draw little white dots at each framestep value */
- UI_ThemeColor(TH_TEXT_HI);
- glBegin(GL_POINTS);
- for (a=0, fp=fp_start; a<len; a+=stepsize, fp+=(stepsize*3))
- glVertex3fv(fp);
- glEnd();
-
- /* Draw frame numbers at each framestep value */
- if (arm->pathflag & ARM_PATH_FNUMS) {
- for (a=0, fp=fp_start; a<len; a+=stepsize, fp+=(stepsize*3)) {
- char str[32];
-
- /* only draw framenum if several consecutive highlighted points don't occur on same point */
- if (a == 0) {
- sprintf(str, "%d", (a+sfra));
- view3d_cached_text_draw_add(fp[0], fp[1], fp[2], str, 0);
- }
- else if ((a > stepsize) && (a < len-stepsize)) {
- if ((equals_v3v3(fp, fp-(stepsize*3))==0) || (equals_v3v3(fp, fp+(stepsize*3))==0)) {
- sprintf(str, "%d", (a+sfra));
- view3d_cached_text_draw_add(fp[0], fp[1], fp[2], str, 0);
- }
- }
- }
- }
-
- /* Keyframes - dots and numbers */
- if (arm->pathflag & ARM_PATH_KFRAS) {
- /* build list of all keyframes in active action for pchan */
- BLI_dlrbTree_init(&keys);
-
- if (adt) {
- bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name);
- if (agrp) {
- agroup_to_keylist(adt, agrp, &keys, NULL);
- BLI_dlrbTree_linkedlist_sync(&keys);
- }
- }
-
- /* Draw slightly-larger yellow dots at each keyframe */
- UI_ThemeColor(TH_VERTEX_SELECT);
- glPointSize(5.0f);
-
- glBegin(GL_POINTS);
- for (a=0, fp=fp_start; a<len; a++, fp+=3) {
- for (ak= keys.first; ak; ak= ak->next) {
- if (ak->cfra == (a+sfra))
- glVertex3fv(fp);
- }
- }
- glEnd();
-
- glPointSize(1.0f);
-
- /* Draw frame numbers of keyframes */
- if ((arm->pathflag & ARM_PATH_FNUMS) || (arm->pathflag & ARM_PATH_KFNOS)) {
- for(a=0, fp=fp_start; a<len; a++, fp+=3) {
- for (ak= keys.first; ak; ak= ak->next) {
- if (ak->cfra == (a+sfra)) {
- char str[32];
-
- sprintf(str, "%d", (a+sfra));
- view3d_cached_text_draw_add(fp[0], fp[1], fp[2], str, 0);
- }
- }
- }
- }
-
- BLI_dlrbTree_free(&keys);
- }
- }
- }
+ if ((pchan->bone->layer & arm->layer) && (pchan->mpath))
+ draw_motion_path_instance(scene, v3d, ar, ob, pchan, avs, pchan->mpath);
}
- if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glPopMatrix();
+ /* cleanup after drawing */
+ draw_motion_paths_cleanup(scene, v3d, ar);
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c3e248c9d7c..b10b74ff160 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -5180,6 +5180,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
/* no return after this point, otherwise leaks */
view3d_cached_text_draw_begin();
+
/* draw keys? */
#if 0 // XXX old animation system
@@ -5260,8 +5261,19 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
/* patch? children objects with a timeoffs change the parents. How to solve! */
/* if( ((int)ob->ctime) != F_(scene->r.cfra)) where_is_object(scene, ob); */
- /* draw paths... */
- // TODO...
+ /* draw motion paths (in view space) */
+ if (ob->mpath) {
+ bAnimVizSettings *avs= &ob->avs;
+
+ /* setup drawing environment for paths */
+ draw_motion_paths_init(scene, v3d, ar);
+
+ /* draw motion path for object */
+ draw_motion_path_instance(scene, v3d, ar, ob, NULL, avs, ob->mpath);
+
+ /* cleanup after drawing */
+ draw_motion_paths_cleanup(scene, v3d, ar);
+ }
/* multiply view with object matrix.
* local viewmat and persmat, to calculate projections */