GPv3: Texture offset modifier
Port of the GPv2 texture modifier for transforming UVs of stroke points. Pull Request: https://projects.blender.org/blender/blender/pulls/119050
This commit is contained in:
parent
6dfb1cdf22
commit
d7c718dfd4
@ -108,6 +108,7 @@ class OBJECT_MT_modifier_add_edit(ModifierAddMenu, Menu):
|
|||||||
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_MIX')
|
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_MIX')
|
||||||
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_PROXIMITY')
|
self.operator_modifier_add(layout, 'VERTEX_WEIGHT_PROXIMITY')
|
||||||
if ob_type == 'GREASEPENCIL':
|
if ob_type == 'GREASEPENCIL':
|
||||||
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_TEXTURE')
|
||||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_TIME')
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_TIME')
|
||||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_VERTEX_WEIGHT_PROXIMITY')
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_VERTEX_WEIGHT_PROXIMITY')
|
||||||
self.operator_modifier_add(layout, 'GREASE_PENCIL_VERTEX_WEIGHT_ANGLE')
|
self.operator_modifier_add(layout, 'GREASE_PENCIL_VERTEX_WEIGHT_ANGLE')
|
||||||
|
@ -76,12 +76,12 @@ class Drawing : public ::GreasePencilDrawing {
|
|||||||
void tag_positions_changed();
|
void tag_positions_changed();
|
||||||
void tag_topology_changed();
|
void tag_topology_changed();
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Returns the matrices that transform from a 3D point in layer-space to a 2D point in
|
* Returns the matrices that transform from a 3D point in layer-space to a 2D point in
|
||||||
* texture-space.
|
* texture-space.
|
||||||
*/
|
*/
|
||||||
Span<float4x2> texture_matrices() const;
|
Span<float4x2> texture_matrices() const;
|
||||||
/*
|
/**
|
||||||
* Sets the matrices the that transform from a 3D point in layer-space to a 2D point in
|
* Sets the matrices the that transform from a 3D point in layer-space to a 2D point in
|
||||||
* texture-space
|
* texture-space
|
||||||
*/
|
*/
|
||||||
|
@ -1840,6 +1840,55 @@ static void legacy_object_modifier_subdiv(Object &object, GpencilModifierData &l
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void legacy_object_modifier_texture(Object &object, GpencilModifierData &legacy_md)
|
||||||
|
{
|
||||||
|
ModifierData &md = legacy_object_modifier_common(
|
||||||
|
object, eModifierType_GreasePencilTexture, legacy_md);
|
||||||
|
auto &md_texture = reinterpret_cast<GreasePencilTextureModifierData &>(md);
|
||||||
|
auto &legacy_md_texture = reinterpret_cast<TextureGpencilModifierData &>(legacy_md);
|
||||||
|
|
||||||
|
switch (eTextureGpencil_Mode(legacy_md_texture.mode)) {
|
||||||
|
case STROKE:
|
||||||
|
md_texture.mode = MOD_GREASE_PENCIL_TEXTURE_STROKE;
|
||||||
|
break;
|
||||||
|
case FILL:
|
||||||
|
md_texture.mode = MOD_GREASE_PENCIL_TEXTURE_FILL;
|
||||||
|
break;
|
||||||
|
case STROKE_AND_FILL:
|
||||||
|
md_texture.mode = MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (eTextureGpencil_Fit(legacy_md_texture.fit_method)) {
|
||||||
|
case GP_TEX_FIT_STROKE:
|
||||||
|
md_texture.fit_method = MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE;
|
||||||
|
break;
|
||||||
|
case GP_TEX_CONSTANT_LENGTH:
|
||||||
|
md_texture.fit_method = MOD_GREASE_PENCIL_TEXTURE_CONSTANT_LENGTH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
md_texture.uv_offset = legacy_md_texture.uv_offset;
|
||||||
|
md_texture.uv_scale = legacy_md_texture.uv_scale;
|
||||||
|
md_texture.fill_rotation = legacy_md_texture.fill_rotation;
|
||||||
|
copy_v2_v2(md_texture.fill_offset, legacy_md_texture.fill_offset);
|
||||||
|
md_texture.fill_scale = legacy_md_texture.fill_scale;
|
||||||
|
md_texture.layer_pass = legacy_md_texture.layer_pass;
|
||||||
|
md_texture.alignment_rotation = legacy_md_texture.alignment_rotation;
|
||||||
|
|
||||||
|
legacy_object_modifier_influence(md_texture.influence,
|
||||||
|
legacy_md_texture.layername,
|
||||||
|
legacy_md_texture.layer_pass,
|
||||||
|
legacy_md_texture.flag & GP_TEX_INVERT_LAYER,
|
||||||
|
legacy_md_texture.flag & GP_TEX_INVERT_LAYERPASS,
|
||||||
|
&legacy_md_texture.material,
|
||||||
|
legacy_md_texture.pass_index,
|
||||||
|
legacy_md_texture.flag & GP_TEX_INVERT_MATERIAL,
|
||||||
|
legacy_md_texture.flag & GP_TEX_INVERT_PASS,
|
||||||
|
legacy_md_texture.vgname,
|
||||||
|
legacy_md_texture.flag & GP_TEX_INVERT_VGROUP,
|
||||||
|
nullptr,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
static void legacy_object_modifier_thickness(Object &object, GpencilModifierData &legacy_md)
|
static void legacy_object_modifier_thickness(Object &object, GpencilModifierData &legacy_md)
|
||||||
{
|
{
|
||||||
ModifierData &md = legacy_object_modifier_common(
|
ModifierData &md = legacy_object_modifier_common(
|
||||||
@ -2286,6 +2335,9 @@ static void legacy_object_modifiers(Main & /*bmain*/, Object &object)
|
|||||||
case eGpencilModifierType_Subdiv:
|
case eGpencilModifierType_Subdiv:
|
||||||
legacy_object_modifier_subdiv(object, *gpd_md);
|
legacy_object_modifier_subdiv(object, *gpd_md);
|
||||||
break;
|
break;
|
||||||
|
case eGpencilModifierType_Texture:
|
||||||
|
legacy_object_modifier_texture(object, *gpd_md);
|
||||||
|
break;
|
||||||
case eGpencilModifierType_Thick:
|
case eGpencilModifierType_Thick:
|
||||||
legacy_object_modifier_thickness(object, *gpd_md);
|
legacy_object_modifier_thickness(object, *gpd_md);
|
||||||
break;
|
break;
|
||||||
@ -2310,7 +2362,6 @@ static void legacy_object_modifiers(Main & /*bmain*/, Object &object)
|
|||||||
case eGpencilModifierType_Simplify:
|
case eGpencilModifierType_Simplify:
|
||||||
legacy_object_modifier_simplify(object, *gpd_md);
|
legacy_object_modifier_simplify(object, *gpd_md);
|
||||||
break;
|
break;
|
||||||
case eGpencilModifierType_Texture:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +538,10 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
"fill_color", bke::AttrDomain::Curve, ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
|
"fill_color", bke::AttrDomain::Curve, ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
|
||||||
const VArray<int> materials = *attributes.lookup_or_default<int>(
|
const VArray<int> materials = *attributes.lookup_or_default<int>(
|
||||||
"material_index", bke::AttrDomain::Curve, 0);
|
"material_index", bke::AttrDomain::Curve, 0);
|
||||||
|
const VArray<float> u_translations = *attributes.lookup_or_default<float>(
|
||||||
|
"u_translation", bke::AttrDomain::Curve, 0.0f);
|
||||||
|
const VArray<float> u_scales = *attributes.lookup_or_default<float>(
|
||||||
|
"u_scale", bke::AttrDomain::Curve, 1.0f);
|
||||||
const Span<uint3> triangles = info.drawing.triangles();
|
const Span<uint3> triangles = info.drawing.triangles();
|
||||||
const Span<float4x2> texture_matrices = info.drawing.texture_matrices();
|
const Span<float4x2> texture_matrices = info.drawing.texture_matrices();
|
||||||
const Span<int> verts_start_offsets = verts_start_offsets_per_visible_drawing[drawing_i];
|
const Span<int> verts_start_offsets = verts_start_offsets_per_visible_drawing[drawing_i];
|
||||||
@ -554,7 +558,7 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
int8_t end_cap,
|
int8_t end_cap,
|
||||||
int point_i,
|
int point_i,
|
||||||
int idx,
|
int idx,
|
||||||
float length,
|
float u_stroke,
|
||||||
const float4x2 &texture_matrix,
|
const float4x2 &texture_matrix,
|
||||||
GreasePencilStrokeVert &s_vert,
|
GreasePencilStrokeVert &s_vert,
|
||||||
GreasePencilColorVert &c_vert) {
|
GreasePencilColorVert &c_vert) {
|
||||||
@ -572,7 +576,7 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
|
|
||||||
s_vert.packed_asp_hard_rot = pack_rotation_aspect_hardness(
|
s_vert.packed_asp_hard_rot = pack_rotation_aspect_hardness(
|
||||||
rotations[point_i], stroke_point_aspect_ratios[curve_i], stroke_hardnesses[curve_i]);
|
rotations[point_i], stroke_point_aspect_ratios[curve_i], stroke_hardnesses[curve_i]);
|
||||||
s_vert.u_stroke = length;
|
s_vert.u_stroke = u_stroke;
|
||||||
copy_v2_v2(s_vert.uv_fill, texture_matrix * float4(pos, 1.0f));
|
copy_v2_v2(s_vert.uv_fill, texture_matrix * float4(pos, 1.0f));
|
||||||
|
|
||||||
copy_v4_v4(c_vert.vcol, vertex_colors[point_i]);
|
copy_v4_v4(c_vert.vcol, vertex_colors[point_i]);
|
||||||
@ -612,16 +616,18 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write all the point attributes to the vertex buffers. Create a quad for each point. */
|
/* Write all the point attributes to the vertex buffers. Create a quad for each point. */
|
||||||
|
const float u_scale = u_scales[curve_i];
|
||||||
|
const float u_translation = u_translations[curve_i];
|
||||||
for (const int i : IndexRange(points.size())) {
|
for (const int i : IndexRange(points.size())) {
|
||||||
const int idx = i + 1;
|
const int idx = i + 1;
|
||||||
const float length = (i >= 1) ? lengths[i - 1] : 0.0f;
|
const float u_stroke = u_scale * (i > 0 ? lengths[i - 1] : 0.0f) + u_translation;
|
||||||
populate_point(verts_range,
|
populate_point(verts_range,
|
||||||
curve_i,
|
curve_i,
|
||||||
start_caps[curve_i],
|
start_caps[curve_i],
|
||||||
end_caps[curve_i],
|
end_caps[curve_i],
|
||||||
points[i],
|
points[i],
|
||||||
idx,
|
idx,
|
||||||
length,
|
u_stroke,
|
||||||
texture_matrix,
|
texture_matrix,
|
||||||
verts_slice[idx],
|
verts_slice[idx],
|
||||||
cols_slice[idx]);
|
cols_slice[idx]);
|
||||||
@ -629,14 +635,14 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||||||
|
|
||||||
if (is_cyclic) {
|
if (is_cyclic) {
|
||||||
const int idx = points.size() + 1;
|
const int idx = points.size() + 1;
|
||||||
const float length = points.size() > 1 ? lengths[points.size() - 1] : 0.0f;
|
const float u_stroke = u_scale * lengths[points.size() - 1] + u_translation;
|
||||||
populate_point(verts_range,
|
populate_point(verts_range,
|
||||||
curve_i,
|
curve_i,
|
||||||
start_caps[curve_i],
|
start_caps[curve_i],
|
||||||
end_caps[curve_i],
|
end_caps[curve_i],
|
||||||
points[0],
|
points[0],
|
||||||
idx,
|
idx,
|
||||||
length,
|
u_stroke,
|
||||||
texture_matrix,
|
texture_matrix,
|
||||||
verts_slice[idx],
|
verts_slice[idx],
|
||||||
cols_slice[idx]);
|
cols_slice[idx]);
|
||||||
|
@ -1071,5 +1071,15 @@
|
|||||||
.distance = 0.1f, \
|
.distance = 0.1f, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define _DNA_DEFAULT_GreasePencilTextureModifierData \
|
||||||
|
{ \
|
||||||
|
.uv_offset = 0.0f, \
|
||||||
|
.uv_scale = 1.0f, \
|
||||||
|
.fill_rotation = 0.0f, \
|
||||||
|
.fill_offset = {0.0f, 0.0f}, \
|
||||||
|
.fill_scale = 1.0f, \
|
||||||
|
.fit_method = GP_TEX_CONSTANT_LENGTH, \
|
||||||
|
.mode = 0, \
|
||||||
|
}
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
@ -120,6 +120,7 @@ typedef enum ModifierType {
|
|||||||
eModifierType_GreasePencilShrinkwrap = 83,
|
eModifierType_GreasePencilShrinkwrap = 83,
|
||||||
eModifierType_GreasePencilBuild = 84,
|
eModifierType_GreasePencilBuild = 84,
|
||||||
eModifierType_GreasePencilSimplify = 85,
|
eModifierType_GreasePencilSimplify = 85,
|
||||||
|
eModifierType_GreasePencilTexture = 86,
|
||||||
NUM_MODIFIER_TYPES,
|
NUM_MODIFIER_TYPES,
|
||||||
} ModifierType;
|
} ModifierType;
|
||||||
|
|
||||||
@ -3430,3 +3431,35 @@ typedef enum GreasePencilSimplifyModifierMode {
|
|||||||
MOD_GREASE_PENCIL_SIMPLIFY_SAMPLE = 2,
|
MOD_GREASE_PENCIL_SIMPLIFY_SAMPLE = 2,
|
||||||
MOD_GREASE_PENCIL_SIMPLIFY_MERGE = 3,
|
MOD_GREASE_PENCIL_SIMPLIFY_MERGE = 3,
|
||||||
} GreasePencilSimplifyModifierMode;
|
} GreasePencilSimplifyModifierMode;
|
||||||
|
|
||||||
|
typedef struct GreasePencilTextureModifierData {
|
||||||
|
ModifierData modifier;
|
||||||
|
GreasePencilModifierInfluenceData influence;
|
||||||
|
/* Offset value to add to uv_fac. */
|
||||||
|
float uv_offset;
|
||||||
|
float uv_scale;
|
||||||
|
float fill_rotation;
|
||||||
|
float fill_offset[2];
|
||||||
|
float fill_scale;
|
||||||
|
/* Custom index for passes. */
|
||||||
|
int layer_pass;
|
||||||
|
/* Texture fit options. */
|
||||||
|
short fit_method;
|
||||||
|
short mode;
|
||||||
|
/* Dot texture rotation. */
|
||||||
|
float alignment_rotation;
|
||||||
|
char _pad[4];
|
||||||
|
} GreasePencilTextureModifierData;
|
||||||
|
|
||||||
|
/* Texture->fit_method */
|
||||||
|
typedef enum GreasePencilTextureModifierFit {
|
||||||
|
MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE = 0,
|
||||||
|
MOD_GREASE_PENCIL_TEXTURE_CONSTANT_LENGTH = 1,
|
||||||
|
} GreasePencilTextureModifierFit;
|
||||||
|
|
||||||
|
/* Texture->mode */
|
||||||
|
typedef enum GreasePencilTextureModifierMode {
|
||||||
|
MOD_GREASE_PENCIL_TEXTURE_STROKE = 0,
|
||||||
|
MOD_GREASE_PENCIL_TEXTURE_FILL = 1,
|
||||||
|
MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL = 2,
|
||||||
|
} GreasePencilTextureModifierMode;
|
||||||
|
@ -360,6 +360,7 @@ SDNA_DEFAULT_DECL_STRUCT(GreasePencilSimplifyModifierData);
|
|||||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilEnvelopeModifierData);
|
SDNA_DEFAULT_DECL_STRUCT(GreasePencilEnvelopeModifierData);
|
||||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilOutlineModifierData);
|
SDNA_DEFAULT_DECL_STRUCT(GreasePencilOutlineModifierData);
|
||||||
SDNA_DEFAULT_DECL_STRUCT(GreasePencilShrinkwrapModifierData);
|
SDNA_DEFAULT_DECL_STRUCT(GreasePencilShrinkwrapModifierData);
|
||||||
|
SDNA_DEFAULT_DECL_STRUCT(GreasePencilTextureModifierData);
|
||||||
|
|
||||||
#undef SDNA_DEFAULT_DECL_STRUCT
|
#undef SDNA_DEFAULT_DECL_STRUCT
|
||||||
|
|
||||||
@ -637,6 +638,7 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
|
|||||||
SDNA_DEFAULT_DECL(GreasePencilEnvelopeModifierData),
|
SDNA_DEFAULT_DECL(GreasePencilEnvelopeModifierData),
|
||||||
SDNA_DEFAULT_DECL(GreasePencilOutlineModifierData),
|
SDNA_DEFAULT_DECL(GreasePencilOutlineModifierData),
|
||||||
SDNA_DEFAULT_DECL(GreasePencilShrinkwrapModifierData),
|
SDNA_DEFAULT_DECL(GreasePencilShrinkwrapModifierData),
|
||||||
|
SDNA_DEFAULT_DECL(GreasePencilTextureModifierData),
|
||||||
};
|
};
|
||||||
#undef SDNA_DEFAULT_DECL
|
#undef SDNA_DEFAULT_DECL
|
||||||
#undef SDNA_DEFAULT_DECL_EX
|
#undef SDNA_DEFAULT_DECL_EX
|
||||||
|
@ -134,6 +134,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
|
|||||||
ICON_MOD_TIME,
|
ICON_MOD_TIME,
|
||||||
"Time Offset",
|
"Time Offset",
|
||||||
"Offset keyframes"},
|
"Offset keyframes"},
|
||||||
|
{eModifierType_GreasePencilTexture,
|
||||||
|
"GREASE_PENCIL_TEXTURE",
|
||||||
|
ICON_MOD_UVPROJECT,
|
||||||
|
"Texture Mapping",
|
||||||
|
"Change stroke UV texture values"},
|
||||||
|
|
||||||
RNA_ENUM_ITEM_HEADING(N_("Generate"), nullptr),
|
RNA_ENUM_ITEM_HEADING(N_("Generate"), nullptr),
|
||||||
{eModifierType_Array,
|
{eModifierType_Array,
|
||||||
@ -2002,6 +2007,7 @@ RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilEnvelope);
|
|||||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOutline);
|
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilOutline);
|
||||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilShrinkwrap);
|
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilShrinkwrap);
|
||||||
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilBuild);
|
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilBuild);
|
||||||
|
RNA_MOD_GREASE_PENCIL_MATERIAL_FILTER_SET(GreasePencilTexture);
|
||||||
|
|
||||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOffset);
|
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOffset);
|
||||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOpacity);
|
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilOpacity);
|
||||||
@ -2017,6 +2023,7 @@ RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilArmature);
|
|||||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilSimplify);
|
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilSimplify);
|
||||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilEnvelope);
|
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilEnvelope);
|
||||||
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilShrinkwrap);
|
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilShrinkwrap);
|
||||||
|
RNA_MOD_GREASE_PENCIL_VERTEX_GROUP_SET(GreasePencilTexture);
|
||||||
|
|
||||||
static void rna_GreasePencilLineartModifier_material_set(PointerRNA *ptr,
|
static void rna_GreasePencilLineartModifier_material_set(PointerRNA *ptr,
|
||||||
PointerRNA value,
|
PointerRNA value,
|
||||||
@ -10805,6 +10812,116 @@ static void rna_def_modifier_grease_pencil_build(BlenderRNA *brna)
|
|||||||
RNA_define_lib_overridable(false);
|
RNA_define_lib_overridable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_def_modifier_grease_pencil_texture(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
static const EnumPropertyItem fit_type_items[] = {
|
||||||
|
{MOD_GREASE_PENCIL_TEXTURE_CONSTANT_LENGTH,
|
||||||
|
"CONSTANT_LENGTH",
|
||||||
|
0,
|
||||||
|
"Constant Length",
|
||||||
|
"Keep the texture at a constant length regardless of the length of each stroke"},
|
||||||
|
{MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE,
|
||||||
|
"FIT_STROKE",
|
||||||
|
0,
|
||||||
|
"Stroke Length",
|
||||||
|
"Scale the texture to fit the length of each stroke"},
|
||||||
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EnumPropertyItem mode_items[] = {
|
||||||
|
{MOD_GREASE_PENCIL_TEXTURE_STROKE,
|
||||||
|
"STROKE",
|
||||||
|
0,
|
||||||
|
"Stroke",
|
||||||
|
"Manipulate only stroke texture coordinates"},
|
||||||
|
{MOD_GREASE_PENCIL_TEXTURE_FILL,
|
||||||
|
"FILL",
|
||||||
|
0,
|
||||||
|
"Fill",
|
||||||
|
"Manipulate only fill texture coordinates"},
|
||||||
|
{MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL,
|
||||||
|
"STROKE_AND_FILL",
|
||||||
|
0,
|
||||||
|
"Stroke & Fill",
|
||||||
|
"Manipulate both stroke and fill texture coordinates"},
|
||||||
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
|
srna = RNA_def_struct(brna, "GreasePencilTextureModifier", "Modifier");
|
||||||
|
RNA_def_struct_ui_text(
|
||||||
|
srna, "Grease Pencil Texture Modifier", "Transform stroke texture coordinates Modifier");
|
||||||
|
RNA_def_struct_sdna(srna, "GreasePencilTextureModifierData");
|
||||||
|
RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
|
||||||
|
|
||||||
|
rna_def_modifier_grease_pencil_layer_filter(srna);
|
||||||
|
rna_def_modifier_grease_pencil_material_filter(
|
||||||
|
srna, "rna_GreasePencilTextureModifier_material_filter_set");
|
||||||
|
rna_def_modifier_grease_pencil_vertex_group(
|
||||||
|
srna, "rna_GreasePencilTextureModifier_vertex_group_name_set");
|
||||||
|
|
||||||
|
rna_def_modifier_panel_open_prop(srna, "open_influence_panel", 0);
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(true);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "uv_offset", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, nullptr, "uv_offset");
|
||||||
|
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, -100.0, 100.0, 0.1, 3);
|
||||||
|
RNA_def_property_ui_text(prop, "UV Offset", "Offset value to add to stroke UVs");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "uv_scale", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_float_sdna(prop, nullptr, "uv_scale");
|
||||||
|
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||||
|
RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
|
||||||
|
RNA_def_property_ui_text(prop, "UV Scale", "Factor to scale the UVs");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
/* Rotation of Dot Texture. */
|
||||||
|
prop = RNA_def_property(srna, "alignment_rotation", PROP_FLOAT, PROP_ANGLE);
|
||||||
|
RNA_def_property_float_sdna(prop, nullptr, "alignment_rotation");
|
||||||
|
RNA_def_property_float_default(prop, 0.0f);
|
||||||
|
RNA_def_property_range(prop, -DEG2RADF(90.0f), DEG2RADF(90.0f));
|
||||||
|
RNA_def_property_ui_range(prop, -DEG2RADF(90.0f), DEG2RADF(90.0f), 10, 3);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Rotation", "Additional rotation applied to dots and square strokes");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "fill_rotation", PROP_FLOAT, PROP_ANGLE);
|
||||||
|
RNA_def_property_float_sdna(prop, nullptr, "fill_rotation");
|
||||||
|
RNA_def_property_ui_text(prop, "Fill Rotation", "Additional rotation of the fill UV");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "fill_offset", PROP_FLOAT, PROP_COORDS);
|
||||||
|
RNA_def_property_float_sdna(prop, nullptr, "fill_offset");
|
||||||
|
RNA_def_property_array(prop, 2);
|
||||||
|
RNA_def_property_ui_text(prop, "Fill Offset", "Additional offset of the fill UV");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "fill_scale", PROP_FLOAT, PROP_COORDS);
|
||||||
|
RNA_def_property_float_sdna(prop, nullptr, "fill_scale");
|
||||||
|
RNA_def_property_range(prop, 0.01f, 100.0f);
|
||||||
|
RNA_def_property_ui_text(prop, "Fill Scale", "Additional scale of the fill UV");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, nullptr, "fit_method");
|
||||||
|
RNA_def_property_enum_items(prop, fit_type_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Fit Method", "");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, nullptr, "mode");
|
||||||
|
RNA_def_property_enum_items(prop, mode_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Mode", "");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(false);
|
||||||
|
}
|
||||||
|
|
||||||
void RNA_def_modifier(BlenderRNA *brna)
|
void RNA_def_modifier(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
StructRNA *srna;
|
StructRNA *srna;
|
||||||
@ -10999,6 +11116,7 @@ void RNA_def_modifier(BlenderRNA *brna)
|
|||||||
rna_def_modifier_grease_pencil_outline(brna);
|
rna_def_modifier_grease_pencil_outline(brna);
|
||||||
rna_def_modifier_grease_pencil_shrinkwrap(brna);
|
rna_def_modifier_grease_pencil_shrinkwrap(brna);
|
||||||
rna_def_modifier_grease_pencil_build(brna);
|
rna_def_modifier_grease_pencil_build(brna);
|
||||||
|
rna_def_modifier_grease_pencil_texture(brna);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,6 +68,7 @@ set(SRC
|
|||||||
intern/MOD_grease_pencil_shrinkwrap.cc
|
intern/MOD_grease_pencil_shrinkwrap.cc
|
||||||
intern/MOD_grease_pencil_smooth.cc
|
intern/MOD_grease_pencil_smooth.cc
|
||||||
intern/MOD_grease_pencil_subdiv.cc
|
intern/MOD_grease_pencil_subdiv.cc
|
||||||
|
intern/MOD_grease_pencil_texture.cc
|
||||||
intern/MOD_grease_pencil_thickness.cc
|
intern/MOD_grease_pencil_thickness.cc
|
||||||
intern/MOD_grease_pencil_time.cc
|
intern/MOD_grease_pencil_time.cc
|
||||||
intern/MOD_grease_pencil_tint.cc
|
intern/MOD_grease_pencil_tint.cc
|
||||||
|
@ -98,6 +98,7 @@ extern ModifierTypeInfo modifierType_GreasePencilEnvelope;
|
|||||||
extern ModifierTypeInfo modifierType_GreasePencilOutline;
|
extern ModifierTypeInfo modifierType_GreasePencilOutline;
|
||||||
extern ModifierTypeInfo modifierType_GreasePencilShrinkwrap;
|
extern ModifierTypeInfo modifierType_GreasePencilShrinkwrap;
|
||||||
extern ModifierTypeInfo modifierType_GreasePencilBuild;
|
extern ModifierTypeInfo modifierType_GreasePencilBuild;
|
||||||
|
extern ModifierTypeInfo modifierType_GreasePencilTexture;
|
||||||
|
|
||||||
/* MOD_util.cc */
|
/* MOD_util.cc */
|
||||||
|
|
||||||
|
397
source/blender/modifiers/intern/MOD_grease_pencil_texture.cc
Normal file
397
source/blender/modifiers/intern/MOD_grease_pencil_texture.cc
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup modifiers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BKE_attribute.hh"
|
||||||
|
#include "BLI_index_range.hh"
|
||||||
|
#include "BLI_math_base.hh"
|
||||||
|
#include "BLI_span.hh"
|
||||||
|
|
||||||
|
#include "DNA_defaults.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
|
||||||
|
#include "BKE_curves.hh"
|
||||||
|
#include "BKE_geometry_set.hh"
|
||||||
|
#include "BKE_grease_pencil.hh"
|
||||||
|
#include "BKE_instances.hh"
|
||||||
|
#include "BKE_modifier.hh"
|
||||||
|
#include "BKE_screen.hh"
|
||||||
|
|
||||||
|
#include "BLO_read_write.hh"
|
||||||
|
|
||||||
|
#include "DEG_depsgraph_query.hh"
|
||||||
|
|
||||||
|
#include "UI_interface.hh"
|
||||||
|
#include "UI_resources.hh"
|
||||||
|
|
||||||
|
#include "BLT_translation.hh"
|
||||||
|
|
||||||
|
#include "WM_api.hh"
|
||||||
|
#include "WM_types.hh"
|
||||||
|
|
||||||
|
#include "RNA_access.hh"
|
||||||
|
#include "RNA_prototypes.h"
|
||||||
|
|
||||||
|
#include "MOD_grease_pencil_util.hh"
|
||||||
|
#include "MOD_ui_common.hh"
|
||||||
|
|
||||||
|
namespace blender {
|
||||||
|
|
||||||
|
static void init_data(ModifierData *md)
|
||||||
|
{
|
||||||
|
auto *tmd = reinterpret_cast<GreasePencilTextureModifierData *>(md);
|
||||||
|
|
||||||
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(tmd, modifier));
|
||||||
|
|
||||||
|
MEMCPY_STRUCT_AFTER(tmd, DNA_struct_default_get(GreasePencilTextureModifierData), modifier);
|
||||||
|
modifier::greasepencil::init_influence_data(&tmd->influence, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
|
||||||
|
{
|
||||||
|
const auto *tmd = reinterpret_cast<const GreasePencilTextureModifierData *>(md);
|
||||||
|
auto *tmmd = reinterpret_cast<GreasePencilTextureModifierData *>(target);
|
||||||
|
|
||||||
|
modifier::greasepencil::free_influence_data(&tmmd->influence);
|
||||||
|
|
||||||
|
BKE_modifier_copydata_generic(md, target, flag);
|
||||||
|
modifier::greasepencil::copy_influence_data(&tmd->influence, &tmmd->influence, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_data(ModifierData *md)
|
||||||
|
{
|
||||||
|
auto *tmd = reinterpret_cast<GreasePencilTextureModifierData *>(md);
|
||||||
|
modifier::greasepencil::free_influence_data(&tmd->influence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreach_ID_link(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
|
||||||
|
{
|
||||||
|
auto *tmd = reinterpret_cast<GreasePencilTextureModifierData *>(md);
|
||||||
|
modifier::greasepencil::foreach_influence_ID_link(&tmd->influence, ob, walk, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_stroke_transforms(bke::greasepencil::Drawing &drawing,
|
||||||
|
const IndexMask &curves_mask,
|
||||||
|
const float offset,
|
||||||
|
const float rotation,
|
||||||
|
const float scale,
|
||||||
|
const bool normalize_u)
|
||||||
|
{
|
||||||
|
bke::CurvesGeometry &curves = drawing.strokes_for_write();
|
||||||
|
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||||
|
const VArray<bool> cyclic = curves.cyclic();
|
||||||
|
|
||||||
|
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||||
|
bke::SpanAttributeWriter<float> u_translations = attributes.lookup_or_add_for_write_span<float>(
|
||||||
|
"u_translation", bke::AttrDomain::Curve);
|
||||||
|
bke::SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
|
||||||
|
"rotation", bke::AttrDomain::Point);
|
||||||
|
bke::SpanAttributeWriter<float> u_scales = attributes.lookup_or_add_for_write_span<float>(
|
||||||
|
"u_scale",
|
||||||
|
bke::AttrDomain::Curve,
|
||||||
|
bke::AttributeInitVArray(VArray<float>::ForSingle(1.0f, curves.curves_num())));
|
||||||
|
|
||||||
|
curves.ensure_evaluated_lengths();
|
||||||
|
|
||||||
|
curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
|
||||||
|
const IndexRange points = points_by_curve[curve_i];
|
||||||
|
const bool is_cyclic = cyclic[curve_i];
|
||||||
|
const Span<float> lengths = curves.evaluated_lengths_for_curve(curve_i, is_cyclic);
|
||||||
|
const float norm = normalize_u ? math::safe_rcp(lengths.last()) : 1.0f;
|
||||||
|
|
||||||
|
u_translations.span[curve_i] += offset;
|
||||||
|
u_scales.span[curve_i] *= scale * norm;
|
||||||
|
for (const int point_i : points) {
|
||||||
|
rotations.span[point_i] += rotation;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
u_translations.finish();
|
||||||
|
u_scales.finish();
|
||||||
|
rotations.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
static float2 rotate_by_angle(const float2 &p, const float angle)
|
||||||
|
{
|
||||||
|
const float cos_angle = math::cos(angle);
|
||||||
|
const float sin_angle = math::sin(angle);
|
||||||
|
return float2(p.x * cos_angle - p.y * sin_angle, p.x * sin_angle + p.y * cos_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This gets the legacy stroke-space to layer-space matrix.
|
||||||
|
*/
|
||||||
|
static void get_legacy_stroke_matrix(const Span<float3> positions,
|
||||||
|
float3x4 &stroke_to_layer,
|
||||||
|
float4x3 &layer_to_stroke)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
using namespace blender::math;
|
||||||
|
|
||||||
|
if (positions.size() < 2) {
|
||||||
|
stroke_to_layer = float3x4::identity();
|
||||||
|
layer_to_stroke = float4x3::identity();
|
||||||
|
}
|
||||||
|
|
||||||
|
const float3 &pt0 = positions[0];
|
||||||
|
const float3 &pt1 = positions[1];
|
||||||
|
const float3 &pt3 = positions[int(positions.size() * 0.75f)];
|
||||||
|
|
||||||
|
/* Local X axis (p0 -> p1) */
|
||||||
|
const float3 local_x = normalize(pt1 - pt0);
|
||||||
|
|
||||||
|
/* Point vector at 3/4 */
|
||||||
|
const float3 local_3 = (positions.size() == 2) ? (pt3 * 0.001f) - pt0 : pt3 - pt0;
|
||||||
|
|
||||||
|
/* Vector orthogonal to polygon plane. */
|
||||||
|
const float3 normal = cross(local_x, local_3);
|
||||||
|
|
||||||
|
/* Local Y axis (cross to normal/x axis). */
|
||||||
|
const float3 local_y = normalize(cross(normal, local_x));
|
||||||
|
|
||||||
|
/* Get layer space using first point as origin. */
|
||||||
|
stroke_to_layer = float3x4(float4(local_x, 0), float4(local_y, 0), float4(pt0, 1));
|
||||||
|
layer_to_stroke = math::transpose(float3x4(float4(local_x, -dot(pt0, local_x)),
|
||||||
|
float4(local_y, -dot(pt0, local_y)),
|
||||||
|
float4(0, 0, 0, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_fill_transforms(bke::greasepencil::Drawing &drawing,
|
||||||
|
const IndexMask &curves_mask,
|
||||||
|
const float2 &offset,
|
||||||
|
const float rotation,
|
||||||
|
const float scale)
|
||||||
|
{
|
||||||
|
/* Texture matrices are a combination of an unknown 3D transform into UV space, with a known 2D
|
||||||
|
* transform on top.
|
||||||
|
*
|
||||||
|
* However, the modifier offset is not applied directly to the UV transform, since it emulates
|
||||||
|
* legacy behavior of the GPv2 modifier, which applied translation first, before rotating about
|
||||||
|
* (0.5, 0.5) and scaling. To achieve the same result as the legacy modifier, the actual offset
|
||||||
|
* is calculated such that the result matches the GPv2 behavior.
|
||||||
|
*
|
||||||
|
* The canonical transform is
|
||||||
|
* uv = T + R / S * xy
|
||||||
|
*
|
||||||
|
* In terms of legacy variables TL, RL, SL the same transform is described as
|
||||||
|
* uv = (RL * (xy / 2 + TL) + 1/2) / SL
|
||||||
|
*
|
||||||
|
* where the 1/2 scaling factor and offset are the "bounds" transform and rotation center.
|
||||||
|
*
|
||||||
|
* Rearranging into canonical loc/rot/scale terms:
|
||||||
|
* uv = (RL * TL + 1/2) / SL + 1/2 * RL / SL * xy
|
||||||
|
* <=>
|
||||||
|
* T = (RL * TL + 1/2) / SL
|
||||||
|
* R = RL
|
||||||
|
* S = 2*SL
|
||||||
|
* <=>
|
||||||
|
* TL = 1/2 * R^T * (T * S - 1)
|
||||||
|
* RL = R
|
||||||
|
* SL = S/2
|
||||||
|
*/
|
||||||
|
|
||||||
|
bke::CurvesGeometry &curves = drawing.strokes_for_write();
|
||||||
|
const Span<float3> positions = curves.positions();
|
||||||
|
Array<float4x2> texture_matrices(drawing.texture_matrices());
|
||||||
|
|
||||||
|
curves_mask.foreach_index(GrainSize(512), [&](int64_t curve_i) {
|
||||||
|
const IndexRange points = curves.points_by_curve()[curve_i];
|
||||||
|
float4x2 &texture_matrix = texture_matrices[curve_i];
|
||||||
|
/* Factor out the stroke-to-layer transform part used by GPv2.
|
||||||
|
* This may not be the same as the transform used by GPv3 for concave shapes due to a
|
||||||
|
* simplistic normal calculation, but we want to achieve the same effect as GPv2 so have to use
|
||||||
|
* the same matrix. */
|
||||||
|
float3x4 stroke_to_layer;
|
||||||
|
float4x3 layer_to_stroke;
|
||||||
|
get_legacy_stroke_matrix(positions.slice(points), stroke_to_layer, layer_to_stroke);
|
||||||
|
const float3x2 uv_matrix = texture_matrix * stroke_to_layer;
|
||||||
|
const float2 uv_translation = uv_matrix[2];
|
||||||
|
float2 inv_uv_scale;
|
||||||
|
const float2 axis_u = math::normalize_and_get_length(uv_matrix[0], inv_uv_scale[0]);
|
||||||
|
const float2 axis_v = math::normalize_and_get_length(uv_matrix[1], inv_uv_scale[1]);
|
||||||
|
const float uv_rotation = math::atan2(axis_u[1], axis_u[0]);
|
||||||
|
const float2 uv_scale = math::safe_rcp(inv_uv_scale);
|
||||||
|
|
||||||
|
const float2 legacy_uv_translation = rotate_by_angle(0.5f * uv_scale * uv_translation - 0.5f,
|
||||||
|
-uv_rotation);
|
||||||
|
const float legacy_uv_rotation = uv_rotation;
|
||||||
|
const float2 legacy_uv_scale = 0.5f * uv_scale;
|
||||||
|
|
||||||
|
const float2 legacy_uv_translation_new = legacy_uv_translation + offset;
|
||||||
|
const float legacy_uv_rotation_new = legacy_uv_rotation + rotation;
|
||||||
|
const float2 legacy_uv_scale_new = legacy_uv_scale * scale;
|
||||||
|
|
||||||
|
const float2 uv_translation_new =
|
||||||
|
(rotate_by_angle(legacy_uv_translation_new, legacy_uv_rotation_new) + 0.5f) *
|
||||||
|
math::safe_rcp(legacy_uv_scale_new);
|
||||||
|
const float uv_rotation_new = legacy_uv_rotation_new;
|
||||||
|
const float2 uv_scale_new = 2.0f * legacy_uv_scale_new;
|
||||||
|
|
||||||
|
const float cos_uv_rotation_new = math::cos(uv_rotation_new);
|
||||||
|
const float sin_uv_rotation_new = math::sin(uv_rotation_new);
|
||||||
|
const float2 inv_uv_scale_new = math::safe_rcp(uv_scale_new);
|
||||||
|
const float3x2 uv_matrix_new = float3x2(
|
||||||
|
inv_uv_scale_new[0] * float2(cos_uv_rotation_new, sin_uv_rotation_new),
|
||||||
|
inv_uv_scale_new[1] * float2(-sin_uv_rotation_new, cos_uv_rotation_new),
|
||||||
|
uv_translation_new);
|
||||||
|
texture_matrix = uv_matrix_new * layer_to_stroke;
|
||||||
|
});
|
||||||
|
|
||||||
|
drawing.set_texture_matrices(texture_matrices, curves_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void modify_curves(const GreasePencilTextureModifierData &tmd,
|
||||||
|
const ModifierEvalContext &ctx,
|
||||||
|
bke::greasepencil::Drawing &drawing)
|
||||||
|
{
|
||||||
|
IndexMaskMemory mask_memory;
|
||||||
|
const IndexMask curves_mask = modifier::greasepencil::get_filtered_stroke_mask(
|
||||||
|
ctx.object, drawing.strokes(), tmd.influence, mask_memory);
|
||||||
|
|
||||||
|
const bool normalize_u = (tmd.fit_method == MOD_GREASE_PENCIL_TEXTURE_FIT_STROKE);
|
||||||
|
switch (GreasePencilTextureModifierMode(tmd.mode)) {
|
||||||
|
case MOD_GREASE_PENCIL_TEXTURE_STROKE:
|
||||||
|
write_stroke_transforms(
|
||||||
|
drawing, curves_mask, tmd.uv_offset, tmd.alignment_rotation, tmd.uv_scale, normalize_u);
|
||||||
|
break;
|
||||||
|
case MOD_GREASE_PENCIL_TEXTURE_FILL:
|
||||||
|
write_fill_transforms(
|
||||||
|
drawing, curves_mask, tmd.fill_offset, tmd.fill_rotation, tmd.fill_scale);
|
||||||
|
break;
|
||||||
|
case MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL:
|
||||||
|
write_stroke_transforms(
|
||||||
|
drawing, curves_mask, tmd.uv_offset, tmd.alignment_rotation, tmd.uv_scale, normalize_u);
|
||||||
|
write_fill_transforms(
|
||||||
|
drawing, curves_mask, tmd.fill_offset, tmd.fill_rotation, tmd.fill_scale);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void modify_geometry_set(ModifierData *md,
|
||||||
|
const ModifierEvalContext *ctx,
|
||||||
|
bke::GeometrySet *geometry_set)
|
||||||
|
{
|
||||||
|
using bke::greasepencil::Drawing;
|
||||||
|
using bke::greasepencil::Layer;
|
||||||
|
|
||||||
|
const auto &tmd = *reinterpret_cast<const GreasePencilTextureModifierData *>(md);
|
||||||
|
|
||||||
|
if (!geometry_set->has_grease_pencil()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GreasePencil &grease_pencil = *geometry_set->get_grease_pencil_for_write();
|
||||||
|
|
||||||
|
IndexMaskMemory mask_memory;
|
||||||
|
const IndexMask layer_mask = modifier::greasepencil::get_filtered_layer_mask(
|
||||||
|
grease_pencil, tmd.influence, mask_memory);
|
||||||
|
const int frame = grease_pencil.runtime->eval_frame;
|
||||||
|
const Vector<Drawing *> drawings = modifier::greasepencil::get_drawings_for_write(
|
||||||
|
grease_pencil, layer_mask, frame);
|
||||||
|
threading::parallel_for_each(drawings,
|
||||||
|
[&](Drawing *drawing) { modify_curves(tmd, *ctx, *drawing); });
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
const auto &tmd = *static_cast<GreasePencilTextureModifierData *>(ptr->data);
|
||||||
|
const auto mode = GreasePencilTextureModifierMode(tmd.mode);
|
||||||
|
uiLayout *col;
|
||||||
|
|
||||||
|
uiLayoutSetPropSep(layout, true);
|
||||||
|
|
||||||
|
uiItemR(layout, ptr, "mode", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||||
|
|
||||||
|
if (ELEM(mode, MOD_GREASE_PENCIL_TEXTURE_STROKE, MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL)) {
|
||||||
|
col = uiLayoutColumn(layout, false);
|
||||||
|
uiItemR(col, ptr, "fit_method", UI_ITEM_NONE, IFACE_("Stroke Fit Method"), ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "uv_offset", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "alignment_rotation", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "uv_scale", UI_ITEM_NONE, IFACE_("Scale"), ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL) {
|
||||||
|
uiItemS(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ELEM(mode, MOD_GREASE_PENCIL_TEXTURE_FILL, MOD_GREASE_PENCIL_TEXTURE_STROKE_AND_FILL)) {
|
||||||
|
col = uiLayoutColumn(layout, false);
|
||||||
|
uiItemR(col, ptr, "fill_rotation", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "fill_offset", UI_ITEM_NONE, IFACE_("Offset"), ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "fill_scale", UI_ITEM_NONE, IFACE_("Scale"), ICON_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uiLayout *influence_panel = uiLayoutPanelProp(
|
||||||
|
C, layout, ptr, "open_influence_panel", "Influence"))
|
||||||
|
{
|
||||||
|
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_panel_end(layout, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panel_register(ARegionType *region_type)
|
||||||
|
{
|
||||||
|
modifier_panel_register(region_type, eModifierType_GreasePencilTexture, panel_draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_write(BlendWriter *writer, const ID * /*id_owner*/, const ModifierData *md)
|
||||||
|
{
|
||||||
|
const auto *tmd = reinterpret_cast<const GreasePencilTextureModifierData *>(md);
|
||||||
|
|
||||||
|
BLO_write_struct(writer, GreasePencilTextureModifierData, tmd);
|
||||||
|
modifier::greasepencil::write_influence_data(writer, &tmd->influence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void blend_read(BlendDataReader *reader, ModifierData *md)
|
||||||
|
{
|
||||||
|
auto *tmd = reinterpret_cast<GreasePencilTextureModifierData *>(md);
|
||||||
|
|
||||||
|
modifier::greasepencil::read_influence_data(reader, &tmd->influence);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender
|
||||||
|
|
||||||
|
ModifierTypeInfo modifierType_GreasePencilTexture = {
|
||||||
|
/*idname*/ "GreasePencilTexture",
|
||||||
|
/*name*/ N_("TimeOffset"),
|
||||||
|
/*struct_name*/ "GreasePencilTextureModifierData",
|
||||||
|
/*struct_size*/ sizeof(GreasePencilTextureModifierData),
|
||||||
|
/*srna*/ &RNA_GreasePencilTextureModifier,
|
||||||
|
/*type*/ ModifierTypeType::NonGeometrical,
|
||||||
|
/*flags*/ eModifierTypeFlag_AcceptsGreasePencil | eModifierTypeFlag_SupportsEditmode |
|
||||||
|
eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_SupportsMapping,
|
||||||
|
/*icon*/ ICON_MOD_UVPROJECT,
|
||||||
|
|
||||||
|
/*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,
|
||||||
|
};
|
@ -289,5 +289,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
|||||||
INIT_TYPE(GreasePencilOutline);
|
INIT_TYPE(GreasePencilOutline);
|
||||||
INIT_TYPE(GreasePencilShrinkwrap);
|
INIT_TYPE(GreasePencilShrinkwrap);
|
||||||
INIT_TYPE(GreasePencilBuild);
|
INIT_TYPE(GreasePencilBuild);
|
||||||
|
INIT_TYPE(GreasePencilTexture);
|
||||||
#undef INIT_TYPE
|
#undef INIT_TYPE
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user