Fix #129252: GPv3: Primitive tool doesn't write to fill_opacity attribute

The primitive tool didn't write to the `fill_opacity` attribute meaning that primitives wouldn't
show up correctly when using fill materials with a strength < 1.

The fix does multiple things:
* Make sure to create and write to the `fill_opacity` attribute if necessary.
* Remove the `skipped_attribute_ids` function and build the set of attributes to skip
   where the attributes are written to. This is more flexible.

Pull Request: https://projects.blender.org/blender/blender/pulls/129644
This commit is contained in:
Falk David
2024-10-31 17:10:48 +01:00
committed by Falk David
parent 7e87da72ab
commit 50f01f4dce

View File

@@ -29,6 +29,8 @@
#include "DEG_depsgraph_query.hh"
#include "DNA_material_types.h"
#include "ED_grease_pencil.hh"
#include "ED_screen.hh"
#include "ED_space_api.hh"
@@ -121,12 +123,14 @@ struct PrimitiveToolOperation {
DrawingPlacement placement;
bke::greasepencil::Drawing *drawing;
Brush *brush;
BrushGpencilSettings *settings;
std::optional<ColorGeometry4f> vertex_color;
std::optional<ColorGeometry4f> fill_color;
int material_index;
bool use_fill;
float softness;
Brush *brush;
float fill_opacity;
float4x2 texture_space;
OperatorMode mode;
@@ -422,43 +426,11 @@ static int grease_pencil_primitive_curve_points_number(PrimitiveToolOperation &p
return 0;
}
/* Attributes that are defined explicitly and should not be copied from original geometry. */
static Set<std::string> skipped_attribute_ids(const PrimitiveToolOperation &ptd,
const bke::AttrDomain domain)
{
switch (domain) {
case bke::AttrDomain::Point:
if (ptd.vertex_color) {
return {"position", "radius", "opacity", "vertex_color"};
}
else {
return {"position", "radius", "opacity"};
}
case bke::AttrDomain::Curve:
if (ptd.fill_color) {
return {"curve_type",
"material_index",
"cyclic",
"softness",
"start_cap",
"end_cap",
"fill_color"};
}
else {
return {"curve_type", "material_index", "cyclic", "softness", "start_cap", "end_cap"};
}
default:
return {};
}
return {};
}
static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
{
bke::CurvesGeometry &curves = ptd.drawing->strokes_for_write();
const int last_points_num = curves.points_by_curve()[curves.curves_range().last()].size();
const int new_points_num = grease_pencil_primitive_curve_points_number(ptd);
curves.resize(curves.points_num() - last_points_num + new_points_num, curves.curves_num());
@@ -471,13 +443,11 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
primitive_calulate_curve_positions_2d(ptd, positions_2d);
ptd.placement.project(positions_2d, positions_3d);
Set<std::string> point_attributes_to_skip;
MutableSpan<float> new_radii = ptd.drawing->radii_for_write().slice(curve_points);
MutableSpan<float> new_opacities = ptd.drawing->opacities_for_write().slice(curve_points);
if (ptd.vertex_color) {
ptd.drawing->vertex_colors_for_write().slice(curve_points).fill(*ptd.vertex_color);
}
const ToolSettings *ts = ptd.vc.scene->toolsettings;
const GP_Sculpt_Settings *gset = &ts->gp_sculpt;
@@ -502,19 +472,19 @@ static void grease_pencil_primitive_update_curves(PrimitiveToolOperation &ptd)
new_radii[point] = radius;
new_opacities[point] = opacity;
}
point_attributes_to_skip.add_multiple({"position", "radius", "opacity"});
if (ptd.vertex_color) {
ptd.drawing->vertex_colors_for_write().slice(curve_points).fill(*ptd.vertex_color);
point_attributes_to_skip.add("vertex_color");
}
/* Initialize the rest of the attributes with default values. */
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
bke::fill_attribute_range_default(
attributes,
bke::AttrDomain::Point,
bke::attribute_filter_from_skip_ref(skipped_attribute_ids(ptd, bke::AttrDomain::Point)),
curve_points);
bke::fill_attribute_range_default(
attributes,
bke::AttrDomain::Curve,
bke::attribute_filter_from_skip_ref(skipped_attribute_ids(ptd, bke::AttrDomain::Curve)),
curves.curves_range().take_back(1));
bke::fill_attribute_range_default(attributes,
bke::AttrDomain::Point,
bke::attribute_filter_from_skip_ref(point_attributes_to_skip),
curve_points);
ptd.drawing->tag_topology_changed();
ptd.drawing->set_texture_matrices({ptd.texture_space},
@@ -529,6 +499,8 @@ static void grease_pencil_primitive_init_curves(PrimitiveToolOperation &ptd)
curves.resize(curves.points_num() + 1, curves.curves_num() + 1);
curves.offsets_for_write().last(1) = num_old_points;
Set<std::string> curve_attributes_to_skip;
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
bke::SpanAttributeWriter<int> materials = attributes.lookup_or_add_for_write_span<int>(
"material_index", bke::AttrDomain::Curve);
@@ -543,6 +515,7 @@ static void grease_pencil_primitive_init_curves(PrimitiveToolOperation &ptd)
"start_cap", bke::AttrDomain::Curve);
start_caps.span.last() = ptd.settings->caps_type;
start_caps.finish();
curve_attributes_to_skip.add("start_cap");
}
if (ptd.settings->caps_type != GP_STROKE_CAP_TYPE_ROUND || attributes.contains("end_cap")) {
@@ -550,6 +523,7 @@ static void grease_pencil_primitive_init_curves(PrimitiveToolOperation &ptd)
"end_cap", bke::AttrDomain::Curve);
end_caps.span.last() = ptd.settings->caps_type;
end_caps.finish();
curve_attributes_to_skip.add("end_cap");
}
const bool is_cyclic = ELEM(ptd.type, PrimitiveType::Box, PrimitiveType::Circle);
@@ -557,29 +531,36 @@ static void grease_pencil_primitive_init_curves(PrimitiveToolOperation &ptd)
materials.span.last() = ptd.material_index;
softness.span.last() = ptd.softness;
if (ptd.use_fill && (ptd.fill_opacity < 1.0f || attributes.contains("fill_opacity"))) {
bke::SpanAttributeWriter<float> fill_opacities =
attributes.lookup_or_add_for_write_span<float>(
"fill_opacity",
bke::AttrDomain::Curve,
bke::AttributeInitVArray(VArray<float>::ForSingle(1.0f, curves.curves_num())));
fill_opacities.span.last() = ptd.fill_opacity;
fill_opacities.finish();
curve_attributes_to_skip.add("fill_opacity");
}
if (ptd.fill_color) {
ptd.drawing->fill_colors_for_write().last() = *ptd.fill_color;
curve_attributes_to_skip.add("fill_color");
}
cyclic.finish();
materials.finish();
softness.finish();
curve_attributes_to_skip.add_multiple({"material_index", "cyclic", "softness"});
curves.curve_types_for_write().last() = CURVE_TYPE_POLY;
curves.update_curve_types();
curve_attributes_to_skip.add("curve_type");
/* Initialize the rest of the attributes with default values. */
bke::fill_attribute_range_default(
attributes,
bke::AttrDomain::Point,
bke::attribute_filter_from_skip_ref(skipped_attribute_ids(ptd, bke::AttrDomain::Point)),
curves.points_range().take_back(1));
bke::fill_attribute_range_default(
attributes,
bke::AttrDomain::Curve,
bke::attribute_filter_from_skip_ref(skipped_attribute_ids(ptd, bke::AttrDomain::Curve)),
curves.curves_range().take_back(1));
bke::fill_attribute_range_default(attributes,
bke::AttrDomain::Curve,
bke::attribute_filter_from_skip_ref(curve_attributes_to_skip),
curves.curves_range().take_back(1));
grease_pencil_primitive_update_curves(ptd);
}
@@ -757,6 +738,7 @@ static int grease_pencil_primitive_invoke(bContext *C, wmOperator *op, const wmE
Material *material = BKE_grease_pencil_object_material_ensure_from_active_input_brush(
CTX_data_main(C), vc.obact, ptd.brush);
ptd.material_index = BKE_object_material_index_get(vc.obact, material);
ptd.use_fill = (material->gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0;
const bool use_vertex_color = (vc.scene->toolsettings->gp_paint->mode ==
GPPAINT_FLAG_USE_VERTEXCOLOR);
@@ -776,6 +758,7 @@ static int grease_pencil_primitive_invoke(bContext *C, wmOperator *op, const wmE
ptd.fill_color = std::nullopt;
}
ptd.fill_opacity = ptd.brush->alpha;
ptd.softness = 1.0 - ptd.settings->hardness;
ptd.texture_space = ed::greasepencil::calculate_texture_space(