From f2d3d321bbffc745232f23519019cb0a585055ab Mon Sep 17 00:00:00 2001 From: Amelie Date: Tue, 11 Jul 2023 15:11:14 +0200 Subject: [PATCH] GPv3: Add access functions for opacity and radius attributes We need setters and getters for these two very commonly accessed attributes of grease pencil. The code is based on the implementation of `CurvesGeometry::positions()` and `CurvesGeometry::positions_for_write()`. Co-authored-by: Falk David Pull Request: https://projects.blender.org/blender/blender/pulls/109733 --- .../blender/blenkernel/BKE_grease_pencil.hh | 14 +++++ .../blenkernel/intern/grease_pencil.cc | 59 +++++++++++++++++++ .../intern/grease_pencil_convert_legacy.cc | 15 ++--- .../intern/draw_cache_impl_grease_pencil.cc | 6 +- .../sculpt_paint/grease_pencil_paint.cc | 14 ++--- 5 files changed, 86 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/BKE_grease_pencil.hh b/source/blender/blenkernel/BKE_grease_pencil.hh index e6100d2be7f..1c07b49ad14 100644 --- a/source/blender/blenkernel/BKE_grease_pencil.hh +++ b/source/blender/blenkernel/BKE_grease_pencil.hh @@ -14,6 +14,7 @@ #include "BLI_math_vector_types.hh" #include "BLI_shared_cache.hh" #include "BLI_utility_mixins.hh" +#include "BLI_virtual_array.hh" #include "DNA_gpencil_legacy_types.h" #include "DNA_grease_pencil_types.h" @@ -76,6 +77,19 @@ class Drawing : public ::GreasePencilDrawing { */ Span triangles() const; void tag_positions_changed(); + + /** + * Radii of the points. Values are expected to be in blender units. + */ + VArray radii() const; + MutableSpan radii_for_write(); + + /** + * Opacities for the points. Used by the render engine as an alpha value so they are expected to + * be between 0 and 1 inclusive. + */ + VArray opacities() const; + MutableSpan opacities_for_write(); }; class LayerGroup; diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index c4b8a9d968d..1160ea0f28e 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -29,6 +29,7 @@ #include "BLI_string_ref.hh" #include "BLI_string_utils.h" #include "BLI_vector_set.hh" +#include "BLI_virtual_array.hh" #include "BLO_read_write.h" @@ -250,6 +251,40 @@ IDTypeInfo IDType_ID_GP = { namespace blender::bke::greasepencil { +static const std::string ATTR_OPACITY = "opacity"; +static const std::string ATTR_RADIUS = "radius"; + +/* Curves attributes getters */ +static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain) +{ + return domain == ATTR_DOMAIN_POINT ? curves.points_num() : curves.curves_num(); +} +static CustomData &domain_custom_data(CurvesGeometry &curves, const eAttrDomain domain) +{ + return domain == ATTR_DOMAIN_POINT ? curves.point_data : curves.curve_data; +} +template +static MutableSpan get_mutable_attribute(CurvesGeometry &curves, + const eAttrDomain domain, + const StringRefNull name, + const T default_value = T()) +{ + const int num = domain_num(curves, domain); + const eCustomDataType type = cpp_type_to_custom_data_type(CPPType::get()); + CustomData &custom_data = domain_custom_data(curves, domain); + + T *data = (T *)CustomData_get_layer_named_for_write(&custom_data, type, name.c_str(), num); + if (data != nullptr) { + return {data, num}; + } + data = (T *)CustomData_add_layer_named(&custom_data, type, CD_SET_DEFAULT, num, name.c_str()); + MutableSpan span = {data, num}; + if (num > 0 && span.first() != default_value) { + span.fill(default_value); + } + return span; +} + Drawing::Drawing() { this->base.type = GP_DRAWING; @@ -344,6 +379,30 @@ bke::CurvesGeometry &Drawing::strokes_for_write() return this->geometry.wrap(); } +VArray Drawing::radii() const +{ + return *this->strokes().attributes().lookup_or_default( + ATTR_RADIUS, ATTR_DOMAIN_POINT, 0.01f); +} + +MutableSpan Drawing::radii_for_write() +{ + return get_mutable_attribute( + this->geometry.wrap(), ATTR_DOMAIN_POINT, ATTR_RADIUS, 0.01f); +} + +VArray Drawing::opacities() const +{ + return *this->strokes().attributes().lookup_or_default( + ATTR_OPACITY, ATTR_DOMAIN_POINT, 1.0f); +} + +MutableSpan Drawing::opacities_for_write() +{ + return get_mutable_attribute( + this->geometry.wrap(), ATTR_DOMAIN_POINT, ATTR_OPACITY, 1.0f); +} + void Drawing::tag_positions_changed() { this->geometry.wrap().tag_positions_changed(); diff --git a/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc b/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc index 115a7b8ea08..7bd5c56f059 100644 --- a/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc +++ b/source/blender/blenkernel/intern/grease_pencil_convert_legacy.cc @@ -40,7 +40,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, } /* Resize the CurvesGeometry. */ - CurvesGeometry &curves = r_drawing.geometry.wrap(); + Drawing &drawing = r_drawing.wrap(); + CurvesGeometry &curves = drawing.strokes_for_write(); curves.resize(num_points, num_strokes); if (num_strokes > 0) { curves.offsets_for_write().copy_from(offsets); @@ -53,10 +54,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, /* Point Attributes. */ MutableSpan positions = curves.positions_for_write(); - SpanAttributeWriter radii = attributes.lookup_or_add_for_write_span( - "radius", ATTR_DOMAIN_POINT); - SpanAttributeWriter opacities = attributes.lookup_or_add_for_write_span( - "opacity", ATTR_DOMAIN_POINT); + MutableSpan radii = drawing.radii_for_write(); + MutableSpan opacities = drawing.opacities_for_write(); SpanAttributeWriter delta_times = attributes.lookup_or_add_for_write_span( "delta_time", ATTR_DOMAIN_POINT); SpanAttributeWriter rotations = attributes.lookup_or_add_for_write_span( @@ -118,8 +117,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, Span stroke_points{gps->points, gps->totpoints}; MutableSpan stroke_positions = positions.slice(stroke_points_range); - MutableSpan stroke_radii = radii.span.slice(stroke_points_range); - MutableSpan stroke_opacities = opacities.span.slice(stroke_points_range); + MutableSpan stroke_radii = radii.slice(stroke_points_range); + MutableSpan stroke_opacities = opacities.slice(stroke_points_range); MutableSpan stroke_deltatimes = delta_times.span.slice(stroke_points_range); MutableSpan stroke_rotations = rotations.span.slice(stroke_points_range); MutableSpan stroke_vertex_colors = vertex_colors.span.slice( @@ -153,8 +152,6 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf, } } - radii.finish(); - opacities.finish(); delta_times.finish(); rotations.finish(); vertex_colors.finish(); diff --git a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc index a8db94bf0ac..272e31b346f 100644 --- a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc @@ -315,10 +315,8 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr const OffsetIndices points_by_curve = curves.points_by_curve(); const Span positions = curves.positions(); const VArray cyclic = curves.cyclic(); - const VArray radii = *attributes.lookup_or_default( - "radius", ATTR_DOMAIN_POINT, 1.0f); - const VArray opacities = *attributes.lookup_or_default( - "opacity", ATTR_DOMAIN_POINT, 1.0f); + const VArray radii = drawing.radii(); + const VArray opacities = drawing.opacities(); /* Assumes that if the ".selection" attribute does not exist, all points are selected. */ const VArray selection_float = *attributes.lookup_or_default( ".selection", ATTR_DOMAIN_POINT, true); diff --git a/source/blender/editors/sculpt_paint/grease_pencil_paint.cc b/source/blender/editors/sculpt_paint/grease_pencil_paint.cc index fd0f6fd3fde..846764b7406 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_paint.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_paint.cc @@ -91,7 +91,7 @@ void PaintOperation::on_stroke_done(const bContext &C) const Span stroke_points = grease_pencil_eval.runtime->stroke_buffer(); - CurvesGeometry &curves = drawing_orig.geometry.wrap(); + CurvesGeometry &curves = drawing_orig.strokes_for_write(); int num_old_curves = curves.curves_num(); int num_old_points = curves.points_num(); @@ -107,16 +107,14 @@ void PaintOperation::on_stroke_done(const bContext &C) /* Set position, radius and opacity attribute. */ bke::MutableAttributeAccessor attributes = curves.attributes_for_write(); MutableSpan positions = curves.positions_for_write(); - SpanAttributeWriter radii = attributes.lookup_or_add_for_write_span( - "radius", ATTR_DOMAIN_POINT); - SpanAttributeWriter opacities = attributes.lookup_or_add_for_write_span( - "opacity", ATTR_DOMAIN_POINT); + MutableSpan radii = drawing_orig.radii_for_write(); + MutableSpan opacities = drawing_orig.opacities_for_write(); for (const int i : IndexRange(stroke_points.size())) { const bke::greasepencil::StrokePoint &point = stroke_points[i]; const int point_i = new_points_range[i]; positions[point_i] = point.position; - radii.span[point_i] = point.radius; - opacities.span[point_i] = point.opacity; + radii[point_i] = point.radius; + opacities[point_i] = point.opacity; } /* Set material index attribute. */ @@ -149,8 +147,6 @@ void PaintOperation::on_stroke_done(const bContext &C) grease_pencil_eval.runtime->stroke_cache.clear(); drawing_orig.tag_positions_changed(); - radii.finish(); - opacities.finish(); materials.finish(); DEG_id_tag_update(&grease_pencil_orig.id, ID_RECALC_GEOMETRY);