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
This commit is contained in:
parent
c1cf66bff3
commit
a2c5c2b406
@ -1 +1 @@
|
||||
Subproject commit 8a05b618f031582c006c6f62b9e60619ab3eef8b
|
||||
Subproject commit 62e82958a760dad775d9b3387d7fb535fd6de4c6
|
@ -1 +1 @@
|
||||
Subproject commit 67f1fbca1482d9d9362a4001332e785c3fd5d230
|
||||
Subproject commit 4475cbd11a636382d57571e0f5dfeff1f90bd6b7
|
@ -1 +1 @@
|
||||
Subproject commit ef6ef414d22c2578fad99327743b925ab640a99c
|
||||
Subproject commit 788441f2930465bbfba8f0797b12dcef1d46694d
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,6 +336,7 @@ set(ICON_NAMES
|
||||
lightprobe_cubemap
|
||||
lightprobe_planar
|
||||
lightprobe_grid
|
||||
mod_dash
|
||||
color_red
|
||||
color_green
|
||||
color_blue
|
||||
|
@ -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)
|
||||
|
@ -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", "");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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[]);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
387
source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
Normal file
387
source/blender/gpencil_modifiers/intern/MOD_gpencildash.c
Normal file
@ -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,
|
||||
};
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5cf2fc3e5dc28025394b57d8743401295528f310
|
||||
Subproject commit c8579c5cf43229843df505da9644b5b0b7201974
|
Loading…
x
Reference in New Issue
Block a user