D1873: Customize style for animation motion paths

New options to define the style of the animation paths in order to get
better visibility in complex scenes.

Now is possible define the color, thickness and several options relative
to the style of the lines used to draw motion path.
This commit is contained in:
Antonio Vazquez 2017-01-20 16:49:14 +01:00
parent 1ad04c7d65
commit 404e59c842
6 changed files with 217 additions and 64 deletions

View File

@ -86,8 +86,12 @@ class MotionPathButtonsPanel:
col = split.column()
col.label(text="Show:")
col.prop(mps, "show_frame_numbers", text="Frame Numbers")
if mpath is not None:
col.prop(mpath, "lines", text='Lines')
col.prop(mpath, "line_thickness", text='Thickness')
col = split.column()
col.label('')
col.prop(mps, "show_keyframe_highlight", text="Keyframes")
sub = col.column()
sub.enabled = mps.show_keyframe_highlight
@ -95,6 +99,14 @@ class MotionPathButtonsPanel:
sub.prop(mps, "show_keyframe_action_all", text="+ Non-Grouped Keyframes")
sub.prop(mps, "show_keyframe_numbers", text="Keyframe Numbers")
# Customize path
if mpath is not None:
row = layout.row(align=True)
row.prop(mpath, "use_custom_color", text='', toggle=True, icon='COLOR')
sub = row.row(align=True)
sub.enabled = mpath.use_custom_color
sub.prop(mpath, "color", text='')
# FIXME: this panel still needs to be ported so that it will work correctly with animviz
class OnionSkinButtonsPanel:

View File

@ -201,7 +201,15 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec
mpath->flag |= MOTIONPATH_FLAG_BHEAD;
else
mpath->flag &= ~MOTIONPATH_FLAG_BHEAD;
/* set default custom values */
mpath->color[0] = 1.0; /* Red */
mpath->color[1] = 0.0;
mpath->color[2] = 0.0;
mpath->line_thickness = 1;
mpath->flag |= MOTIONPATH_FLAG_LINES; /* draw lines by default */
/* allocate a cache */
mpath->points = MEM_callocN(sizeof(bMotionPathVert) * mpath->length, "bMotionPathVerts");

View File

@ -1474,6 +1474,36 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
for (Brush *br = main->brush.first; br; br = br->id.next) {
br->fill_threshold /= sqrt_3;
}
/* Custom motion paths */
if (!DNA_struct_elem_find(fd->filesdna, "bMotionPath", "int", "line_thickness")) {
Object *ob;
for (ob = main->object.first; ob; ob = ob->id.next) {
bMotionPath *mpath;
bPoseChannel *pchan;
mpath = ob->mpath;
if (mpath) {
mpath->color[0] = 1.0f;
mpath->color[1] = 0.0f;
mpath->color[2] = 0.0f;
mpath->line_thickness = 1;
mpath->flag |= MOTIONPATH_FLAG_LINES;
}
/* bones motion path */
if (ob->pose) {
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
mpath = pchan->mpath;
if (mpath) {
mpath->color[0] = 1.0f;
mpath->color[1] = 0.0f;
mpath->color[2] = 0.0f;
mpath->line_thickness = 1;
mpath->flag |= MOTIONPATH_FLAG_LINES;
}
}
}
}
}
}
/* To be added to next subversion bump! */

View File

@ -75,6 +75,80 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar)
glLoadMatrixf(rv3d->viewmat);
}
/* set color
* - more intense for active/selected bones, less intense for unselected bones
* - black for before current frame, green for current frame, blue for after current frame
* - intensity decreases as distance from current frame increases
*
* If the user select custom color, the color is replaced for the color selected in UI panel
* - 75% Darker color is used for previous frames
* - 50% Darker color for current frame
* - User selected color for next frames
*/
void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra,
float prev_color[3], float frame_color[3], float next_color[3])
{
int frame = sfra + i;
int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
float intensity; /* how faint */
if (frame < CFRA) {
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
/* Custom color: previous frames color is darker than current frame */
glColor3fv(prev_color);
}
else {
/* black - before cfra */
if (sel) {
/* intensity = 0.5f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
}
else {
/* intensity = 0.8f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
}
UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
}
}
else if (frame > CFRA) {
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
/* Custom color: next frames color is equal to user selected color */
glColor3fv(next_color);
}
else {
/* blue - after cfra */
if (sel) {
/* intensity = 0.5f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
}
else {
/* intensity = 0.8f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
}
UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
}
}
else {
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
/* Custom color: current frame color is slightly darker than user selected color */
glColor3fv(frame_color);
}
else {
/* green - on cfra */
if (sel) {
intensity = 0.5f;
}
else {
intensity = 0.99f;
}
UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
}
}
#undef SET_INTENSITY
}
/* Draw the given motion path for an Object or a Bone
* - assumes that the viewport has already been initialized properly
* i.e. draw_motion_paths_init() has been called
@ -86,6 +160,28 @@ void draw_motion_path_instance(Scene *scene,
bMotionPathVert *mpv, *mpv_start;
int i, stepsize = avs->path_step;
int sfra, efra, sind, len;
float prev_color[3];
float frame_color[3];
float next_color[3];
/* Custom color - Previous frames: color is darker than current frame */
prev_color[0] = mpath->color[0] * 0.25f;
prev_color[1] = mpath->color[1] * 0.25f;
prev_color[2] = mpath->color[2] * 0.25f;
/* Custom color - Current frame: color is slightly darker than user selected color */
frame_color[0] = mpath->color[0] * 0.50f;
frame_color[1] = mpath->color[1] * 0.50f;
frame_color[2] = mpath->color[2] * 0.50f;
/* Custom color - Next frames: color is equal to user selection */
next_color[0] = mpath->color[0];
next_color[1] = mpath->color[1];
next_color[2] = mpath->color[2];
/* Save old line width */
GLfloat old_width;
glGetFloatv(GL_LINE_WIDTH, &old_width);
/* get frame ranges */
if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
@ -130,64 +226,27 @@ void draw_motion_path_instance(Scene *scene,
mpv_start = (mpath->points + sind);
/* draw curve-line of path */
glBegin(GL_LINE_STRIP);
for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
float intensity; /* how faint */
int frame = sfra + i;
int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
/* set color
* - more intense for active/selected bones, less intense for unselected bones
* - black for before current frame, green for current frame, blue for after current frame
* - intensity decreases as distance from current frame increases
*/
#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
if (frame < CFRA) {
/* black - before cfra */
if (sel) {
/* intensity = 0.5f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
}
else {
/* intensity = 0.8f; */
intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
}
UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
}
else if (frame > CFRA) {
/* blue - after cfra */
if (sel) {
/* intensity = 0.5f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
}
else {
/* intensity = 0.8f; */
intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
}
UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
}
else {
/* green - on cfra */
if (sel) {
intensity = 0.5f;
}
else {
intensity = 0.99f;
}
UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
}
#undef SET_INTENSITY
/* Draw lines only if line drawing option is enabled */
if (mpath->flag & MOTIONPATH_FLAG_LINES) {
/* set line thickness */
glLineWidth(mpath->line_thickness);
/* draw a vertex with this color */
glVertex3fv(mpv->co);
glBegin(GL_LINE_STRIP);
for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
/* Set color */
set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color);
/* draw a vertex with this color */
glVertex3fv(mpv->co);
}
glEnd();
/* back to old line thickness */
glLineWidth(old_width);
}
glEnd();
glPointSize(1.0);
/* Point must be bigger than line thickness */
glPointSize(mpath->line_thickness + 1.0);
/* draw little black point at each frame
* NOTE: this is not really visible/noticeable
@ -197,8 +256,13 @@ void draw_motion_path_instance(Scene *scene,
glVertex3fv(mpv->co);
glEnd();
/* Draw little white dots at each framestep value */
UI_ThemeColor(TH_TEXT_HI);
/* Draw little white dots at each framestep value or replace with custom color */
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
glColor4fv(mpath->color);
}
else {
UI_ThemeColor(TH_TEXT_HI);
}
glBegin(GL_POINTS);
for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize)
glVertex3fv(mpv->co);
@ -208,11 +272,11 @@ void draw_motion_path_instance(Scene *scene,
* NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
*/
if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) &&
(sfra < CFRA) && (CFRA <= efra))
(sfra < CFRA) && (CFRA <= efra))
{
UI_ThemeColor(TH_CFRAME);
glPointSize(6.0f);
glPointSize(mpath->line_thickness + 5.0);
glBegin(GL_POINTS);
mpv = mpv_start + (CFRA - sfra);
glVertex3fv(mpv->co);
@ -289,7 +353,13 @@ void draw_motion_path_instance(Scene *scene,
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
col[3] = 255;
glPointSize(4.0f);
/* if custom, point must be bigger than line */
if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
glPointSize(mpath->line_thickness + 3.0);
}
else {
glPointSize(4.0f);
}
glColor3ubv(col);
glBegin(GL_POINTS);

View File

@ -76,6 +76,8 @@ typedef struct bMotionPath {
int start_frame; /* for drawing paths, the start frame number */
int end_frame; /* for drawing paths, the end frame number */
float color[3]; /* optional custom color */
int line_thickness; /* line thickness */
int flag; /* baking settings - eMotionPath_Flag */
} bMotionPath;
@ -84,7 +86,11 @@ typedef enum eMotionPath_Flag {
/* (for bones) path represents the head of the bone */
MOTIONPATH_FLAG_BHEAD = (1 << 0),
/* motion path is being edited */
MOTIONPATH_FLAG_EDIT = (1 << 1)
MOTIONPATH_FLAG_EDIT = (1 << 1),
/* Custom colors */
MOTIONPATH_FLAG_CUSTOM = (1 << 2),
/* Draw lines or only points */
MOTIONPATH_FLAG_LINES = (1 << 3)
} eMotionPath_Flag;
/* Visualization General --------------------------- */

View File

@ -153,7 +153,20 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
prop = RNA_def_property(srna, "length", PROP_INT, PROP_TIME);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Length", "Number of frames cached");
/* 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_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* Line width */
prop = RNA_def_property(srna, "line_thickness", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "line_thickness");
RNA_def_property_range(prop, 1, 6);
RNA_def_property_ui_text(prop, "Line thickness", "Line thickness for drawing path");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* Settings */
prop = RNA_def_property(srna, "use_bone_head", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_BHEAD);
@ -164,6 +177,19 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
prop = RNA_def_property(srna, "is_modified", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_EDIT);
RNA_def_property_ui_text(prop, "Edit Path", "Path is being edited");
/* Use custom color */
prop = RNA_def_property(srna, "use_custom_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_CUSTOM);
RNA_def_property_ui_text(prop, "Custom colors", "Use custom color for this motion path");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
/* Draw lines between keyframes */
prop = RNA_def_property(srna, "lines", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_LINES);
RNA_def_property_ui_text(prop, "Lines", "Draw straight lines between keyframe points");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
/* --- */
@ -337,6 +363,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna)
"Number of frames to show after the current frame "
"(only for 'Around Current Frame' Onion-skinning method)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */
}
/* --- */