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 <falk@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/109733
This commit is contained in:
@@ -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<uint3> triangles() const;
|
||||
void tag_positions_changed();
|
||||
|
||||
/**
|
||||
* Radii of the points. Values are expected to be in blender units.
|
||||
*/
|
||||
VArray<float> radii() const;
|
||||
MutableSpan<float> 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<float> opacities() const;
|
||||
MutableSpan<float> opacities_for_write();
|
||||
};
|
||||
|
||||
class LayerGroup;
|
||||
|
||||
@@ -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<typename T>
|
||||
static MutableSpan<T> 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<T>());
|
||||
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<T> 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<float> Drawing::radii() const
|
||||
{
|
||||
return *this->strokes().attributes().lookup_or_default<float>(
|
||||
ATTR_RADIUS, ATTR_DOMAIN_POINT, 0.01f);
|
||||
}
|
||||
|
||||
MutableSpan<float> Drawing::radii_for_write()
|
||||
{
|
||||
return get_mutable_attribute<float>(
|
||||
this->geometry.wrap(), ATTR_DOMAIN_POINT, ATTR_RADIUS, 0.01f);
|
||||
}
|
||||
|
||||
VArray<float> Drawing::opacities() const
|
||||
{
|
||||
return *this->strokes().attributes().lookup_or_default<float>(
|
||||
ATTR_OPACITY, ATTR_DOMAIN_POINT, 1.0f);
|
||||
}
|
||||
|
||||
MutableSpan<float> Drawing::opacities_for_write()
|
||||
{
|
||||
return get_mutable_attribute<float>(
|
||||
this->geometry.wrap(), ATTR_DOMAIN_POINT, ATTR_OPACITY, 1.0f);
|
||||
}
|
||||
|
||||
void Drawing::tag_positions_changed()
|
||||
{
|
||||
this->geometry.wrap().tag_positions_changed();
|
||||
|
||||
@@ -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<float3> positions = curves.positions_for_write();
|
||||
SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_span<float>(
|
||||
"radius", ATTR_DOMAIN_POINT);
|
||||
SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
|
||||
"opacity", ATTR_DOMAIN_POINT);
|
||||
MutableSpan<float> radii = drawing.radii_for_write();
|
||||
MutableSpan<float> opacities = drawing.opacities_for_write();
|
||||
SpanAttributeWriter<float> delta_times = attributes.lookup_or_add_for_write_span<float>(
|
||||
"delta_time", ATTR_DOMAIN_POINT);
|
||||
SpanAttributeWriter<float> rotations = attributes.lookup_or_add_for_write_span<float>(
|
||||
@@ -118,8 +117,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
||||
|
||||
Span<bGPDspoint> stroke_points{gps->points, gps->totpoints};
|
||||
MutableSpan<float3> stroke_positions = positions.slice(stroke_points_range);
|
||||
MutableSpan<float> stroke_radii = radii.span.slice(stroke_points_range);
|
||||
MutableSpan<float> stroke_opacities = opacities.span.slice(stroke_points_range);
|
||||
MutableSpan<float> stroke_radii = radii.slice(stroke_points_range);
|
||||
MutableSpan<float> stroke_opacities = opacities.slice(stroke_points_range);
|
||||
MutableSpan<float> stroke_deltatimes = delta_times.span.slice(stroke_points_range);
|
||||
MutableSpan<float> stroke_rotations = rotations.span.slice(stroke_points_range);
|
||||
MutableSpan<ColorGeometry4f> 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();
|
||||
|
||||
@@ -315,10 +315,8 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr
|
||||
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
const Span<float3> positions = curves.positions();
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
const VArray<float> radii = *attributes.lookup_or_default<float>(
|
||||
"radius", ATTR_DOMAIN_POINT, 1.0f);
|
||||
const VArray<float> opacities = *attributes.lookup_or_default<float>(
|
||||
"opacity", ATTR_DOMAIN_POINT, 1.0f);
|
||||
const VArray<float> radii = drawing.radii();
|
||||
const VArray<float> opacities = drawing.opacities();
|
||||
/* Assumes that if the ".selection" attribute does not exist, all points are selected. */
|
||||
const VArray<float> selection_float = *attributes.lookup_or_default<float>(
|
||||
".selection", ATTR_DOMAIN_POINT, true);
|
||||
|
||||
@@ -91,7 +91,7 @@ void PaintOperation::on_stroke_done(const bContext &C)
|
||||
|
||||
const Span<bke::greasepencil::StrokePoint> 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<float3> positions = curves.positions_for_write();
|
||||
SpanAttributeWriter<float> radii = attributes.lookup_or_add_for_write_span<float>(
|
||||
"radius", ATTR_DOMAIN_POINT);
|
||||
SpanAttributeWriter<float> opacities = attributes.lookup_or_add_for_write_span<float>(
|
||||
"opacity", ATTR_DOMAIN_POINT);
|
||||
MutableSpan<float> radii = drawing_orig.radii_for_write();
|
||||
MutableSpan<float> 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);
|
||||
|
||||
Reference in New Issue
Block a user