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:
authorYimingWu <xp8110@outlook.com>2021-09-15 09:24:28 +0300
committerYimingWu <xp8110@outlook.com>2021-09-15 09:38:32 +0300
commita2c5c2b4068d12e26a8c9d640a389b410c7507f3 (patch)
tree95cecf0a24aee13ffb6feb90892622b8841409cf
parentc1cf66bff3c0753512a2d1f2f8c03430bdd1f045 (diff)
GPencil: Dot dash modifier.
Create dot-dash effect for grease pencil strokes. User can manually edit the length, gap and styles for each segment of dashed lines. The values in each segment can all be key-framed to make animations. Reviewed By: Hans Goudey (HooglyBoogly), Antonio Vazquez (antoniov) Differential Revision: http://developer.blender.org/D11876
m---------release/datafiles/locale0
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c9
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt1
-rw-r--r--source/blender/editors/object/CMakeLists.txt5
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c238
-rw-r--r--source/blender/editors/object/object_intern.h4
-rw-r--r--source/blender/editors/object/object_ops.c4
-rw-r--r--source/blender/gpencil_modifiers/CMakeLists.txt1
-rw-r--r--source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c1
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencildash.c387
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_defaults.h18
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h34
-rw-r--r--source/blender/makesdna/intern/dna_defaults.c4
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c200
m---------source/tools0
19 files changed, 905 insertions, 4 deletions
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 8a05b618f031582c006c6f62b9e60619ab3eef8
+Subproject 62e82958a760dad775d9b3387d7fb535fd6de4c
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject 67f1fbca1482d9d9362a4001332e785c3fd5d23
+Subproject 4475cbd11a636382d57571e0f5dfeff1f90bd6b
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject ef6ef414d22c2578fad99327743b925ab640a99
+Subproject 788441f2930465bbfba8f0797b12dcef1d46694
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index a30376b9bad..b120c901499 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -938,6 +938,11 @@ void BKE_gpencil_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
BKE_curvemapping_blend_write(writer, gpmd->curve_intensity);
}
}
+ else if (md->type == eGpencilModifierType_Dash) {
+ DashGpencilModifierData *gpmd = (DashGpencilModifierData *)md;
+ BLO_write_struct_array(
+ writer, DashGpencilModifierSegment, gpmd->segments_len, gpmd->segments);
+ }
}
}
@@ -1017,6 +1022,10 @@ void BKE_gpencil_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb)
BKE_curvemapping_init(gpmd->curve_intensity);
}
}
+ else if (md->type == eGpencilModifierType_Dash) {
+ DashGpencilModifierData *gpmd = (DashGpencilModifierData *)md;
+ BLO_read_data_address(reader, &gpmd->segments);
+ }
}
}
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 669ceb37328..702fd2e375a 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -336,6 +336,7 @@ set(ICON_NAMES
lightprobe_cubemap
lightprobe_planar
lightprobe_grid
+ mod_dash
color_red
color_green
color_blue
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 18f2b58eb65..040b5cd5066 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -37,6 +37,9 @@ set(INC
../../../../intern/clog
../../../../intern/glew-mx
../../../../intern/guardedalloc
+
+ # dna_type_offsets.h in BLO_read_write.h
+ ${CMAKE_BINARY_DIR}/source/blender/makesdna/intern
)
set(SRC
@@ -93,3 +96,5 @@ if(WITH_EXPERIMENTAL_FEATURES)
endif()
blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
+
+add_dependencies(bf_editor_object bf_dna)
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index 3995728c428..e3c2932e17a 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -28,6 +28,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_defaults.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
@@ -35,6 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -55,6 +57,8 @@
#include "ED_object.h"
#include "ED_screen.h"
+#include "BLT_translation.h"
+
#include "UI_interface.h"
#include "WM_api.h"
@@ -939,3 +943,237 @@ void OBJECT_OT_gpencil_modifier_copy_to_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
gpencil_edit_modifier_properties(ot);
}
+
+/************************* Dash Modifier *******************************/
+
+static bool dash_segment_poll(bContext *C)
+{
+ return gpencil_edit_modifier_poll_generic(C, &RNA_DashGpencilModifierData, 0, false);
+}
+
+static bool dash_segment_name_exists_fn(void *arg, const char *name)
+{
+ const DashGpencilModifierData *dmd = (const DashGpencilModifierData *)arg;
+ for (int i = 0; i < dmd->segments_len; i++) {
+ if (STREQ(dmd->segments[i].name, name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static int dash_segment_add_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)gpencil_edit_modifier_property_get(
+ op, ob, eGpencilModifierType_Dash);
+
+ const int new_active_index = dmd->segment_active_index + 1;
+ DashGpencilModifierSegment *new_segments = MEM_malloc_arrayN(
+ dmd->segments_len + 1, sizeof(DashGpencilModifierSegment), __func__);
+
+ if (dmd->segments_len != 0) {
+ /* Copy the segments before the new segment. */
+ memcpy(new_segments, dmd->segments, sizeof(DashGpencilModifierSegment) * new_active_index);
+ /* Copy the segments after the new segment. */
+ memcpy(new_segments + new_active_index + 1,
+ dmd->segments + new_active_index,
+ sizeof(DashGpencilModifierSegment) * (dmd->segments_len - new_active_index));
+ }
+
+ /* Create the new segment. */
+ DashGpencilModifierSegment *ds = &new_segments[new_active_index];
+ memcpy(
+ ds, DNA_struct_default_get(DashGpencilModifierSegment), sizeof(DashGpencilModifierSegment));
+ BLI_uniquename_cb(
+ dash_segment_name_exists_fn, dmd, DATA_("Segment"), '.', ds->name, sizeof(ds->name));
+ ds->dmd = dmd;
+
+ MEM_SAFE_FREE(dmd->segments);
+ dmd->segments = new_segments;
+ dmd->segments_len++;
+ dmd->segment_active_index++;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int dash_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op, NULL, NULL)) {
+ return dash_segment_add_exec(C, op);
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void GPENCIL_OT_segment_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Segment";
+ ot->description = "Add a segment to the dash modifier";
+ ot->idname = "GPENCIL_OT_segment_add";
+
+ /* api callbacks */
+ ot->poll = dash_segment_poll;
+ ot->invoke = dash_segment_add_invoke;
+ ot->exec = dash_segment_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+}
+
+static int dash_segment_remove_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)gpencil_edit_modifier_property_get(
+ op, ob, eGpencilModifierType_Dash);
+
+ if (dmd->segment_active_index < 0 || dmd->segment_active_index >= dmd->segments_len) {
+ return OPERATOR_CANCELLED;
+ }
+
+ if (dmd->segments_len == 1) {
+ MEM_SAFE_FREE(dmd->segments);
+ dmd->segment_active_index = -1;
+ }
+ else {
+ DashGpencilModifierSegment *new_segments = MEM_malloc_arrayN(
+ dmd->segments_len, sizeof(DashGpencilModifierSegment), __func__);
+
+ /* Copy the segments before the deleted segment. */
+ memcpy(new_segments,
+ dmd->segments,
+ sizeof(DashGpencilModifierSegment) * dmd->segment_active_index);
+
+ /* Copy the segments after the deleted segment. */
+ memcpy(new_segments + dmd->segment_active_index,
+ dmd->segments + dmd->segment_active_index + 1,
+ sizeof(DashGpencilModifierSegment) *
+ (dmd->segments_len - dmd->segment_active_index - 1));
+
+ MEM_freeN(dmd->segments);
+ dmd->segments = new_segments;
+ dmd->segment_active_index = MAX2(dmd->segment_active_index - 1, 0);
+ }
+
+ dmd->segments_len--;
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int dash_segment_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op, NULL, NULL)) {
+ return dash_segment_remove_exec(C, op);
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void GPENCIL_OT_segment_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Dash Segment";
+ ot->description = "Remove the active segment from the dash modifier";
+ ot->idname = "GPENCIL_OT_segment_remove";
+
+ /* api callbacks */
+ ot->poll = dash_segment_poll;
+ ot->invoke = dash_segment_remove_invoke;
+ ot->exec = dash_segment_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+
+ RNA_def_int(
+ ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of the segment to remove", 0, INT_MAX);
+}
+
+enum {
+ GP_SEGEMENT_MOVE_UP = -1,
+ GP_SEGEMENT_MOVE_DOWN = 1,
+};
+
+static int dash_segment_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)gpencil_edit_modifier_property_get(
+ op, ob, eGpencilModifierType_Dash);
+
+ if (dmd->segments_len < 2) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int direction = RNA_enum_get(op->ptr, "type");
+ if (direction == GP_SEGEMENT_MOVE_UP) {
+ if (dmd->segment_active_index == 0) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SWAP(DashGpencilModifierSegment,
+ dmd->segments[dmd->segment_active_index],
+ dmd->segments[dmd->segment_active_index - 1]);
+
+ dmd->segment_active_index--;
+ }
+ else if (direction == GP_SEGEMENT_MOVE_DOWN) {
+ if (dmd->segment_active_index == dmd->segments_len - 1) {
+ return OPERATOR_CANCELLED;
+ }
+
+ SWAP(DashGpencilModifierSegment,
+ dmd->segments[dmd->segment_active_index],
+ dmd->segments[dmd->segment_active_index + 1]);
+
+ dmd->segment_active_index++;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int dash_segment_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (gpencil_edit_modifier_invoke_properties(C, op, NULL, NULL)) {
+ return dash_segment_move_exec(C, op);
+ }
+ return OPERATOR_CANCELLED;
+}
+
+void GPENCIL_OT_segment_move(wmOperatorType *ot)
+{
+ static const EnumPropertyItem segment_move[] = {
+ {GP_SEGEMENT_MOVE_UP, "UP", 0, "Up", ""},
+ {GP_SEGEMENT_MOVE_DOWN, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Move Dash Segment";
+ ot->description = "Move the active dash segment up or down";
+ ot->idname = "GPENCIL_OT_segment_move";
+
+ /* api callbacks */
+ ot->poll = dash_segment_poll;
+ ot->invoke = dash_segment_move_invoke;
+ ot->exec = dash_segment_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+
+ ot->prop = RNA_def_enum(ot->srna, "type", segment_move, 0, "Type", "");
+}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 10e016738d0..b2d3216b101 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -202,6 +202,10 @@ void OBJECT_OT_gpencil_modifier_apply(struct wmOperatorType *ot);
void OBJECT_OT_gpencil_modifier_copy(struct wmOperatorType *ot);
void OBJECT_OT_gpencil_modifier_copy_to_selected(struct wmOperatorType *ot);
+void GPENCIL_OT_segment_add(struct wmOperatorType *ot);
+void GPENCIL_OT_segment_remove(struct wmOperatorType *ot);
+void GPENCIL_OT_segment_move(struct wmOperatorType *ot);
+
/* object_shader_fx.c */
void OBJECT_OT_shaderfx_add(struct wmOperatorType *ot);
void OBJECT_OT_shaderfx_copy(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index c1928cf7f8a..4b8431be530 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -156,6 +156,10 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy);
WM_operatortype_append(OBJECT_OT_gpencil_modifier_copy_to_selected);
+ WM_operatortype_append(GPENCIL_OT_segment_add);
+ WM_operatortype_append(GPENCIL_OT_segment_remove);
+ WM_operatortype_append(GPENCIL_OT_segment_move);
+
/* grease pencil line art */
WM_operatortypes_lineart();
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index ec965c9a29f..adf68e534bb 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -52,6 +52,7 @@ set(SRC
intern/MOD_gpencilarray.c
intern/MOD_gpencilbuild.c
intern/MOD_gpencilcolor.c
+ intern/MOD_gpencildash.c
intern/MOD_gpencilhook.c
intern/MOD_gpencillattice.c
intern/MOD_gpencillength.c
diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
index 18310bd5dff..043186155b7 100644
--- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
+++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h
@@ -46,6 +46,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply;
extern GpencilModifierTypeInfo modifierType_Gpencil_Texture;
extern GpencilModifierTypeInfo modifierType_Gpencil_Weight;
extern GpencilModifierTypeInfo modifierType_Gpencil_Lineart;
+extern GpencilModifierTypeInfo modifierType_Gpencil_Dash;
/* MOD_gpencil_util.c */
void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index 6409c86b6e3..5eb1eeab780 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -65,6 +65,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
INIT_GP_TYPE(Texture);
INIT_GP_TYPE(Weight);
INIT_GP_TYPE(Lineart);
+ INIT_GP_TYPE(Dash);
#undef INIT_GP_TYPE
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c b/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
new file mode 100644
index 00000000000..ba33edd6a94
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
@@ -0,0 +1,387 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup modifiers
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#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_screen_types.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 "MEM_guardedalloc.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+
+#include "BLT_translation.h"
+
+#include "MOD_gpencil_modifiertypes.h"
+#include "MOD_gpencil_ui_common.h"
+#include "MOD_gpencil_util.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+
+static void initData(GpencilModifierData *md)
+{
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)md;
+
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(dmd, modifier));
+
+ MEMCPY_STRUCT_AFTER(dmd, DNA_struct_default_get(DashGpencilModifierData), modifier);
+
+ DashGpencilModifierSegment *ds = DNA_struct_default_alloc(DashGpencilModifierSegment);
+ ds->dmd = dmd;
+ BLI_strncpy(ds->name, DATA_("Segment"), sizeof(ds->name));
+
+ dmd->segments = ds;
+}
+
+static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
+{
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)target;
+ const DashGpencilModifierData *dmd_src = (const DashGpencilModifierData *)md;
+
+ BKE_gpencil_modifier_copydata_generic(md, target);
+
+ dmd->segments = MEM_dupallocN(dmd_src->segments);
+}
+
+static void freeData(GpencilModifierData *md)
+{
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)md;
+
+ MEM_SAFE_FREE(dmd->segments);
+}
+
+/**
+ * Gap==0 means to start the next segment at the immediate next point, which will leave a visual
+ * gap of "1 point". This makes the algorithm give the same visual appearance as displayed on the
+ * UI and also simplifies the check for "no-length" situation where SEG==0 (which will not produce
+ * any effective dash).
+ */
+static int real_gap(const DashGpencilModifierSegment *ds)
+{
+ return ds->gap - 1;
+}
+
+static bool stroke_dash(const bGPDstroke *gps,
+ const DashGpencilModifierData *dmd,
+ ListBase *r_strokes)
+{
+ int new_stroke_offset = 0;
+ int trim_start = 0;
+
+ for (int i = 0; i < dmd->segments_len; i++) {
+ if (dmd->segments[i].dash + real_gap(&dmd->segments[i]) < 1) {
+ BLI_assert_unreachable();
+ /* This means there's a part that doesn't have any length, can't do dot-dash. */
+ return false;
+ }
+ }
+
+ const DashGpencilModifierSegment *const first_segment = &dmd->segments[0];
+ const DashGpencilModifierSegment *const last_segment = &dmd->segments[dmd->segments_len - 1];
+ const DashGpencilModifierSegment *ds = first_segment;
+
+ /* Determine starting configuration using offset. */
+ int offset_trim = dmd->dash_offset;
+ while (offset_trim < 0) {
+ ds = (ds == first_segment) ? last_segment : ds - 1;
+ offset_trim += ds->dash + real_gap(ds);
+ }
+
+ /* This segment is completely removed from view by the index offset, ignore it. */
+ while (ds->dash + real_gap(ds) < offset_trim) {
+ offset_trim -= ds->dash + real_gap(ds);
+ ds = (ds == last_segment) ? first_segment : ds + 1;
+ }
+
+ /* This segment is partially visible at the beginning of the stroke. */
+ if (ds->dash > offset_trim) {
+ trim_start = offset_trim;
+ }
+ else {
+ /* This segment is not visible but the gap immediately after this segment is partially visible,
+ * use next segment's dash. */
+ new_stroke_offset += ds->dash + real_gap(ds) - offset_trim;
+ ds = (ds == last_segment) ? first_segment : ds + 1;
+ }
+
+ while (new_stroke_offset < gps->totpoints - 1) {
+ const int seg = ds->dash - trim_start;
+ if (!(seg || real_gap(ds))) {
+ ds = (ds == last_segment) ? first_segment : ds + 1;
+ continue;
+ }
+
+ const int size = MIN2(gps->totpoints - new_stroke_offset, seg);
+ if (size == 0) {
+ continue;
+ }
+
+ bGPDstroke *stroke = BKE_gpencil_stroke_new(
+ ds->mat_nr < 0 ? gps->mat_nr : ds->mat_nr, size, gps->thickness);
+
+ for (int is = 0; is < size; is++) {
+ bGPDspoint *p = &gps->points[new_stroke_offset + is];
+ stroke->points[is].x = p->x;
+ stroke->points[is].y = p->y;
+ stroke->points[is].z = p->z;
+ stroke->points[is].pressure = p->pressure * ds->radius;
+ stroke->points[is].strength = p->strength * ds->opacity;
+ }
+ BLI_addtail(r_strokes, stroke);
+
+ if (gps->dvert) {
+ BKE_gpencil_dvert_ensure(stroke);
+ for (int di = 0; di < stroke->totpoints; di++) {
+ MDeformVert *dv = &gps->dvert[new_stroke_offset + di];
+ if (dv && dv->totweight && dv->dw) {
+ MDeformWeight *dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ __func__);
+ memcpy(dw, dv->dw, sizeof(MDeformWeight) * dv->totweight);
+ stroke->dvert[di].dw = dw;
+ stroke->dvert[di].totweight = dv->totweight;
+ stroke->dvert[di].flag = dv->flag;
+ }
+ }
+ }
+
+ new_stroke_offset += seg + real_gap(ds);
+ ds = (ds == last_segment) ? first_segment : ds + 1;
+ trim_start = 0;
+ }
+
+ return true;
+}
+
+static void apply_dash_for_frame(
+ Object *ob, bGPDlayer *gpl, bGPdata *gpd, bGPDframe *gpf, DashGpencilModifierData *dmd)
+{
+ if (dmd->segments_len == 0) {
+ return;
+ }
+
+ ListBase result = {NULL, NULL};
+
+ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ if (is_stroke_affected_by_modifier(ob,
+ dmd->layername,
+ dmd->material,
+ dmd->pass_index,
+ dmd->layer_pass,
+ 1,
+ gpl,
+ gps,
+ dmd->flag & GP_LENGTH_INVERT_LAYER,
+ dmd->flag & GP_LENGTH_INVERT_PASS,
+ dmd->flag & GP_LENGTH_INVERT_LAYERPASS,
+ dmd->flag & GP_LENGTH_INVERT_MATERIAL)) {
+ stroke_dash(gps, dmd, &result);
+ BLI_remlink(&gpf->strokes, gps);
+ BKE_gpencil_free_stroke(gps);
+ }
+ }
+ bGPDstroke *gps_dash;
+ while ((gps_dash = BLI_pophead(&result))) {
+ BLI_addtail(&gpf->strokes, gps_dash);
+ BKE_gpencil_stroke_geometry_update(gpd, gps_dash);
+ }
+}
+
+static void bakeModifier(Main *UNUSED(bmain),
+ Depsgraph *UNUSED(depsgraph),
+ GpencilModifierData *md,
+ Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ apply_dash_for_frame(ob, gpl, gpd, gpf, (DashGpencilModifierData *)md);
+ }
+ }
+}
+
+/* -------------------------------- */
+
+/* Generic "generateStrokes" callback */
+static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob)
+{
+ bGPdata *gpd = ob->data;
+
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ BKE_gpencil_frame_active_set(depsgraph, gpd);
+ bGPDframe *gpf = gpl->actframe;
+ if (gpf == NULL) {
+ return;
+ }
+ apply_dash_for_frame(ob, gpl, gpd, gpf, (DashGpencilModifierData *)md);
+ }
+}
+
+static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
+{
+ DashGpencilModifierData *mmd = (DashGpencilModifierData *)md;
+
+ walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER);
+}
+
+static void segment_list_item(struct uiList *UNUSED(ui_list),
+ 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 panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL);
+
+ uiLayoutSetPropSep(layout, true);
+
+ uiItemR(layout, ptr, "dash_offset", 0, NULL, ICON_NONE);
+
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayoutSetPropSep(row, false);
+
+ uiTemplateList(row,
+ (bContext *)C,
+ "MOD_UL_dash_segment",
+ "",
+ ptr,
+ "segments",
+ ptr,
+ "segment_active_index",
+ NULL,
+ 3,
+ 10,
+ 0,
+ 1,
+ UI_TEMPLATE_LIST_FLAG_NONE);
+
+ uiLayout *col = uiLayoutColumn(row, false);
+ uiLayoutSetContextPointer(col, "modifier", ptr);
+
+ uiLayout *sub = uiLayoutColumn(col, true);
+ uiItemO(sub, "", ICON_ADD, "GPENCIL_OT_segment_add");
+ uiItemO(sub, "", ICON_REMOVE, "GPENCIL_OT_segment_remove");
+ uiItemS(col);
+ sub = uiLayoutColumn(col, true);
+ uiItemEnumO_string(sub, "", ICON_TRIA_UP, "GPENCIL_OT_segment_move", "type", "UP");
+ uiItemEnumO_string(sub, "", ICON_TRIA_DOWN, "GPENCIL_OT_segment_move", "type", "DOWN");
+
+ DashGpencilModifierData *dmd = ptr->data;
+
+ if (dmd->segment_active_index >= 0 && dmd->segment_active_index < dmd->segments_len) {
+ PointerRNA ds_ptr;
+ RNA_pointer_create(ptr->owner_id,
+ &RNA_DashGpencilModifierSegment,
+ &dmd->segments[dmd->segment_active_index],
+ &ds_ptr);
+
+ sub = uiLayoutColumn(layout, true);
+ uiItemR(sub, &ds_ptr, "dash", 0, NULL, ICON_NONE);
+ uiItemR(sub, &ds_ptr, "gap", 0, NULL, ICON_NONE);
+
+ sub = uiLayoutColumn(layout, false);
+ uiItemR(sub, &ds_ptr, "radius", 0, NULL, ICON_NONE);
+ uiItemR(sub, &ds_ptr, "opacity", 0, NULL, ICON_NONE);
+ uiItemR(sub, &ds_ptr, "material_index", 0, NULL, ICON_NONE);
+ }
+
+ gpencil_modifier_panel_end(layout, ptr);
+}
+
+static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel)
+{
+ gpencil_modifier_masking_panel_draw(panel, true, false);
+}
+
+static void panelRegister(ARegionType *region_type)
+{
+ PanelType *panel_type = gpencil_modifier_panel_register(
+ region_type, eGpencilModifierType_Dash, panel_draw);
+ gpencil_modifier_subpanel_register(
+ region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type);
+
+ uiListType *list_type = MEM_callocN(sizeof(uiListType), "dash modifier segment uilist");
+ strcpy(list_type->idname, "MOD_UL_dash_segment");
+ list_type->draw_item = segment_list_item;
+ WM_uilisttype_add(list_type);
+}
+
+GpencilModifierTypeInfo modifierType_Gpencil_Dash = {
+ /* name */ "Dot Dash",
+ /* structName */ "DashGpencilModifierData",
+ /* structSize */ sizeof(DashGpencilModifierData),
+ /* type */ eGpencilModifierTypeType_Gpencil,
+ /* flags */ eGpencilModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformStroke */ NULL,
+ /* generateStrokes */ generateStrokes,
+ /* bakeModifier */ bakeModifier,
+ /* remapTime */ NULL,
+
+ /* initData */ initData,
+ /* freeData */ freeData,
+ /* isDisabled */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* foreachIDLink */ foreachIDLink,
+ /* foreachTexLink */ NULL,
+ /* panelRegister */ panelRegister,
+};
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h
index 8ab15b97537..450527c7443 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h
@@ -319,5 +319,23 @@
.material = NULL,\
}
+#define _DNA_DEFAULT_DashGpencilModifierData \
+ { \
+ .dash_offset = 0, \
+ .segments = NULL, \
+ .segments_len = 1, \
+ .segment_active_index = 0, \
+ }
+
+#define _DNA_DEFAULT_DashGpencilModifierSegment \
+ { \
+ .name = "", \
+ .dash = 2, \
+ .gap = 1, \
+ .radius = 1.0f, \
+ .opacity = 1.0f, \
+ .mat_nr = -1, \
+ }
+
/* clang-format off */
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index c91afa58cb1..d3429329ef6 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -56,6 +56,7 @@ typedef enum GpencilModifierType {
eGpencilModifierType_Lineart = 19,
eGpencilModifierType_Length = 20,
eGpencilModifierType_Weight = 21,
+ eGpencilModifierType_Dash = 22,
/* Keep last. */
NUM_GREASEPENCIL_MODIFIER_TYPES,
} GpencilModifierType;
@@ -507,6 +508,39 @@ typedef enum eLengthGpencil_Type {
GP_LENGTH_ABSOLUTE = 1,
} eLengthGpencil_Type;
+typedef struct DashGpencilModifierSegment {
+ char name[64];
+ /* For path reference. */
+ struct DashGpencilModifierData *dmd;
+ int dash;
+ int gap;
+ float radius;
+ float opacity;
+ int mat_nr;
+ int _pad;
+} DashGpencilModifierSegment;
+
+typedef struct DashGpencilModifierData {
+ GpencilModifierData modifier;
+ /** Material for filtering. */
+ struct Material *material;
+ /** Layer name. */
+ char layername[64];
+ /** Custom index for passes. */
+ int pass_index;
+ /** Flags. */
+ int flag;
+ /** Custom index for passes. */
+ int layer_pass;
+
+ int dash_offset;
+
+ DashGpencilModifierSegment *segments;
+ int segments_len;
+ int segment_active_index;
+
+} DashGpencilModifierData;
+
typedef struct MirrorGpencilModifierData {
GpencilModifierData modifier;
struct Object *object;
diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c
index 3570f5a6a6f..4cb8610f6ac 100644
--- a/source/blender/makesdna/intern/dna_defaults.c
+++ b/source/blender/makesdna/intern/dna_defaults.c
@@ -321,6 +321,8 @@ SDNA_DEFAULT_DECL_STRUCT(TintGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(WeightGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(LineartGpencilModifierData);
SDNA_DEFAULT_DECL_STRUCT(LengthGpencilModifierData);
+SDNA_DEFAULT_DECL_STRUCT(DashGpencilModifierData);
+SDNA_DEFAULT_DECL_STRUCT(DashGpencilModifierSegment);
#undef SDNA_DEFAULT_DECL_STRUCT
@@ -549,6 +551,8 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
SDNA_DEFAULT_DECL(WeightGpencilModifierData),
SDNA_DEFAULT_DECL(LineartGpencilModifierData),
SDNA_DEFAULT_DECL(LengthGpencilModifierData),
+ SDNA_DEFAULT_DECL(DashGpencilModifierData),
+ SDNA_DEFAULT_DECL(DashGpencilModifierSegment),
};
#undef SDNA_DEFAULT_DECL
#undef SDNA_DEFAULT_DECL_EX
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f5ebdbb569e..ce53e3390e1 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -222,6 +222,8 @@ extern StructRNA RNA_CurvePoint;
extern StructRNA RNA_CurveProfile;
extern StructRNA RNA_CurveProfilePoint;
extern StructRNA RNA_DampedTrackConstraint;
+extern StructRNA RNA_DashGpencilModifierData;
+extern StructRNA RNA_DashGpencilModifierSegment;
extern StructRNA RNA_DataTransferModifier;
extern StructRNA RNA_DecimateModifier;
extern StructRNA RNA_Depsgraph;
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index e125149dad2..4fa33424994 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -35,6 +35,7 @@
#include "BLI_math.h"
#include "BLI_rand.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -68,6 +69,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = {
ICON_MOD_BUILD,
"Build",
"Create duplication of strokes"},
+ {eGpencilModifierType_Dash,
+ "GP_DASH",
+ ICON_MOD_DASH,
+ "Dot Dash",
+ "Generate dot-dash styled strokes"},
{eGpencilModifierType_Lineart,
"GP_LINEART",
ICON_MOD_LINEART,
@@ -268,6 +274,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr)
return &RNA_TextureGpencilModifier;
case eGpencilModifierType_Lineart:
return &RNA_LineartGpencilModifier;
+ case eGpencilModifierType_Dash:
+ return &RNA_DashGpencilModifierData;
/* Default */
case eGpencilModifierType_None:
case NUM_GREASEPENCIL_MODIFIER_TYPES:
@@ -282,19 +290,19 @@ static void rna_GpencilModifier_name_set(PointerRNA *ptr, const char *value)
GpencilModifierData *gmd = ptr->data;
char oldname[sizeof(gmd->name)];
- /* make a copy of the old name first */
+ /* Make a copy of the old name first. */
BLI_strncpy(oldname, gmd->name, sizeof(gmd->name));
- /* copy the new name into the name slot */
+ /* Copy the new name into the name slot. */
BLI_strncpy_utf8(gmd->name, value, sizeof(gmd->name));
- /* make sure the name is truly unique */
+ /* Make sure the name is truly unique. */
if (ptr->owner_id) {
Object *ob = (Object *)ptr->owner_id;
BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, gmd);
}
- /* fix all the animation data which may link to this */
+ /* Fix all the animation data which may link to this. */
BKE_animdata_fix_paths_rename_all(NULL, "grease_pencil_modifiers", oldname, gmd->name);
}
@@ -674,6 +682,59 @@ static void rna_Lineart_end_level_set(PointerRNA *ptr, int value)
lmd->level_start = MIN2(value, lmd->level_start);
}
+static void rna_GpencilDash_segments_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)ptr->data;
+ rna_iterator_array_begin(
+ iter, dmd->segments, sizeof(DashGpencilModifierSegment), dmd->segments_len, false, NULL);
+}
+
+static char *rna_DashGpencilModifierSegment_path(PointerRNA *ptr)
+{
+ DashGpencilModifierSegment *ds = (DashGpencilModifierSegment *)ptr->data;
+
+ DashGpencilModifierData *dmd = (DashGpencilModifierData *)ds->dmd;
+
+ BLI_assert(dmd != NULL);
+
+ char name_esc[sizeof(dmd->modifier.name) * 2 + 1];
+
+ BLI_str_escape(name_esc, dmd->modifier.name, sizeof(name_esc));
+
+ return BLI_sprintfN("grease_pencil_modifiers[\"%s\"].segments[\"%s\"]", name_esc, ds->name);
+}
+
+static bool dash_segment_name_exists_fn(void *arg, const char *name)
+{
+ const DashGpencilModifierData *dmd = (const DashGpencilModifierData *)arg;
+ for (int i = 0; i < dmd->segments_len; i++) {
+ if (STREQ(dmd->segments[i].name, name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void rna_DashGpencilModifierSegment_name_set(PointerRNA *ptr, const char *value)
+{
+ DashGpencilModifierSegment *ds = ptr->data;
+
+ char oldname[sizeof(ds->name)];
+ BLI_strncpy(oldname, ds->name, sizeof(ds->name));
+
+ BLI_strncpy_utf8(ds->name, value, sizeof(ds->name));
+
+ BLI_assert(ds->dmd != NULL);
+ BLI_uniquename_cb(
+ dash_segment_name_exists_fn, ds->dmd, "Segment", '.', ds->name, sizeof(ds->name));
+
+ char prefix[256];
+ sprintf(prefix, "grease_pencil_modifiers[\"%s\"].segments", ds->dmd->modifier.name);
+
+ /* Fix all the animation data which may link to this. */
+ BKE_animdata_fix_paths_rename_all(NULL, prefix, oldname, ds->name);
+}
+
#else
static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
@@ -3287,6 +3348,136 @@ static void rna_def_modifier_gpencillength(BlenderRNA *brna)
RNA_define_lib_overridable(false);
}
+static void rna_def_modifier_gpencildash(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "DashGpencilModifierSegment", NULL);
+ RNA_def_struct_ui_text(srna, "Dash Modifier Segment", "Configuration for a single dash segment");
+ RNA_def_struct_sdna(srna, "DashGpencilModifierSegment");
+ RNA_def_struct_path_func(srna, "rna_DashGpencilModifierSegment_path");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Name of the dash segment");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DashGpencilModifierSegment_name_set");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER | NA_RENAME, NULL);
+ RNA_def_struct_name_property(srna, prop);
+
+ prop = RNA_def_property(srna, "dash", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, INT16_MAX);
+ RNA_def_property_ui_text(
+ prop,
+ "Dash",
+ "The number of consecutive points from the original stroke to include in this segment");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "gap", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 1, INT16_MAX);
+ RNA_def_property_ui_text(prop, "Gap", "The number of points skipped after this segment");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_FACTOR | PROP_UNSIGNED);
+ RNA_def_property_ui_range(prop, 0, 1, 0.1, 2);
+ RNA_def_property_ui_text(
+ prop, "Radius", "The factor to apply to the original point's radius for the new points");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_range(prop, 0, 1, 0.1, 2);
+ RNA_def_property_ui_text(
+ prop, "Opacity", "The factor to apply to the original point's opacity for the new points");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "mat_nr");
+ RNA_def_property_range(prop, -1, INT16_MAX);
+ RNA_def_property_ui_text(
+ prop,
+ "Material Index",
+ "Use this index on generated segment. -1 means using the existing material");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ srna = RNA_def_struct(brna, "DashGpencilModifierData", "GpencilModifier");
+ RNA_def_struct_ui_text(srna, "Dash Modifier", "Create dot-dash effect for strokes");
+ RNA_def_struct_sdna(srna, "DashGpencilModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_DASH);
+
+ RNA_define_lib_overridable(true);
+
+ prop = RNA_def_property(srna, "segments", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "DashGpencilModifierSegment");
+ RNA_def_property_collection_sdna(prop, NULL, "segments", NULL);
+ RNA_def_property_collection_funcs(prop,
+ "rna_GpencilDash_segments_begin",
+ "rna_iterator_array_next",
+ "rna_iterator_array_end",
+ "rna_iterator_array_get",
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ RNA_def_property_ui_text(prop, "Segments", "");
+
+ prop = RNA_def_property(srna, "segment_active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_text(prop, "Active Dash Segement Index", "Active index in the segment list");
+
+ prop = RNA_def_property(srna, "dash_offset", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(
+ prop,
+ "Offset",
+ "Offset into each stroke before the beginning of the dashed segment generation");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ /* Common properties. */
+
+ prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "layername");
+ RNA_def_property_ui_text(prop, "Layer", "Layer name");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "pass_index");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LENGTH_INVERT_LAYER);
+ RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LENGTH_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LENGTH_INVERT_PASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "layer_pass");
+ RNA_def_property_range(prop, 0, 100);
+ RNA_def_property_ui_text(prop, "Pass", "Layer pass index");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LENGTH_INVERT_LAYERPASS);
+ RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
+ RNA_define_lib_overridable(false);
+}
+
void RNA_def_greasepencil_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3364,6 +3555,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna)
rna_def_modifier_gpencilweight(brna);
rna_def_modifier_gpencillineart(brna);
rna_def_modifier_gpencillength(brna);
+ rna_def_modifier_gpencildash(brna);
}
#endif
diff --git a/source/tools b/source/tools
-Subproject 5cf2fc3e5dc28025394b57d8743401295528f31
+Subproject c8579c5cf43229843df505da9644b5b0b720197