diff options
8 files changed, 534 insertions, 0 deletions
diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index 5ef9ae1bbc6..8dbac602c06 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -47,6 +47,7 @@ set(SRC intern/MOD_gpencilnoise.c intern/MOD_gpenciloffset.c intern/MOD_gpencilopacity.c + intern/MOD_gpenciloutline.c intern/MOD_gpencilshrinkwrap.c intern/MOD_gpencilsimplify.c intern/MOD_gpencilsmooth.c diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h index 9025fecacd8..2f3cf4d2312 100644 --- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h +++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h @@ -20,6 +20,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Color; extern GpencilModifierTypeInfo modifierType_Gpencil_Array; extern GpencilModifierTypeInfo modifierType_Gpencil_Build; extern GpencilModifierTypeInfo modifierType_Gpencil_Opacity; +extern GpencilModifierTypeInfo modifierType_Gpencil_Outline; extern GpencilModifierTypeInfo modifierType_Gpencil_Lattice; extern GpencilModifierTypeInfo modifierType_Gpencil_Length; extern GpencilModifierTypeInfo modifierType_Gpencil_Mirror; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index bd8fd9f72ad..d4ada842d0b 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -41,6 +41,7 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) INIT_GP_TYPE(Array); INIT_GP_TYPE(Build); INIT_GP_TYPE(Opacity); + INIT_GP_TYPE(Outline); INIT_GP_TYPE(Lattice); INIT_GP_TYPE(Length); INIT_GP_TYPE(Mirror); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c new file mode 100644 index 00000000000..9a0ee4d9d92 --- /dev/null +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2022 Blender Foundation. */ + +/** \file + * \ingroup modifiers + */ + +#include <stdio.h> + +#include "BLI_utildefines.h" + +#include "BLI_listbase.h" +#include "BLI_math_vector.h" + +#include "BLT_translation.h" + +#include "DNA_defaults.h" +#include "DNA_gpencil_modifier_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_material_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_material.h" +#include "BKE_scene.h" +#include "BKE_screen.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "BKE_modifier.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "MOD_gpencil_modifiertypes.h" +#include "MOD_gpencil_ui_common.h" +#include "MOD_gpencil_util.h" + +static void initData(GpencilModifierData *md) +{ + OutlineGpencilModifierData *gpmd = (OutlineGpencilModifierData *)md; + + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(gpmd, modifier)); + + MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(OutlineGpencilModifierData), modifier); +} + +static void copyData(const GpencilModifierData *md, GpencilModifierData *target) +{ + BKE_gpencil_modifier_copydata_generic(md, target); +} + +static void free_old_strokes(Depsgraph *depsgraph, Object *ob, bGPdata *gpd) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + /* Free old strokes. */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl); + if (gpf == NULL) { + continue; + } + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + if (gps->flag & GP_STROKE_TAG) { + BLI_remlink(&gpf->strokes, gps); + BKE_gpencil_free_stroke(gps); + } + } + } +} + +static void convert_stroke(GpencilModifierData *md, + Object *ob, + bGPDlayer *gpl, + bGPDframe *gpf, + bGPDstroke *gps, + float viewmat[4][4], + float diff_mat[4][4]) +{ + OutlineGpencilModifierData *mmd = (OutlineGpencilModifierData *)md; + bGPdata *gpd = (bGPdata *)ob->data; + const bool keep = (mmd->flag & GP_OUTLINE_KEEP_SHAPE) != 0; + + if (!is_stroke_affected_by_modifier(ob, + mmd->layername, + mmd->material, + mmd->pass_index, + mmd->layer_pass, + 1, + gpl, + gps, + mmd->flag & GP_OUTLINE_INVERT_LAYER, + mmd->flag & GP_OUTLINE_INVERT_PASS, + mmd->flag & GP_OUTLINE_INVERT_LAYERPASS, + mmd->flag & GP_OUTLINE_INVERT_MATERIAL)) { + return; + } + + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + const bool is_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0; + /* Only strokes type, no fill strokes. */ + if (!is_stroke) { + return; + } + + /* Duplicate the stroke to apply any layer thickness change. */ + bGPDstroke *gps_duplicate = BKE_gpencil_stroke_duplicate(gps, true, false); + + /* Apply layer thickness change. */ + gps_duplicate->thickness += gpl->line_change; + /* Apply object scale to thickness. */ + gps_duplicate->thickness *= mat4_to_scale(ob->obmat); + CLAMP_MIN(gps_duplicate->thickness, 1.0f); + + /* Stroke. */ + const float ovr_thickness = keep ? mmd->thickness : 0.0f; + bGPDstroke *gps_perimeter = BKE_gpencil_stroke_perimeter_from_view( + viewmat, gpd, gpl, gps_duplicate, mmd->subdiv, diff_mat, ovr_thickness); + gps_perimeter->flag &= ~GP_STROKE_SELECT; + gps_perimeter->runtime.gps_orig = gps->runtime.gps_orig; + + /* Assign material. */ + if (mmd->outline_material) { + Material *ma = mmd->outline_material; + int mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob, ma->id.name + 2); + if (mat_idx > -1) { + gps_perimeter->mat_nr = mat_idx; + } + else { + gps_perimeter->mat_nr = gps->mat_nr; + } + } + else { + gps_perimeter->mat_nr = gps->mat_nr; + } + + /* Sample stroke. */ + if (mmd->sample_length > 0.0f) { + BKE_gpencil_stroke_sample(gpd, gps_perimeter, mmd->sample_length, false, 0); + } + /* Set stroke thickness. */ + gps_perimeter->thickness = mmd->thickness; + + /* Set pressure constant. */ + int orig_idx = -1; + float min_distance = FLT_MAX; + bGPDspoint *pt; + for (int i = 0; i < gps_perimeter->totpoints; i++) { + pt = &gps_perimeter->points[i]; + pt->pressure = 1.0f; + pt->runtime.pt_orig = NULL; + /* If any target object is defined, find the nearest point. */ + if (mmd->object) { + float wpt[3]; + mul_v3_m4v3(wpt, diff_mat, &pt->x); + float dist = len_squared_v3v3(wpt, mmd->object->loc); + if (dist < min_distance) { + min_distance = dist; + orig_idx = i; + } + } + } + + if (orig_idx > 0) { + BKE_gpencil_stroke_start_set(gps_perimeter, orig_idx); + BKE_gpencil_stroke_geometry_update(gpd, gps_perimeter); + } + + /* Add perimeter stroke to frame. */ + BLI_insertlinkafter(&gpf->strokes, gps, gps_perimeter); + + /* Free Temp stroke. */ + BKE_gpencil_free_stroke(gps_duplicate); + + /* Tag original stroke to be removed. */ + gps->flag |= GP_STROKE_TAG; +} + +static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Object *ob) +{ + bGPdata *gpd = (bGPdata *)ob->data; + + /* Calc camera view matrix. */ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + /* Ensure the camera is the right one. */ + BKE_scene_camera_switch_update(scene); + + if (!scene->camera) { + return; + } + Object *cam_ob = scene->camera; + float viewmat[4][4]; + invert_m4_m4(viewmat, cam_ob->obmat); + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + bGPDframe *gpf = BKE_gpencil_frame_retime_get(depsgraph, scene, ob, gpl); + if (gpf == NULL) { + continue; + } + /* Prepare transform matrix. */ + float diff_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); + + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + convert_stroke(md, ob, gpl, gpf, gps, viewmat, diff_mat); + } + } + + /* Delete original strokes. */ + free_old_strokes(depsgraph, ob, gpd); +} + +static void bakeModifier(Main *UNUSED(bmain), + Depsgraph *depsgraph, + GpencilModifierData *md, + Object *ob) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + bGPdata *gpd = ob->data; + int oldframe = (int)DEG_get_ctime(depsgraph); + + /* Calc camera view matrix. */ + if (!scene->camera) { + return; + } + Object *cam_ob = scene->camera; + float viewmat[4][4]; + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + scene->r.cfra = gpf->framenum; + BKE_scene_graph_update_for_newframe(depsgraph); + /* Ensure the camera is the right one. */ + BKE_scene_camera_switch_update(scene); + invert_m4_m4(viewmat, cam_ob->obmat); + + /* Prepare transform matrix. */ + float diff_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); + + /* Compute all strokes of this frame. */ + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + convert_stroke(md, ob, gpl, gpf, gps, viewmat, diff_mat); + } + } + } + + /* Delete original strokes. */ + free_old_strokes(depsgraph, ob, gpd); + + /* Return frame state and DB to original state. */ + scene->r.cfra = oldframe; + BKE_scene_graph_update_for_newframe(depsgraph); +} + +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + OutlineGpencilModifierData *mmd = (OutlineGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + walk(userData, ob, (ID **)&mmd->outline_material, IDWALK_CB_USER); + walk(userData, ob, (ID **)&mmd->object, IDWALK_CB_NOP); +} + +static void updateDepsgraph(GpencilModifierData *md, + const ModifierUpdateDepsgraphContext *ctx, + const int UNUSED(mode)) +{ + OutlineGpencilModifierData *lmd = (OutlineGpencilModifierData *)md; + if (ctx->scene->camera) { + DEG_add_object_relation( + ctx->node, ctx->scene->camera, DEG_OB_COMP_TRANSFORM, "Outline Modifier"); + DEG_add_object_relation( + ctx->node, ctx->scene->camera, DEG_OB_COMP_PARAMETERS, "Outline Modifier"); + } + if (lmd->object != NULL) { + DEG_add_object_relation(ctx->node, lmd->object, DEG_OB_COMP_TRANSFORM, "Outline Modifier"); + } + DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Outline Modifier"); +} + +static void panel_draw(const bContext *UNUSED(C), Panel *panel) +{ + uiLayout *layout = panel->layout; + + PointerRNA *ptr = gpencil_modifier_panel_get_property_pointers(panel, NULL); + + uiLayoutSetPropSep(layout, true); + + uiItemR(layout, ptr, "thickness", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_keep_shape", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "subdivision", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "sample_length", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "outline_material", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "object", 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_Outline, panel_draw); + gpencil_modifier_subpanel_register( + region_type, "mask", "Influence", NULL, mask_panel_draw, panel_type); +} + +GpencilModifierTypeInfo modifierType_Gpencil_Outline = { + /* name */ N_("Outline"), + /* structName */ "OutlineGpencilModifierData", + /* structSize */ sizeof(OutlineGpencilModifierData), + /* type */ eGpencilModifierTypeType_Gpencil, + /* flags */ eGpencilModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + + /* deformStroke */ NULL, + /* generateStrokes */ generateStrokes, + /* bakeModifier */ bakeModifier, + /* remapTime */ NULL, + + /* initData */ initData, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepsgraph */ updateDepsgraph, + /* 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 324252ca369..56e317adca5 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -172,6 +172,19 @@ .curve_intensity = NULL, \ } +#define _DNA_DEFAULT_OutlineGpencilModifierData \ + { \ + .material = NULL, \ + .layername = "", \ + .pass_index = 0, \ + .flag = GP_OUTLINE_KEEP_SHAPE, \ + .thickness = 1, \ + .sample_length = 0.0f, \ + .subdiv = 3, \ + .layer_pass = 0, \ + .outline_material = NULL, \ + } + #define _DNA_DEFAULT_SimplifyGpencilModifierData \ { \ .material = NULL, \ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index ca1eac0bde8..629be51893a 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -47,6 +47,7 @@ typedef enum GpencilModifierType { eGpencilModifierType_WeightAngle = 23, eGpencilModifierType_Shrinkwrap = 24, eGpencilModifierType_Envelope = 25, + eGpencilModifierType_Outline = 26, /* Keep last. */ NUM_GREASEPENCIL_MODIFIER_TYPES, } GpencilModifierType; @@ -313,6 +314,38 @@ typedef enum eOpacityGpencil_Flag { GP_OPACITY_WEIGHT_FACTOR = (1 << 8), } eOpacityGpencil_Flag; +typedef struct OutlineGpencilModifierData { + GpencilModifierData modifier; + /** Target stroke origin. */ + struct Object *object; + /** Material for filtering. */ + struct Material *material; + /** Layer name. */ + char layername[64]; + /** Custom index for passes. */ + int pass_index; + /** Flags. */ + int flag; + /** Thickness. */ + int thickness; + /** Sample Length. */ + float sample_length; + /** Subdivisions. */ + int subdiv; + /** Custom index for passes. */ + int layer_pass; + /** Material for outline. */ + struct Material *outline_material; +} OutlineGpencilModifierData; + +typedef enum eOutlineGpencil_Flag { + GP_OUTLINE_INVERT_LAYER = (1 << 0), + GP_OUTLINE_INVERT_PASS = (1 << 1), + GP_OUTLINE_INVERT_LAYERPASS = (1 << 2), + GP_OUTLINE_INVERT_MATERIAL = (1 << 3), + GP_OUTLINE_KEEP_SHAPE = (1 << 4), +} eOutlineGpencil_Flag; + typedef struct ArrayGpencilModifierData { GpencilModifierData modifier; struct Object *object; diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index 197a863db72..3cd0cbcc3d6 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -302,6 +302,7 @@ SDNA_DEFAULT_DECL_STRUCT(MultiplyGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(NoiseGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(OffsetGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(OpacityGpencilModifierData); +SDNA_DEFAULT_DECL_STRUCT(OutlineGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(SimplifyGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(SmoothGpencilModifierData); SDNA_DEFAULT_DECL_STRUCT(SubdivGpencilModifierData); @@ -542,6 +543,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { SDNA_DEFAULT_DECL(NoiseGpencilModifierData), SDNA_DEFAULT_DECL(OffsetGpencilModifierData), SDNA_DEFAULT_DECL(OpacityGpencilModifierData), + SDNA_DEFAULT_DECL(OutlineGpencilModifierData), SDNA_DEFAULT_DECL(SimplifyGpencilModifierData), SDNA_DEFAULT_DECL(SmoothGpencilModifierData), SDNA_DEFAULT_DECL(SubdivGpencilModifierData), diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 2dfd9d46665..0a400d3bcef 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -105,6 +105,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { ICON_GP_MULTIFRAME_EDITING, "Multiple Strokes", "Produce multiple strokes along one stroke"}, + {eGpencilModifierType_Outline, + "GP_OUTLINE", + ICON_MOD_SKIN, + "Outline", + "Convert stroke to perimeter"}, {eGpencilModifierType_Simplify, "GP_SIMPLIFY", ICON_MOD_SIMPLIFY, @@ -286,6 +291,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr) return &RNA_BuildGpencilModifier; case eGpencilModifierType_Opacity: return &RNA_OpacityGpencilModifier; + case eGpencilModifierType_Outline: + return &RNA_OutlineGpencilModifier; case eGpencilModifierType_Lattice: return &RNA_LatticeGpencilModifier; case eGpencilModifierType_Length: @@ -668,6 +675,37 @@ static void rna_OpacityGpencilModifier_material_set(PointerRNA *ptr, rna_GpencilModifier_material_set(ptr, value, ma_target, reports); } +static void rna_OutlineGpencilModifier_object_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) +{ + OutlineGpencilModifierData *omd = ptr->data; + Object *ob = (Object *)value.data; + + omd->object = ob; + id_lib_extern((ID *)ob); +} + +static void rna_OutlineGpencilModifier_material_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *reports) +{ + OutlineGpencilModifierData *omd = (OutlineGpencilModifierData *)ptr->data; + Material **ma_target = &omd->material; + + rna_GpencilModifier_material_set(ptr, value, ma_target, reports); +} + +static void rna_OutlineStrokeGpencilModifier_material_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *reports) +{ + OutlineGpencilModifierData *omd = (OutlineGpencilModifierData *)ptr->data; + Material **ma_target = &omd->outline_material; + + rna_GpencilModifier_material_set(ptr, value, ma_target, reports); +} + static void rna_LatticeGpencilModifier_material_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports) @@ -1972,6 +2010,108 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna) RNA_define_lib_overridable(false); } +static void rna_def_modifier_gpenciloutline(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "OutlineGpencilModifier", "GpencilModifier"); + RNA_def_struct_ui_text(srna, "Outline Modifier", "Outline of Strokes modifier from camera view"); + RNA_def_struct_sdna(srna, "OutlineGpencilModifierData"); + // TODO: add new icon + RNA_def_struct_ui_icon(srna, ICON_MOD_SKIN); + + RNA_define_lib_overridable(true); + + 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); + RNA_def_property_pointer_funcs(prop, + NULL, + "rna_OutlineGpencilModifier_material_set", + NULL, + "rna_GpencilModifier_material_poll"); + 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_OUTLINE_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_OUTLINE_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_OUTLINE_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_OUTLINE_INVERT_LAYERPASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "thickness", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "thickness"); + RNA_def_property_range(prop, 1, 1000); + RNA_def_property_ui_text(prop, "Thickness", "Thickness of the perimeter stroke"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "sample_length", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "sample_length"); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 0.1f, 2); + RNA_def_property_ui_text(prop, "Sample Length", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "subdivision", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "subdiv"); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_text(prop, "Subdivisions", "Number of subdivisions"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "use_keep_shape", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OUTLINE_KEEP_SHAPE); + RNA_def_property_ui_text(prop, "Keep Shape", "Try to keep global shape"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "outline_material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, + NULL, + "rna_OutlineStrokeGpencilModifier_material_set", + NULL, + "rna_GpencilModifier_material_poll"); + RNA_def_property_ui_text(prop, "Outline Material", "Material used for outline strokes"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Target Object", "Target object to define stroke start"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_pointer_funcs(prop, NULL, "rna_OutlineGpencilModifier_object_set", NULL, NULL); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + + RNA_define_lib_overridable(false); +} + static void rna_def_modifier_gpencilarray(BlenderRNA *brna) { StructRNA *srna; @@ -4353,6 +4493,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna) rna_def_modifier_gpencilarray(brna); rna_def_modifier_gpencilbuild(brna); rna_def_modifier_gpencilopacity(brna); + rna_def_modifier_gpenciloutline(brna); rna_def_modifier_gpencillattice(brna); rna_def_modifier_gpencilmirror(brna); rna_def_modifier_gpencilhook(brna); |