Anim: Add custom pre and post frame color to motion path

This PR adds an option to specify custom colors for a
motion path. One for frames before the current frame
and one frame for after. With this it is easier to see
the relation of the motion path to the current frame.
That was already the case with the default colors, but
not with custom colors.

On a technical side note, the colors pre and post the current
frame were already different.
The shader multiplied the custom color by 0.25
for anything pre current frame.

Pull Request: https://projects.blender.org/blender/blender/pulls/119375
This commit is contained in:
Christoph Lendenfeld 2024-04-12 15:11:51 +02:00 committed by Christoph Lendenfeld
parent 3fda0d5f8f
commit 883af6dd63
10 changed files with 87 additions and 46 deletions

@ -107,12 +107,11 @@ class MotionPathButtonsPanel_display:
col = layout.column()
col.prop(mpath, "line_thickness", text="Thickness")
split = col.split(factor=0.6)
split.prop(mpath, "use_custom_color", text="Custom Color")
sub = split.column()
col.prop(mpath, "use_custom_color", text="Custom Color")
sub = layout.column()
sub.enabled = mpath.use_custom_color
sub.prop(mpath, "color", text="")
sub.prop(mpath, "color", text="Before")
sub.prop(mpath, "color_post", text="After")
classes = (

@ -194,6 +194,10 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
mpath->color[1] = 0.0;
mpath->color[2] = 0.0;
mpath->color_post[0] = 0.1;
mpath->color_post[1] = 1.0;
mpath->color_post[2] = 0.1;
mpath->line_thickness = 2;
mpath->flag |= MOTIONPATH_FLAG_LINES;

@ -3147,6 +3147,26 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 14)) {
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
if (bMotionPath *mpath = ob->mpath) {
mpath->color_post[0] = 0.1f;
mpath->color_post[1] = 1.0f;
mpath->color_post[2] = 0.1f;
}
if (!ob->pose) {
continue;
}
LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
if (bMotionPath *mpath = pchan->mpath) {
mpath->color_post[0] = 0.1f;
mpath->color_post[1] = 1.0f;
mpath->color_post[2] = 0.1f;
}
}
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

@ -135,7 +135,9 @@ static void motion_path_cache(OVERLAY_Data *vedata,
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;
const bool use_custom_color = mpath->flag & MOTIONPATH_FLAG_CUSTOM;
const float *color_pre = use_custom_color ? mpath->color : no_custom_col;
const float *color_post = use_custom_color ? mpath->color_post : no_custom_col;
int sfra, efra, stepsize;
motion_path_get_frame_range_to_draw(avs, mpath, cfra, &sfra, &efra, &stepsize);
@ -171,7 +173,8 @@ static void motion_path_cache(OVERLAY_Data *vedata,
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);
DRW_shgroup_uniform_vec3_copy(grp, "customColorPre", color_pre);
DRW_shgroup_uniform_vec3_copy(grp, "customColorPost", color_post);
DRW_shgroup_uniform_mat4_copy(grp, "camera_space_matrix", camera_matrix);
/* Only draw the required range. */
DRW_shgroup_call_range(grp, nullptr, mpath_batch_line_get(mpath), start_index, len);
@ -184,7 +187,8 @@ static void motion_path_cache(OVERLAY_Data *vedata,
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);
DRW_shgroup_uniform_vec3_copy(grp, "customColorPre", color_pre);
DRW_shgroup_uniform_vec3_copy(grp, "customColorPost", color_post);
DRW_shgroup_uniform_mat4_copy(grp, "camera_space_matrix", camera_matrix);
/* Only draw the required range. */
DRW_shgroup_call_range(grp, nullptr, mpath_batch_points_get(mpath), start_index, len);

@ -191,7 +191,8 @@ GPU_SHADER_CREATE_INFO(overlay_motion_path_line)
.vertex_in(0, Type::VEC3, "pos")
.push_constant(Type::IVEC4, "mpathLineSettings")
.push_constant(Type::BOOL, "selected")
.push_constant(Type::VEC3, "customColor")
.push_constant(Type::VEC3, "customColorPre")
.push_constant(Type::VEC3, "customColorPost")
.push_constant(Type::INT, "lineThickness") /* In pixels. */
.push_constant(Type::MAT4, "camera_space_matrix")
.vertex_out(overlay_motion_path_line_iface)
@ -210,7 +211,8 @@ GPU_SHADER_CREATE_INFO(overlay_motion_path_line_no_geom)
.vertex_in(0, Type::VEC3, "pos")
.push_constant(Type::IVEC4, "mpathLineSettings")
.push_constant(Type::BOOL, "selected")
.push_constant(Type::VEC3, "customColor")
.push_constant(Type::VEC3, "customColorPre")
.push_constant(Type::VEC3, "customColorPost")
.push_constant(Type::INT, "lineThickness") /* In pixels. */
.vertex_out(overlay_motion_path_line_iface)
.fragment_out(0, Type::VEC4, "fragColor")
@ -236,7 +238,8 @@ GPU_SHADER_CREATE_INFO(overlay_motion_path_point)
.vertex_in(1, Type::UINT, "flag")
.push_constant(Type::IVEC4, "mpathPointSettings")
.push_constant(Type::BOOL, "showKeyFrames")
.push_constant(Type::VEC3, "customColor")
.push_constant(Type::VEC3, "customColorPre")
.push_constant(Type::VEC3, "customColorPost")
.push_constant(Type::MAT4, "camera_space_matrix")
.vertex_out(overlay_motion_path_point_iface)
.fragment_out(0, Type::VEC4, "fragColor")

@ -36,15 +36,13 @@ void main()
vec3 blend_base = (abs(frame - frameCurrent) == 0) ?
colorCurrentFrame.rgb :
colorBackground.rgb; /* "bleed" CFRAME color to ease color blending */
bool use_custom_color = customColor.x >= 0.0;
/* TODO: We might want something more consistent with custom color and standard colors. */
bool use_custom_color = customColorPre.x >= 0.0;
if (frame < frameCurrent) {
if (use_custom_color) {
/* Custom color: previous frames color is darker than current frame */
interp.color.rgb = customColor * 0.25;
interp.color.rgb = customColorPre;
}
else {
/* black - before frameCurrent */
if (selected) {
intensity = calc_intensity(frameStart, frame, frameCurrent, 0.25, 0.75);
}
@ -56,11 +54,9 @@ void main()
}
else if (frame > frameCurrent) {
if (use_custom_color) {
/* Custom color: next frames color is equal to user selected color */
interp.color.rgb = customColor;
interp.color.rgb = customColorPost;
}
else {
/* blue - after frameCurrent */
if (selected) {
intensity = calc_intensity(frameCurrent, frame, frameEnd, 0.25, 0.75);
}
@ -72,12 +68,11 @@ void main()
}
}
else {
/* Current Frame. */
if (use_custom_color) {
/* Custom color: current frame color is slightly darker than user selected color */
interp.color.rgb = customColor * 0.5;
interp.color.rgb = colorCurrentFrame.rgb;
}
else {
/* green - on frameCurrent */
if (selected) {
intensity = 0.92f;
}

@ -38,15 +38,13 @@ void do_vertex_shader(vec4 pos, int vertex_id, out vec2 out_sspos, out vec4 out_
vec3 blend_base = (abs(frame - frameCurrent) == 0) ?
colorCurrentFrame.rgb :
colorBackground.rgb; /* "bleed" CFRAME color to ease color blending. */
bool use_custom_color = customColor.x >= 0.0;
/* TODO: We might want something more consistent with custom color and standard colors. */
bool use_custom_color = customColorPre.x >= 0.0;
if (frame < frameCurrent) {
if (use_custom_color) {
/* Custom color: previous frames color is darker than current frame */
out_finalcolor.rgb = customColor * 0.25;
out_finalcolor.rgb = customColorPre;
}
else {
/* black - before frameCurrent */
if (selected) {
intensity = SET_INTENSITY(frameStart, frame, frameCurrent, 0.25, 0.75);
}
@ -58,11 +56,9 @@ void do_vertex_shader(vec4 pos, int vertex_id, out vec2 out_sspos, out vec4 out_
}
else if (frame > frameCurrent) {
if (use_custom_color) {
/* Custom color: next frames color is equal to user selected color */
out_finalcolor.rgb = customColor;
out_finalcolor.rgb = customColorPost;
}
else {
/* blue - after frameCurrent */
if (selected) {
intensity = SET_INTENSITY(frameCurrent, frame, frameEnd, 0.25, 0.75);
}
@ -75,20 +71,19 @@ void do_vertex_shader(vec4 pos, int vertex_id, out vec2 out_sspos, out vec4 out_
}
else {
if (use_custom_color) {
/* Custom color: current frame color is slightly darker than user selected color */
out_finalcolor.rgb = customColor * 0.5;
out_finalcolor.rgb = colorCurrentFrame.rgb;
}
else {
/* green - on frameCurrent */
if (selected) {
intensity = 0.92f;
}
else {
intensity = 0.75f;
}
out_finalcolor.rgb = mix(colorBackground.rgb, blend_base, intensity);
out_finalcolor.rgb = mix(colorCurrentFrame.rgb, blend_base, intensity);
}
}
out_finalcolor.a = 1.0;
}

@ -16,8 +16,8 @@ void main()
gl_PointSize = float(pointSize + 2);
int frame = gl_VertexID + cacheStart;
bool use_custom_color = customColor.x >= 0.0;
finalColor = (use_custom_color) ? vec4(customColor, 1.0) : colorVertex;
bool use_custom_color = customColorPre.x >= 0.0;
finalColor = (use_custom_color) ? vec4(customColorPre, 1.0) : colorVertex;
/* Bias to reduce z fighting with the path */
gl_Position.z -= 1e-4;
@ -26,22 +26,33 @@ void main()
gl_PointSize = float(pointSize) + 4;
}
if (showKeyFrames) {
if ((flag & MOTIONPATH_VERT_KEY) != 0u) {
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
*/
/* Draw special dot where the current frame is. */
if (frame == frameCurrent) {
gl_PointSize = float(pointSize + 8);
finalColor = colorCurrentFrame;
/* Bias more to get these on top of keyframes */
gl_Position.z -= 1e-4;
}
else if (frame < frameCurrent) {
if (use_custom_color) {
finalColor = vec4(customColorPre, 1.0);
}
}
else {
/* frame > frameCurrent */
if (use_custom_color) {
finalColor = vec4(customColorPost, 1.0);
}
}
if (showKeyFrames) {
/* Overrides the color to highlight points that are keyframes. */
if ((flag & MOTIONPATH_VERT_KEY) != 0u) {
gl_PointSize = float(pointSize + 5);
finalColor = colorVertexSelect;
/* Bias more to get these on top of regular points */
gl_Position.z -= 1e-4;
}
}
gl_PointSize *= sizePixel;

@ -75,11 +75,13 @@ typedef struct bMotionPath {
/** Optional custom color. */
float color[3];
float color_post[3];
/** Line thickness. */
int line_thickness;
/** Baking settings - eMotionPath_Flag. */
int flag;
char _pad2[4];
/* Used for drawing. */
GPUVertBufHandle *points_vbo;
GPUBatchHandle *batch_line;

@ -157,7 +157,15 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
/* Custom Color */
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Color", "Custom color for motion path");
RNA_def_property_ui_text(
prop, "Color Pre", "Custom color for motion path before the current frame");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW_ANIMVIZ, nullptr);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "color_post", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(
prop, "Color Post", "Custom color for motion path after the current frame");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW_ANIMVIZ, nullptr);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);