WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
11 changed files with 1079 additions and 1 deletions
Showing only changes of commit 6c4a058e8b - Show all commits

View File

@ -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)

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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,
};

View File

@ -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

View File

@ -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

View File

@ -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
}