Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/geometry_component_curve.cc')
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curve.cc228
1 files changed, 138 insertions, 90 deletions
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index 50c0f06b12c..c3d7eff4e6f 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -623,6 +623,103 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data,
}
}
+static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
+ const CustomDataType data_type,
+ const Span<SplinePtr> splines)
+{
+ switch (initializer.type) {
+ case AttributeInit::Type::Default:
+ /* This function shouldn't be called in this case, since there
+ * is no need to copy anything to the new custom data array. */
+ BLI_assert_unreachable();
+ return {};
+ case AttributeInit::Type::VArray:
+ return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
+ case AttributeInit::Type::MoveArray:
+ int total_size = 0;
+ for (const SplinePtr &spline : splines) {
+ total_size += spline->size();
+ }
+ return std::make_unique<fn::GVArray_For_GSpan>(
+ GSpan(*bke::custom_data_type_to_cpp_type(data_type),
+ static_cast<const AttributeInitMove &>(initializer).data,
+ total_size));
+ }
+ BLI_assert_unreachable();
+ return {};
+}
+
+static bool create_point_attribute(GeometryComponent &component,
+ const AttributeIDRef &attribute_id,
+ const AttributeInit &initializer,
+ const CustomDataType data_type)
+{
+ CurveEval *curve = get_curve_from_component_for_write(component);
+ if (curve == nullptr || curve->splines().size() == 0) {
+ return false;
+ }
+
+ MutableSpan<SplinePtr> splines = curve->splines();
+
+ /* First check the one case that allows us to avoid copying the input data. */
+ if (splines.size() == 1 && initializer.type == AttributeInit::Type::MoveArray) {
+ void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
+ if (!splines.first()->attributes.create_by_move(attribute_id, data_type, source_data)) {
+ MEM_freeN(source_data);
+ return false;
+ }
+ return true;
+ }
+
+ /* Otherwise just create a custom data layer on each of the splines. */
+ for (const int i : splines.index_range()) {
+ if (!splines[i]->attributes.create(attribute_id, data_type)) {
+ /* If attribute creation fails on one of the splines, we cannot leave the custom data
+ * layers in the previous splines around, so delete them before returning. However,
+ * this is not an expected case. */
+ BLI_assert_unreachable();
+ return false;
+ }
+ }
+
+ /* With a default initializer type, we can keep the values at their initial values. */
+ if (initializer.type == AttributeInit::Type::Default) {
+ return true;
+ }
+
+ WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(attribute_id);
+ /* We just created the attribute, it should exist. */
+ BLI_assert(write_attribute);
+
+ GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines);
+ /* TODO: When we can call a variant of #set_all with a virtual array argument,
+ * this theoretically unnecessary materialize step could be removed. */
+ GVArray_GSpan source_varray_span{*source_varray};
+ write_attribute.varray->set_all(source_varray_span.data());
+
+ if (initializer.type == AttributeInit::Type::MoveArray) {
+ MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data);
+ }
+
+ return true;
+}
+
+static bool remove_point_attribute(GeometryComponent &component,
+ const AttributeIDRef &attribute_id)
+{
+ CurveEval *curve = get_curve_from_component_for_write(component);
+ if (curve == nullptr) {
+ return false;
+ }
+
+ /* Reuse the boolean for all splines; we expect all splines to have the same attributes. */
+ bool layer_freed = false;
+ for (SplinePtr &spline : curve->splines()) {
+ layer_freed = spline->attributes.remove(attribute_id);
+ }
+ return layer_freed;
+}
+
/**
* Virtual array for any control point data accessed with spans and an offset array.
*/
@@ -980,15 +1077,17 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
public:
BuiltinPointAttributeProvider(std::string attribute_name,
+ const CreatableEnum creatable,
+ const DeletableEnum deletable,
const GetSpan get_span,
const GetMutableSpan get_mutable_span,
const UpdateOnWrite update_on_write)
: BuiltinAttributeProvider(std::move(attribute_name),
ATTR_DOMAIN_POINT,
bke::cpp_type_to_custom_data_type(CPPType::get<T>()),
- CreatableEnum::NonCreatable,
+ creatable,
WritableEnum::Writable,
- DeletableEnum::NonDeletable),
+ deletable),
get_span_(get_span),
get_mutable_span_(get_mutable_span),
update_on_write_(update_on_write)
@@ -1041,15 +1140,20 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
return point_data_gvarray(spans, offsets);
}
- bool try_delete(GeometryComponent &UNUSED(component)) const final
+ bool try_delete(GeometryComponent &component) const final
{
- return false;
+ if (deletable_ == DeletableEnum::NonDeletable) {
+ return false;
+ }
+ return remove_point_attribute(component, name_);
}
- bool try_create(GeometryComponent &UNUSED(component),
- const AttributeInit &UNUSED(initializer)) const final
+ bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final
{
- return false;
+ if (createable_ == CreatableEnum::NonCreatable) {
+ return false;
+ }
+ return create_point_attribute(component, name_, initializer, CD_PROP_INT32);
}
bool exists(const GeometryComponent &component) const final
@@ -1064,6 +1168,10 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
return false;
}
+ if (!curve->splines().first()->attributes.get_for_read(name_)) {
+ return false;
+ }
+
bool has_point = false;
for (const SplinePtr &spline : curve->splines()) {
if (spline->size() != 0) {
@@ -1090,6 +1198,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
PositionAttributeProvider()
: BuiltinPointAttributeProvider(
"position",
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::NonDeletable,
[](const Spline &spline) { return spline.positions(); },
[](Spline &spline) { return spline.positions(); },
[](Spline &spline) { spline.mark_cache_invalid(); })
@@ -1319,39 +1429,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
{
- CurveEval *curve = get_curve_from_component_for_write(component);
- if (curve == nullptr) {
- return false;
- }
-
- /* Reuse the boolean for all splines; we expect all splines to have the same attributes. */
- bool layer_freed = false;
- for (SplinePtr &spline : curve->splines()) {
- layer_freed = spline->attributes.remove(attribute_id);
- }
- return layer_freed;
- }
-
- static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
- const CustomDataType data_type,
- const int total_size)
- {
- switch (initializer.type) {
- case AttributeInit::Type::Default:
- /* This function shouldn't be called in this case, since there
- * is no need to copy anything to the new custom data array. */
- BLI_assert_unreachable();
- return {};
- case AttributeInit::Type::VArray:
- return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
- case AttributeInit::Type::MoveArray:
- return std::make_unique<fn::GVArray_For_GSpan>(
- GSpan(*bke::custom_data_type_to_cpp_type(data_type),
- static_cast<const AttributeInitMove &>(initializer).data,
- total_size));
- }
- BLI_assert_unreachable();
- return {};
+ return remove_point_attribute(component, attribute_id);
}
bool try_create(GeometryComponent &component,
@@ -1364,55 +1442,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
if (domain != ATTR_DOMAIN_POINT) {
return false;
}
- CurveEval *curve = get_curve_from_component_for_write(component);
- if (curve == nullptr || curve->splines().size() == 0) {
- return false;
- }
-
- MutableSpan<SplinePtr> splines = curve->splines();
-
- /* First check the one case that allows us to avoid copying the input data. */
- if (splines.size() == 1 && initializer.type == AttributeInit::Type::MoveArray) {
- void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
- if (!splines[0]->attributes.create_by_move(attribute_id, data_type, source_data)) {
- MEM_freeN(source_data);
- return false;
- }
- return true;
- }
-
- /* Otherwise just create a custom data layer on each of the splines. */
- for (const int i : splines.index_range()) {
- if (!splines[i]->attributes.create(attribute_id, data_type)) {
- /* If attribute creation fails on one of the splines, we cannot leave the custom data
- * layers in the previous splines around, so delete them before returning. However,
- * this is not an expected case. */
- BLI_assert_unreachable();
- return false;
- }
- }
-
- /* With a default initializer type, we can keep the values at their initial values. */
- if (initializer.type == AttributeInit::Type::Default) {
- return true;
- }
-
- WriteAttributeLookup write_attribute = this->try_get_for_write(component, attribute_id);
- /* We just created the attribute, it should exist. */
- BLI_assert(write_attribute);
-
- const int total_size = curve->control_point_offsets().last();
- GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, total_size);
- /* TODO: When we can call a variant of #set_all with a virtual array argument,
- * this theoretically unnecessary materialize step could be removed. */
- GVArray_GSpan source_varray_span{*source_varray};
- write_attribute.varray->set_all(source_varray_span.data());
-
- if (initializer.type == AttributeInit::Type::MoveArray) {
- MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data);
- }
-
- return true;
+ return create_point_attribute(component, attribute_id, initializer, data_type);
}
bool foreach_attribute(const GeometryComponent &component,
@@ -1487,14 +1517,32 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static BezierHandleAttributeProvider handles_start(false);
static BezierHandleAttributeProvider handles_end(true);
+ static BuiltinPointAttributeProvider<int> id(
+ "id",
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Deletable,
+ [](const Spline &spline) {
+ std::optional<GSpan> span = spline.attributes.get_for_read("id");
+ return span ? span->typed<int>() : Span<int>();
+ },
+ [](Spline &spline) {
+ std::optional<GMutableSpan> span = spline.attributes.get_for_write("id");
+ return span ? span->typed<int>() : MutableSpan<int>();
+ },
+ {});
+
static BuiltinPointAttributeProvider<float> radius(
"radius",
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::NonDeletable,
[](const Spline &spline) { return spline.radii(); },
[](Spline &spline) { return spline.radii(); },
nullptr);
static BuiltinPointAttributeProvider<float> tilt(
"tilt",
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::NonDeletable,
[](const Spline &spline) { return spline.tilts(); },
[](Spline &spline) { return spline.tilts(); },
[](Spline &spline) { spline.mark_cache_invalid(); });
@@ -1502,7 +1550,7 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
static DynamicPointAttributeProvider point_custom_data;
return ComponentAttributeProviders(
- {&position, &radius, &tilt, &handles_start, &handles_end, &resolution, &cyclic},
+ {&position, &id, &radius, &tilt, &handles_start, &handles_end, &resolution, &cyclic},
{&spline_custom_data, &point_custom_data});
}