diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 16 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 7 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 4 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_interpolate.c | 224 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 29 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 86 |
6 files changed, 360 insertions, 6 deletions
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 39a97b08df1..69d3b4db54c 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -287,13 +287,16 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) ts->imapaint.paintcursor = NULL; id_us_plus((ID *)ts->imapaint.stencil); ts->particle.paintcursor = NULL; + /* duplicate Grease Pencil Drawing Brushes */ BLI_listbase_clear(&ts->gp_brushes); for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) { bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush); BLI_addtail(&ts->gp_brushes, newbrush); } - + + /* duplicate Grease Pencil interpolation curve */ + ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo); } /* make a private copy of the avicodecdata */ @@ -440,12 +443,17 @@ void BKE_scene_free(Scene *sce) BKE_paint_free(&sce->toolsettings->uvsculpt->paint); MEM_freeN(sce->toolsettings->uvsculpt); } + BKE_paint_free(&sce->toolsettings->imapaint.paint); + /* free Grease Pencil Drawing Brushes */ BKE_gpencil_free_brushes(&sce->toolsettings->gp_brushes); BLI_freelistN(&sce->toolsettings->gp_brushes); - - BKE_paint_free(&sce->toolsettings->imapaint.paint); - + + /* free Grease Pencil interpolation curve */ + if (sce->toolsettings->gp_interpolate.custom_ipo) { + curvemapping_free(sce->toolsettings->gp_interpolate.custom_ipo); + } + MEM_freeN(sce->toolsettings); sce->toolsettings = NULL; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a63b9ed7d19..61f19657349 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5932,6 +5932,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) sce->toolsettings->wpaint->wpaint_prev = NULL; sce->toolsettings->wpaint->tot = 0; } + /* relink grease pencil drawing brushes */ link_list(fd, &sce->toolsettings->gp_brushes); for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) { @@ -5948,6 +5949,12 @@ static void direct_link_scene(FileData *fd, Scene *sce) direct_link_curvemapping(fd, brush->cur_jitter); } } + + /* relink grease pencil interpolation curves */ + sce->toolsettings->gp_interpolate.custom_ipo = newdataadr(fd, sce->toolsettings->gp_interpolate.custom_ipo); + if (sce->toolsettings->gp_interpolate.custom_ipo) { + direct_link_curvemapping(fd, sce->toolsettings->gp_interpolate.custom_ipo); + } } if (sce->ed) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ad1999c0bc7..7b8b95f0005 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2691,6 +2691,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_curvemapping(wd, brush->cur_jitter); } } + /* write grease-pencil custom ipo curve to file */ + if (tos->gp_interpolate.custom_ipo) { + write_curvemapping(wd, tos->gp_interpolate.custom_ipo); + } write_paint(wd, &tos->imapaint.paint); diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index ca511493536..287a6f214c0 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -38,19 +38,22 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_easing.h" +#include "BLI_math.h" #include "BLT_translation.h" +#include "DNA_color_types.h" +#include "DNA_gpencil_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "DNA_gpencil_types.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -681,6 +684,209 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) /* ****************** Interpolate Sequence *********************** */ +/* Helper: Perform easing equation calculations for GP interpolation operator */ +static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_settings, float time) +{ + const float begin = 0.0f; + const float change = 1.0f; + const float duration = 1.0f; + + const float back = ipo_settings->back; + const float amplitude = ipo_settings->amplitude; + const float period = ipo_settings->period; + + eBezTriple_Easing easing = ipo_settings->easing; + float result = time; + + switch (ipo_settings->type) { + case GP_IPO_BACK: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_back_ease_in(time, begin, change, duration, back); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_back_ease_out(time, begin, change, duration, back); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_back_ease_in_out(time, begin, change, duration, back); + break; + + default: /* default/auto: same as ease out */ + result = BLI_easing_back_ease_out(time, begin, change, duration, back); + break; + } + break; + + case GP_IPO_BOUNCE: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_bounce_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_bounce_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_bounce_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease out */ + result = BLI_easing_bounce_ease_out(time, begin, change, duration); + break; + } + break; + + case BEZT_IPO_CIRC: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_circ_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_circ_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_circ_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_circ_ease_in(time, begin, change, duration); + break; + } + break; + + case BEZT_IPO_CUBIC: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_cubic_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_cubic_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_cubic_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_cubic_ease_in(time, begin, change, duration); + break; + } + break; + + case GP_IPO_ELASTIC: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period); + break; + + default: /* default/auto: same as ease out */ + result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); + break; + } + break; + + case GP_IPO_EXPO: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_expo_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_expo_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_expo_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_expo_ease_in(time, begin, change, duration); + break; + } + break; + + case GP_IPO_QUAD: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_quad_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_quad_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_quad_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_quad_ease_in(time, begin, change, duration); + break; + } + break; + + case GP_IPO_QUART: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_quart_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_quart_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_quart_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_quart_ease_in(time, begin, change, duration); + break; + } + break; + + case GP_IPO_QUINT: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_quint_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_quint_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_quint_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_quint_ease_in(time, begin, change, duration); + break; + } + break; + + case GP_IPO_SINE: + switch (easing) { + case BEZT_IPO_EASE_IN: + result = BLI_easing_sine_ease_in(time, begin, change, duration); + break; + case BEZT_IPO_EASE_OUT: + result = BLI_easing_sine_ease_out(time, begin, change, duration); + break; + case BEZT_IPO_EASE_IN_OUT: + result = BLI_easing_sine_ease_in_out(time, begin, change, duration); + break; + + default: /* default/auto: same as ease in */ + result = BLI_easing_sine_ease_in(time, begin, change, duration); + break; + } + break; + + default: + printf("%s: Unknown interpolation type - %d\n", __func__, ipo_settings->type); + break; + } + + return result; +} + static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) { bGPdata *gpd = CTX_data_gpencil_data(C); @@ -730,6 +936,20 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) /* get interpolation factor */ factor = (float)(cframe - prevFrame->framenum) / (nextFrame->framenum - prevFrame->framenum + 1); + if (ipo_settings->type == GP_IPO_CURVEMAP) { + /* custom curvemap */ + if (ipo_settings->custom_ipo) { + factor = curvemapping_evaluateF(ipo_settings->custom_ipo, 0, factor); + } + else { + BKE_report(op->reports, RPT_ERROR, "Custom interpolation curve does not exist"); + } + } + else if (ipo_settings->type >= GP_IPO_BACK) { + /* easing equation... */ + factor = gp_interpolate_seq_easing_calc(ipo_settings, factor); + } + /* create new strokes data with interpolated points reading original stroke */ for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) { bGPDstroke *new_stroke; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 4d09457b3cc..8ee15ef21a3 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1218,6 +1218,14 @@ typedef enum eGP_BrushEdit_SettingsFlag { /* Settings for GP Interpolation Operators */ typedef struct GP_Interpolate_Settings { short flag; /* eGP_Interpolate_SettingsFlag */ + + char type; /* eGP_Interpolate_Type - Interpolation Mode */ + char easing; /* eBezTriple_Easing - Easing mode (if easing equation used) */ + + float back; /* BEZT_IPO_BACK */ + float amplitude, period; /* BEZT_IPO_ELASTIC */ + + struct CurveMapping *custom_ipo; /* custom interpolation curve (for use with GP_IPO_CURVEMAP) */ } GP_Interpolate_Settings; /* GP_Interpolate_Settings.flag */ @@ -1228,6 +1236,27 @@ typedef enum eGP_Interpolate_SettingsFlag { GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED = (1 << 1), } eGP_Interpolate_SettingsFlag; +/* GP_Interpolate_Settings.type */ +typedef enum eGP_Interpolate_Type { + /* Traditional Linear Interpolation */ + GP_IPO_LINEAR = 0, + + /* CurveMap Defined Interpolation */ + GP_IPO_CURVEMAP = 1, + + /* Easing Equations */ + GP_IPO_BACK = 3, + GP_IPO_BOUNCE = 4, + GP_IPO_CIRC = 5, + GP_IPO_CUBIC = 6, + GP_IPO_ELASTIC = 7, + GP_IPO_EXPO = 8, + GP_IPO_QUAD = 9, + GP_IPO_QUART = 10, + GP_IPO_QUINT = 11, + GP_IPO_SINE = 12, +} eGP_Interpolate_Type; + /* *************************************************************** */ /* Transform Orientations */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 8f5304c8f0c..1166fb89a0a 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -407,9 +407,34 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { + /* interpolation */ + {0, "", 0, N_("Interpolation"), "Standard transitions between keyframes"}, + {GP_IPO_LINEAR, "LINEAR", ICON_IPO_LINEAR, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"}, + {GP_IPO_CURVEMAP, "CUSTOM", ICON_IPO_BEZIER, "Custom", "Custom interpolation defined using a curvemap"}, + + /* easing */ + {0, "", 0, N_("Easing (by strength)"), "Predefined inertial transitions, useful for motion graphics (from least to most ''dramatic'')"}, + {GP_IPO_SINE, "SINE", ICON_IPO_SINE, "Sinusoidal", "Sinusoidal easing (weakest, almost linear but with a slight curvature)"}, + {GP_IPO_QUAD, "QUAD", ICON_IPO_QUAD, "Quadratic", "Quadratic easing"}, + {GP_IPO_CUBIC, "CUBIC", ICON_IPO_CUBIC, "Cubic", "Cubic easing"}, + {GP_IPO_QUART, "QUART", ICON_IPO_QUART, "Quartic", "Quartic easing"}, + {GP_IPO_QUINT, "QUINT", ICON_IPO_QUINT, "Quintic", "Quintic easing"}, + {GP_IPO_EXPO, "EXPO", ICON_IPO_EXPO, "Exponential", "Exponential easing (dramatic)"}, + {GP_IPO_CIRC, "CIRC", ICON_IPO_CIRC, "Circular", "Circular easing (strongest and most dynamic)"}, + + {0, "", 0, N_("Dynamic Effects"), "Simple physics-inspired easing effects"}, + {GP_IPO_BACK, "BACK", ICON_IPO_BACK, "Back", "Cubic easing with overshoot and settle"}, + {GP_IPO_BOUNCE, "BOUNCE", ICON_IPO_BOUNCE, "Bounce", "Exponentially decaying parabolic bounce, like when objects collide"}, + {GP_IPO_ELASTIC, "ELASTIC", ICON_IPO_ELASTIC, "Elastic", "Exponentially decaying sine wave, like an elastic band"}, + + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "DNA_anim_types.h" +#include "DNA_color_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" @@ -420,6 +445,7 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { #include "MEM_guardedalloc.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" @@ -453,6 +479,23 @@ static char *rna_GPencilInterpolateSettings_path(PointerRNA *UNUSED(ptr)) return BLI_strdup("tool_settings.gpencil_interpolate"); } +static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value) +{ + GP_Interpolate_Settings *settings = (GP_Interpolate_Settings *)ptr->data; + + /* NOTE: This cast should be fine, as we have a small + finite set of values (eGP_Interpolate_Type) + * that should fit well within a char + */ + settings->type = (char)value; + + /* init custom interpolation curve here now the first time it's used */ + if ((settings->type == GP_IPO_CURVEMAP) && + (settings->custom_ipo == NULL)) + { + settings->custom_ipo = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + } +} + /* Grease pencil Drawing Brushes */ static bGPDbrush *rna_GPencil_brush_new(ToolSettings *ts, const char *name, int setactive) { @@ -2166,6 +2209,49 @@ static void rna_def_gpencil_interpolate(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED); RNA_def_property_ui_text(prop, "Interpolate Selected Strokes", "Interpolate only selected strokes in the original frame"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + /* interpolation type */ + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, rna_enum_gpencil_interpolation_mode_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_GPencilInterpolateSettings_type_set", NULL); + RNA_def_property_ui_text(prop, "Type", + "Interpolation method to use the next time 'Interpolate Sequence' is run"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + /* easing */ + prop = RNA_def_property(srna, "easing", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "easing"); + RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_easing_items); + RNA_def_property_ui_text(prop, "Easing", + "Which ends of the segment between the preceding and following grease pencil frames " + "easing interpolation is applied to"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + /* easing options */ + prop = RNA_def_property(srna, "back", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "back"); + RNA_def_property_ui_text(prop, "Back", "Amount of overshoot for 'back' easing"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "amplitude"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); /* only positive values... */ + RNA_def_property_ui_text(prop, "Amplitude", "Amount to boost elastic bounces for 'elastic' easing"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "period"); + RNA_def_property_ui_text(prop, "Period", "Time between bounces for elastic easing"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); + + /* custom curvemap */ + prop = RNA_def_property(srna, "interpolation_curve", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "custom_ipo"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Interpolation Curve", + "Custom curve to control 'sequence' interpolation between Grease Pencil frames"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); } /* Grease Pencil Drawing Brushes */ |