T54991: Restore support for Motion Path drawing in 2.8
authorJoshua Leung <aligorith@gmail.com>
Fri, 1 Jun 2018 14:38:21 +0000 (16:38 +0200)
committerJoshua Leung <aligorith@gmail.com>
Fri, 1 Jun 2018 14:38:21 +0000 (16:38 +0200)
This commit restores support for Motion Path drawing in 2.8 (as it wasn't ported over
to the new draw engines earlier, and the existing space_view3d/drawanimviz.c code was
removed during the Blender Internal removal).

Notes:
* Motion Paths are now implemented as an overlay (enabled by default).
  Therefore, you can turn all of them on/off from the "Overlays" popover

* By and large, we have kept the same draw style as was used in 2.7
  Further changes can happen later following further design work.

* One change from 2.7 is that thicker lines are used by default (2px vs 1px)

Todo's:
* There are some bad-level calls introduced here (i.e. the actgroup_to_keylist() stuff).
  These were introduced to optimise drawing performance (by avoiding full keyframes -> keylist
  conversion step on each drawcall). Instead, this has been moved to the calculation step
  (in blenkernel).  Soon, there will be some cleanups/improvements with those functions,
  so until then, we'll keep the bad level calls.

Credits:
* ClĂ©ment Foucault (fclem) - Draw Engine magic + Shader Conversion/Optimisation
* Joshua Leung (Aligorith) - COW fixes, UI integration, etc.

Revision History:
See "tmp-b28-motionpath_drawing" branch (rBa12ab5b2ef49ccacae091ccb54d72de0d63f990d)

25 files changed:
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/BKE_anim.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/blender/draw/CMakeLists.txt
source/blender/draw/intern/DRW_render.h
source/blender/draw/intern/draw_anim_viz.c [new file with mode: 0644]
source/blender/draw/intern/draw_common.c
source/blender/draw/intern/draw_common.h
source/blender/draw/intern/draw_manager.c
source/blender/draw/intern/draw_manager.h
source/blender/draw/intern/draw_manager_data.c
source/blender/draw/intern/draw_manager_exec.c
source/blender/draw/modes/draw_mode_engines.h
source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl [new file with mode: 0644]
source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl [new file with mode: 0644]
source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl [new file with mode: 0644]
source/blender/draw/modes/shaders/common_globals_lib.glsl
source/blender/editors/armature/pose_edit.c
source/blender/editors/object/object_edit.c
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_space.c

index b93e24d..8e5ca79 100644 (file)
@@ -3597,6 +3597,7 @@ class VIEW3D_PT_overlay(Panel):
         col.prop(overlay, "show_outline_selected")
         col.prop(overlay, "show_all_objects_origin")
         col.prop(overlay, "show_relationship_lines")
+        col.prop(overlay, "show_motion_paths")
         col.prop(overlay, "show_face_orientation")
         col.prop(overlay, "show_wireframes")
         col.prop(overlay, "show_backface_culling")
index 0fb8316..701be9d 100644 (file)
@@ -48,6 +48,8 @@ struct Main;
 
 void animviz_settings_init(struct bAnimVizSettings *avs);
 
+struct bMotionPath *animviz_copy_motionpath(const struct bMotionPath *mpath_src);
+
 void animviz_free_motionpath_cache(struct bMotionPath *mpath);
 void animviz_free_motionpath(struct bMotionPath *mpath);
 
index 360d9c0..c12dd49 100644 (file)
@@ -582,7 +582,9 @@ void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const
                if (copy_constraints) {
                        BKE_constraints_copy_ex(&listb, &pchan->constraints, flag, true);  // BKE_constraints_copy NULLs listb
                        pchan->constraints = listb;
-                       pchan->mpath = NULL; /* motion paths should not get copied yet... */
+
+                       /* XXX: This is needed for motionpath drawing to work. Dunno why it was setting to null before... */
+                       pchan->mpath = animviz_copy_motionpath(pchan->mpath);
                }
                
                if (pchan->prop) {
index cff9fd4..c7730d8 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "BLI_listbase.h"
 #include "BLI_math.h"
+#include "BLI_dlrbTree.h"
 
 #include "BLT_translation.h"
 
@@ -44,6 +45,7 @@
 #include "DNA_scene_types.h"
 
 #include "BKE_anim.h"
+#include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "DEG_depsgraph_query.h"
 #include "DEG_depsgraph_build.h"
 
+#include "GPU_batch.h"
+
 // XXX bad level call...
+extern short compare_ak_cfraPtr(void *node, void *data);
+extern void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
+extern void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
 
 /* --------------------- */
 /* forward declarations */
@@ -106,6 +113,10 @@ void animviz_free_motionpath_cache(bMotionPath *mpath)
        /* free the path if necessary */
        if (mpath->points)
                MEM_freeN(mpath->points);
+
+       GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+       GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
+       GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
        
        /* reset the relevant parameters */
        mpath->points = NULL;
@@ -130,6 +141,27 @@ void animviz_free_motionpath(bMotionPath *mpath)
 
 /* ------------------- */
 
+/* Make a copy of motionpath data, so that viewing with copy on write works */
+bMotionPath *animviz_copy_motionpath(const bMotionPath *mpath_src)
+{
+       bMotionPath *mpath_dst;
+
+       if (mpath_src == NULL)
+               return NULL;
+
+       mpath_dst = MEM_dupallocN(mpath_src);
+       mpath_dst->points = MEM_dupallocN(mpath_src->points);
+
+       /* should get recreated on draw... */
+       mpath_dst->points_vbo = NULL;
+       mpath_dst->batch_line = NULL;
+       mpath_dst->batch_points = NULL;
+
+       return mpath_dst;
+}
+
+/* ------------------- */
+
 /**
  * Setup motion paths for the given data.
  * \note Only used when explicitly calculating paths on bones which may/may not be consider already
@@ -212,7 +244,7 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec
        mpath->color[1] = 0.0;
        mpath->color[2] = 0.0;
 
-       mpath->line_thickness = 1;
+       mpath->line_thickness = 2;
        mpath->flag |= MOTIONPATH_FLAG_LINES;  /* draw lines by default */
 
        /* allocate a cache */
@@ -232,6 +264,8 @@ typedef struct MPathTarget {
        struct MPathTarget *next, *prev;
        
        bMotionPath *mpath;         /* motion path in question */
+
+       DLRBT_Tree keys;         /* temp, to know where the keyframes are */
        
        /* Original (Source Objects) */
        Object *ob;                 /* source object */
@@ -344,6 +378,13 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
                        /* worldspace object location */
                        copy_v3_v3(mpv->co, ob_eval->obmat[3]);
                }
+
+               float mframe = (float)(CFRA);
+
+               /* Tag if it's a keyframe */
+               if (BLI_dlrbTree_search_exact(&mpt->keys, compare_ak_cfraPtr, &mframe)) {
+                       mpv->flag |= MOTIONPATH_VERT_KEY;
+               }
        }
 }
 
@@ -387,13 +428,44 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
                if (mpt->pchan) {
                        mpt->pchan_eval = BKE_pose_channel_find_name(mpt->ob_eval->pose, mpt->pchan->name);
                }
+
+               AnimData *adt = BKE_animdata_from_id(&mpt->ob_eval->id);
+
+               /* build list of all keyframes in active action for object or pchan */
+               BLI_dlrbTree_init(&mpt->keys);
+
+               if (adt) {
+                       bAnimVizSettings *avs;
+
+                       /* get pointer to animviz settings for each target */
+                       if (mpt->pchan)
+                               avs = &mpt->ob->pose->avs;
+                       else
+                               avs = &mpt->ob->avs;
+
+                       /* it is assumed that keyframes for bones are all grouped in a single group
+                        * unless an option is set to always use the whole action
+                        */
+                       if ((mpt->pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
+                               bActionGroup *agrp = BKE_action_group_find_name(adt->action, mpt->pchan->name);
+
+                               if (agrp) {
+                                       agroup_to_keylist(adt, agrp, &mpt->keys, NULL);
+                                       BLI_dlrbTree_linkedlist_sync(&mpt->keys);
+                               }
+                       }
+                       else {
+                               action_to_keylist(adt, adt->action, &mpt->keys, NULL);
+                               BLI_dlrbTree_linkedlist_sync(&mpt->keys);
+                       }
+               }
        }
-       
+
        /* calculate path over requested range */
        for (CFRA = sfra; CFRA <= efra; CFRA++) {
                /* update relevant data for new frame */
                motionpaths_calc_update_scene(bmain, depsgraph);
-               
+
                /* perform baking for targets */
                motionpaths_calc_bake_targets(scene, targets);
        }
@@ -406,6 +478,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
        /* clear recalc flags from targets */
        for (mpt = targets->first; mpt; mpt = mpt->next) {
                bAnimVizSettings *avs;
+               bMotionPath *mpath = mpt->mpath;
                
                /* get pointer to animviz settings for each target */
                if (mpt->pchan)
@@ -415,6 +488,14 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
                
                /* clear the flag requesting recalculation of targets */
                avs->recalc &= ~ANIMVIZ_RECALC_PATHS;
+
+               /* Clean temp data */
+               BLI_dlrbTree_free(&mpt->keys);
+
+               /* Free previous batches to force update. */
+               GWN_VERTBUF_DISCARD_SAFE(mpath->points_vbo);
+               GWN_BATCH_DISCARD_SAFE(mpath->batch_line);
+               GWN_BATCH_DISCARD_SAFE(mpath->batch_points);
        }
 }
 
index 3448327..c4460d5 100644 (file)
@@ -1228,7 +1228,8 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
        BLI_listbase_clear(&ob_dst->drawdata);
        BLI_listbase_clear(&ob_dst->pc_ids);
 
-       ob_dst->mpath = NULL;
+       ob_dst->avs = ob_src->avs;
+       ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath);
 
        copy_object_lod(ob_dst, ob_src, flag_subdata);
        
index 6c2293d..fedf916 100644 (file)
@@ -2965,6 +2965,10 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
        
        /* relink points cache */
        mpath->points = newdataadr(fd, mpath->points);
+
+       mpath->points_vbo = NULL;
+       mpath->batch_line = NULL;
+       mpath->batch_points = NULL;
 }
 
 /* ************ READ NODE TREE *************** */
index 0eeb6ba..2b6d261 100644 (file)
@@ -53,6 +53,7 @@ set(INC_SYS
 )
 
 set(SRC
+       intern/draw_anim_viz.c
        intern/draw_armature.c
        intern/draw_cache.c
        intern/draw_cache_impl_curve.c
@@ -241,6 +242,9 @@ data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC)
 data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
 data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
 data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
+data_to_c_simple(modes/shaders/animviz_mpath_lines_vert.glsl SRC)
+data_to_c_simple(modes/shaders/animviz_mpath_lines_geom.glsl SRC)
+data_to_c_simple(modes/shaders/animviz_mpath_points_vert.glsl SRC)
 data_to_c_simple(modes/shaders/armature_axes_vert.glsl SRC)
 data_to_c_simple(modes/shaders/armature_sphere_solid_vert.glsl SRC)
 data_to_c_simple(modes/shaders/armature_sphere_solid_frag.glsl SRC)
index 44fb71a..081bae9 100644 (file)
@@ -344,6 +344,8 @@ void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batc
 
 void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
 void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4]);
+void DRW_shgroup_call_range_add(
+        DRWShadingGroup *shgroup, struct Gwn_Batch *geom, float (*obmat)[4], uint v_sta, uint v_count);
 void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, unsigned int point_count, float (*obmat)[4]);
 void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, unsigned int line_count, float (*obmat)[4]);
 void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, unsigned int tria_count, float (*obmat)[4]);
diff --git a/source/blender/draw/intern/draw_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c
new file mode 100644 (file)
index 0000000..ff1289b
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2009/2018 by the Blender Foundation.
+ *
+ * Contributor(s): Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/draw/intern/draw_anim_viz.c
+ *  \ingroup draw
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "BLI_sys_types.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_math.h"
+#include "BLI_dlrbTree.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+
+#include "ED_keyframes_draw.h"
+
+#include "UI_resources.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "draw_common.h"
+#include "draw_manager_text.h"
+
+#include "draw_mode_engines.h"
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+
+/* ********************************* Lists ************************************** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself.
+ */
+
+/* XXX: How to show frame numbers, etc.?  Currently only doing the dots and lines */
+typedef struct MPATH_PassList {
+       struct DRWPass *lines;
+       struct DRWPass *points;
+} MPATH_PassList;
+
+typedef struct MPATH_StorageList {
+       struct MPATH_PrivateData *g_data;
+} MPATH_StorageList;
+
+typedef struct MPATH_Data {
+       void *engine_type;
+       DRWViewportEmptyList *fbl;
+       DRWViewportEmptyList *txl;
+       MPATH_PassList *psl;
+       MPATH_StorageList *stl;
+} MPATH_Data;
+
+struct {
+       GPUShader *mpath_line_sh;
+       GPUShader *mpath_points_sh;
+} e_data = {0};
+
+/* *************************** Path Cache *********************************** */
+
+/* Just convert the CPU cache to GPU cache. */
+static Gwn_VertBuf *mpath_vbo_get(bMotionPath *mpath)
+{
+       if (!mpath->points_vbo) {
+               Gwn_VertFormat format = {0};
+               /* Match structure of bMotionPathVert. */
+               uint pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+               GWN_vertformat_attr_add(&format, "flag", GWN_COMP_I32, 1, GWN_FETCH_INT);
+               mpath->points_vbo = GWN_vertbuf_create_with_format(&format);
+               GWN_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
+
+               /* meh... a useless memcpy. */
+               Gwn_VertBufRaw raw_data;
+               GWN_vertbuf_attr_get_raw_data(mpath->points_vbo, pos, &raw_data);
+               memcpy(GWN_vertbuf_raw_step(&raw_data), mpath->points, sizeof(bMotionPathVert) * mpath->length);
+       }
+       return mpath->points_vbo;
+}
+
+static Gwn_Batch *mpath_batch_line_get(bMotionPath *mpath)
+{
+       if (!mpath->batch_line) {
+               mpath->batch_line = GWN_batch_create(GWN_PRIM_LINE_STRIP, mpath_vbo_get(mpath), NULL);
+       }
+       return mpath->batch_line;
+}
+
+static Gwn_Batch *mpath_batch_points_get(bMotionPath *mpath)
+{
+       if (!mpath->batch_points) {
+               mpath->batch_points = GWN_batch_create(GWN_PRIM_POINTS, mpath_vbo_get(mpath), NULL);
+       }
+       return mpath->batch_points;
+}
+
+/* *************************** Draw Engine Entrypoints ************************** */
+
+static void MPATH_engine_init(void *UNUSED(vedata))
+{
+}
+
+static void MPATH_engine_free(void)
+{
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void MPATH_cache_init(void *vedata)
+{
+       MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
+
+       {
+               DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+               psl->lines = DRW_pass_create("Motionpath Line Pass", state);
+       }
+
+       {
+               DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_POINT;
+               psl->points = DRW_pass_create("Motionpath Point Pass", state);
+       }
+}
+
+static void MPATH_cache_motion_path(MPATH_PassList *psl,
+                                    Object *ob, bPoseChannel *pchan,
+                                    bAnimVizSettings *avs, bMotionPath *mpath)
+{
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       struct DRWTextStore *dt = DRW_text_cache_ensure();
+       int txt_flag = DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_ASCII;
+       int stepsize = avs->path_step;
+       int sfra, efra, sind, len;
+       int cfra = (int)DEG_get_ctime(draw_ctx->depsgraph);
+       bool sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
+       bool show_keyframes = (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) != 0;
+       bMotionPathVert *mpv, *mpv_start;
+
+       /* get frame ranges */
+       if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
+               /* With "Around Current", we only choose frames from around
+                * the current frame to draw.
+                */
+               sfra = cfra - avs->path_bc;
+               efra = cfra + avs->path_ac + 1;
+       }
+       else {
+               /* Use the current display range */
+               sfra = avs->path_sf;
+               efra = avs->path_ef;
+       }
+
+       /* no matter what, we can only show what is in the cache and no more
+        * - abort if whole range is past ends of path
+        * - otherwise clamp endpoints to extents of path
+        */
+       if (sfra < mpath->start_frame) {
+               /* start clamp */
+               sfra = mpath->start_frame;
+       }
+       if (efra > mpath->end_frame) {
+               /* end clamp */
+               efra = mpath->end_frame;
+       }
+
+       if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) {
+               /* whole path is out of bounds */
+               return;
+       }
+
+       len = efra - sfra;
+
+       if ((len <= 0) || (mpath->points == NULL)) {
+               return;
+       }
+
+       sind = sfra - mpath->start_frame;
+       mpv_start = (mpath->points + sind);
+
+       bool use_custom_col = (mpath->flag & MOTIONPATH_FLAG_CUSTOM) != 0;
+
+       /* draw curve-line of path */
+       /* Draw lines only if line drawing option is enabled */
+       if (mpath->flag & MOTIONPATH_FLAG_LINES) {
+               DRWShadingGroup *shgrp = DRW_shgroup_create(mpath_line_shader_get(), psl->lines);
+               DRW_shgroup_uniform_int_copy(shgrp, "frameCurrent", cfra);
+               DRW_shgroup_uniform_int_copy(shgrp, "frameStart", sfra);
+               DRW_shgroup_uniform_int_copy(shgrp, "frameEnd", efra);
+               DRW_shgroup_uniform_int_copy(shgrp, "cacheStart", mpath->start_frame);
+               DRW_shgroup_uniform_int_copy(shgrp, "lineThickness", mpath->line_thickness);
+               DRW_shgroup_uniform_bool_copy(shgrp, "selected", sel);
+               DRW_shgroup_uniform_bool_copy(shgrp, "useCustomColor", use_custom_col);
+               DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+               DRW_shgroup_uniform_block(shgrp, "globalsBlock", globals_ubo);
+               if (use_custom_col) {
+                       DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
+               }
+               /* Only draw the required range. */
+               DRW_shgroup_call_range_add(shgrp, mpath_batch_line_get(mpath), NULL, sind, len);
+       }
+
+       /* Draw points. */
+       DRWShadingGroup *shgrp = DRW_shgroup_create(mpath_points_shader_get(), psl->points);
+       DRW_shgroup_uniform_int_copy(shgrp, "frameCurrent", cfra);
+       DRW_shgroup_uniform_int_copy(shgrp, "cacheStart", mpath->start_frame);
+       DRW_shgroup_uniform_int_copy(shgrp, "pointSize", mpath->line_thickness);
+       DRW_shgroup_uniform_int_copy(shgrp, "stepSize", stepsize);
+       DRW_shgroup_uniform_bool_copy(shgrp, "selected", sel);
+       DRW_shgroup_uniform_bool_copy(shgrp, "showKeyFrames", show_keyframes);
+       DRW_shgroup_uniform_bool_copy(shgrp, "useCustomColor", use_custom_col);
+       DRW_shgroup_uniform_block(shgrp, "globalsBlock", globals_ubo);
+       if (use_custom_col) {
+               DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
+       }
+       /* Only draw the required range. */
+       DRW_shgroup_call_range_add(shgrp, mpath_batch_points_get(mpath), NULL, sind, len);
+
+       /* Draw frame numbers at each framestep value */
+       bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;
+       if ((avs->path_viewflag & (MOTIONPATH_VIEW_FNUMS)) || (show_kf_no && show_keyframes)) {
+               int i;
+               unsigned char col[4], col_kf[4];
+               UI_GetThemeColor3ubv(TH_TEXT_HI, col);
+               UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col_kf);
+               col[3] = col_kf[3] = 255;
+
+               for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
+                       int frame = sfra + i;
+                       char numstr[32];
+                       size_t numstr_len;
+                       float co[3];
+                       bool is_keyframe = (mpv->flag & MOTIONPATH_VERT_KEY) != 0;
+
+                       if ((show_keyframes && show_kf_no && is_keyframe) ||
+                           ((avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) && (i == 0)))
+                       {
+                               numstr_len = sprintf(numstr, " %d", frame);
+                               mul_v3_m4v3(co, ob->imat, mpv->co);
+                               DRW_text_cache_add(dt, co, numstr, numstr_len, 0, txt_flag, (is_keyframe) ? col_kf : col);
+                       }
+                       else if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
+                               bMotionPathVert *mpvP = (mpv - stepsize);
+                               bMotionPathVert *mpvN = (mpv + stepsize);
+                               /* only draw framenum if several consecutive highlighted points don't occur on same point */
+                               if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
+                                       numstr_len = sprintf(numstr, " %d", frame);
+                                       mul_v3_m4v3(co, ob->imat, mpv->co);
+                                       DRW_text_cache_add(dt, co, numstr, numstr_len, 0, txt_flag, col);
+                               }
+                       }
+               }
+       }
+}
+
+/* Add geometry to shading groups. Execute for each objects */
+static void MPATH_cache_populate(void *vedata, Object *ob)
+{
+       MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+
+       if (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_MOTION_PATHS) {
+               return;
+       }
+
+       if (ob->type == OB_ARMATURE) {
+               if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
+                       for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+                               if (pchan->mpath) {
+                                       MPATH_cache_motion_path(psl, ob, pchan, &ob->pose->avs, pchan->mpath);
+                               }
+                       }
+               }
+       }
+       else {
+               if (ob->mpath) {
+                       MPATH_cache_motion_path(psl, ob, NULL, &ob->avs, ob->mpath);
+               }
+       }
+}
+
+/* Draw time! Control rendering pipeline from here */
+static void MPATH_draw_scene(void *vedata)
+{
+       MPATH_PassList *psl = ((MPATH_Data *)vedata)->psl;
+       DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+       
+       MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl)
+
+       DRW_draw_pass(psl->lines);
+       DRW_draw_pass(psl->points);
+
+       MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl)
+}
+
+/* *************************** Draw Engine Defines ****************************** */
+
+static const DrawEngineDataSize MPATH_data_size = DRW_VIEWPORT_DATA_SIZE(MPATH_Data);
+
+DrawEngineType draw_engine_motion_path_type = {
+       NULL, NULL,
+       N_("MotionPath"),
+       &MPATH_data_size,
+       &MPATH_engine_init,
+       &MPATH_engine_free,
+       &MPATH_cache_init,
+       &MPATH_cache_populate,
+       NULL,
+       NULL,
+       &MPATH_draw_scene,
+       NULL,
+       NULL,
+};
+
index 11e0430..fb8833f 100644 (file)
@@ -92,6 +92,10 @@ void DRW_globals_update(void)
        UI_GetThemeColor4fv(TH_NURB_SEL_ULINE, ts.colorNurbSelUline);
        UI_GetThemeColor4fv(TH_ACTIVE_SPLINE, ts.colorActiveSpline);
 
+       UI_GetThemeColor4fv(TH_BONE_POSE, ts.colorBonePose);
+
+       UI_GetThemeColor4fv(TH_CFRAME, ts.colorCurrentFrame);
+
        /* Grid */
        UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid);
        /* emphasise division lines lighter instead of darker, if background is darker than grid */
@@ -153,6 +157,10 @@ void DRW_globals_update(void)
 
 /* ********************************* SHGROUP ************************************* */
 
+extern char datatoc_animviz_mpath_lines_vert_glsl[];
+extern char datatoc_animviz_mpath_lines_geom_glsl[];
+extern char datatoc_animviz_mpath_points_vert_glsl[];
+
 extern char datatoc_armature_axes_vert_glsl[];
 extern char datatoc_armature_sphere_solid_vert_glsl[];
 extern char datatoc_armature_sphere_solid_frag_glsl[];
@@ -167,7 +175,12 @@ extern char datatoc_armature_shape_outline_vert_glsl[];
 extern char datatoc_armature_shape_outline_geom_glsl[];
 extern char datatoc_armature_stick_vert_glsl[];
 extern char datatoc_armature_stick_frag_glsl[];
+
+extern char datatoc_common_globals_lib_glsl[];
+
 extern char datatoc_gpu_shader_flat_color_frag_glsl[];
+extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
 
 extern char datatoc_object_mball_handles_vert_glsl[];
 
@@ -182,6 +195,9 @@ static struct {
        struct GPUShader *bone_sphere_outline;
        struct GPUShader *bone_stick;
 
+       struct GPUShader *mpath_line_sh;
+       struct GPUShader *mpath_points_sh;
+
        struct GPUShader *mball_handles;
 } g_shaders = {NULL};
 
@@ -692,6 +708,33 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass)
        return grp;
 }
 
+struct GPUShader *mpath_line_shader_get(void)
+{
+       if (g_shaders.mpath_line_sh == NULL) {
+               g_shaders.mpath_line_sh = DRW_shader_create_with_lib(
+                       datatoc_animviz_mpath_lines_vert_glsl,
+                       datatoc_animviz_mpath_lines_geom_glsl,
+                       datatoc_gpu_shader_3D_smooth_color_frag_glsl,
+                       datatoc_common_globals_lib_glsl,
+                       NULL);
+       }
+       return g_shaders.mpath_line_sh;
+}
+
+
+struct GPUShader *mpath_points_shader_get(void)
+{
+       if (g_shaders.mpath_points_sh == NULL) {
+               g_shaders.mpath_points_sh = DRW_shader_create_with_lib(
+                       datatoc_animviz_mpath_points_vert_glsl,
+                       NULL,
+                       datatoc_gpu_shader_point_varying_color_frag_glsl,
+                       datatoc_common_globals_lib_glsl,
+                       NULL);
+       }
+       return g_shaders.mpath_points_sh;
+}
+
 /* ******************************************** COLOR UTILS *********************************************** */
 
 /* TODO FINISH */
index 49a1ae4..e4c0380 100644 (file)
@@ -87,6 +87,10 @@ typedef struct GlobalsUboStorage {
        float colorNurbSelUline[4];
        float colorActiveSpline[4];
 
+       float colorBonePose[4];
+
+       float colorCurrentFrame[4];
+
        float colorGrid[4];
        float colorGridEmphasise[4];
        float colorGridAxisX[4];
@@ -131,6 +135,9 @@ struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pas
 struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass);
 struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass);
 
+struct GPUShader *mpath_line_shader_get(void);
+struct GPUShader *mpath_points_shader_get(void);
+
 int DRW_object_wire_theme_get(
         struct Object *ob, struct ViewLayer *view_layer, float **r_color);
 float *DRW_color_background_blend_get(int theme_id);
index b96ab74..60e9af7 100644 (file)
@@ -1051,6 +1051,8 @@ static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int dr
 static void drw_engines_enable_from_object_mode(void)
 {
        use_drw_engine(&draw_engine_object_type);
+       /* TODO(fclem) remove this, it does not belong to it's own engine. */
+       use_drw_engine(&draw_engine_motion_path_type);
 }
 
 static void drw_engines_enable_from_mode(int mode)
@@ -1347,7 +1349,9 @@ void DRW_draw_render_loop_ex(
 
        drw_debug_draw();
 
+       glDisable(GL_DEPTH_TEST);
        drw_engines_draw_text();
+       glEnable(GL_DEPTH_TEST);
 
        if (DST.draw_ctx.evil_C) {
                /* needed so manipulator isn't obscured */
@@ -2047,6 +2051,7 @@ void DRW_engines_register(void)
        DRW_engine_register(&draw_engine_edit_metaball_type);
        DRW_engine_register(&draw_engine_edit_surface_type);
        DRW_engine_register(&draw_engine_edit_text_type);
+       DRW_engine_register(&draw_engine_motion_path_type);
        DRW_engine_register(&draw_engine_overlay_type);
        DRW_engine_register(&draw_engine_paint_texture_type);
        DRW_engine_register(&draw_engine_paint_vertex_type);
index b24a845..ae485ba 100644 (file)
@@ -126,6 +126,7 @@ typedef struct DRWCallState {
 
 typedef enum {
        DRW_CALL_SINGLE,                 /* A single batch */
+       DRW_CALL_RANGE,                  /* Like single but only draw a range of vertices/indices. */
        DRW_CALL_INSTANCES,              /* Draw instances without any instancing attribs. */
        DRW_CALL_GENERATE,               /* Uses a callback to draw with any number of batches. */
        DRW_CALL_PROCEDURAL,             /* Generate a drawcall without any Gwn_Batch. */
@@ -139,6 +140,10 @@ typedef struct DRWCall {
                struct { /* type == DRW_CALL_SINGLE */
                        Gwn_Batch *geometry;
                } single;
+               struct { /* type == DRW_CALL_RANGE */
+                       Gwn_Batch *geometry;
+                       uint start, count;
+               } range;
                struct { /* type == DRW_CALL_INSTANCES */
                        Gwn_Batch *geometry;
                        /* Count can be adjusted between redraw. If needed, we can add fixed count. */
index 25d720a..9b707a8 100644 (file)
@@ -366,6 +366,25 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm
        BLI_LINKS_APPEND(&shgroup->calls, call);
 }
 
+void DRW_shgroup_call_range_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint v_sta, uint v_count)
+{
+       BLI_assert(geom != NULL);
+       BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
+       BLI_assert(v_count);
+
+       DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+       call->state = drw_call_state_create(shgroup, obmat, NULL);
+       call->type = DRW_CALL_RANGE;
+       call->range.geometry = geom;
+       call->range.start = v_sta;
+       call->range.count = v_count;
+#ifdef USE_GPU_SELECT
+       call->select_id = DST.select_id;
+#endif
+
+       BLI_LINKS_APPEND(&shgroup->calls, call);
+}
+
 static void drw_shgroup_call_procedural_add_ex(
         DRWShadingGroup *shgroup, Gwn_PrimType prim_type, uint vert_count, float (*obmat)[4])
 {
@@ -398,12 +417,11 @@ void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, uint tr
        drw_shgroup_call_procedural_add_ex(shgroup, GWN_PRIM_TRIS, tria_count * 3, obmat);
 }
 
-
 /* These calls can be culled and are optimized for redraw */
 void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, bool bypass_culling)
 {
        BLI_assert(geom != NULL);
-       BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+       BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
 
        DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
        call->state = drw_call_state_object(shgroup, ob->obmat, ob);
@@ -423,7 +441,7 @@ void DRW_shgroup_call_object_add_with_callback(
         DRWCallVisibilityFn *callback, void *user_data)
 {
        BLI_assert(geom != NULL);
-       BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+       BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
 
        DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
        call->state = drw_call_state_object(shgroup, ob->obmat, ob);
@@ -441,7 +459,7 @@ void DRW_shgroup_call_object_add_with_callback(
 void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4], uint *count)
 {
        BLI_assert(geom != NULL);
-       BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+       BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
 
        DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
        call->state = drw_call_state_create(shgroup, obmat, NULL);
@@ -459,7 +477,7 @@ void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, f
 void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob, uint *count)
 {
        BLI_assert(geom != NULL);
-       BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+       BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
 
        DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
        call->state = drw_call_state_object(shgroup, ob->obmat, ob);
@@ -479,7 +497,7 @@ void DRW_shgroup_call_generate_add(
         float (*obmat)[4])
 {
        BLI_assert(geometry_fn != NULL);
-       BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+       BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
 
        DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
        call->state = drw_call_state_create(shgroup, obmat, NULL);
index 9fd0435..cb2cad8 100644 (file)
@@ -1150,6 +1150,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
                                case DRW_CALL_SINGLE:
                                        draw_geometry_execute(shgroup, call->single.geometry);
                                        break;
+                               case DRW_CALL_RANGE:
+                                       draw_geometry_execute_ex(shgroup, call->range.geometry, call->range.start, call->range.count, false);
+                                       break;
                                case DRW_CALL_INSTANCES:
                                        draw_geometry_execute_ex(shgroup, call->instances.geometry, 0, *call->instances.count, true);
                                        break;
index 9522e3c..f88d49d 100644 (file)
@@ -34,6 +34,7 @@ extern DrawEngineType draw_engine_edit_mesh_type;
 extern DrawEngineType draw_engine_edit_metaball_type;
 extern DrawEngineType draw_engine_edit_surface_type;
 extern DrawEngineType draw_engine_edit_text_type;
+extern DrawEngineType draw_engine_motion_path_type;
 extern DrawEngineType draw_engine_paint_texture_type;
 extern DrawEngineType draw_engine_paint_vertex_type;
 extern DrawEngineType draw_engine_paint_weight_type;
diff --git a/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl b/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl
new file mode 100644 (file)
index 0000000..d9d5988
--- /dev/null
@@ -0,0 +1,38 @@
+
+layout(lines) in;
+layout(triangle_strip, max_vertices = 4) out;
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+uniform int lineThickness = 2;
+
+in vec4 finalColor_geom[];
+in vec2 ssPos[];
+
+out vec4 finalColor;
+
+vec2 compute_dir(vec2 v0, vec2 v1)
+{
+       vec2 dir = normalize(v1 - v0 + 1e-8);
+       dir = vec2(-dir.y, dir.x);
+       return dir;
+}
+
+void main(void)
+{
+       vec2 t;
+       vec2 edge_dir = compute_dir(ssPos[0], ssPos[1]) / viewportSize;
+
+       bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+       finalColor = finalColor_geom[0];
+       t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[0].gl_Position.w : 1.0));
+       gl_Position = gl_in[0].gl_Position + vec4(t, 0.0, 0.0); EmitVertex();
+       gl_Position = gl_in[0].gl_Position - vec4(t, 0.0, 0.0); EmitVertex();
+
+       finalColor = finalColor_geom[1];
+       t = edge_dir * (float(lineThickness) * (is_persp ? gl_in[1].gl_Position.w : 1.0));
+       gl_Position = gl_in[1].gl_Position + vec4(t, 0.0, 0.0); EmitVertex();
+       gl_Position = gl_in[1].gl_Position - vec4(t, 0.0, 0.0); EmitVertex();
+       EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl b/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl
new file mode 100644 (file)
index 0000000..276f400
--- /dev/null
@@ -0,0 +1,91 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+uniform int frameCurrent;
+uniform int frameStart;
+uniform int frameEnd;
+uniform int cacheStart;
+uniform bool selected;
+uniform bool useCustomColor;
+uniform vec3 customColor;
+
+in vec3 pos;
+
+out vec2 ssPos;
+out vec4 finalColor_geom;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+       return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+#define SET_INTENSITY(A, B, C, min, max) (((1.0 - (float(C - B) / float(C - A))) * (max - min)) + min)
+
+void main()
+{
+       gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
+
+       ssPos = proj(gl_Position);
+
+       int frame = gl_VertexID + cacheStart;
+
+       float intensity;  /* how faint */
+
+       vec3 blend_base = (abs(frame - frameCurrent) == 1) ? colorCurrentFrame.rgb : colorBackground.rgb; /* "bleed" cframe color to ease color blending */
+
+       /* TODO: We might want something more consistent with custom color and standard colors. */
+       if (frame < frameCurrent) {
+               if (useCustomColor) {
+                       /* Custom color: previous frames color is darker than current frame */
+                       finalColor_geom.rgb = customColor * 0.25;
+               }
+               else {
+                       /* black - before frameCurrent */
+                       if (selected) {
+                               intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75);
+                       }
+                       else {
+                               intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.68, 0.92);
+                       }
+                       finalColor_geom.rgb = mix(colorWire.rgb, blend_base, intensity);
+               }
+       }
+       else if (frame > frameCurrent) {
+               if (useCustomColor) {
+                       /* Custom color: next frames color is equal to user selected color */
+                       finalColor_geom.rgb = customColor;
+               }
+               else {
+                       /* blue - after frameCurrent */
+                       if (selected) {
+                               intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75);
+                       }
+                       else {
+                               intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.68, 0.92);
+                       }
+
+                       finalColor_geom.rgb = mix(colorBonePose.rgb, blend_base, intensity);
+               }
+       }
+       else {
+               if (useCustomColor) {
+                       /* Custom color: current frame color is slightly darker than user selected color */
+                       finalColor_geom.rgb = customColor * 0.5;
+               }
+               else {
+                       /* green - on frameCurrent */
+                       if (selected) {
+                               intensity = 0.5f;
+                       }
+                       else {
+                               intensity = 0.99f;
+                       }
+                       finalColor_geom.rgb = clamp(mix(colorCurrentFrame.rgb, colorBackground.rgb, intensity) - 0.1, 0.0, 0.1);
+               }
+       }
+
+       finalColor_geom.a = 1.0;
+}
diff --git a/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl b/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl
new file mode 100644 (file)
index 0000000..3b2f170
--- /dev/null
@@ -0,0 +1,47 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+uniform int pointSize = 2;
+uniform int frameCurrent;
+uniform int cacheStart;
+uniform bool showKeyFrames = true;
+uniform bool useCustomColor;
+uniform vec3 customColor;
+
+in vec3 pos;
+in int flag;
+
+#define MOTIONPATH_VERT_SEL (1 << 0)
+#define MOTIONPATH_VERT_KEY (1 << 1)
+
+out vec4 finalColor;
+
+void main()
+{
+       gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
+       gl_PointSize = float(pointSize + 2);
+
+       int frame = gl_VertexID + cacheStart;
+       finalColor = (useCustomColor) ? vec4(customColor, 1.0) : vec4(1.0);
+
+       /* Bias to reduce z fighting with the path */
+       gl_Position.z -= 1e-4;
+
+       if (showKeyFrames) {
+               if ((flag & MOTIONPATH_VERT_KEY) != 0) {
+                       gl_PointSize = float(pointSize + 5);
+                       finalColor = colorVertexSelect;
+                       /* Bias more to get these on top of regular points */
+                       gl_Position.z -= 1e-4;
+               }
+               /* Draw big green dot where the current frame is.
+                * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
+                */
+               if (frame == frameCurrent) {
+                       gl_PointSize = float(pointSize + 8);
+                       finalColor = colorCurrentFrame;
+                       /* Bias more to get these on top of keyframes */
+                       gl_Position.z -= 1e-4;
+               }
+       }
+}
index 4a0104e..c55457b 100644 (file)
@@ -48,6 +48,10 @@ layout(std140) uniform globalsBlock {
        vec4 colorNurbSelUline;
        vec4 colorActiveSpline;
 
+       vec4 colorBonePose;
+
+       vec4 colorCurrentFrame;
+
        vec4 colorGrid;
        vec4 colorGridEmphasise;
        vec4 colorGridAxisX;
index 932919c..aae8d4b 100644 (file)
@@ -193,6 +193,9 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
        /* recalculate paths, then free */
        animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
        BLI_freelistN(&targets);
+       
+       /* tag armature object for copy on write - so paths will draw/redraw */
+       DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
 }
 
 
index a05b711..b27e0c9 100644 (file)
@@ -1004,6 +1004,15 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene)
        /* recalculate paths, then free */
        animviz_calc_motionpaths(depsgraph, bmain, scene, &targets);
        BLI_freelistN(&targets);
+       
+       /* tag objects for copy on write - so paths will draw/redraw */
+       CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
+       {
+               if (ob->mpath) {
+                       DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
+               }
+       }
+       CTX_DATA_END;
 }
 
 
index 4911b21..4ad4ae9 100644 (file)
@@ -61,7 +61,8 @@ typedef struct bMotionPathVert {
 /* bMotionPathVert->flag */
 typedef enum eMotionPathVert_Flag {
        /* vert is selected */
-       MOTIONPATH_VERT_SEL     = (1 << 0)
+       MOTIONPATH_VERT_SEL     = (1 << 0),
+       MOTIONPATH_VERT_KEY     = (1 << 1),
 } eMotionPathVert_Flag;
 
 /* ........ */
@@ -79,6 +80,12 @@ typedef struct bMotionPath {
        float color[3];             /* optional custom color */
        int line_thickness;         /* line thickness */
        int flag;                   /* baking settings - eMotionPath_Flag */
+
+       /* Used for drawing. */
+       struct Gwn_VertBuf *points_vbo;
+       struct Gwn_Batch *batch_line;
+       struct Gwn_Batch *batch_points;
+       void *pad;
 } bMotionPath;
 
 /* bMotionPath->flag */
index 7ce19b9..2ef5350 100644 (file)
@@ -359,6 +359,7 @@ enum {
        V3D_OVERLAY_LOOK_DEV          = (1 << 3),
        V3D_OVERLAY_WIREFRAMES        = (1 << 4),
        V3D_OVERLAY_HIDE_TEXT         = (1 << 5),
+       V3D_OVERLAY_HIDE_MOTION_PATHS = (1 << 6),
 };
 
 /* View3DOverlay->edit_flag */
index 845fe4f..a4b9f07 100644 (file)
@@ -2489,6 +2489,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Bone Selection", "Show the Bone Selection Overlay");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 
+       prop = RNA_def_property(srna, "show_motion_paths", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_HIDE_MOTION_PATHS);
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_ui_text(prop, "Motion Paths", "Show the Motion Paths Overlay");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
        prop = RNA_def_property(srna, "show_look_dev", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_LOOK_DEV);
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);