WIP: Brush assets project #106303
|
@ -71,7 +71,7 @@ class OBJECT_MT_modifier_add(ModifierAddMenu, Menu):
|
|||
if geometry_nodes_supported:
|
||||
self.operator_modifier_add(layout, 'NODES')
|
||||
layout.separator()
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE'}:
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'LATTICE', 'GREASEPENCIL'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_edit")
|
||||
if ob_type in {'MESH', 'CURVE', 'FONT', 'SURFACE', 'VOLUME'}:
|
||||
layout.menu("OBJECT_MT_modifier_add_generate")
|
||||
|
@ -105,6 +105,8 @@ class OBJECT_MT_modifier_add_edit(ModifierAddMenu, Menu):
|
|||
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_EDIT')
|
||||
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_MIX')
|
||||
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_PROXIMITY')
|
||||
if ob_type == 'GREASEPENCIL':
|
||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_OPACITY')
|
||||
layout.template_modifier_asset_menu_items(catalog_path=self.bl_label)
|
||||
|
||||
|
||||
|
|
|
@ -801,4 +801,11 @@
|
|||
.mat_ofs = 0, \
|
||||
}
|
||||
|
||||
#define _DNA_DEFAULT_GreasePencilOpacityModifierData \
|
||||
{ \
|
||||
.color_mode = MOD_GREASE_PENCIL_COLOR_BOTH, \
|
||||
.color_factor = 1.0f, \
|
||||
.hardness_factor = 1.0f, \
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
|
|
@ -93,6 +93,7 @@ typedef enum ModifierType {
|
|||
eModifierType_MeshToVolume = 58,
|
||||
eModifierType_VolumeDisplace = 59,
|
||||
eModifierType_VolumeToMesh = 60,
|
||||
eModifierType_GreasePencilOpacity = 61,
|
||||
NUM_MODIFIER_TYPES,
|
||||
} ModifierType;
|
||||
|
||||
|
@ -2484,3 +2485,65 @@ typedef enum VolumeToMeshResolutionMode {
|
|||
typedef enum VolumeToMeshFlag {
|
||||
VOLUME_TO_MESH_USE_SMOOTH_SHADE = 1 << 0,
|
||||
} VolumeToMeshFlag;
|
||||
|
||||
/**
|
||||
* Common influence data for grease pencil modifiers.
|
||||
* Not all parts may be used by all modifier types.
|
||||
*/
|
||||
typedef struct GreasePencilModifierInfluenceData {
|
||||
/** GreasePencilModifierInfluenceFlag */
|
||||
int flag;
|
||||
char _pad1[4];
|
||||
/** Filter by layer name. */
|
||||
char layer_name[64];
|
||||
/** Filter by stroke material. */
|
||||
struct Material *material;
|
||||
/** Filter by layer pass. */
|
||||
int layer_pass;
|
||||
/** Filter by material pass. */
|
||||
int material_pass;
|
||||
/** #MAX_VGROUP_NAME. */
|
||||
char vertex_group_name[64];
|
||||
struct CurveMapping *custom_curve;
|
||||
void *_pad2;
|
||||
} GreasePencilModifierInfluenceData;
|
||||
|
||||
typedef enum GreasePencilModifierInfluenceFlag {
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER = (1 << 0),
|
||||
GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER = (1 << 1),
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER = (1 << 2),
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER = (1 << 3),
|
||||
GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER = (1 << 4),
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER = (1 << 5),
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP = (1 << 6),
|
||||
GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE = (1 << 7),
|
||||
} GreasePencilModifierInfluenceFlag;
|
||||
|
||||
typedef struct GreasePencilOpacityModifierData {
|
||||
ModifierData modifier;
|
||||
GreasePencilModifierInfluenceData influence;
|
||||
/** GreasePencilOpacityModifierFlag */
|
||||
int flag;
|
||||
/** GreasePencilModifierColorMode */
|
||||
char color_mode;
|
||||
char _pad1[3];
|
||||
float color_factor;
|
||||
float hardness_factor;
|
||||
void *_pad2;
|
||||
} GreasePencilOpacityModifierData;
|
||||
|
||||
/** Which attributes are affected by color modifiers. */
|
||||
typedef enum GreasePencilModifierColorMode {
|
||||
MOD_GREASE_PENCIL_COLOR_STROKE = 0,
|
||||
MOD_GREASE_PENCIL_COLOR_FILL = 1,
|
||||
MOD_GREASE_PENCIL_COLOR_BOTH = 2,
|
||||
MOD_GREASE_PENCIL_COLOR_HARDNESS = 3,
|
||||
} GreasePencilModifierColorMode;
|
||||
|
||||
typedef enum GreasePencilOpacityModifierFlag {
|
||||
MOD_GREASE_PENCIL_OPACITY_OPEN_INFLUENCE_PANEL = (1 << 0),
|
||||
/* Use vertex group as opacity factors instead of influence. */
|
||||
MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR = (1 << 1),
|
||||
/* Set the opacity for every point in a stroke, otherwise multiply existing opacity. */
|
||||
MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY = (1 << 2),
|
||||
} GreasePencilOpacityModifierFlag;
|
||||
|
|
|
@ -322,6 +322,7 @@ SDNA_DEFAULT_DECL_STRUCT(DashGpencilModifierData);
|
|||
SDNA_DEFAULT_DECL_STRUCT(DashGpencilModifierSegment);
|
||||
SDNA_DEFAULT_DECL_STRUCT(ShrinkwrapGpencilModifierData);
|
||||
SDNA_DEFAULT_DECL_STRUCT(EnvelopeGpencilModifierData);
|
||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilOpacityModifierData);
|
||||
|
||||
#undef SDNA_DEFAULT_DECL_STRUCT
|
||||
|
||||
|
@ -566,6 +567,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
|
|||
SDNA_DEFAULT_DECL(DashGpencilModifierSegment),
|
||||
SDNA_DEFAULT_DECL(ShrinkwrapGpencilModifierData),
|
||||
SDNA_DEFAULT_DECL(EnvelopeGpencilModifierData),
|
||||
SDNA_DEFAULT_DECL(GreasePencilOpacityModifierData),
|
||||
};
|
||||
#undef SDNA_DEFAULT_DECL
|
||||
#undef SDNA_DEFAULT_DECL_EX
|
||||
|
|
|
@ -100,6 +100,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
|
|||
ICON_MOD_VERTEX_WEIGHT,
|
||||
"Vertex Weight Proximity",
|
||||
"Set the vertex group weights based on the distance to another target object"},
|
||||
{eModifierType_GreasePencilOpacity,
|
||||
"GREASE_PENCIL_OPACITY",
|
||||
ICON_MOD_OPACITY,
|
||||
"Opacity",
|
||||
"Change the opacity of the strokes"},
|
||||
|
||||
RNA_ENUM_ITEM_HEADING(N_("Generate"), nullptr),
|
||||
{eModifierType_Array,
|
||||
|
@ -668,11 +673,13 @@ const EnumPropertyItem rna_enum_subdivision_boundary_smooth_items[] = {
|
|||
#ifdef RNA_RUNTIME
|
||||
# include "DNA_curve_types.h"
|
||||
# include "DNA_fluid_types.h"
|
||||
# include "DNA_material_types.h"
|
||||
# include "DNA_particle_types.h"
|
||||
|
||||
# include "BKE_cachefile.h"
|
||||
# include "BKE_context.hh"
|
||||
# include "BKE_deform.h"
|
||||
# include "BKE_material.h"
|
||||
# include "BKE_mesh_runtime.hh"
|
||||
# include "BKE_modifier.hh"
|
||||
# include "BKE_object.hh"
|
||||
|
@ -1705,6 +1712,78 @@ static IDProperty **rna_NodesModifier_properties(PointerRNA *ptr)
|
|||
NodesModifierSettings *settings = &nmd->settings;
|
||||
return &settings->properties;
|
||||
}
|
||||
|
||||
bool rna_GreasePencilModifier_material_poll(PointerRNA *ptr, PointerRNA value)
|
||||
{
|
||||
Object *ob = reinterpret_cast<Object *>(ptr->owner_id);
|
||||
Material *ma = reinterpret_cast<Material *>(value.owner_id);
|
||||
|
||||
return BKE_object_material_index_get(ob, ma) != -1;
|
||||
}
|
||||
|
||||
/* Write material to a generic target pointer without the final modifier struct. */
|
||||
static void rna_GreasePencilModifier_material_set(PointerRNA *ptr,
|
||||
PointerRNA value,
|
||||
ReportList *reports,
|
||||
Material **ma_target)
|
||||
{
|
||||
Object *ob = reinterpret_cast<Object *>(ptr->owner_id);
|
||||
Material *ma = reinterpret_cast<Material *>(value.owner_id);
|
||||
|
||||
if (ma == nullptr || BKE_object_material_index_get(ob, ma) != -1) {
|
||||
id_lib_extern(reinterpret_cast<ID *>(ob));
|
||||
*ma_target = ma;
|
||||
}
|
||||
else {
|
||||
BKE_reportf(
|
||||
reports,
|
||||
RPT_ERROR,
|
||||
"Cannot assign material '%s', it has to be used by the grease pencil object already",
|
||||
ma->id.name);
|
||||
}
|
||||
}
|
||||
|
||||
# define RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(_type) \
|
||||
static void rna_##_type##Modifier_material_filter_set( \
|
||||
PointerRNA *ptr, PointerRNA value, ReportList *reports) \
|
||||
{ \
|
||||
_type##ModifierData *tmd = static_cast<_type##ModifierData *>(ptr->data); \
|
||||
rna_GreasePencilModifier_material_set(ptr, value, reports, &tmd->influence.material); \
|
||||
}
|
||||
|
||||
# define RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(_type) \
|
||||
static void rna_##_type##Modifier_vertex_group_name_set(PointerRNA *ptr, const char *value) \
|
||||
{ \
|
||||
_type##ModifierData *tmd = static_cast<_type##ModifierData *>(ptr->data); \
|
||||
rna_object_vgroup_name_set(ptr, \
|
||||
value, \
|
||||
tmd->influence.vertex_group_name, \
|
||||
sizeof(tmd->influence.vertex_group_name)); \
|
||||
}
|
||||
|
||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOpacity);
|
||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOpacity);
|
||||
|
||||
static void rna_GreasePencilOpacityModifier_opacity_factor_range(
|
||||
PointerRNA *ptr, float *min, float *max, float *softmin, float *softmax)
|
||||
{
|
||||
GreasePencilOpacityModifierData *omd = static_cast<GreasePencilOpacityModifierData *>(ptr->data);
|
||||
|
||||
*min = 0.0f;
|
||||
*softmin = 0.0f;
|
||||
*softmax = (omd->flag & MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY) ? 1.0f : 2.0f;
|
||||
*max = *softmax;
|
||||
}
|
||||
|
||||
static void rna_GreasePencilOpacityModifier_opacity_factor_max_set(PointerRNA *ptr, float value)
|
||||
{
|
||||
GreasePencilOpacityModifierData *omd = static_cast<GreasePencilOpacityModifierData *>(ptr->data);
|
||||
|
||||
omd->color_factor = (omd->flag & MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY) ?
|
||||
std::min(value, 1.0f) :
|
||||
value;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_modifier_panel_open_prop(StructRNA *srna, const char *identifier, const int id)
|
||||
|
@ -7423,6 +7502,186 @@ static void rna_def_modifier_volume_to_mesh(BlenderRNA *brna)
|
|||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
static void rna_def_modifier_grease_pencil_layer_filter(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "layer_filter", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "influence.layer_name");
|
||||
RNA_def_property_ui_text(prop, "Layer", "Layer name");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_layer_pass_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER);
|
||||
RNA_def_property_ui_text(prop, "Use Layer Pass", "Use layer pass filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "layer_pass_filter", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "influence.layer_pass");
|
||||
RNA_def_property_range(prop, 0, 100);
|
||||
RNA_def_property_ui_text(prop, "Layer Pass", "Layer pass filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "invert_layer_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER);
|
||||
RNA_def_property_ui_text(prop, "Invert Layer", "Invert layer filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "invert_layer_pass_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER);
|
||||
RNA_def_property_ui_text(prop, "Invert Layer Pass", "Invert layer pass filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_grease_pencil_material_filter(StructRNA *srna,
|
||||
const char *material_set_fn)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "material_filter", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "influence.material");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, nullptr, material_set_fn, nullptr, "rna_GreasePencilModifier_material_poll");
|
||||
RNA_def_property_ui_text(prop, "Material", "Material used for filtering");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_material_pass_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER);
|
||||
RNA_def_property_ui_text(prop, "Use Material Pass", "Use material pass filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "material_pass_filter", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "influence.material_pass");
|
||||
RNA_def_property_range(prop, 0, 100);
|
||||
RNA_def_property_ui_text(prop, "Material Pass", "Material pass");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "invert_material_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER);
|
||||
RNA_def_property_ui_text(prop, "Invert Material", "Invert material filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "invert_material_pass_filter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER);
|
||||
RNA_def_property_ui_text(prop, "Invert Material Pass", "Invert material pass filter");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_grease_pencil_vertex_group(StructRNA *srna,
|
||||
const char *vertex_group_name_set_fn)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "vertex_group_name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "influence.vertex_group_name");
|
||||
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform");
|
||||
RNA_def_property_string_funcs(prop, nullptr, nullptr, vertex_group_name_set_fn);
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
|
||||
RNA_def_property_ui_text(prop, "Invert Vertex Group", "Invert vertex group weights");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_grease_pencil_custom_curve(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "influence.flag", GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Use Custom Curve", "Use a custom curve to define a factor along the strokes");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "custom_curve", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, nullptr, "influence.custom_curve");
|
||||
RNA_def_property_ui_text(prop, "Curve", "Custom curve to apply effect");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
}
|
||||
|
||||
static void rna_def_modifier_grease_pencil_opacity(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem color_mode_items[] = {
|
||||
{MOD_GREASE_PENCIL_COLOR_BOTH, "BOTH", 0, "Stroke & Fill", "Modify fill and stroke colors"},
|
||||
{MOD_GREASE_PENCIL_COLOR_STROKE, "STROKE", 0, "Stroke", "Modify stroke color only"},
|
||||
{MOD_GREASE_PENCIL_COLOR_FILL, "FILL", 0, "Fill", "Modify fill color only"},
|
||||
{MOD_GREASE_PENCIL_COLOR_HARDNESS, "HARDNESS", 0, "Hardness", "Modify stroke hardness"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "GreasePencilOpacityModifier", "Modifier");
|
||||
RNA_def_struct_ui_text(srna, "Grease Pencil Opacity Modifier", "");
|
||||
RNA_def_struct_sdna(srna, "GreasePencilOpacityModifierData");
|
||||
RNA_def_struct_ui_icon(srna, ICON_MOD_OPACITY);
|
||||
|
||||
rna_def_modifier_grease_pencil_layer_filter(srna);
|
||||
rna_def_modifier_grease_pencil_material_filter(
|
||||
srna, "rna_GreasePencilOpacityModifier_material_filter_set");
|
||||
rna_def_modifier_grease_pencil_vertex_group(
|
||||
srna, "rna_GreasePencilOpacityModifier_vertex_group_name_set");
|
||||
rna_def_modifier_grease_pencil_custom_curve(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "open_influence_panel", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "flag", MOD_GREASE_PENCIL_OPACITY_OPEN_INFLUENCE_PANEL);
|
||||
RNA_def_property_ui_text(prop, "Open Influence Panel", "Open the influence panel");
|
||||
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, nullptr);
|
||||
|
||||
RNA_define_lib_overridable(true);
|
||||
|
||||
prop = RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, color_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Attributes to modify");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "color_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "color_factor");
|
||||
RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 2);
|
||||
RNA_def_property_float_funcs(prop,
|
||||
nullptr,
|
||||
"rna_GreasePencilOpacityModifier_opacity_factor_max_set",
|
||||
"rna_GreasePencilOpacityModifier_opacity_factor_range");
|
||||
RNA_def_property_ui_text(prop, "Opacity Factor", "Factor of opacity");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "hardness_factor", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "hardness_factor");
|
||||
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.0, FLT_MAX, 0.1, 2);
|
||||
RNA_def_property_ui_text(prop, "Hardness Factor", "Factor of stroke hardness");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_weight_as_factor", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "flag", MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Use Weight as Factor", "Use vertex group weight as factor instead of influence");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_uniform_opacity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "flag", MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Uniform Opacity", "Replace the stroke opacity instead of modulating each point");
|
||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
void RNA_def_modifier(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
|
@ -7583,6 +7842,7 @@ void RNA_def_modifier(BlenderRNA *brna)
|
|||
rna_def_modifier_mesh_to_volume(brna);
|
||||
rna_def_modifier_volume_displace(brna);
|
||||
rna_def_modifier_volume_to_mesh(brna);
|
||||
rna_def_modifier_grease_pencil_opacity(brna);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,8 @@ set(SRC
|
|||
intern/MOD_edgesplit.cc
|
||||
intern/MOD_explode.cc
|
||||
intern/MOD_fluid.cc
|
||||
intern/MOD_grease_pencil_opacity.cc
|
||||
intern/MOD_grease_pencil_util.cc
|
||||
intern/MOD_hook.cc
|
||||
intern/MOD_laplaciandeform.cc
|
||||
intern/MOD_laplaciansmooth.cc
|
||||
|
@ -97,6 +99,7 @@ set(SRC
|
|||
|
||||
MOD_modifiertypes.hh
|
||||
MOD_nodes.hh
|
||||
intern/MOD_grease_pencil_util.hh
|
||||
intern/MOD_meshcache_util.hh
|
||||
intern/MOD_solidify_util.hh
|
||||
intern/MOD_ui_common.hh
|
||||
|
|
|
@ -73,6 +73,7 @@ extern ModifierTypeInfo modifierType_Nodes;
|
|||
extern ModifierTypeInfo modifierType_MeshToVolume;
|
||||
extern ModifierTypeInfo modifierType_VolumeDisplace;
|
||||
extern ModifierTypeInfo modifierType_VolumeToMesh;
|
||||
extern ModifierTypeInfo modifierType_GreasePencilOpacity;
|
||||
|
||||
/* MOD_util.cc */
|
||||
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_colortools.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_modifier.hh"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "MOD_grease_pencil_util.hh"
|
||||
#include "MOD_modifiertypes.hh"
|
||||
#include "MOD_ui_common.hh"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace blender {
|
||||
|
||||
using bke::greasepencil::Drawing;
|
||||
using bke::greasepencil::FramesMapKey;
|
||||
using bke::greasepencil::Layer;
|
||||
|
||||
static void init_data(ModifierData *md)
|
||||
{
|
||||
auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
|
||||
|
||||
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(omd, modifier));
|
||||
|
||||
MEMCPY_STRUCT_AFTER(omd, DNA_struct_default_get(GreasePencilOpacityModifierData), modifier);
|
||||
modifier::greasepencil::init_influence_data(&omd->influence, true);
|
||||
}
|
||||
|
||||
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
|
||||
{
|
||||
const auto *omd = reinterpret_cast<const GreasePencilOpacityModifierData *>(md);
|
||||
auto *tomd = reinterpret_cast<GreasePencilOpacityModifierData *>(target);
|
||||
|
||||
modifier::greasepencil::free_influence_data(&tomd->influence);
|
||||
|
||||
BKE_modifier_copydata_generic(md, target, flag);
|
||||
modifier::greasepencil::copy_influence_data(&omd->influence, &tomd->influence, flag);
|
||||
}
|
||||
|
||||
static void free_data(ModifierData *md)
|
||||
{
|
||||
auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
|
||||
modifier::greasepencil::free_influence_data(&omd->influence);
|
||||
}
|
||||
|
||||
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
|
||||
{
|
||||
auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
|
||||
modifier::greasepencil::foreach_influence_ID_link(&omd->influence, ob, walk, user_data);
|
||||
}
|
||||
|
||||
static void modify_stroke_color(const GreasePencilOpacityModifierData &omd,
|
||||
bke::CurvesGeometry &curves,
|
||||
const IndexMask &curves_mask)
|
||||
{
|
||||
const bool use_uniform_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_UNIFORM_OPACITY);
|
||||
const bool use_weight_as_factor = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR);
|
||||
const bool invert_vertex_group = (omd.influence.flag &
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
|
||||
const bool use_curve = (omd.influence.flag & GREASE_PENCIL_INFLUENCE_USE_CUSTOM_CURVE);
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
|
||||
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
bke::SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
|
||||
"opacity", bke::AttrDomain::Point);
|
||||
const VArray<float> vgroup_weights =
|
||||
attributes
|
||||
.lookup_or_default<float>(omd.influence.vertex_group_name, bke::AttrDomain::Point, 1.0f)
|
||||
.varray;
|
||||
|
||||
curves_mask.foreach_index(GrainSize(512), [&](const int64_t curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
for (const int64_t point_i : points) {
|
||||
const float curve_input = points.size() >= 2 ?
|
||||
(float(point_i - points.first()) / float(points.size() - 1)) :
|
||||
0.0f;
|
||||
const float curve_factor = use_curve ? BKE_curvemapping_evaluateF(
|
||||
omd.influence.custom_curve, 0, curve_input) :
|
||||
1.0f;
|
||||
|
||||
if (use_uniform_opacity) {
|
||||
opacities.span[point_i] = std::clamp(omd.color_factor * curve_factor, 0.0f, 1.0f);
|
||||
}
|
||||
else if (use_weight_as_factor) {
|
||||
/* Use vertex group weights as opacity factors. */
|
||||
opacities.span[point_i] = std::clamp(
|
||||
omd.color_factor * curve_factor * vgroup_weights[point_i], 0.0f, 1.0f);
|
||||
}
|
||||
else {
|
||||
/* Use vertex group weights as influence factors. */
|
||||
const float vgroup_weight = vgroup_weights[point_i];
|
||||
const float vgroup_influence = invert_vertex_group ? 1.0f - vgroup_weight : vgroup_weight;
|
||||
opacities.span[point_i] = std::clamp(
|
||||
opacities.span[point_i] + omd.color_factor * curve_factor * vgroup_influence - 1.0f,
|
||||
0.0f,
|
||||
1.0f);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
opacities.finish();
|
||||
}
|
||||
|
||||
static void modify_fill_color(const GreasePencilOpacityModifierData &omd,
|
||||
bke::CurvesGeometry &curves,
|
||||
const IndexMask &curves_mask)
|
||||
{
|
||||
const bool use_vgroup_opacity = (omd.flag & MOD_GREASE_PENCIL_OPACITY_USE_WEIGHT_AS_FACTOR);
|
||||
const bool invert_vertex_group = (omd.influence.flag &
|
||||
GREASE_PENCIL_INFLUENCE_INVERT_VERTEX_GROUP);
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
|
||||
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
/* Fill color opacity per stroke. */
|
||||
bke::SpanAttributeWriter<float> fill_opacities = attributes.lookup_or_add_for_write_span<float>(
|
||||
"fill_opacity", bke::AttrDomain::Curve);
|
||||
VArray<float> vgroup_weights = attributes
|
||||
.lookup_or_default<float>(omd.influence.vertex_group_name,
|
||||
bke::AttrDomain::Point,
|
||||
1.0f)
|
||||
.varray;
|
||||
|
||||
curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
|
||||
if (use_vgroup_opacity) {
|
||||
/* Use the first stroke point as vertex weight. */
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
const float stroke_weight = points.is_empty() ? 1.0f : vgroup_weights[points.first()];
|
||||
const float stroke_influence = invert_vertex_group ? 1.0f - stroke_weight : stroke_weight;
|
||||
|
||||
fill_opacities.span[curve_i] = std::clamp(stroke_influence, 0.0f, 1.0f);
|
||||
}
|
||||
else {
|
||||
fill_opacities.span[curve_i] = std::clamp(omd.color_factor, 0.0f, 1.0f);
|
||||
}
|
||||
});
|
||||
|
||||
fill_opacities.finish();
|
||||
}
|
||||
|
||||
static void modify_hardness(const GreasePencilOpacityModifierData &omd,
|
||||
bke::CurvesGeometry &curves,
|
||||
const IndexMask &curves_mask)
|
||||
{
|
||||
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
bke::SpanAttributeWriter<float> hardnesses = attributes.lookup_for_write_span<float>("hardness");
|
||||
if (!hardnesses) {
|
||||
return;
|
||||
}
|
||||
|
||||
curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
|
||||
hardnesses.span[curve_i] = std::clamp(
|
||||
hardnesses.span[curve_i] * omd.hardness_factor, 0.0f, 1.0f);
|
||||
});
|
||||
|
||||
hardnesses.finish();
|
||||
}
|
||||
|
||||
static void modify_curves(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
bke::CurvesGeometry &curves)
|
||||
{
|
||||
auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
|
||||
|
||||
IndexMaskMemory mask_memory;
|
||||
IndexMask curves_mask = modifier::greasepencil::get_filtered_stroke_mask(
|
||||
ctx->object, curves, omd->influence, mask_memory);
|
||||
|
||||
switch (omd->color_mode) {
|
||||
case MOD_GREASE_PENCIL_COLOR_STROKE:
|
||||
modify_stroke_color(*omd, curves, curves_mask);
|
||||
break;
|
||||
case MOD_GREASE_PENCIL_COLOR_FILL:
|
||||
modify_fill_color(*omd, curves, curves_mask);
|
||||
break;
|
||||
case MOD_GREASE_PENCIL_COLOR_BOTH:
|
||||
modify_stroke_color(*omd, curves, curves_mask);
|
||||
modify_fill_color(*omd, curves, curves_mask);
|
||||
break;
|
||||
case MOD_GREASE_PENCIL_COLOR_HARDNESS:
|
||||
modify_hardness(*omd, curves, curves_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void modify_geometry_set(ModifierData *md,
|
||||
const ModifierEvalContext *ctx,
|
||||
bke::GeometrySet *geometry_set)
|
||||
{
|
||||
auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
|
||||
const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
|
||||
const int frame = scene->r.cfra;
|
||||
|
||||
GreasePencil *grease_pencil = geometry_set->get_grease_pencil_for_write();
|
||||
if (grease_pencil == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
IndexMaskMemory mask_memory;
|
||||
IndexMask layer_mask = modifier::greasepencil::get_filtered_layer_mask(
|
||||
*grease_pencil, omd->influence, mask_memory);
|
||||
Vector<Drawing *> drawings = modifier::greasepencil::get_drawings_for_write(
|
||||
*grease_pencil, layer_mask, frame);
|
||||
threading::parallel_for_each(drawings.index_range(), [&](int64_t i) {
|
||||
modify_curves(md, ctx, drawings[i]->strokes_for_write());
|
||||
});
|
||||
}
|
||||
|
||||
static void panel_draw(const bContext *C, Panel *panel)
|
||||
{
|
||||
uiLayout *layout = panel->layout;
|
||||
|
||||
PointerRNA ob_ptr;
|
||||
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
const GreasePencilModifierColorMode color_mode = GreasePencilModifierColorMode(
|
||||
RNA_enum_get(ptr, "color_mode"));
|
||||
|
||||
uiItemR(layout, ptr, "color_mode", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
||||
if (color_mode == MOD_GREASE_PENCIL_COLOR_HARDNESS) {
|
||||
uiItemR(layout, ptr, "hardness_factor", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
else {
|
||||
const bool use_uniform_opacity = RNA_boolean_get(ptr, "use_uniform_opacity");
|
||||
const bool use_weight_as_factor = RNA_boolean_get(ptr, "use_weight_as_factor");
|
||||
|
||||
uiItemR(layout, ptr, "use_uniform_opacity", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
const char *text = (use_uniform_opacity) ? IFACE_("Opacity") : IFACE_("Opacity Factor");
|
||||
|
||||
uiLayout *row = uiLayoutRow(layout, true);
|
||||
uiLayoutSetActive(row, !use_weight_as_factor || use_uniform_opacity);
|
||||
uiItemR(row, ptr, "color_factor", UI_ITEM_NONE, text, ICON_NONE);
|
||||
if (!use_uniform_opacity) {
|
||||
uiLayout *sub = uiLayoutRow(row, true);
|
||||
uiLayoutSetActive(sub, true);
|
||||
uiItemR(row, ptr, "use_weight_as_factor", UI_ITEM_NONE, "", ICON_MOD_VERTEX_WEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
if (uiLayout *influence_panel = uiLayoutPanel(
|
||||
C, layout, "Influence", ptr, "open_influence_panel"))
|
||||
{
|
||||
modifier::greasepencil::draw_layer_filter_settings(C, influence_panel, ptr);
|
||||
modifier::greasepencil::draw_material_filter_settings(C, influence_panel, ptr);
|
||||
modifier::greasepencil::draw_vertex_group_settings(C, influence_panel, ptr);
|
||||
modifier::greasepencil::draw_custom_curve_settings(C, influence_panel, ptr);
|
||||
}
|
||||
|
||||
modifier_panel_end(layout, ptr);
|
||||
}
|
||||
|
||||
static void panel_register(ARegionType *region_type)
|
||||
{
|
||||
modifier_panel_register(region_type, eModifierType_GreasePencilOpacity, panel_draw);
|
||||
}
|
||||
|
||||
static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
|
||||
{
|
||||
const auto *omd = reinterpret_cast<const GreasePencilOpacityModifierData *>(md);
|
||||
|
||||
BLO_write_struct(writer, GreasePencilOpacityModifierData, omd);
|
||||
modifier::greasepencil::write_influence_data(writer, &omd->influence);
|
||||
}
|
||||
|
||||
static void blend_read(BlendDataReader *reader, ModifierData *md)
|
||||
{
|
||||
auto *omd = reinterpret_cast<GreasePencilOpacityModifierData *>(md);
|
||||
|
||||
modifier::greasepencil::read_influence_data(reader, &omd->influence);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
|
||||
ModifierTypeInfo modifierType_GreasePencilOpacity = {
|
||||
/*idname*/ "GreasePencilOpacity",
|
||||
/*name*/ N_("GreasePencilOpacity"),
|
||||
/*struct_name*/ "GreasePencilOpacityModifierData",
|
||||
/*struct_size*/ sizeof(GreasePencilOpacityModifierData),
|
||||
/*srna*/ &RNA_GreasePencilOpacityModifier,
|
||||
/*type*/ ModifierTypeType::Nonconstructive,
|
||||
/*flags*/
|
||||
static_cast<ModifierTypeFlag>(
|
||||
eModifierTypeFlag_AcceptsGreasePencil | eModifierTypeFlag_SupportsEditmode |
|
||||
eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping),
|
||||
/*icon*/ ICON_MOD_OPACITY,
|
||||
|
||||
/*copy_data*/ blender::copy_data,
|
||||
|
||||
/*deform_verts*/ nullptr,
|
||||
/*deform_matrices*/ nullptr,
|
||||
/*deform_verts_EM*/ nullptr,
|
||||
/*deform_matrices_EM*/ nullptr,
|
||||
/*modify_mesh*/ nullptr,
|
||||
/*modify_geometry_set*/ blender::modify_geometry_set,
|
||||
|
||||
/*init_data*/ blender::init_data,
|
||||
/*required_data_mask*/ nullptr,
|
||||
/*free_data*/ blender::free_data,
|
||||
/*is_disabled*/ nullptr,
|
||||
/*update_depsgraph*/ nullptr,
|
||||
/*depends_on_time*/ nullptr,
|
||||
/*depends_on_normals*/ nullptr,
|
||||
/*foreach_ID_link*/ blender::foreach_ID_link,
|
||||
/*foreach_tex_link*/ nullptr,
|
||||
/*free_runtime_data*/ nullptr,
|
||||
/*panel_register*/ blender::panel_register,
|
||||
/*blend_write*/ blender::blend_write,
|
||||
/*blend_read*/ blender::blend_read,
|
||||
};
|
|
@ -0,0 +1,333 @@
|
|||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#include "MOD_grease_pencil_util.hh"
|
||||
|
||||
#include "BLI_set.hh"
|
||||
|
||||
#include "DNA_grease_pencil_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "BKE_colortools.hh"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_material.h"
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "MOD_ui_common.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "UI_interface.hh"
|
||||
|
||||
namespace blender::modifier::greasepencil {
|
||||
|
||||
using bke::greasepencil::Drawing;
|
||||
using bke::greasepencil::Layer;
|
||||
|
||||
void init_influence_data(GreasePencilModifierInfluenceData *influence_data,
|
||||
const bool has_custom_curve)
|
||||
{
|
||||
if (has_custom_curve) {
|
||||
influence_data->custom_curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemapping_init(influence_data->custom_curve);
|
||||
}
|
||||
}
|
||||
|
||||
void copy_influence_data(const GreasePencilModifierInfluenceData *influence_data_src,
|
||||
GreasePencilModifierInfluenceData *influence_data_dst,
|
||||
const int /*flag*/)
|
||||
{
|
||||
memcpy(influence_data_dst, influence_data_src, sizeof(GreasePencilModifierInfluenceData));
|
||||
influence_data_dst->custom_curve = BKE_curvemapping_copy(influence_data_src->custom_curve);
|
||||
}
|
||||
|
||||
void free_influence_data(GreasePencilModifierInfluenceData *influence_data)
|
||||
{
|
||||
if (influence_data->custom_curve) {
|
||||
BKE_curvemapping_free(influence_data->custom_curve);
|
||||
influence_data->custom_curve = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void foreach_influence_ID_link(GreasePencilModifierInfluenceData *influence_data,
|
||||
Object *ob,
|
||||
IDWalkFunc walk,
|
||||
void *user_data)
|
||||
{
|
||||
walk(user_data, ob, (ID **)&influence_data->material, IDWALK_CB_USER);
|
||||
}
|
||||
|
||||
void write_influence_data(BlendWriter *writer,
|
||||
const GreasePencilModifierInfluenceData *influence_data)
|
||||
{
|
||||
if (influence_data->custom_curve) {
|
||||
BKE_curvemapping_blend_write(writer, influence_data->custom_curve);
|
||||
}
|
||||
}
|
||||
|
||||
void read_influence_data(BlendDataReader *reader,
|
||||
GreasePencilModifierInfluenceData *influence_data)
|
||||
{
|
||||
BLO_read_data_address(reader, &influence_data->custom_curve);
|
||||
if (influence_data->custom_curve) {
|
||||
BKE_curvemapping_blend_read(reader, influence_data->custom_curve);
|
||||
/* Make sure the internal table exists. */
|
||||
BKE_curvemapping_init(influence_data->custom_curve);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_layer_filter_settings(const bContext * /*C*/, uiLayout *layout, PointerRNA *ptr)
|
||||
{
|
||||
PointerRNA ob_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Object, ptr->owner_id);
|
||||
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
|
||||
const bool use_layer_pass = RNA_boolean_get(ptr, "use_layer_pass_filter");
|
||||
uiLayout *row, *col, *sub, *subsub;
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
col = uiLayoutColumn(layout, true);
|
||||
row = uiLayoutRow(col, true);
|
||||
uiLayoutSetPropDecorate(row, false);
|
||||
uiItemPointerR(row, ptr, "layer_filter", &obj_data_ptr, "layers", nullptr, ICON_GREASEPENCIL);
|
||||
sub = uiLayoutRow(row, true);
|
||||
uiItemR(sub, ptr, "invert_layer_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
|
||||
|
||||
row = uiLayoutRowWithHeading(col, true, "Layer Pass");
|
||||
uiLayoutSetPropDecorate(row, false);
|
||||
sub = uiLayoutRow(row, true);
|
||||
uiItemR(sub, ptr, "use_layer_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
|
||||
subsub = uiLayoutRow(sub, true);
|
||||
uiLayoutSetActive(subsub, use_layer_pass);
|
||||
uiItemR(subsub, ptr, "layer_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
|
||||
uiItemR(subsub, ptr, "invert_layer_pass_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
|
||||
}
|
||||
|
||||
void draw_material_filter_settings(const bContext * /*C*/, uiLayout *layout, PointerRNA *ptr)
|
||||
{
|
||||
PointerRNA ob_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Object, ptr->owner_id);
|
||||
PointerRNA obj_data_ptr = RNA_pointer_get(&ob_ptr, "data");
|
||||
const bool use_material_pass = RNA_boolean_get(ptr, "use_material_pass_filter");
|
||||
uiLayout *row, *col, *sub, *subsub;
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
col = uiLayoutColumn(layout, true);
|
||||
row = uiLayoutRow(col, true);
|
||||
uiLayoutSetPropDecorate(row, false);
|
||||
uiItemPointerR(
|
||||
row, ptr, "material_filter", &obj_data_ptr, "materials", nullptr, ICON_SHADING_TEXTURE);
|
||||
sub = uiLayoutRow(row, true);
|
||||
uiItemR(sub, ptr, "invert_material_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
|
||||
|
||||
row = uiLayoutRowWithHeading(col, true, "Material Pass");
|
||||
uiLayoutSetPropDecorate(row, false);
|
||||
sub = uiLayoutRow(row, true);
|
||||
uiItemR(sub, ptr, "use_material_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
|
||||
subsub = uiLayoutRow(sub, true);
|
||||
uiLayoutSetActive(subsub, use_material_pass);
|
||||
uiItemR(subsub, ptr, "material_pass_filter", UI_ITEM_NONE, "", ICON_NONE);
|
||||
uiItemR(subsub, ptr, "invert_material_pass_filter", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
|
||||
}
|
||||
|
||||
void draw_vertex_group_settings(const bContext * /*C*/, uiLayout *layout, PointerRNA *ptr)
|
||||
{
|
||||
PointerRNA ob_ptr = RNA_pointer_create(ptr->owner_id, &RNA_Object, ptr->owner_id);
|
||||
bool has_vertex_group = RNA_string_length(ptr, "vertex_group_name") != 0;
|
||||
uiLayout *row, *sub;
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
row = uiLayoutRow(layout, true);
|
||||
uiItemPointerR(row, ptr, "vertex_group_name", &ob_ptr, "vertex_groups", nullptr, ICON_NONE);
|
||||
sub = uiLayoutRow(row, true);
|
||||
uiLayoutSetActive(sub, has_vertex_group);
|
||||
uiLayoutSetPropDecorate(sub, false);
|
||||
uiItemR(sub, ptr, "invert_vertex_group", UI_ITEM_NONE, "", ICON_ARROW_LEFTRIGHT);
|
||||
}
|
||||
|
||||
void draw_custom_curve_settings(const bContext * /*C*/, uiLayout *layout, PointerRNA *ptr)
|
||||
{
|
||||
bool use_custom_curve = RNA_boolean_get(ptr, "use_custom_curve");
|
||||
|
||||
uiLayoutSetPropSep(layout, true);
|
||||
|
||||
uiItemR(layout, ptr, "use_custom_curve", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
if (use_custom_curve) {
|
||||
uiTemplateCurveMapping(layout, ptr, "custom_curve", 0, false, false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of pass IDs used by grease pencil materials.
|
||||
* This way the material pass can be looked up by index instead of having to get the material for
|
||||
* each curve.
|
||||
*/
|
||||
static Vector<int> get_grease_pencil_material_passes(const Object *ob)
|
||||
{
|
||||
short *totcol = BKE_object_material_len_p(const_cast<Object *>(ob));
|
||||
Vector<int> result(*totcol);
|
||||
Material *ma = nullptr;
|
||||
for (short i = 0; i < *totcol; i++) {
|
||||
ma = BKE_object_material_get(const_cast<Object *>(ob), i + 1);
|
||||
/* Pass index of the grease pencil material. */
|
||||
result[i] = ma->gp_style->index;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
|
||||
const std::optional<StringRef> layer_name_filter,
|
||||
const std::optional<int> layer_pass_filter,
|
||||
const bool layer_filter_invert,
|
||||
const bool layer_pass_filter_invert,
|
||||
IndexMaskMemory &memory)
|
||||
{
|
||||
const IndexMask full_mask = grease_pencil.layers().index_range();
|
||||
if (!layer_name_filter && !layer_pass_filter) {
|
||||
return full_mask;
|
||||
}
|
||||
|
||||
bke::AttributeAccessor layer_attributes = grease_pencil.attributes();
|
||||
const Span<const Layer *> layers = grease_pencil.layers();
|
||||
const VArray<int> layer_passes =
|
||||
layer_attributes.lookup_or_default<int>("pass", bke::AttrDomain::Layer, 0).varray;
|
||||
|
||||
IndexMask result = IndexMask::from_predicate(
|
||||
full_mask, GrainSize(4096), memory, [&](const int64_t layer_i) {
|
||||
if (layer_name_filter) {
|
||||
const Layer &layer = *layers[layer_i];
|
||||
const bool match = (layer.name() == layer_name_filter.value());
|
||||
if (match == layer_filter_invert) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (layer_pass_filter) {
|
||||
const int layer_pass = layer_passes.get(layer_i);
|
||||
const bool match = (layer_pass == layer_pass_filter.value());
|
||||
if (match == layer_pass_filter_invert) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
|
||||
const GreasePencilModifierInfluenceData &influence_data,
|
||||
IndexMaskMemory &memory)
|
||||
{
|
||||
return get_filtered_layer_mask(
|
||||
grease_pencil,
|
||||
influence_data.layer_name[0] != '\0' ?
|
||||
std::make_optional<StringRef>(influence_data.layer_name) :
|
||||
std::nullopt,
|
||||
(influence_data.flag & GREASE_PENCIL_INFLUENCE_USE_LAYER_PASS_FILTER) ?
|
||||
std::make_optional<int>(influence_data.layer_pass) :
|
||||
std::nullopt,
|
||||
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_LAYER_FILTER,
|
||||
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_LAYER_PASS_FILTER,
|
||||
memory);
|
||||
}
|
||||
|
||||
static IndexMask get_filtered_stroke_mask(const Object *ob,
|
||||
const bke::CurvesGeometry &curves,
|
||||
const Material *material_filter,
|
||||
const std::optional<int> material_pass_filter,
|
||||
const bool material_filter_invert,
|
||||
const bool material_pass_filter_invert,
|
||||
IndexMaskMemory &memory)
|
||||
{
|
||||
const IndexMask full_mask = curves.curves_range();
|
||||
if (!material_filter && !material_pass_filter) {
|
||||
return full_mask;
|
||||
}
|
||||
|
||||
const int material_filter_index = BKE_object_material_index_get(
|
||||
const_cast<Object *>(ob), const_cast<Material *>(material_filter));
|
||||
const Vector<int> material_pass_by_index = get_grease_pencil_material_passes(ob);
|
||||
|
||||
bke::AttributeAccessor attributes = curves.attributes();
|
||||
VArray<int> stroke_materials =
|
||||
attributes.lookup_or_default<int>("material_index", bke::AttrDomain::Curve, 0).varray;
|
||||
|
||||
IndexMask result = IndexMask::from_predicate(
|
||||
full_mask, GrainSize(4096), memory, [&](const int64_t stroke_i) {
|
||||
const int material_index = stroke_materials.get(stroke_i);
|
||||
if (material_filter != nullptr) {
|
||||
const bool match = (material_index == material_filter_index);
|
||||
if (match == material_filter_invert) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (material_pass_filter) {
|
||||
const int material_pass = material_pass_by_index[material_index];
|
||||
const bool match = (material_pass == material_pass_filter.value());
|
||||
if (match == material_pass_filter_invert) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
IndexMask get_filtered_stroke_mask(const Object *ob,
|
||||
const bke::CurvesGeometry &curves,
|
||||
const GreasePencilModifierInfluenceData &influence_data,
|
||||
IndexMaskMemory &memory)
|
||||
{
|
||||
return get_filtered_stroke_mask(
|
||||
ob,
|
||||
curves,
|
||||
influence_data.material,
|
||||
(influence_data.flag & GREASE_PENCIL_INFLUENCE_USE_MATERIAL_PASS_FILTER) ?
|
||||
std::make_optional<int>(influence_data.material_pass) :
|
||||
std::nullopt,
|
||||
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_FILTER,
|
||||
influence_data.flag & GREASE_PENCIL_INFLUENCE_INVERT_MATERIAL_PASS_FILTER,
|
||||
memory);
|
||||
}
|
||||
|
||||
Vector<bke::greasepencil::Drawing *> get_drawings_for_write(GreasePencil &grease_pencil,
|
||||
const IndexMask &layer_mask,
|
||||
int frame)
|
||||
{
|
||||
/* Set of unique drawing indices. */
|
||||
Set<int> drawing_indices;
|
||||
for (const int64_t i : layer_mask.index_range()) {
|
||||
Layer *layer = grease_pencil.layers_for_write()[layer_mask[i]];
|
||||
const int drawing_index = layer->drawing_index_at(frame);
|
||||
if (drawing_index >= 0) {
|
||||
drawing_indices.add(drawing_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* List of owned drawings, ignore drawing references to other data blocks. */
|
||||
Vector<bke::greasepencil::Drawing *> drawings;
|
||||
for (const int drawing_index : drawing_indices) {
|
||||
GreasePencilDrawingBase *drawing_base = grease_pencil.drawing(drawing_index);
|
||||
if (drawing_base->type == GP_DRAWING) {
|
||||
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_base);
|
||||
drawings.append(&drawing->wrap());
|
||||
}
|
||||
}
|
||||
return drawings;
|
||||
}
|
||||
|
||||
} // namespace blender::modifier::greasepencil
|
|
@ -0,0 +1,66 @@
|
|||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BKE_modifier.hh"
|
||||
|
||||
struct ARegionType;
|
||||
struct bContext;
|
||||
struct GreasePencil;
|
||||
struct GreasePencilModifierInfluenceData;
|
||||
struct GreasePencilModifierLayerFilter;
|
||||
struct GreasePencilModifierMaterialFilter;
|
||||
struct PanelType;
|
||||
struct PointerRNA;
|
||||
struct uiLayout;
|
||||
namespace blender::bke {
|
||||
class CurvesGeometry;
|
||||
namespace greasepencil {
|
||||
class Drawing;
|
||||
}
|
||||
} // namespace blender::bke
|
||||
|
||||
namespace blender::modifier::greasepencil {
|
||||
|
||||
void init_influence_data(GreasePencilModifierInfluenceData *influence_data, bool has_custom_curve);
|
||||
void copy_influence_data(const GreasePencilModifierInfluenceData *influence_data_src,
|
||||
GreasePencilModifierInfluenceData *influence_data_dst,
|
||||
int flag);
|
||||
void free_influence_data(GreasePencilModifierInfluenceData *influence_data);
|
||||
void foreach_influence_ID_link(GreasePencilModifierInfluenceData *influence_data,
|
||||
Object *ob,
|
||||
IDWalkFunc walk,
|
||||
void *user_data);
|
||||
void write_influence_data(BlendWriter *writer,
|
||||
const GreasePencilModifierInfluenceData *influence_data);
|
||||
void read_influence_data(BlendDataReader *reader,
|
||||
GreasePencilModifierInfluenceData *influence_data);
|
||||
|
||||
void draw_layer_filter_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr);
|
||||
void draw_material_filter_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr);
|
||||
void draw_vertex_group_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr);
|
||||
void draw_custom_curve_settings(const bContext *C, uiLayout *layout, PointerRNA *ptr);
|
||||
|
||||
IndexMask get_filtered_layer_mask(const GreasePencil &grease_pencil,
|
||||
const GreasePencilModifierInfluenceData &influence_data,
|
||||
IndexMaskMemory &memory);
|
||||
|
||||
IndexMask get_filtered_stroke_mask(const Object *ob,
|
||||
const bke::CurvesGeometry &curves,
|
||||
const GreasePencilModifierInfluenceData &influence_data,
|
||||
IndexMaskMemory &memory);
|
||||
|
||||
Vector<bke::greasepencil::Drawing *> get_drawings_for_write(GreasePencil &grease_pencil,
|
||||
const IndexMask &layer_mask,
|
||||
int frame);
|
||||
|
||||
} // namespace blender::modifier::greasepencil
|
|
@ -270,5 +270,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
|||
INIT_TYPE(VolumeDisplace);
|
||||
INIT_TYPE(VolumeToMesh);
|
||||
INIT_TYPE(Nodes);
|
||||
INIT_TYPE(GreasePencilOpacity);
|
||||
#undef INIT_TYPE
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue