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/startup/bl_ui/space_view3d.py1
-rw-r--r--source/blender/blenkernel/BKE_anim.h2
-rw-r--r--source/blender/blenkernel/intern/action.c4
-rw-r--r--source/blender/blenkernel/intern/anim.c87
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/blenloader/intern/readfile.c4
-rw-r--r--source/blender/draw/CMakeLists.txt4
-rw-r--r--source/blender/draw/intern/DRW_render.h2
-rw-r--r--source/blender/draw/intern/draw_anim_viz.c351
-rw-r--r--source/blender/draw/intern/draw_common.c43
-rw-r--r--source/blender/draw/intern/draw_common.h7
-rw-r--r--source/blender/draw/intern/draw_manager.c5
-rw-r--r--source/blender/draw/intern/draw_manager.h5
-rw-r--r--source/blender/draw/intern/draw_manager_data.c30
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c3
-rw-r--r--source/blender/draw/modes/draw_mode_engines.h1
-rw-r--r--source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl38
-rw-r--r--source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl91
-rw-r--r--source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl47
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl4
-rw-r--r--source/blender/editors/armature/pose_edit.c3
-rw-r--r--source/blender/editors/object/object_edit.c9
-rw-r--r--source/blender/makesdna/DNA_action_types.h9
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_space.c6
25 files changed, 748 insertions, 12 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index b93e24da87a..8e5ca798ac3 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -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")
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 0fb83162459..701be9d44cc 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 360d9c019ba..c12dd49b47e 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -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) {
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index cff9fd4a7c8..c7730d8877b 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -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"
@@ -59,7 +61,12 @@
#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);
}
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 3448327586e..c4460d5d909 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -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);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 6c2293d2ec1..fedf91669d6 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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 *************** */
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 0eeb6bae09e..2b6d261d43e 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -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)
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 44fb71a231b..081bae944d8 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -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
index 00000000000..ff1289b2a21
--- /dev/null
+++ b/source/blender/draw/intern/draw_anim_viz.c
@@ -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,
+};
+
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 11e04306143..fb8833f40c3 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -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 */
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 49a1ae42198..e4c038006b5 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -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);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index b96ab74fa86..60e9af78df9 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -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);
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index b24a8458de2..ae485ba9489 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -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. */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 25d720abc71..9b707a81761 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -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);
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 9fd0435aa78..cb2cad8a36e 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -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;
diff --git a/source/blender/draw/modes/draw_mode_engines.h b/source/blender/draw/modes/draw_mode_engines.h
index 9522e3cddc6..f88d49dfa96 100644
--- a/source/blender/draw/modes/draw_mode_engines.h
+++ b/source/blender/draw/modes/draw_mode_engines.h
@@ -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
index 00000000000..d9d59880e99
--- /dev/null
+++ b/source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl
@@ -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
index 00000000000..276f4004fb6
--- /dev/null
+++ b/source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl
@@ -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
index 00000000000..3b2f170ca22
--- /dev/null
+++ b/source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl
@@ -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;
+ }
+ }
+}
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
index 4a0104e2cf2..c55457bb6d2 100644
--- a/source/blender/draw/modes/shaders/common_globals_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -48,6 +48,10 @@ layout(std140) uniform globalsBlock {
vec4 colorNurbSelUline;
vec4 colorActiveSpline;
+ vec4 colorBonePose;
+
+ vec4 colorCurrentFrame;
+
vec4 colorGrid;
vec4 colorGridEmphasise;
vec4 colorGridAxisX;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 932919cb19d..aae8d4bc0a5 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -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);
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index a05b7111846..b27e0c96660 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -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;
}
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 4911b21cd2b..4ad4ae97f1a 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -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 */
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 7ce19b92aae..2ef5350c70e 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -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 */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 845fe4f89bc..a4b9f077738 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -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);