diff options
Diffstat (limited to 'source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c')
-rw-r--r-- | source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c | 211 |
1 files changed, 201 insertions, 10 deletions
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c index 1d45030b68b..b04fdeb0a83 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c @@ -9,6 +9,11 @@ #include <stdlib.h> #include <string.h> +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -16,20 +21,33 @@ #include "DNA_defaults.h" #include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "BKE_context.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_main.h" +#include "BKE_modifier.h" #include "BKE_screen.h" -#include "UI_interface.h" -#include "UI_resources.h" - #include "RNA_access.h" +#include "RNA_prototypes.h" #include "MOD_gpencil_modifiertypes.h" #include "MOD_gpencil_ui_common.h" +#include "MOD_gpencil_util.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "WM_api.h" + +#include "DEG_depsgraph.h" static void initData(GpencilModifierData *md) { @@ -38,11 +56,26 @@ static void initData(GpencilModifierData *md) BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier)); MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(TimeGpencilModifierData), modifier); + TimeGpencilModifierSegment *ds = DNA_struct_default_alloc(TimeGpencilModifierSegment); + ds->gpmd = gpmd; + BLI_strncpy(ds->name, DATA_("Segment"), sizeof(ds->name)); + + gpmd->segments = ds; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { + TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)target; + const TimeGpencilModifierData *gpmd_src = (const TimeGpencilModifierData *)md; BKE_gpencil_modifier_copydata_generic(md, target); + gpmd->segments = MEM_dupallocN(gpmd_src->segments); +} + +static void freeData(GpencilModifierData *md) +{ + TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)md; + + MEM_SAFE_FREE(gpmd->segments); } static int remapTime(struct GpencilModifierData *md, @@ -60,6 +93,7 @@ static int remapTime(struct GpencilModifierData *md, int efra = custom ? mmd->efra : scene->r.efra; int offset = mmd->offset; int nfra = 0; + CLAMP_MIN(sfra, 0); CLAMP_MIN(efra, 0); @@ -100,6 +134,7 @@ static int remapTime(struct GpencilModifierData *md, /* apply frame scale */ cfra *= mmd->frame_scale; + CLAMP_MIN(cfra, 1); /* if fix mode, return predefined frame number */ if (mmd->mode == GP_TIME_MODE_FIX) { @@ -146,10 +181,111 @@ static int remapTime(struct GpencilModifierData *md, } } + if (mmd->mode == GP_TIME_MODE_CHAIN) { + int sequence_length = 0; + int frame_key = 0; + int *segment_arr; + int start, end; + if (mmd->segments_len > 0) { + for (int i = 0; i < mmd->segments_len; i++) { + start = mmd->segments[i].seg_start; + end = mmd->segments[i].seg_end; + if (mmd->segments[i].seg_end < mmd->segments[i].seg_start) { + start = mmd->segments[i].seg_end; + end = mmd->segments[i].seg_start; + } + + if (ELEM(mmd->segments[i].seg_mode, GP_TIME_SEG_MODE_PINGPONG)) { + sequence_length += ((end - start) * mmd->segments[i].seg_repeat) * 2 + 1; + } + else { + sequence_length += ((end - start + 1) * mmd->segments[i].seg_repeat); + } + } + segment_arr = MEM_malloc_arrayN(sequence_length, sizeof(int *), __func__); + + for (int i = 0; i < mmd->segments_len; i++) { + + if (mmd->segments[i].seg_end < mmd->segments[i].seg_start) { + start = mmd->segments[i].seg_end; + end = mmd->segments[i].seg_start; + } + else { + start = mmd->segments[i].seg_start; + end = mmd->segments[i].seg_end; + } + for (int a = 0; a < mmd->segments[i].seg_repeat; a++) { + switch (mmd->segments[i].seg_mode) { + case GP_TIME_SEG_MODE_NORMAL: + for (int b = 0; b < end - start + 1; b++) { + segment_arr[frame_key] = start + b; + frame_key++; + } + break; + case GP_TIME_SEG_MODE_REVERSE: + for (int b = 0; b < end - start + 1; b++) { + segment_arr[frame_key] = end - b; + frame_key++; + } + break; + case GP_TIME_SEG_MODE_PINGPONG: + for (int b = 0; b < end - start; b++) { + segment_arr[frame_key] = start + b; + frame_key++; + } + for (int b = 0; b < end - start; b++) { + segment_arr[frame_key] = end - b; + frame_key++; + if (a == mmd->segments[i].seg_repeat - 1 && b == end - start - 1) { + segment_arr[frame_key] = start; + frame_key++; + } + } + break; + } + } + } + + if ((mmd->flag & GP_TIME_KEEP_LOOP) == 0) { + if ((cfra + offset - 1) < sequence_length) { + nfra = segment_arr[(cfra - 1 + offset)]; + } + else { + nfra = segment_arr[frame_key - 1]; + } + } + else { + nfra = segment_arr[(cfra - 1 + offset) % sequence_length]; + } + + MEM_freeN(segment_arr); + } + } + return nfra; } -static void panel_draw(const bContext *UNUSED(C), Panel *panel) +static void segment_list_item(struct uiList *UNUSED(ui_list), + const struct bContext *UNUSED(C), + struct uiLayout *layout, + struct PointerRNA *UNUSED(idataptr), + struct PointerRNA *itemptr, + int UNUSED(icon), + struct PointerRNA *UNUSED(active_dataptr), + const char *UNUSED(active_propname), + int UNUSED(index), + int UNUSED(flt_flag)) +{ + uiLayout *row = uiLayoutRow(layout, true); + uiItemR(row, itemptr, "name", UI_ITEM_R_NO_BG, "", ICON_NONE); +} +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + TimeGpencilModifierData *mmd = (TimeGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} +static void panel_draw(const bContext *C, Panel *panel) { uiLayout *row, *col; uiLayout *layout = panel->layout; @@ -175,6 +311,56 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetActive(row, mode != GP_TIME_MODE_FIX); uiItemR(row, ptr, "use_keep_loop", 0, NULL, ICON_NONE); + if (mode == GP_TIME_MODE_CHAIN) { + + row = uiLayoutRow(layout, false); + uiLayoutSetPropSep(row, false); + + uiTemplateList(row, + (bContext *)C, + "MOD_UL_time_segment", + "", + ptr, + "segments", + ptr, + "segment_active_index", + NULL, + 3, + 10, + 0, + 1, + UI_TEMPLATE_LIST_FLAG_NONE); + + col = uiLayoutColumn(row, false); + uiLayoutSetContextPointer(col, "modifier", ptr); + + uiLayout *sub = uiLayoutColumn(col, true); + uiItemO(sub, "", ICON_ADD, "GPENCIL_OT_time_segment_add"); + uiItemO(sub, "", ICON_REMOVE, "GPENCIL_OT_time_segment_remove"); + uiItemS(col); + sub = uiLayoutColumn(col, true); + uiItemEnumO_string(sub, "", ICON_TRIA_UP, "GPENCIL_OT_time_segment_move", "type", "UP"); + uiItemEnumO_string(sub, "", ICON_TRIA_DOWN, "GPENCIL_OT_time_segment_move", "type", "DOWN"); + + TimeGpencilModifierData *gpmd = ptr->data; + if (gpmd->segment_active_index >= 0 && gpmd->segment_active_index < gpmd->segments_len) { + PointerRNA ds_ptr; + RNA_pointer_create(ptr->owner_id, + &RNA_TimeGpencilModifierSegment, + &gpmd->segments[gpmd->segment_active_index], + &ds_ptr); + + sub = uiLayoutColumn(layout, true); + uiItemR(sub, &ds_ptr, "seg_mode", 0, NULL, ICON_NONE); + sub = uiLayoutColumn(layout, true); + uiItemR(sub, &ds_ptr, "seg_start", 0, NULL, ICON_NONE); + uiItemR(sub, &ds_ptr, "seg_end", 0, NULL, ICON_NONE); + uiItemR(sub, &ds_ptr, "seg_repeat", 0, NULL, ICON_NONE); + } + + gpencil_modifier_panel_end(layout, ptr); + } + gpencil_modifier_panel_end(layout, ptr); } @@ -186,7 +372,7 @@ static void custom_range_header_draw(const bContext *UNUSED(C), Panel *panel) int mode = RNA_enum_get(ptr, "mode"); - uiLayoutSetActive(layout, mode != GP_TIME_MODE_FIX); + uiLayoutSetActive(layout, (mode != GP_TIME_MODE_FIX && mode != GP_TIME_MODE_CHAIN)); uiItemR(layout, ptr, "use_custom_frame_range", 0, NULL, ICON_NONE); } @@ -201,9 +387,9 @@ static void custom_range_panel_draw(const bContext *UNUSED(C), Panel *panel) int mode = RNA_enum_get(ptr, "mode"); uiLayoutSetPropSep(layout, true); - - uiLayoutSetActive( - layout, (mode != GP_TIME_MODE_FIX) && (RNA_boolean_get(ptr, "use_custom_frame_range"))); + uiLayoutSetActive(layout, + (mode != GP_TIME_MODE_FIX && mode != GP_TIME_MODE_CHAIN) && + RNA_boolean_get(ptr, "use_custom_frame_range")); col = uiLayoutColumn(layout, true); uiItemR(col, ptr, "frame_start", 0, IFACE_("Frame Start"), ICON_NONE); @@ -227,6 +413,11 @@ static void panelRegister(ARegionType *region_type) panel_type); gpencil_modifier_subpanel_register( region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); + + uiListType *list_type = MEM_callocN(sizeof(uiListType), "time modifier segment uilist"); + strcpy(list_type->idname, "MOD_UL_time_segment"); + list_type->draw_item = segment_list_item; + WM_uilisttype_add(list_type); } GpencilModifierTypeInfo modifierType_Gpencil_Time = { @@ -244,11 +435,11 @@ GpencilModifierTypeInfo modifierType_Gpencil_Time = { /* remapTime */ remapTime, /* initData */ initData, - /* freeData */ NULL, + /* freeData */ freeData, /* isDisabled */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, /* panelRegister */ panelRegister, }; |