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
path: root/source
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2018-06-01 17:38:21 +0300
committerJoshua Leung <aligorith@gmail.com>2018-06-01 17:38:21 +0300
commit72a360827bc47e68bf47a5aa4ad9185b031423c4 (patch)
treec0e27dc580fca576dc7e3fc0ee21db2559d0f80c /source
parent44a8070db3c03a4e12d1ec1ca15432ec2b36e2fc (diff)
T54991: Restore support for Motion Path drawing in 2.8
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)
Diffstat (limited to 'source')
-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
24 files changed, 747 insertions, 12 deletions
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);