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:
Diffstat (limited to 'source/blender/draw/engines/overlay/overlay_motion_path.cc')
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.cc220
1 files changed, 220 insertions, 0 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.cc b/source/blender/draw/engines/overlay/overlay_motion_path.cc
new file mode 100644
index 00000000000..00b2a8665fd
--- /dev/null
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.cc
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2019 Blender Foundation. */
+
+/** \file
+ * \ingroup draw_engine
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "DNA_armature_types.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_batch.h"
+
+#include "UI_resources.h"
+
+#include "draw_manager_text.h"
+
+#include "overlay_private.hh"
+
+void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ DRWShadingGroup *grp;
+ GPUShader *sh;
+
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ DRW_PASS_CREATE(psl->motion_paths_ps, state | pd->clipping_state);
+
+ sh = OVERLAY_shader_motion_path_line();
+ pd->motion_path_lines_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+
+ sh = OVERLAY_shader_motion_path_vert();
+ pd->motion_path_points_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+}
+
+/* Just convert the CPU cache to GPU cache. */
+/* T0D0(fclem) This should go into a draw_cache_impl_motionpath. */
+static GPUVertBuf *mpath_vbo_get(bMotionPath *mpath)
+{
+ if (!mpath->points_vbo) {
+ GPUVertFormat format = {0};
+ /* Match structure of bMotionPathVert. */
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "flag", GPU_COMP_I32, 1, GPU_FETCH_INT);
+ mpath->points_vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(mpath->points_vbo, mpath->length);
+ /* meh... a useless memcpy. */
+ memcpy(GPU_vertbuf_get_data(mpath->points_vbo),
+ mpath->points,
+ sizeof(bMotionPathVert) * mpath->length);
+ }
+ return mpath->points_vbo;
+}
+
+static GPUBatch *mpath_batch_line_get(bMotionPath *mpath)
+{
+ if (!mpath->batch_line) {
+ mpath->batch_line = GPU_batch_create(GPU_PRIM_LINE_STRIP, mpath_vbo_get(mpath), nullptr);
+ }
+ return mpath->batch_line;
+}
+
+static GPUBatch *mpath_batch_points_get(bMotionPath *mpath)
+{
+ if (!mpath->batch_points) {
+ mpath->batch_points = GPU_batch_create(GPU_PRIM_POINTS, mpath_vbo_get(mpath), nullptr);
+ }
+ return mpath->batch_points;
+}
+
+static void motion_path_get_frame_range_to_draw(bAnimVizSettings *avs,
+ bMotionPath *mpath,
+ int current_frame,
+ int *r_start,
+ int *r_end,
+ int *r_step)
+{
+ int start, end;
+
+ if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
+ start = current_frame - avs->path_bc;
+ end = current_frame + avs->path_ac + 1;
+ }
+ else {
+ start = avs->path_sf;
+ end = avs->path_ef;
+ }
+
+ if (start > end) {
+ SWAP(int, start, end);
+ }
+
+ CLAMP(start, mpath->start_frame, mpath->end_frame);
+ CLAMP(end, mpath->start_frame, mpath->end_frame);
+
+ *r_start = start;
+ *r_end = end;
+ *r_step = max_ii(avs->path_step, 1);
+}
+
+static void motion_path_cache(OVERLAY_Data *vedata,
+ Object *ob,
+ bPoseChannel *pchan,
+ bAnimVizSettings *avs,
+ bMotionPath *mpath)
+{
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ struct DRWTextStore *dt = DRW_text_cache_ensure();
+ int txt_flag = DRW_TEXT_CACHE_GLOBALSPACE;
+ int cfra = (int)DEG_get_ctime(draw_ctx->depsgraph);
+ bool selected = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->base_flag & BASE_SELECTED);
+ bool show_keyframes = (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) != 0;
+ bool show_keyframes_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;
+ bool show_frame_no = (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) != 0;
+ bool show_lines = (mpath->flag & MOTIONPATH_FLAG_LINES) != 0;
+ float no_custom_col[3] = {-1.0f, -1.0f, -1.0f};
+ float *color = (mpath->flag & MOTIONPATH_FLAG_CUSTOM) ? mpath->color : no_custom_col;
+
+ int sfra, efra, stepsize;
+ motion_path_get_frame_range_to_draw(avs, mpath, cfra, &sfra, &efra, &stepsize);
+
+ int len = efra - sfra;
+ if (len == 0) {
+ return;
+ }
+ int start_index = sfra - mpath->start_frame;
+
+ /* Draw curve-line of path. */
+ if (show_lines) {
+ const int motion_path_settings[4] = {cfra, sfra, efra, mpath->start_frame};
+ DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->motion_path_lines_grp);
+ DRW_shgroup_uniform_ivec4_copy(grp, "mpathLineSettings", motion_path_settings);
+ DRW_shgroup_uniform_int_copy(grp, "lineThickness", mpath->line_thickness);
+ DRW_shgroup_uniform_bool_copy(grp, "selected", selected);
+ DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
+ /* Only draw the required range. */
+ DRW_shgroup_call_range(grp, nullptr, mpath_batch_line_get(mpath), start_index, len);
+ }
+
+ /* Draw points. */
+ {
+ int pt_size = max_ii(mpath->line_thickness - 1, 1);
+ const int motion_path_settings[4] = {pt_size, cfra, mpath->start_frame, stepsize};
+ DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->motion_path_points_grp);
+ DRW_shgroup_uniform_ivec4_copy(grp, "mpathPointSettings", motion_path_settings);
+ DRW_shgroup_uniform_bool_copy(grp, "showKeyFrames", show_keyframes);
+ DRW_shgroup_uniform_vec3_copy(grp, "customColor", color);
+ /* Only draw the required range. */
+ DRW_shgroup_call_range(grp, nullptr, mpath_batch_points_get(mpath), start_index, len);
+ }
+
+ /* Draw frame numbers at each frame-step value. */
+ if (show_frame_no || (show_keyframes_no && show_keyframes)) {
+ int i;
+ uchar col[4], col_kf[4];
+ /* Color Management: Exception here as texts are drawn in sRGB space directly. */
+ UI_GetThemeColor3ubv(TH_TEXT_HI, col);
+ UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col_kf);
+ col[3] = col_kf[3] = 255;
+
+ bMotionPathVert *mpv = mpath->points + start_index;
+ for (i = 0; i < len; i += stepsize, mpv += stepsize) {
+ int frame = sfra + i;
+ char numstr[32];
+ size_t numstr_len;
+ bool is_keyframe = (mpv->flag & MOTIONPATH_VERT_KEY) != 0;
+
+ if ((show_keyframes && show_keyframes_no && is_keyframe) || (show_frame_no && (i == 0))) {
+ numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), " %d", frame);
+ DRW_text_cache_add(
+ dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, (is_keyframe) ? col_kf : col);
+ }
+ else if (show_frame_no) {
+ bMotionPathVert *mpvP = (mpv - stepsize);
+ bMotionPathVert *mpvN = (mpv + stepsize);
+ /* Only draw frame number 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 = BLI_snprintf_rlen(numstr, sizeof(numstr), " %d", frame);
+ DRW_text_cache_add(dt, mpv->co, numstr, numstr_len, 0, 0, txt_flag, col);
+ }
+ }
+ }
+ }
+}
+
+void OVERLAY_motion_path_cache_populate(OVERLAY_Data *vedata, Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ if (ob->type == OB_ARMATURE) {
+ if (OVERLAY_armature_is_pose_mode(ob, draw_ctx)) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ if (pchan->mpath) {
+ motion_path_cache(vedata, ob, pchan, &ob->pose->avs, pchan->mpath);
+ }
+ }
+ }
+ }
+
+ if (ob->mpath) {
+ motion_path_cache(vedata, ob, nullptr, &ob->avs, ob->mpath);
+ }
+}
+
+void OVERLAY_motion_path_draw(OVERLAY_Data *vedata)
+{
+ OVERLAY_PassList *psl = vedata->psl;
+
+ DRW_draw_pass(psl->motion_paths_ps);
+}