From 72a360827bc47e68bf47a5aa4ad9185b031423c4 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 1 Jun 2018 16:38:21 +0200 Subject: T54991: Restore support for Motion Path drawing in 2.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- source/blender/blenkernel/BKE_anim.h | 2 + source/blender/blenkernel/intern/action.c | 4 +- source/blender/blenkernel/intern/anim.c | 87 ++++- source/blender/blenkernel/intern/object.c | 3 +- source/blender/blenloader/intern/readfile.c | 4 + source/blender/draw/CMakeLists.txt | 4 + source/blender/draw/intern/DRW_render.h | 2 + source/blender/draw/intern/draw_anim_viz.c | 351 +++++++++++++++++++++ source/blender/draw/intern/draw_common.c | 43 +++ source/blender/draw/intern/draw_common.h | 7 + source/blender/draw/intern/draw_manager.c | 5 + source/blender/draw/intern/draw_manager.h | 5 + source/blender/draw/intern/draw_manager_data.c | 30 +- source/blender/draw/intern/draw_manager_exec.c | 3 + source/blender/draw/modes/draw_mode_engines.h | 1 + .../modes/shaders/animviz_mpath_lines_geom.glsl | 38 +++ .../modes/shaders/animviz_mpath_lines_vert.glsl | 91 ++++++ .../modes/shaders/animviz_mpath_points_vert.glsl | 47 +++ .../draw/modes/shaders/common_globals_lib.glsl | 4 + source/blender/editors/armature/pose_edit.c | 3 + source/blender/editors/object/object_edit.c | 9 + source/blender/makesdna/DNA_action_types.h | 9 +- source/blender/makesdna/DNA_view3d_types.h | 1 + source/blender/makesrna/intern/rna_space.c | 6 + 24 files changed, 747 insertions(+), 12 deletions(-) create mode 100644 source/blender/draw/intern/draw_anim_viz.c create mode 100644 source/blender/draw/modes/shaders/animviz_mpath_lines_geom.glsl create mode 100644 source/blender/draw/modes/shaders/animviz_mpath_lines_vert.glsl create mode 100644 source/blender/draw/modes/shaders/animviz_mpath_points_vert.glsl (limited to 'source') 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 +#include +#include + +#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); -- cgit v1.2.3