Compare commits
102 Commits
soc-2021-s
...
temp-virtu
Author | SHA1 | Date | |
---|---|---|---|
e1c1c65578 | |||
2154631e85 | |||
71b7e59e28 | |||
7106fe299e | |||
4b8e52bdbc | |||
462d3bde6e | |||
e354ff5b86 | |||
27da814444 | |||
493571c3c3 | |||
a6eb04cce4 | |||
139f69b3b9 | |||
8a1cc2f291 | |||
572fa82cc9 | |||
c8ab4dcce1 | |||
55a6af1c1e | |||
0827245a91 | |||
2f284f42b6 | |||
1131bf6ec6 | |||
2b0e890a55 | |||
c4d3380d2e | |||
05cef9da88 | |||
43a53f97c4 | |||
1d7a893d12 | |||
5e60ba93f7 | |||
65258dc98f | |||
d449e66c1d | |||
01fe332b9d | |||
d6b0f3a3a4 | |||
928b7b5340 | |||
aa22839aa1 | |||
78daf1b697 | |||
dcd9b21d07 | |||
42b350ed7f | |||
e79c7e088e | |||
99c5b788eb | |||
a2b5a74d49 | |||
84626dfa16 | |||
3d0abb3be9 | |||
9b6c13e66c | |||
7f4273d373 | |||
d1b8d6acd3 | |||
2267f19486 | |||
acd8874205 | |||
a69bd34fad | |||
2516fc953a | |||
50f93cbf52 | |||
8af541dcfd | |||
f8c0682a67 | |||
b40e753c81 | |||
2cff0676af | |||
b0444a347b | |||
becfc547b9 | |||
6a558a18f9 | |||
c066102f30 | |||
ba49545060 | |||
ca70c0521a | |||
4323b3f592 | |||
d1e6606d4d | |||
b64ad0b30a | |||
ed4b15ecd3 | |||
f79a673bf1 | |||
1438f16663 | |||
d613451c3a | |||
3f8ac0e5ef | |||
56bd1f46bd | |||
1e4cbec720 | |||
f9b669c588 | |||
1ac0a2db11 | |||
771cce22f1 | |||
c1a1046ed7 | |||
f430e7850a | |||
116eb09681 | |||
841d393c15 | |||
bc1acbcc5a | |||
cd49f68db6 | |||
5b51065347 | |||
e736fe67c9 | |||
1d20f60616 | |||
91b58c95ac | |||
955b01e359 | |||
1b3758f205 | |||
33870b21f3 | |||
e49f70745b | |||
c48a99542d | |||
68b5670268 | |||
dea268de72 | |||
399463c548 | |||
1d94de4ac3 | |||
0453361d20 | |||
b21a3ae6ad | |||
edb8ccf31f | |||
7af712c343 | |||
a9e0cb6ec8 | |||
5a7b30f8f9 | |||
024c07af84 | |||
c256298924 | |||
a11950531f | |||
ae01d1db98 | |||
f3a5b31196 | |||
8d1a5fcfea | |||
39c4103f9e | |||
4e03ac6b25 |
@@ -115,10 +115,10 @@ struct AttributeInitDefault : public AttributeInit {
|
||||
* Note that this can be used to fill the new attribute with the default
|
||||
*/
|
||||
struct AttributeInitVArray : public AttributeInit {
|
||||
const blender::fn::GVArray *varray;
|
||||
blender::fn::GVArray varray;
|
||||
|
||||
AttributeInitVArray(const blender::fn::GVArray *varray)
|
||||
: AttributeInit(Type::VArray), varray(varray)
|
||||
AttributeInitVArray(blender::fn::GVArray varray)
|
||||
: AttributeInit(Type::VArray), varray(std::move(varray))
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -150,9 +150,7 @@ namespace blender::bke {
|
||||
|
||||
using fn::CPPType;
|
||||
using fn::GVArray;
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArray;
|
||||
using fn::GVMutableArrayPtr;
|
||||
|
||||
const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
|
||||
CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
|
||||
@@ -164,14 +162,14 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
|
||||
*/
|
||||
struct ReadAttributeLookup {
|
||||
/* The virtual array that is used to read from this attribute. */
|
||||
GVArrayPtr varray;
|
||||
GVArray varray;
|
||||
/* Domain the attribute lives on in the geometry. */
|
||||
AttributeDomain domain;
|
||||
|
||||
/* Convenience function to check if the attribute has been found. */
|
||||
operator bool() const
|
||||
{
|
||||
return this->varray.get() != nullptr;
|
||||
return this->varray;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -180,7 +178,7 @@ struct ReadAttributeLookup {
|
||||
*/
|
||||
struct WriteAttributeLookup {
|
||||
/* The virtual array that is used to read from and write to the attribute. */
|
||||
GVMutableArrayPtr varray;
|
||||
GVMutableArray varray;
|
||||
/* Domain the attributes lives on in the geometry. */
|
||||
AttributeDomain domain;
|
||||
/* Call this after changing the attribute to invalidate caches that depend on this attribute. */
|
||||
@@ -189,7 +187,7 @@ struct WriteAttributeLookup {
|
||||
/* Convenience function to check if the attribute has been found. */
|
||||
operator bool() const
|
||||
{
|
||||
return this->varray.get() != nullptr;
|
||||
return this->varray;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -209,7 +207,7 @@ class OutputAttribute {
|
||||
using SaveFn = std::function<void(OutputAttribute &)>;
|
||||
|
||||
private:
|
||||
GVMutableArrayPtr varray_;
|
||||
GVMutableArray varray_;
|
||||
AttributeDomain domain_ = ATTR_DOMAIN_AUTO;
|
||||
SaveFn save_;
|
||||
std::unique_ptr<fn::GVMutableArray_GSpan> optional_span_varray_;
|
||||
@@ -219,7 +217,7 @@ class OutputAttribute {
|
||||
public:
|
||||
OutputAttribute();
|
||||
OutputAttribute(OutputAttribute &&other);
|
||||
OutputAttribute(GVMutableArrayPtr varray,
|
||||
OutputAttribute(GVMutableArray varray,
|
||||
AttributeDomain domain,
|
||||
SaveFn save,
|
||||
const bool ignore_old_values);
|
||||
@@ -229,7 +227,7 @@ class OutputAttribute {
|
||||
operator bool() const;
|
||||
|
||||
GVMutableArray &operator*();
|
||||
GVMutableArray *operator->();
|
||||
fn::GVMutableArray *operator->();
|
||||
GVMutableArray &varray();
|
||||
AttributeDomain domain() const;
|
||||
const CPPType &cpp_type() const;
|
||||
@@ -247,16 +245,14 @@ class OutputAttribute {
|
||||
template<typename T> class OutputAttribute_Typed {
|
||||
private:
|
||||
OutputAttribute attribute_;
|
||||
std::unique_ptr<fn::GVMutableArray_Typed<T>> optional_varray_;
|
||||
VMutableArray<T> *varray_ = nullptr;
|
||||
VMutableArray<T> varray_;
|
||||
|
||||
public:
|
||||
OutputAttribute_Typed();
|
||||
OutputAttribute_Typed(OutputAttribute attribute) : attribute_(std::move(attribute))
|
||||
{
|
||||
if (attribute_) {
|
||||
optional_varray_ = std::make_unique<fn::GVMutableArray_Typed<T>>(attribute_.varray());
|
||||
varray_ = &**optional_varray_;
|
||||
varray_ = attribute_.varray().template typed<T>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,22 +271,22 @@ template<typename T> class OutputAttribute_Typed {
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return varray_ != nullptr;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
VMutableArray<T> &operator*()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
VMutableArray<T> *operator->()
|
||||
{
|
||||
return varray_;
|
||||
return &varray_;
|
||||
}
|
||||
|
||||
VMutableArray<T> &varray()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
AttributeDomain domain() const
|
||||
@@ -351,18 +347,17 @@ class CustomDataAttributes {
|
||||
|
||||
std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
|
||||
|
||||
blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const;
|
||||
blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const;
|
||||
|
||||
template<typename T>
|
||||
blender::fn::GVArray_Typed<T> get_for_read(const AttributeIDRef &attribute_id,
|
||||
const T &default_value) const
|
||||
blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
|
||||
{
|
||||
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
|
||||
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
|
||||
GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value);
|
||||
return blender::fn::GVArray_Typed<T>(std::move(varray));
|
||||
GVArray varray = this->get_for_read(attribute_id, type, &default_value);
|
||||
return varray.typed<T>();
|
||||
}
|
||||
|
||||
std::optional<blender::fn::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
|
||||
@@ -460,7 +455,7 @@ inline bool AttributeIDRef::should_be_kept() const
|
||||
inline OutputAttribute::OutputAttribute() = default;
|
||||
inline OutputAttribute::OutputAttribute(OutputAttribute &&other) = default;
|
||||
|
||||
inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
|
||||
inline OutputAttribute::OutputAttribute(GVMutableArray varray,
|
||||
AttributeDomain domain,
|
||||
SaveFn save,
|
||||
const bool ignore_old_values)
|
||||
@@ -473,22 +468,22 @@ inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
|
||||
|
||||
inline OutputAttribute::operator bool() const
|
||||
{
|
||||
return varray_.get() != nullptr;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
inline GVMutableArray &OutputAttribute::operator*()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
inline GVMutableArray *OutputAttribute::operator->()
|
||||
inline fn::GVMutableArray *OutputAttribute::operator->()
|
||||
{
|
||||
return varray_.get();
|
||||
return &varray_;
|
||||
}
|
||||
|
||||
inline GVMutableArray &OutputAttribute::varray()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
inline AttributeDomain OutputAttribute::domain() const
|
||||
@@ -498,7 +493,7 @@ inline AttributeDomain OutputAttribute::domain() const
|
||||
|
||||
inline const CPPType &OutputAttribute::cpp_type() const
|
||||
{
|
||||
return varray_->type();
|
||||
return varray_.type();
|
||||
}
|
||||
|
||||
inline CustomDataType OutputAttribute::custom_data_type() const
|
||||
|
@@ -119,10 +119,21 @@ class GeometryComponent {
|
||||
/* Get a read-only attribute for the domain based on the given attribute. This can be used to
|
||||
* interpolate from one domain to another.
|
||||
* Returns null if the interpolation is not implemented. */
|
||||
virtual std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const;
|
||||
blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain)
|
||||
.template typed<T>();
|
||||
}
|
||||
|
||||
/* Returns true when the attribute has been deleted. */
|
||||
bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
|
||||
@@ -146,16 +157,15 @@ class GeometryComponent {
|
||||
/* Get a virtual array to read the data of an attribute on the given domain and data type.
|
||||
* Returns null when the attribute does not exist or cannot be converted to the requested domain
|
||||
* and data type. */
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const;
|
||||
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const;
|
||||
|
||||
/* Get a virtual array to read the data of an attribute on the given domain. The data type is
|
||||
* left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
|
||||
* requested domain. */
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const;
|
||||
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain) const;
|
||||
|
||||
/* Get a virtual array to read data of an attribute with the given data type. The domain is
|
||||
* left unchanged. Returns null when the attribute does not exist or cannot be converted to the
|
||||
@@ -165,25 +175,22 @@ class GeometryComponent {
|
||||
|
||||
/* Get a virtual array to read the data of an attribute. If that is not possible, the returned
|
||||
* virtual array will contain a default value. This never returns null. */
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr) const;
|
||||
blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr) const;
|
||||
|
||||
/* Should be used instead of the method above when the requested data type is known at compile
|
||||
* time for better type safety. */
|
||||
template<typename T>
|
||||
blender::fn::GVArray_Typed<T> attribute_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
blender::VArray<T> attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
{
|
||||
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
|
||||
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
|
||||
std::unique_ptr varray = this->attribute_get_for_read(
|
||||
attribute_id, domain, type, &default_value);
|
||||
return blender::fn::GVArray_Typed<T>(std::move(varray));
|
||||
return this->attribute_get_for_read(attribute_id, domain, type, &default_value)
|
||||
.template typed<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,6 +241,11 @@ class GeometryComponent {
|
||||
|
||||
private:
|
||||
virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
|
||||
|
||||
virtual blender::fn::GVArray attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -391,10 +403,6 @@ class MeshComponent : public GeometryComponent {
|
||||
Mesh *get_for_write();
|
||||
|
||||
int attribute_domain_size(const AttributeDomain domain) const final;
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
@@ -405,6 +413,11 @@ class MeshComponent : public GeometryComponent {
|
||||
|
||||
private:
|
||||
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
|
||||
|
||||
blender::fn::GVArray attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
};
|
||||
|
||||
/** A geometry component that stores a point cloud. */
|
||||
@@ -469,10 +482,6 @@ class CurveComponent : public GeometryComponent {
|
||||
CurveEval *get_for_write();
|
||||
|
||||
int attribute_domain_size(const AttributeDomain domain) const final;
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
@@ -485,6 +494,11 @@ class CurveComponent : public GeometryComponent {
|
||||
|
||||
private:
|
||||
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
|
||||
|
||||
blender::fn::GVArray attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
};
|
||||
|
||||
class InstanceReference {
|
||||
@@ -759,9 +773,9 @@ class AttributeFieldInput : public fn::FieldInput {
|
||||
return name_;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
|
||||
std::string socket_inspection_name() const override;
|
||||
|
||||
@@ -776,9 +790,9 @@ class IDAttributeFieldInput : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
|
||||
std::string socket_inspection_name() const override;
|
||||
|
||||
@@ -815,9 +829,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
|
||||
return fn::Field<T>{field_input};
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
|
||||
std::string socket_inspection_name() const override;
|
||||
|
||||
|
@@ -187,14 +187,14 @@ class Spline {
|
||||
blender::MutableSpan<T> dst) const
|
||||
{
|
||||
this->sample_with_index_factors(
|
||||
blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst));
|
||||
blender::fn::GVArray(src), index_factors, blender::fn::GMutableSpan(dst));
|
||||
}
|
||||
template<typename T>
|
||||
void sample_with_index_factors(blender::Span<T> src,
|
||||
blender::Span<float> index_factors,
|
||||
blender::MutableSpan<T> dst) const
|
||||
{
|
||||
this->sample_with_index_factors(blender::VArray_For_Span(src), index_factors, dst);
|
||||
this->sample_with_index_factors(blender::VArray<T>::ForSpan(src), index_factors, dst);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,13 +202,11 @@ class Spline {
|
||||
* evaluated points. For poly splines, the lifetime of the returned virtual array must not
|
||||
* exceed the lifetime of the input data.
|
||||
*/
|
||||
virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
|
||||
const blender::fn::GVArray &src) const = 0;
|
||||
blender::fn::GVArrayPtr interpolate_to_evaluated(blender::fn::GSpan data) const;
|
||||
template<typename T>
|
||||
blender::fn::GVArray_Typed<T> interpolate_to_evaluated(blender::Span<T> data) const
|
||||
virtual blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const = 0;
|
||||
blender::fn::GVArray interpolate_to_evaluated(blender::fn::GSpan data) const;
|
||||
template<typename T> blender::VArray<T> interpolate_to_evaluated(blender::Span<T> data) const
|
||||
{
|
||||
return blender::fn::GVArray_Typed<T>(this->interpolate_to_evaluated(blender::fn::GSpan(data)));
|
||||
return this->interpolate_to_evaluated(blender::fn::GSpan(data)).typed<T>();
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -338,7 +336,7 @@ class BezierSpline final : public Spline {
|
||||
};
|
||||
InterpolationData interpolation_data_from_index_factor(const float index_factor) const;
|
||||
|
||||
virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
|
||||
virtual blender::fn::GVArray interpolate_to_evaluated(
|
||||
const blender::fn::GVArray &src) const override;
|
||||
|
||||
void evaluate_segment(const int index,
|
||||
@@ -475,7 +473,7 @@ class NURBSpline final : public Spline {
|
||||
|
||||
blender::Span<blender::float3> evaluated_positions() const final;
|
||||
|
||||
blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
|
||||
protected:
|
||||
void correct_end_tangents() const final;
|
||||
@@ -526,7 +524,7 @@ class PolySpline final : public Spline {
|
||||
|
||||
blender::Span<blender::float3> evaluated_positions() const final;
|
||||
|
||||
blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
|
||||
protected:
|
||||
void correct_end_tangents() const final;
|
||||
|
@@ -50,9 +50,7 @@ using blender::bke::AttributeIDRef;
|
||||
using blender::bke::OutputAttribute;
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_SingleValue;
|
||||
using blender::fn::GVMutableArray_For_GMutableSpan;
|
||||
using blender::fn::GVMutableArrayImpl_For_GMutableSpan;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
@@ -207,7 +205,7 @@ fn::GMutableSpan OutputAttribute::as_span()
|
||||
{
|
||||
if (!optional_span_varray_) {
|
||||
const bool materialize_old_values = !ignore_old_values_;
|
||||
optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(*varray_,
|
||||
optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(varray_,
|
||||
materialize_old_values);
|
||||
}
|
||||
fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_;
|
||||
@@ -249,8 +247,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), data);
|
||||
return true;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
@@ -305,8 +303,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), data);
|
||||
return true;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
@@ -337,8 +335,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
|
||||
return layer.name == attribute_id.name();
|
||||
}
|
||||
|
||||
GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
|
||||
const GeometryComponent &component) const
|
||||
GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const
|
||||
{
|
||||
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
||||
if (custom_data == nullptr) {
|
||||
@@ -503,7 +500,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
|
||||
continue;
|
||||
}
|
||||
GSpan data{*type, layer.data, domain_size};
|
||||
return {std::make_unique<GVArray_For_GSpan>(data), domain_};
|
||||
return {GVArray::ForSpan(data), domain_};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -533,7 +530,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
|
||||
continue;
|
||||
}
|
||||
GMutableSpan data{*type, layer.data, domain_size};
|
||||
return {std::make_unique<GVMutableArray_For_GMutableSpan>(data), domain_};
|
||||
return {GVMutableArray::ForSpan(data), domain_};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -749,25 +746,25 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
|
||||
* value if the attribute doesn't exist. If no default value is provided, the default value for the
|
||||
* type will be used.
|
||||
*/
|
||||
GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
{
|
||||
const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
|
||||
std::optional<GSpan> attribute = this->get_for_read(attribute_id);
|
||||
if (!attribute) {
|
||||
const int domain_size = this->size_;
|
||||
return std::make_unique<GVArray_For_SingleValue>(
|
||||
return GVArray::ForSingle(
|
||||
*type, domain_size, (default_value == nullptr) ? type->default_value() : default_value);
|
||||
}
|
||||
|
||||
if (attribute->type() == *type) {
|
||||
return std::make_unique<GVArray_For_GSpan>(*attribute);
|
||||
return GVArray::ForSpan(*attribute);
|
||||
}
|
||||
const blender::nodes::DataTypeConversions &conversions =
|
||||
blender::nodes::get_implicit_type_conversions();
|
||||
return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type);
|
||||
return conversions.try_convert(GVArray::ForSpan(*attribute), *type);
|
||||
}
|
||||
|
||||
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id)
|
||||
@@ -906,8 +903,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
@@ -1094,15 +1091,15 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
|
||||
std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
|
||||
static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray,
|
||||
const blender::fn::CPPType &to_type)
|
||||
{
|
||||
const blender::nodes::DataTypeConversions &conversions =
|
||||
blender::nodes::get_implicit_type_conversions();
|
||||
return conversions.try_convert(std::move(varray), to_type);
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
|
||||
blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
|
||||
const AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const
|
||||
@@ -1112,7 +1109,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
|
||||
blender::fn::GVArray varray = std::move(attribute.varray);
|
||||
if (!ELEM(domain, ATTR_DOMAIN_AUTO, attribute.domain)) {
|
||||
varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
|
||||
if (!varray) {
|
||||
@@ -1122,7 +1119,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
|
||||
|
||||
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
BLI_assert(cpp_type != nullptr);
|
||||
if (varray->type() != *cpp_type) {
|
||||
if (varray.type() != *cpp_type) {
|
||||
varray = try_adapt_data_type(std::move(varray), *cpp_type);
|
||||
if (!varray) {
|
||||
return {};
|
||||
@@ -1132,7 +1129,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
|
||||
return varray;
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read(
|
||||
blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
|
||||
const AttributeIDRef &attribute_id, const AttributeDomain domain) const
|
||||
{
|
||||
if (!this->attribute_domain_supported(domain)) {
|
||||
@@ -1160,7 +1157,7 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
||||
}
|
||||
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
BLI_assert(type != nullptr);
|
||||
if (attribute.varray->type() == *type) {
|
||||
if (attribute.varray.type() == *type) {
|
||||
return attribute;
|
||||
}
|
||||
const blender::nodes::DataTypeConversions &conversions =
|
||||
@@ -1168,14 +1165,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
||||
return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read(
|
||||
const AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
{
|
||||
std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read(
|
||||
attribute_id, domain, data_type);
|
||||
blender::fn::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type);
|
||||
if (varray) {
|
||||
return varray;
|
||||
}
|
||||
@@ -1184,11 +1179,11 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read
|
||||
default_value = type->default_value();
|
||||
}
|
||||
const int domain_size = this->attribute_domain_size(domain);
|
||||
return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
|
||||
return blender::fn::GVArray::ForSingle(*type, domain_size, default_value);
|
||||
}
|
||||
|
||||
class GVMutableAttribute_For_OutputAttribute
|
||||
: public blender::fn::GVMutableArray_For_GMutableSpan {
|
||||
: public blender::fn::GVMutableArrayImpl_For_GMutableSpan {
|
||||
public:
|
||||
GeometryComponent *component;
|
||||
std::string attribute_name;
|
||||
@@ -1197,7 +1192,7 @@ class GVMutableAttribute_For_OutputAttribute
|
||||
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
|
||||
GeometryComponent &component,
|
||||
const AttributeIDRef &attribute_id)
|
||||
: blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component)
|
||||
: blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component)
|
||||
{
|
||||
if (attribute_id.is_named()) {
|
||||
this->attribute_name = attribute_id.name();
|
||||
@@ -1223,7 +1218,8 @@ static void save_output_attribute(OutputAttribute &output_attribute)
|
||||
using namespace blender::bke;
|
||||
|
||||
GVMutableAttribute_For_OutputAttribute &varray =
|
||||
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray());
|
||||
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(
|
||||
*output_attribute.varray().get_implementation());
|
||||
|
||||
GeometryComponent &component = *varray.component;
|
||||
AttributeIDRef attribute_id;
|
||||
@@ -1251,7 +1247,7 @@ static void save_output_attribute(OutputAttribute &output_attribute)
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
|
||||
for (const int i : IndexRange(varray.size())) {
|
||||
varray.get(i, buffer);
|
||||
write_attribute.varray->set_by_relocate(i, buffer);
|
||||
write_attribute.varray.set_by_relocate(i, buffer);
|
||||
}
|
||||
if (write_attribute.tag_modified_fn) {
|
||||
write_attribute.tag_modified_fn();
|
||||
@@ -1294,9 +1290,9 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
if (!attribute) {
|
||||
if (default_value) {
|
||||
const int64_t domain_size = component.attribute_domain_size(domain);
|
||||
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
|
||||
component.attribute_try_create_builtin(attribute_name,
|
||||
AttributeInitVArray(&default_varray));
|
||||
component.attribute_try_create_builtin(
|
||||
attribute_name,
|
||||
AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
|
||||
}
|
||||
else {
|
||||
component.attribute_try_create_builtin(attribute_name, AttributeInitDefault());
|
||||
@@ -1311,9 +1307,8 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
/* Builtin attribute is on different domain. */
|
||||
return {};
|
||||
}
|
||||
|
||||
GVMutableArrayPtr varray = std::move(attribute.varray);
|
||||
if (varray->type() == *cpp_type) {
|
||||
GVMutableArray varray = std::move(attribute.varray);
|
||||
if (varray.type() == *cpp_type) {
|
||||
/* Builtin attribute matches exactly. */
|
||||
return OutputAttribute(std::move(varray),
|
||||
domain,
|
||||
@@ -1333,9 +1328,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id);
|
||||
if (!attribute) {
|
||||
if (default_value) {
|
||||
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
|
||||
component.attribute_try_create(
|
||||
attribute_id, domain, data_type, AttributeInitVArray(&default_varray));
|
||||
attribute_id,
|
||||
domain,
|
||||
data_type,
|
||||
AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
|
||||
}
|
||||
else {
|
||||
component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault());
|
||||
@@ -1347,7 +1344,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (attribute.domain == domain && attribute.varray->type() == *cpp_type) {
|
||||
if (attribute.domain == domain && attribute.varray.type() == *cpp_type) {
|
||||
/* Existing generic attribute matches exactly. */
|
||||
|
||||
return OutputAttribute(std::move(attribute.varray),
|
||||
@@ -1366,11 +1363,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
}
|
||||
else {
|
||||
/* Fill the temporary array with values from the existing attribute. */
|
||||
GVArrayPtr old_varray = component.attribute_get_for_read(
|
||||
GVArray old_varray = component.attribute_get_for_read(
|
||||
attribute_id, domain, data_type, default_value);
|
||||
old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
|
||||
old_varray.materialize_to_uninitialized(IndexRange(domain_size), data);
|
||||
}
|
||||
GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>(
|
||||
GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>(
|
||||
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id);
|
||||
|
||||
return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
|
||||
@@ -1394,21 +1391,21 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const
|
||||
GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &UNUSED(scope)) const
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type);
|
||||
GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
|
||||
if (attribute) {
|
||||
return scope.add(std::move(attribute));
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string AttributeFieldInput::socket_inspection_name() const
|
||||
@@ -1441,25 +1438,25 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
|
||||
}
|
||||
}
|
||||
|
||||
const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
const StringRef name = get_random_id_attribute_name(domain);
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
|
||||
GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
|
||||
if (attribute) {
|
||||
BLI_assert(attribute->size() == component.attribute_domain_size(domain));
|
||||
return scope.add(std::move(attribute));
|
||||
BLI_assert(attribute.size() == component.attribute_domain_size(domain));
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/* Use the index as the fallback if no random ID attribute exists. */
|
||||
return fn::IndexFieldInput::get_index_varray(mask, scope);
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string IDAttributeFieldInput::socket_inspection_name() const
|
||||
@@ -1479,19 +1476,20 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
|
||||
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
|
||||
}
|
||||
|
||||
const GVArray *AnonymousAttributeFieldInput::get_varray_for_context(
|
||||
const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
|
||||
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &UNUSED(scope)) const
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(
|
||||
GVArray attribute = component.attribute_try_get_for_read(
|
||||
anonymous_id_.get(), domain, data_type);
|
||||
return scope.add(std::move(attribute));
|
||||
return attribute;
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
|
||||
|
@@ -24,9 +24,6 @@
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArrayPtr;
|
||||
|
||||
/**
|
||||
* Utility to group together multiple functions that are used to access custom data on geometry
|
||||
* components in a generic way.
|
||||
@@ -86,7 +83,7 @@ class BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0;
|
||||
virtual GVArray try_get_for_read(const GeometryComponent &component) const = 0;
|
||||
virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component) const = 0;
|
||||
virtual bool try_delete(GeometryComponent &component) const = 0;
|
||||
virtual bool try_create(GeometryComponent &UNUSED(component),
|
||||
@@ -188,8 +185,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
|
||||
*/
|
||||
class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
|
||||
private:
|
||||
using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
|
||||
using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
|
||||
const AttributeDomain domain_;
|
||||
const CustomDataType attribute_type_;
|
||||
const CustomDataType stored_type_;
|
||||
@@ -232,8 +229,8 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
|
||||
* if the stored type is the same as the attribute type.
|
||||
*/
|
||||
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
||||
using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
|
||||
using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
|
||||
using UpdateOnRead = void (*)(const GeometryComponent &component);
|
||||
using UpdateOnWrite = void (*)(GeometryComponent &component);
|
||||
const CustomDataType stored_type_;
|
||||
@@ -266,7 +263,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final;
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final;
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final;
|
||||
bool try_delete(GeometryComponent &component) const final;
|
||||
bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final;
|
||||
|
@@ -32,8 +32,6 @@
|
||||
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray_Typed;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
@@ -218,7 +216,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info,
|
||||
Span<float3> normals = spline.evaluated_normals();
|
||||
Span<float3> profile_positions = profile.evaluated_positions();
|
||||
|
||||
GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
VArray<float> radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
for (const int i_ring : IndexRange(info.spline_vert_len)) {
|
||||
float4x4 point_matrix = float4x4::from_normalized_axis_data(
|
||||
positions[i_ring], normals[i_ring], tangents[i_ring]);
|
||||
@@ -486,8 +484,8 @@ static void copy_curve_point_attribute_to_mesh(const GSpan src,
|
||||
const ResultInfo &info,
|
||||
ResultAttributeData &dst)
|
||||
{
|
||||
GVArrayPtr interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray->get_internal_span();
|
||||
GVArray interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray.get_internal_span();
|
||||
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
@@ -552,8 +550,8 @@ static void copy_profile_point_attribute_to_mesh(const GSpan src,
|
||||
const ResultInfo &info,
|
||||
ResultAttributeData &dst)
|
||||
{
|
||||
GVArrayPtr interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray->get_internal_span();
|
||||
GVArray interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray.get_internal_span();
|
||||
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
@@ -28,10 +28,8 @@
|
||||
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_GSpan;
|
||||
using blender::fn::GVArrayPtr;
|
||||
using blender::fn::GVMutableArray_For_GMutableSpan;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Geometry Component Implementation
|
||||
@@ -253,15 +251,15 @@ void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray)
|
||||
static GVArray adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArray varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(curve.splines().size());
|
||||
adapt_curve_domain_point_to_spline_impl<T>(curve, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_curve_domain_point_to_spline_impl<T>(curve, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -272,29 +270,29 @@ static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVA
|
||||
* attributes. The goal is to avoid copying the spline value for every one of its control points
|
||||
* unless it is necessary (in that case the materialize functions will be called).
|
||||
*/
|
||||
template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
|
||||
GVArrayPtr original_varray_;
|
||||
template<typename T> class VArray_For_SplineToPoint final : public VArrayImpl<T> {
|
||||
GVArray original_varray_;
|
||||
/* Store existing data materialized if it was not already a span. This is expected
|
||||
* to be worth it because a single spline's value will likely be accessed many times. */
|
||||
fn::GVArray_Span<T> original_data_;
|
||||
VArray_Span<T> original_data_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VArray_For_SplineToPoint(GVArrayPtr original_varray, Array<int> offsets)
|
||||
: VArray<T>(offsets.last()),
|
||||
VArray_For_SplineToPoint(GVArray original_varray, Array<int> offsets)
|
||||
: VArrayImpl<T>(offsets.last()),
|
||||
original_varray_(std::move(original_varray)),
|
||||
original_data_(*original_varray_),
|
||||
original_data_(original_varray_.typed<T>()),
|
||||
offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
T get_impl(const int64_t index) const final
|
||||
T get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return original_data_[indices.spline_index];
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
const int total_size = offsets_.last();
|
||||
if (mask.is_range() && mask.as_range() == IndexRange(total_size)) {
|
||||
@@ -315,7 +313,7 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
|
||||
}
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
T *dst = r_span.data();
|
||||
const int total_size = offsets_.last();
|
||||
@@ -338,29 +336,29 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
|
||||
}
|
||||
};
|
||||
|
||||
static GVArrayPtr adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArrayPtr varray)
|
||||
static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArray varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
Array<int> offsets = curve.control_point_offsets();
|
||||
new_varray = std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplineToPoint<T>>>(
|
||||
offsets.last(), std::move(varray), std::move(offsets));
|
||||
new_varray = VArray<T>::template For<VArray_For_SplineToPoint<T>>(std::move(varray),
|
||||
std::move(offsets));
|
||||
});
|
||||
return new_varray;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
GVArrayPtr CurveComponent::attribute_try_adapt_domain(GVArrayPtr varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
if (varray->size() == 0) {
|
||||
if (varray.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
if (from_domain == to_domain) {
|
||||
@@ -402,8 +400,8 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen
|
||||
namespace blender::bke {
|
||||
|
||||
class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
||||
using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data);
|
||||
using AsReadAttribute = GVArray (*)(const CurveEval &data);
|
||||
using AsWriteAttribute = GVMutableArray (*)(CurveEval &data);
|
||||
const AsReadAttribute as_read_attribute_;
|
||||
const AsWriteAttribute as_write_attribute_;
|
||||
|
||||
@@ -424,7 +422,7 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
@@ -483,19 +481,15 @@ static void set_spline_resolution(SplinePtr &spline, const int resolution)
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr make_resolution_read_attribute(const CurveEval &curve)
|
||||
static GVArray make_resolution_read_attribute(const CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, int, get_spline_resolution>>(
|
||||
curve.splines());
|
||||
return VArray<int>::ForDerivedSpan<SplinePtr, get_spline_resolution>(curve.splines());
|
||||
}
|
||||
|
||||
static GVMutableArrayPtr make_resolution_write_attribute(CurveEval &curve)
|
||||
static GVMutableArray make_resolution_write_attribute(CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_DerivedSpan<SplinePtr,
|
||||
int,
|
||||
get_spline_resolution,
|
||||
set_spline_resolution>>(
|
||||
curve.splines());
|
||||
return VMutableArray<int>::
|
||||
ForDerivedSpan<SplinePtr, get_spline_resolution, set_spline_resolution>(curve.splines());
|
||||
}
|
||||
|
||||
static bool get_cyclic_value(const SplinePtr &spline)
|
||||
@@ -511,16 +505,14 @@ static void set_cyclic_value(SplinePtr &spline, const bool value)
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr make_cyclic_read_attribute(const CurveEval &curve)
|
||||
static GVArray make_cyclic_read_attribute(const CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value>>(
|
||||
curve.splines());
|
||||
return VArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value>(curve.splines());
|
||||
}
|
||||
|
||||
static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve)
|
||||
static GVMutableArray make_cyclic_write_attribute(CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<
|
||||
fn::GVMutableArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value, set_cyclic_value>>(
|
||||
return VMutableArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value, set_cyclic_value>(
|
||||
curve.splines());
|
||||
}
|
||||
|
||||
@@ -623,9 +615,9 @@ 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)
|
||||
static GVArray varray_from_initializer(const AttributeInit &initializer,
|
||||
const CustomDataType data_type,
|
||||
const Span<SplinePtr> splines)
|
||||
{
|
||||
switch (initializer.type) {
|
||||
case AttributeInit::Type::Default:
|
||||
@@ -634,16 +626,15 @@ static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
case AttributeInit::Type::VArray:
|
||||
return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
|
||||
return static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
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));
|
||||
return GVArray::ForSpan(GSpan(*bke::custom_data_type_to_cpp_type(data_type),
|
||||
static_cast<const AttributeInitMove &>(initializer).data,
|
||||
total_size));
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
@@ -691,11 +682,11 @@ static bool create_point_attribute(GeometryComponent &component,
|
||||
/* We just created the attribute, it should exist. */
|
||||
BLI_assert(write_attribute);
|
||||
|
||||
GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines);
|
||||
GVArray 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());
|
||||
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);
|
||||
@@ -723,29 +714,29 @@ static bool remove_point_attribute(GeometryComponent &component,
|
||||
/**
|
||||
* Virtual array for any control point data accessed with spans and an offset array.
|
||||
*/
|
||||
template<typename T> class VArray_For_SplinePoints : public VArray<T> {
|
||||
template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> {
|
||||
private:
|
||||
const Array<Span<T>> data_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets)
|
||||
: VArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
: VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
T get_impl(const int64_t index) const final
|
||||
T get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return data_[indices.spline_index][indices.point_index];
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize(data_.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
@@ -754,30 +745,30 @@ template<typename T> class VArray_For_SplinePoints : public VArray<T> {
|
||||
/**
|
||||
* Mutable virtual array for any control point data accessed with spans and an offset array.
|
||||
*/
|
||||
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArray<T> {
|
||||
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> {
|
||||
private:
|
||||
Array<MutableSpan<T>> data_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
|
||||
: VMutableArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
: VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
T get_impl(const int64_t index) const final
|
||||
T get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return data_[indices.spline_index][indices.point_index];
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, T value) final
|
||||
void set(const int64_t index, T value) final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
data_[indices.spline_index][indices.point_index] = value;
|
||||
}
|
||||
|
||||
void set_all_impl(Span<T> src) final
|
||||
void set_all(Span<T> src) final
|
||||
{
|
||||
for (const int spline_index : data_.index_range()) {
|
||||
const int offset = offsets_[spline_index];
|
||||
@@ -786,30 +777,28 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl
|
||||
}
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize({(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize_to_uninitialized(
|
||||
{(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> GVArrayPtr point_data_gvarray(Array<Span<T>> spans, Array<int> offsets)
|
||||
template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplinePoints<T>>>(
|
||||
offsets.last(), std::move(spans), std::move(offsets));
|
||||
return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> offsets)
|
||||
VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
|
||||
{
|
||||
return std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_SplinePoints<T>>>(
|
||||
offsets.last(), std::move(spans), std::move(offsets));
|
||||
return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans),
|
||||
std::move(offsets));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -820,24 +809,24 @@ GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> off
|
||||
* \note There is no need to check the handle type to avoid changing auto handles, since
|
||||
* retrieving write access to the position data will mark them for recomputation anyway.
|
||||
*/
|
||||
class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
|
||||
class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> {
|
||||
private:
|
||||
MutableSpan<SplinePtr> splines_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
|
||||
: VMutableArray<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
|
||||
: VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
float3 get_impl(const int64_t index) const final
|
||||
float3 get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return splines_[indices.spline_index]->positions()[indices.point_index];
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, float3 value) final
|
||||
void set(const int64_t index, float3 value) final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
Spline &spline = *splines_[indices.spline_index];
|
||||
@@ -852,7 +841,7 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
|
||||
}
|
||||
}
|
||||
|
||||
void set_all_impl(Span<float3> src) final
|
||||
void set_all(Span<float3> src) final
|
||||
{
|
||||
for (const int spline_index : splines_.index_range()) {
|
||||
Spline &spline = *splines_[spline_index];
|
||||
@@ -885,21 +874,20 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
|
||||
return spans;
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
Array<Span<float3>> spans = this->get_position_spans();
|
||||
point_attribute_materialize(spans.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask,
|
||||
MutableSpan<float3> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
Array<Span<float3>> spans = this->get_position_spans();
|
||||
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
};
|
||||
|
||||
class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
class VArray_For_BezierHandle final : public VArrayImpl<float3> {
|
||||
private:
|
||||
Span<SplinePtr> splines_;
|
||||
Array<int> offsets_;
|
||||
@@ -907,7 +895,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
|
||||
public:
|
||||
VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right)
|
||||
: VArray<float3>(offsets.last()),
|
||||
: VArrayImpl<float3>(offsets.last()),
|
||||
splines_(std::move(splines)),
|
||||
offsets_(std::move(offsets)),
|
||||
is_right_(is_right)
|
||||
@@ -929,7 +917,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
return float3(0);
|
||||
}
|
||||
|
||||
float3 get_impl(const int64_t index) const final
|
||||
float3 get(const int64_t index) const final
|
||||
{
|
||||
return get_internal(index, splines_, offsets_, is_right_);
|
||||
}
|
||||
@@ -976,19 +964,18 @@ class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
materialize_internal(mask, splines_, offsets_, is_right_, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask,
|
||||
MutableSpan<float3> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span);
|
||||
}
|
||||
};
|
||||
|
||||
class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
|
||||
private:
|
||||
MutableSpan<SplinePtr> splines_;
|
||||
Array<int> offsets_;
|
||||
@@ -998,19 +985,19 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines,
|
||||
Array<int> offsets,
|
||||
const bool is_right)
|
||||
: VMutableArray<float3>(offsets.last()),
|
||||
: VMutableArrayImpl<float3>(offsets.last()),
|
||||
splines_(splines),
|
||||
offsets_(std::move(offsets)),
|
||||
is_right_(is_right)
|
||||
{
|
||||
}
|
||||
|
||||
float3 get_impl(const int64_t index) const final
|
||||
float3 get(const int64_t index) const final
|
||||
{
|
||||
return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_);
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, float3 value) final
|
||||
void set(const int64_t index, float3 value) final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
Spline &spline = *splines_[indices.spline_index];
|
||||
@@ -1026,7 +1013,7 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
}
|
||||
}
|
||||
|
||||
void set_all_impl(Span<float3> src) final
|
||||
void set_all(Span<float3> src) final
|
||||
{
|
||||
for (const int spline_index : splines_.index_range()) {
|
||||
Spline &spline = *splines_[spline_index];
|
||||
@@ -1049,13 +1036,12 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
}
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask,
|
||||
MutableSpan<float3> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
VArray_For_BezierHandle::materialize_to_uninitialized_internal(
|
||||
mask, splines_, offsets_, is_right_, r_span);
|
||||
@@ -1097,7 +1083,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const override
|
||||
{
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
@@ -1110,7 +1096,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
|
||||
Span<SplinePtr> splines = curve->splines();
|
||||
if (splines.size() == 1) {
|
||||
return std::make_unique<fn::GVArray_For_GSpan>(get_span_(*splines.first()));
|
||||
return GVArray::ForSpan(get_span_(*splines.first()));
|
||||
}
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
@@ -1119,7 +1105,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
spans[i] = get_span_(*splines[i]);
|
||||
}
|
||||
|
||||
return point_data_gvarray(spans, offsets);
|
||||
return point_data_varray(spans, offsets);
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
|
||||
@@ -1144,8 +1130,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
|
||||
MutableSpan<SplinePtr> splines = curve->splines();
|
||||
if (splines.size() == 1) {
|
||||
return {std::make_unique<fn::GVMutableArray_For_GMutableSpan>(
|
||||
get_mutable_span_(*splines.first())),
|
||||
return {GVMutableArray::ForSpan(get_mutable_span_(*splines.first())),
|
||||
domain_,
|
||||
std::move(tag_modified_fn)};
|
||||
}
|
||||
@@ -1156,7 +1141,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
spans[i] = get_mutable_span_(*splines[i]);
|
||||
}
|
||||
|
||||
return {point_data_gvarray(spans, offsets), domain_, tag_modified_fn};
|
||||
return {point_data_varray(spans, offsets), domain_, tag_modified_fn};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &component) const final
|
||||
@@ -1248,10 +1233,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
|
||||
};
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
return {std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<float3,
|
||||
VMutableArray_For_SplinePosition>>(
|
||||
offsets.last(), curve->splines(), std::move(offsets)),
|
||||
return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(),
|
||||
std::move(offsets)),
|
||||
domain_,
|
||||
tag_modified_fn};
|
||||
}
|
||||
@@ -1273,7 +1256,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const override
|
||||
{
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
@@ -1285,8 +1268,8 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
|
||||
}
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
return std::make_unique<fn::GVArray_For_EmbeddedVArray<float3, VArray_For_BezierHandle>>(
|
||||
offsets.last(), curve->splines(), std::move(offsets), is_right_);
|
||||
return VArray<float3>::For<VArray_For_BezierHandle>(
|
||||
curve->splines(), std::move(offsets), is_right_);
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
|
||||
@@ -1303,12 +1286,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
|
||||
auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); };
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
return {
|
||||
std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<float3, VMutableArray_For_BezierHandles>>(
|
||||
offsets.last(), curve->splines(), std::move(offsets), is_right_),
|
||||
domain_,
|
||||
tag_modified_fn};
|
||||
return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>(
|
||||
curve->splines(), std::move(offsets), is_right_),
|
||||
domain_,
|
||||
tag_modified_fn};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &UNUSED(component)) const final
|
||||
@@ -1387,7 +1368,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
|
||||
/* First check for the simpler situation when we can return a simpler span virtual array. */
|
||||
if (spans.size() == 1) {
|
||||
return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT};
|
||||
return {GVArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
ReadAttributeLookup attribute = {};
|
||||
@@ -1399,7 +1380,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
data[i] = spans[i].typed<T>();
|
||||
BLI_assert(data[i].data() != nullptr);
|
||||
}
|
||||
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
});
|
||||
return attribute;
|
||||
}
|
||||
@@ -1440,7 +1421,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
|
||||
/* First check for the simpler situation when we can return a simpler span virtual array. */
|
||||
if (spans.size() == 1) {
|
||||
return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT};
|
||||
return {GVMutableArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
WriteAttributeLookup attribute = {};
|
||||
@@ -1452,7 +1433,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
data[i] = spans[i].typed<T>();
|
||||
BLI_assert(data[i].data() != nullptr);
|
||||
}
|
||||
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
});
|
||||
return attribute;
|
||||
}
|
||||
|
@@ -389,25 +389,22 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const InstancesComponent &instances_component = static_cast<const InstancesComponent &>(
|
||||
component);
|
||||
Span<float4x4> transforms = instances_component.instance_transforms();
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<float4x4, float3, get_transform_position>>(
|
||||
transforms);
|
||||
return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms);
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
|
||||
{
|
||||
InstancesComponent &instances_component = static_cast<InstancesComponent &>(component);
|
||||
MutableSpan<float4x4> transforms = instances_component.instance_transforms();
|
||||
return {
|
||||
std::make_unique<fn::GVMutableArray_For_DerivedSpan<float4x4,
|
||||
float3,
|
||||
get_transform_position,
|
||||
set_transform_position>>(transforms),
|
||||
domain_};
|
||||
return {VMutableArray<float3>::ForDerivedSpan<float4x4,
|
||||
get_transform_position,
|
||||
set_transform_position>(transforms),
|
||||
domain_};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &UNUSED(component)) const final
|
||||
@@ -435,13 +432,13 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
|
||||
if (instances.instance_ids().is_empty()) {
|
||||
return {};
|
||||
}
|
||||
return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids());
|
||||
return VArray<int>::ForSpan(instances.instance_ids());
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
|
||||
@@ -450,8 +447,7 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
|
||||
if (instances.instance_ids().is_empty()) {
|
||||
return {};
|
||||
}
|
||||
return {std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids()),
|
||||
domain_};
|
||||
return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &component) const final
|
||||
@@ -477,8 +473,8 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::VArray: {
|
||||
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data());
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), ids.data());
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
|
@@ -32,8 +32,6 @@
|
||||
/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */
|
||||
extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id);
|
||||
|
||||
using blender::fn::GVArray;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Geometry Component Implementation
|
||||
* \{ */
|
||||
@@ -203,17 +201,17 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
/* We compute all interpolated values at once, because for this interpolation, one has to
|
||||
* iterate over all loops anyway. */
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -239,14 +237,14 @@ static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
});
|
||||
return new_varray;
|
||||
}
|
||||
@@ -295,15 +293,15 @@ void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -368,15 +366,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -424,15 +422,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_face_to_point_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -453,15 +451,15 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_face_to_corner(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -507,15 +505,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -567,15 +565,15 @@ void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_point_to_face_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_point_to_face_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -617,15 +615,15 @@ void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -678,15 +676,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -728,15 +726,15 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -788,15 +786,15 @@ void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -804,15 +802,15 @@ static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr va
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
blender::fn::GVArrayPtr varray,
|
||||
blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
if (varray->size() == 0) {
|
||||
if (varray.size() == 0) {
|
||||
return {};
|
||||
}
|
||||
if (from_domain == to_domain) {
|
||||
@@ -823,11 +821,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, varray);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, varray);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -836,11 +834,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, varray);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, varray);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -849,11 +847,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, varray);
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, varray);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -862,11 +860,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_EDGE: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, varray);
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, varray);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -896,9 +894,9 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com
|
||||
namespace blender::bke {
|
||||
|
||||
template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
|
||||
static GVArrayPtr make_derived_read_attribute(const void *data, const int domain_size)
|
||||
static GVArray make_derived_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<StructT, ElemT, GetFunc>>(
|
||||
return VArray<ElemT>::template ForDerivedSpan<StructT, GetFunc>(
|
||||
Span<StructT>((const StructT *)data, domain_size));
|
||||
}
|
||||
|
||||
@@ -906,23 +904,22 @@ template<typename StructT,
|
||||
typename ElemT,
|
||||
ElemT (*GetFunc)(const StructT &),
|
||||
void (*SetFunc)(StructT &, ElemT)>
|
||||
static GVMutableArrayPtr make_derived_write_attribute(void *data, const int domain_size)
|
||||
static GVMutableArray make_derived_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(
|
||||
return VMutableArray<ElemT>::template ForDerivedSpan<StructT, GetFunc, SetFunc>(
|
||||
MutableSpan<StructT>((StructT *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
|
||||
MutableSpan<T>((T *)data, domain_size));
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
static float3 get_vertex_position(const MVert &vert)
|
||||
@@ -999,23 +996,23 @@ static void set_crease(MEdge &edge, float value)
|
||||
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
|
||||
}
|
||||
|
||||
class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
|
||||
class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
|
||||
private:
|
||||
MDeformVert *dverts_;
|
||||
const int dvert_index_;
|
||||
|
||||
public:
|
||||
VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
|
||||
: VMutableArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
: VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
{
|
||||
}
|
||||
|
||||
float get_impl(const int64_t index) const override
|
||||
float get(const int64_t index) const override
|
||||
{
|
||||
return get_internal(dverts_, dvert_index_, index);
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, const float value) override
|
||||
void set(const int64_t index, const float value) override
|
||||
{
|
||||
MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
|
||||
weight->weight = value;
|
||||
@@ -1036,18 +1033,18 @@ class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
|
||||
}
|
||||
};
|
||||
|
||||
class VArray_For_VertexWeights final : public VArray<float> {
|
||||
class VArray_For_VertexWeights final : public VArrayImpl<float> {
|
||||
private:
|
||||
const MDeformVert *dverts_;
|
||||
const int dvert_index_;
|
||||
|
||||
public:
|
||||
VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index)
|
||||
: VArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
: VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
{
|
||||
}
|
||||
|
||||
float get_impl(const int64_t index) const override
|
||||
float get(const int64_t index) const override
|
||||
{
|
||||
return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index);
|
||||
}
|
||||
@@ -1078,12 +1075,10 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
|
||||
}
|
||||
if (mesh->dvert == nullptr) {
|
||||
static const float default_value = 0.0f;
|
||||
return {std::make_unique<fn::GVArray_For_SingleValueRef>(
|
||||
CPPType::get<float>(), mesh->totvert, &default_value),
|
||||
ATTR_DOMAIN_POINT};
|
||||
return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT};
|
||||
}
|
||||
return {std::make_unique<fn::GVArray_For_EmbeddedVArray<float, VArray_For_VertexWeights>>(
|
||||
mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
return {VArray<float>::For<VArray_For_VertexWeights>(
|
||||
mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
@@ -1114,11 +1109,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
|
||||
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
|
||||
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
|
||||
}
|
||||
return {
|
||||
std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<float, VMutableArray_For_VertexWeights>>(
|
||||
mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
ATTR_DOMAIN_POINT};
|
||||
return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>(
|
||||
mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
|
||||
@@ -1184,7 +1177,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
@@ -1197,8 +1190,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<fn::GVArray_For_Span<float3>>(
|
||||
Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
}
|
||||
|
||||
Array<float3> normals(mesh->totpoly);
|
||||
@@ -1207,7 +1199,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
|
||||
}
|
||||
|
||||
return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final
|
||||
|
@@ -141,16 +141,15 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con
|
||||
namespace blender::bke {
|
||||
|
||||
template<typename T>
|
||||
static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
|
||||
MutableSpan<T>((T *)data, domain_size));
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -364,12 +364,12 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
|
||||
result.attribute_try_create(
|
||||
entry.key, domain_output, data_type_output, AttributeInitDefault());
|
||||
WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id);
|
||||
if (!write_attribute || &write_attribute.varray->type() != cpp_type ||
|
||||
if (!write_attribute || &write_attribute.varray.type() != cpp_type ||
|
||||
write_attribute.domain != domain_output) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fn::GVMutableArray_GSpan dst_span{*write_attribute.varray};
|
||||
fn::GVMutableArray_GSpan dst_span{write_attribute.varray};
|
||||
|
||||
int offset = 0;
|
||||
for (const GeometryInstanceGroup &set_group : set_groups) {
|
||||
@@ -381,11 +381,11 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
|
||||
if (domain_size == 0) {
|
||||
continue; /* Domain size is 0, so no need to increment the offset. */
|
||||
}
|
||||
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
|
||||
GVArray source_attribute = component.attribute_try_get_for_read(
|
||||
attribute_id, domain_output, data_type_output);
|
||||
|
||||
if (source_attribute) {
|
||||
fn::GVArray_GSpan src_span{*source_attribute};
|
||||
fn::GVArray_GSpan src_span{source_attribute};
|
||||
const void *src_buffer = src_span.data();
|
||||
for (const int UNUSED(i) : set_group.transforms.index_range()) {
|
||||
void *dst_buffer = dst_span[offset];
|
||||
|
@@ -269,7 +269,7 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_
|
||||
eAttributeMapMode mode)
|
||||
{
|
||||
if (src_attribute && dst_attribute) {
|
||||
this->sample_data(*src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
|
||||
this->sample_data(src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,14 +30,12 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::VArray;
|
||||
using blender::attribute_math::convert_to_static_type;
|
||||
using blender::bke::AttributeIDRef;
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_Typed;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
Spline::Type Spline::type() const
|
||||
{
|
||||
@@ -416,7 +414,7 @@ Span<float3> Spline::evaluated_normals() const
|
||||
}
|
||||
|
||||
/* Rotate the generated normals with the interpolated tilt data. */
|
||||
GVArray_Typed<float> tilts = this->interpolate_to_evaluated(this->tilts());
|
||||
VArray<float> tilts = this->interpolate_to_evaluated(this->tilts());
|
||||
for (const int i : normals.index_range()) {
|
||||
normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]);
|
||||
}
|
||||
@@ -529,9 +527,9 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated)
|
||||
}
|
||||
}
|
||||
|
||||
GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const
|
||||
GVArray Spline::interpolate_to_evaluated(GSpan data) const
|
||||
{
|
||||
return this->interpolate_to_evaluated(GVArray_For_GSpan(data));
|
||||
return this->interpolate_to_evaluated(GVArray::ForSpan(data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -547,7 +545,7 @@ void Spline::sample_with_index_factors(const GVArray &src,
|
||||
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
const GVArray_Typed<T> src_typed = src.typed<T>();
|
||||
const VArray<T> src_typed = src.typed<T>();
|
||||
MutableSpan<T> dst_typed = dst.typed<T>();
|
||||
if (src.size() == 1) {
|
||||
dst_typed.fill(src_typed[0]);
|
||||
|
@@ -25,9 +25,8 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::VArray;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_For_ArrayContainer;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
void BezierSpline::copy_settings(Spline &dst) const
|
||||
{
|
||||
@@ -697,26 +696,26 @@ static void interpolate_to_evaluated_impl(const BezierSpline &spline,
|
||||
}
|
||||
}
|
||||
|
||||
GVArrayPtr BezierSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
GVArray BezierSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
{
|
||||
BLI_assert(src.size() == this->size());
|
||||
|
||||
if (src.is_single()) {
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
const int eval_size = this->evaluated_points_size();
|
||||
if (eval_size == 1) {
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
GVArrayPtr new_varray;
|
||||
GVArray new_varray;
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(eval_size);
|
||||
interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values);
|
||||
new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -26,10 +26,8 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::VArray;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_For_ArrayContainer;
|
||||
using blender::fn::GVArray_Typed;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
void NURBSpline::copy_settings(Spline &dst) const
|
||||
{
|
||||
@@ -410,23 +408,23 @@ void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights,
|
||||
mixer.finalize();
|
||||
}
|
||||
|
||||
GVArrayPtr NURBSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
{
|
||||
BLI_assert(src.size() == this->size());
|
||||
|
||||
if (src.is_single()) {
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
Span<BasisCache> basis_cache = this->calculate_basis_cache();
|
||||
|
||||
GVArrayPtr new_varray;
|
||||
GVArray new_varray;
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(this->evaluated_points_size());
|
||||
interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values);
|
||||
new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -448,8 +446,8 @@ Span<float3> NURBSpline::evaluated_positions() const
|
||||
evaluated_position_cache_.resize(eval_size);
|
||||
|
||||
/* TODO: Avoid copying the evaluated data from the temporary array. */
|
||||
GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
|
||||
evaluated->materialize(evaluated_position_cache_);
|
||||
VArray<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
|
||||
evaluated.materialize(evaluated_position_cache_);
|
||||
|
||||
position_cache_dirty_ = false;
|
||||
return evaluated_position_cache_;
|
||||
|
@@ -23,7 +23,6 @@ using blender::float3;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
void PolySpline::copy_settings(Spline &UNUSED(dst)) const
|
||||
{
|
||||
@@ -122,9 +121,8 @@ Span<float3> PolySpline::evaluated_positions() const
|
||||
* the original data. Therefore the lifetime of the returned virtual array must not be longer than
|
||||
* the source data.
|
||||
*/
|
||||
GVArrayPtr PolySpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
{
|
||||
BLI_assert(src.size() == this->size());
|
||||
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
320
source/blender/blenlib/BLI_any.hh
Normal file
320
source/blender/blenlib/BLI_any.hh
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*
|
||||
* A #blender::Any is a type-safe container for single values of any copy constructible type.
|
||||
* It is similar to #std::any but provides the following two additional features:
|
||||
* - Adjustable inline buffer capacity and alignment. #std::any has a small inline buffer in most
|
||||
* implementations as well, but its size is not guaranteed.
|
||||
* - Can store additional user-defined type information without increasing the stack size of #Any.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "BLI_memory_utils.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Contains function pointers that manage the memory in an #Any.
|
||||
* Additional type specific #ExtraInfo can be embedded here as well.
|
||||
*/
|
||||
template<typename ExtraInfo> struct AnyTypeInfo {
|
||||
void (*copy_construct)(void *dst, const void *src);
|
||||
void (*move_construct)(void *dst, void *src);
|
||||
void (*destruct)(void *src);
|
||||
const void *(*get)(const void *src);
|
||||
ExtraInfo extra_info;
|
||||
|
||||
/**
|
||||
* Used when #T is stored directly in the inline buffer of the #Any.
|
||||
*/
|
||||
template<typename T> static const AnyTypeInfo &get_for_inline()
|
||||
{
|
||||
static AnyTypeInfo funcs = {[](void *dst, const void *src) { new (dst) T(*(const T *)src); },
|
||||
[](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
|
||||
[](void *src) { ((T *)src)->~T(); },
|
||||
[](const void *src) { return src; },
|
||||
ExtraInfo::template get<T>()};
|
||||
return funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr
|
||||
* instead. In this scenario, the #std::unique_ptr is stored in the inline buffer.
|
||||
*/
|
||||
template<typename T> static const AnyTypeInfo &get_for_unique_ptr()
|
||||
{
|
||||
using Ptr = std::unique_ptr<T>;
|
||||
static AnyTypeInfo funcs = {
|
||||
|
||||
[](void *dst, const void *src) { new (dst) Ptr(new T(**(const Ptr *)src)); },
|
||||
[](void *dst, void *src) { new (dst) Ptr(new T(std::move(**(Ptr *)src))); },
|
||||
[](void *src) { ((Ptr *)src)->~Ptr(); },
|
||||
[](const void *src) -> const void * { return &**(const Ptr *)src; },
|
||||
ExtraInfo::template get<T>()};
|
||||
return funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when the #Any does not contain any type currently.
|
||||
*/
|
||||
static const AnyTypeInfo &get_for_empty()
|
||||
{
|
||||
static AnyTypeInfo funcs = {[](void *UNUSED(dst), const void *UNUSED(src)) {},
|
||||
[](void *UNUSED(dst), void *UNUSED(src)) {},
|
||||
[](void *UNUSED(src)) {},
|
||||
[](const void *UNUSED(src)) -> const void * { return nullptr; },
|
||||
ExtraInfo{}};
|
||||
return funcs;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dummy extra info that is used when no additional type information should be stored in the #Any.
|
||||
*/
|
||||
struct NoExtraInfo {
|
||||
template<typename T> static NoExtraInfo get()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<
|
||||
/**
|
||||
* Either void or a struct that contains data members for additional type information.
|
||||
* The struct has to have a static `ExtraInfo get<T>()` method that initializes the struct
|
||||
* based on a type.
|
||||
*/
|
||||
typename ExtraInfo = void,
|
||||
/**
|
||||
* Size of the inline buffer. This allows types that are small enough to be stored directly
|
||||
* inside the #Any without an additional allocation.
|
||||
*/
|
||||
size_t InlineBufferCapacity = 8,
|
||||
/**
|
||||
* Required minimum alignment of the inline buffer. If this is smaller than the alignment
|
||||
* requirement of a used type, a separate allocation is necessary.
|
||||
*/
|
||||
size_t Alignment = 8>
|
||||
class Any {
|
||||
private:
|
||||
/* Makes it possible to use void in the template parameters. */
|
||||
using RealExtraInfo =
|
||||
std::conditional_t<std::is_void_v<ExtraInfo>, detail::NoExtraInfo, ExtraInfo>;
|
||||
using Info = detail::AnyTypeInfo<RealExtraInfo>;
|
||||
|
||||
/**
|
||||
* Inline buffer that either contains nothing, the stored value directly, or a #std::unique_ptr
|
||||
* to the value.
|
||||
*/
|
||||
AlignedBuffer<std::max(InlineBufferCapacity, sizeof(std::unique_ptr<int>)), Alignment> buffer_{};
|
||||
|
||||
/**
|
||||
* Information about the type that is currently stored.
|
||||
*/
|
||||
const Info *info_ = &Info::get_for_empty();
|
||||
|
||||
public:
|
||||
/** Only copy constructible types can be stored in #Any. */
|
||||
template<typename T> static constexpr inline bool is_allowed_v = std::is_copy_constructible_v<T>;
|
||||
|
||||
/**
|
||||
* Checks if the type will be stored in the inline buffer or if it requires a separate
|
||||
* allocation.
|
||||
*/
|
||||
template<typename T>
|
||||
static constexpr inline bool is_inline_v = std::is_nothrow_move_constructible_v<T> &&
|
||||
sizeof(T) <= InlineBufferCapacity &&
|
||||
alignof(T) <= Alignment;
|
||||
|
||||
/**
|
||||
* Checks if #T is the same type as this #Any, because in this case the behavior of e.g. the
|
||||
* assignment operator is different.
|
||||
*/
|
||||
template<typename T>
|
||||
static constexpr inline bool is_same_any_v = std::is_same_v<std::decay_t<T>, Any>;
|
||||
|
||||
private:
|
||||
template<typename T> const Info &get_info() const
|
||||
{
|
||||
using DecayT = std::decay_t<T>;
|
||||
static_assert(is_allowed_v<DecayT>);
|
||||
if constexpr (is_inline_v<DecayT>) {
|
||||
return Info::template get_for_inline<DecayT>();
|
||||
}
|
||||
else {
|
||||
return Info::template get_for_unique_ptr<DecayT>();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Any() = default;
|
||||
|
||||
Any(const Any &other) : info_(other.info_)
|
||||
{
|
||||
info_->copy_construct(&buffer_, &other.buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \note: The #other #Any will not be empty afterwards if it was not before. Just its value is in
|
||||
* a moved-from state.
|
||||
*/
|
||||
Any(Any &&other) noexcept : info_(other.info_)
|
||||
{
|
||||
info_->move_construct(&buffer_, &other.buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new #Any that contains the given type #T from #args. The #std::in_place_type_t is
|
||||
* used to disambiguate this and the copy/move constructors.
|
||||
*/
|
||||
template<typename T, typename... Args> explicit Any(std::in_place_type_t<T>, Args &&...args)
|
||||
{
|
||||
using DecayT = std::decay_t<T>;
|
||||
static_assert(is_allowed_v<DecayT>);
|
||||
info_ = &this->template get_info<DecayT>();
|
||||
if constexpr (is_inline_v<DecayT>) {
|
||||
/* Construct the value directly in the inline buffer. */
|
||||
new (&buffer_) DecayT(std::forward<Args>(args)...);
|
||||
}
|
||||
else {
|
||||
/* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline
|
||||
* buffer. */
|
||||
new (&buffer_) std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new #Any that contains the given value.
|
||||
*/
|
||||
template<typename T, typename X = std::enable_if_t<!is_same_any_v<T>, void>>
|
||||
Any(T &&value) : Any(std::in_place_type<T>, std::forward<T>(value))
|
||||
{
|
||||
}
|
||||
|
||||
~Any()
|
||||
{
|
||||
info_->destruct(&buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \note: Only needed because the template below does not count as copy assignment operator.
|
||||
*/
|
||||
Any &operator=(const Any &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
this->~Any();
|
||||
new (this) Any(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assign any value to the #Any. */
|
||||
template<typename T> Any &operator=(T &&other)
|
||||
{
|
||||
if constexpr (is_same_any_v<T>) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
this->~Any();
|
||||
new (this) Any(std::forward<T>(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Destruct any existing value to make it empty. */
|
||||
void reset()
|
||||
{
|
||||
info_->destruct(&buffer_);
|
||||
info_ = &Info::get_for_empty();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return this->has_value();
|
||||
}
|
||||
|
||||
bool has_value() const
|
||||
{
|
||||
return info_ != &Info::get_for_empty();
|
||||
}
|
||||
|
||||
template<typename T, typename... Args> std::decay_t<T> &emplace(Args &&...args)
|
||||
{
|
||||
this->~Any();
|
||||
new (this) Any(std::in_place_type<T>, std::forward<Args>(args)...);
|
||||
return this->get<T>();
|
||||
}
|
||||
|
||||
/** Return true when the value that is currently stored is a #T. */
|
||||
template<typename T> bool is() const
|
||||
{
|
||||
return info_ == &this->template get_info<T>();
|
||||
}
|
||||
|
||||
/** Get a pointer to the stored value. */
|
||||
void *get()
|
||||
{
|
||||
return const_cast<void *>(info_->get(&buffer_));
|
||||
}
|
||||
|
||||
/** Get a pointer to the stored value. */
|
||||
const void *get() const
|
||||
{
|
||||
return info_->get(&buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the stored value. This invokes undefined behavior when #T does not have the
|
||||
* correct type.
|
||||
*/
|
||||
template<typename T> std::decay_t<T> &get()
|
||||
{
|
||||
BLI_assert(this->is<T>());
|
||||
return *static_cast<std::decay_t<T> *>(this->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the stored value. This invokes undefined behavior when #T does not have the
|
||||
* correct type.
|
||||
*/
|
||||
template<typename T> const std::decay_t<T> &get() const
|
||||
{
|
||||
BLI_assert(this->is<T>());
|
||||
return *static_cast<const std::decay_t<T> *>(this->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra information that has been stored for the contained type.
|
||||
*/
|
||||
const RealExtraInfo &extra_info() const
|
||||
{
|
||||
return info_->extra_info;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender
|
File diff suppressed because it is too large
Load Diff
@@ -165,6 +165,7 @@ set(SRC
|
||||
|
||||
BLI_alloca.h
|
||||
BLI_allocator.hh
|
||||
BLI_any.hh
|
||||
BLI_args.h
|
||||
BLI_array.h
|
||||
BLI_array.hh
|
||||
@@ -411,6 +412,7 @@ blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
tests/BLI_any_test.cc
|
||||
tests/BLI_array_store_test.cc
|
||||
tests/BLI_array_test.cc
|
||||
tests/BLI_array_utils_test.cc
|
||||
|
108
source/blender/blenlib/tests/BLI_any_test.cc
Normal file
108
source/blender/blenlib/tests/BLI_any_test.cc
Normal file
@@ -0,0 +1,108 @@
|
||||
/* Apache License, Version 2.0 */
|
||||
|
||||
#include "BLI_any.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
namespace blender::tests {
|
||||
|
||||
TEST(any, DefaultConstructor)
|
||||
{
|
||||
Any a;
|
||||
EXPECT_FALSE(a.has_value());
|
||||
}
|
||||
|
||||
TEST(any, AssignInt)
|
||||
{
|
||||
Any<> a = 5;
|
||||
EXPECT_TRUE(a.has_value());
|
||||
EXPECT_TRUE(a.is<int>());
|
||||
EXPECT_FALSE(a.is<float>());
|
||||
const int &value = a.get<int>();
|
||||
EXPECT_EQ(value, 5);
|
||||
a = 10;
|
||||
EXPECT_EQ(value, 10);
|
||||
|
||||
Any b = a;
|
||||
EXPECT_TRUE(b.has_value());
|
||||
EXPECT_EQ(b.get<int>(), 10);
|
||||
|
||||
Any c = std::move(a);
|
||||
EXPECT_TRUE(c);
|
||||
EXPECT_EQ(c.get<int>(), 10);
|
||||
|
||||
EXPECT_EQ(a.get<int>(), 10); /* NOLINT: bugprone-use-after-move */
|
||||
|
||||
a.reset();
|
||||
EXPECT_FALSE(a);
|
||||
}
|
||||
|
||||
TEST(any, AssignMap)
|
||||
{
|
||||
Any<> a = Map<int, int>();
|
||||
EXPECT_TRUE(a.has_value());
|
||||
EXPECT_TRUE((a.is<Map<int, int>>()));
|
||||
EXPECT_FALSE((a.is<Map<int, float>>()));
|
||||
Map<int, int> &map = a.get<Map<int, int>>();
|
||||
map.add(4, 2);
|
||||
EXPECT_EQ((a.get<Map<int, int>>().lookup(4)), 2);
|
||||
|
||||
Any b = a;
|
||||
EXPECT_TRUE(b);
|
||||
EXPECT_EQ((b.get<Map<int, int>>().lookup(4)), 2);
|
||||
|
||||
Any c = std::move(a);
|
||||
c = c;
|
||||
EXPECT_TRUE(b);
|
||||
EXPECT_EQ((c.get<Map<int, int>>().lookup(4)), 2);
|
||||
|
||||
EXPECT_TRUE((a.get<Map<int, int>>().is_empty())); /* NOLINT: bugprone-use-after-move */
|
||||
}
|
||||
|
||||
TEST(any, AssignAny)
|
||||
{
|
||||
Any<> a = 5;
|
||||
Any<> b = std::string("hello");
|
||||
Any c;
|
||||
|
||||
Any z;
|
||||
EXPECT_FALSE(z.has_value());
|
||||
|
||||
z = a;
|
||||
EXPECT_TRUE(z.has_value());
|
||||
EXPECT_EQ(z.get<int>(), 5);
|
||||
|
||||
z = b;
|
||||
EXPECT_EQ(z.get<std::string>(), "hello");
|
||||
|
||||
z = c;
|
||||
EXPECT_FALSE(z.has_value());
|
||||
|
||||
z = Any(std::in_place_type<Any<>>, a);
|
||||
EXPECT_FALSE(z.is<int>());
|
||||
EXPECT_TRUE(z.is<Any<>>());
|
||||
EXPECT_EQ(z.get<Any<>>().get<int>(), 5);
|
||||
}
|
||||
|
||||
struct ExtraSizeInfo {
|
||||
size_t size;
|
||||
|
||||
template<typename T> static ExtraSizeInfo get()
|
||||
{
|
||||
return {sizeof(T)};
|
||||
}
|
||||
};
|
||||
|
||||
TEST(any, ExtraInfo)
|
||||
{
|
||||
using MyAny = Any<ExtraSizeInfo>;
|
||||
|
||||
MyAny a = 5;
|
||||
EXPECT_EQ(a.extra_info().size, sizeof(int));
|
||||
|
||||
a = std::string("hello");
|
||||
EXPECT_EQ(a.extra_info().size, sizeof(std::string));
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
@@ -12,7 +12,7 @@ namespace blender::tests {
|
||||
TEST(virtual_array, Span)
|
||||
{
|
||||
std::array<int, 5> data = {3, 4, 5, 6, 7};
|
||||
VArray_For_Span<int> varray{data};
|
||||
VArray<int> varray = VArray<int>::ForSpan(data);
|
||||
EXPECT_EQ(varray.size(), 5);
|
||||
EXPECT_EQ(varray.get(0), 3);
|
||||
EXPECT_EQ(varray.get(4), 7);
|
||||
@@ -23,7 +23,7 @@ TEST(virtual_array, Span)
|
||||
|
||||
TEST(virtual_array, Single)
|
||||
{
|
||||
VArray_For_Single<int> varray{10, 4};
|
||||
VArray<int> varray = VArray<int>::ForSingle(10, 4);
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray.get(0), 10);
|
||||
EXPECT_EQ(varray.get(3), 10);
|
||||
@@ -35,7 +35,7 @@ TEST(virtual_array, Array)
|
||||
{
|
||||
Array<int> array = {1, 2, 3, 5, 8};
|
||||
{
|
||||
VArray_For_ArrayContainer varray{array};
|
||||
VArray<int> varray = VArray<int>::ForContainer(array);
|
||||
EXPECT_EQ(varray.size(), 5);
|
||||
EXPECT_EQ(varray[0], 1);
|
||||
EXPECT_EQ(varray[2], 3);
|
||||
@@ -43,7 +43,7 @@ TEST(virtual_array, Array)
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
}
|
||||
{
|
||||
VArray_For_ArrayContainer varray{std::move(array)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
|
||||
EXPECT_EQ(varray.size(), 5);
|
||||
EXPECT_EQ(varray[0], 1);
|
||||
EXPECT_EQ(varray[2], 3);
|
||||
@@ -51,7 +51,7 @@ TEST(virtual_array, Array)
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
}
|
||||
{
|
||||
VArray_For_ArrayContainer varray{array}; /* NOLINT: bugprone-use-after-move */
|
||||
VArray<int> varray = VArray<int>::ForContainer(array); /* NOLINT: bugprone-use-after-move */
|
||||
EXPECT_TRUE(varray.is_empty());
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ TEST(virtual_array, Array)
|
||||
TEST(virtual_array, Vector)
|
||||
{
|
||||
Vector<int> vector = {9, 8, 7, 6};
|
||||
VArray_For_ArrayContainer varray{std::move(vector)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 9);
|
||||
EXPECT_EQ(varray[3], 6);
|
||||
@@ -68,7 +68,7 @@ TEST(virtual_array, Vector)
|
||||
TEST(virtual_array, StdVector)
|
||||
{
|
||||
std::vector<int> vector = {5, 6, 7, 8};
|
||||
VArray_For_ArrayContainer varray{std::move(vector)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 5);
|
||||
EXPECT_EQ(varray[1], 6);
|
||||
@@ -77,7 +77,7 @@ TEST(virtual_array, StdVector)
|
||||
TEST(virtual_array, StdArray)
|
||||
{
|
||||
std::array<int, 4> array = {2, 3, 4, 5};
|
||||
VArray_For_ArrayContainer varray{array};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 2);
|
||||
EXPECT_EQ(varray[1], 3);
|
||||
@@ -86,7 +86,7 @@ TEST(virtual_array, StdArray)
|
||||
TEST(virtual_array, VectorSet)
|
||||
{
|
||||
VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1};
|
||||
VArray_For_ArrayContainer varray{std::move(vector_set)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(vector_set));
|
||||
EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 5);
|
||||
@@ -98,7 +98,7 @@ TEST(virtual_array, VectorSet)
|
||||
TEST(virtual_array, Func)
|
||||
{
|
||||
auto func = [](int64_t index) { return (int)(index * index); };
|
||||
VArray_For_Func<int, decltype(func)> varray{10, func};
|
||||
VArray<int> varray = VArray<int>::ForFunc(10, func);
|
||||
EXPECT_EQ(varray.size(), 10);
|
||||
EXPECT_EQ(varray[0], 0);
|
||||
EXPECT_EQ(varray[3], 9);
|
||||
@@ -108,7 +108,7 @@ TEST(virtual_array, Func)
|
||||
TEST(virtual_array, AsSpan)
|
||||
{
|
||||
auto func = [](int64_t index) { return (int)(10 * index); };
|
||||
VArray_For_Func<int, decltype(func)> func_varray{10, func};
|
||||
VArray<int> func_varray = VArray<int>::ForFunc(10, func);
|
||||
VArray_Span span_varray{func_varray};
|
||||
EXPECT_EQ(span_varray.size(), 10);
|
||||
Span<int> span = span_varray;
|
||||
@@ -134,13 +134,14 @@ TEST(virtual_array, DerivedSpan)
|
||||
vector.append({3, 4, 5});
|
||||
vector.append({1, 1, 1});
|
||||
{
|
||||
VArray_For_DerivedSpan<std::array<int, 3>, int, get_x> varray{vector};
|
||||
VArray<int> varray = VArray<int>::ForDerivedSpan<std::array<int, 3>, get_x>(vector);
|
||||
EXPECT_EQ(varray.size(), 2);
|
||||
EXPECT_EQ(varray[0], 3);
|
||||
EXPECT_EQ(varray[1], 1);
|
||||
}
|
||||
{
|
||||
VMutableArray_For_DerivedSpan<std::array<int, 3>, int, get_x, set_x> varray{vector};
|
||||
VMutableArray<int> varray =
|
||||
VMutableArray<int>::ForDerivedSpan<std::array<int, 3>, get_x, set_x>(vector);
|
||||
EXPECT_EQ(varray.size(), 2);
|
||||
EXPECT_EQ(varray[0], 3);
|
||||
EXPECT_EQ(varray[1], 1);
|
||||
@@ -151,4 +152,32 @@ TEST(virtual_array, DerivedSpan)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(virtual_array, MutableToImmutable)
|
||||
{
|
||||
std::array<int, 4> array = {4, 2, 6, 4};
|
||||
{
|
||||
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
|
||||
VArray<int> varray = mutable_varray;
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[1], 2);
|
||||
EXPECT_EQ(mutable_varray.size(), 4);
|
||||
}
|
||||
{
|
||||
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
|
||||
EXPECT_EQ(mutable_varray.size(), 4);
|
||||
VArray<int> varray = std::move(mutable_varray);
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[1], 2);
|
||||
EXPECT_EQ(mutable_varray.size(), 0);
|
||||
}
|
||||
{
|
||||
VArray<int> varray = VMutableArray<int>::ForSpan(array);
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[1], 2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
@@ -72,7 +72,7 @@ static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type(
|
||||
void ExtraColumns::foreach_default_column_ids(
|
||||
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
|
||||
{
|
||||
for (const auto &item : columns_.items()) {
|
||||
for (const auto item : columns_.items()) {
|
||||
SpreadsheetColumnID column_id;
|
||||
column_id.name = (char *)item.key.c_str();
|
||||
fn(column_id, true);
|
||||
@@ -159,12 +159,12 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
if (!attribute) {
|
||||
return {};
|
||||
}
|
||||
const fn::GVArray *varray = scope_.add(std::move(attribute.varray));
|
||||
fn::GVArray varray = std::move(attribute.varray);
|
||||
if (attribute.domain != domain_) {
|
||||
return {};
|
||||
}
|
||||
int domain_size = varray->size();
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type());
|
||||
int domain_size = varray.size();
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type());
|
||||
switch (type) {
|
||||
case CD_PROP_FLOAT:
|
||||
return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT,
|
||||
@@ -172,7 +172,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_float = value;
|
||||
});
|
||||
case CD_PROP_INT32:
|
||||
@@ -182,7 +182,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
int value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_int = value;
|
||||
},
|
||||
STREQ(column_id.name, "id") ? 5.5f : 0.0f);
|
||||
@@ -192,7 +192,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
bool value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_bool = value;
|
||||
});
|
||||
case CD_PROP_FLOAT2: {
|
||||
@@ -201,7 +201,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float2 value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_float2 = value;
|
||||
});
|
||||
}
|
||||
@@ -211,7 +211,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float3 value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_float3 = value;
|
||||
});
|
||||
}
|
||||
@@ -221,7 +221,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
ColorGeometry4f value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_color = value;
|
||||
});
|
||||
}
|
||||
@@ -644,7 +644,7 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet,
|
||||
|
||||
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
|
||||
const int domain_size = component.attribute_domain_size(domain);
|
||||
for (const auto &item : fields_to_show.items()) {
|
||||
for (const auto item : fields_to_show.items()) {
|
||||
StringRef name = item.key;
|
||||
const GField &field = item.value;
|
||||
|
||||
|
@@ -248,9 +248,9 @@ class FieldInput : public FieldNode {
|
||||
* Get the value of this specific input based on the given context. The returned virtual array,
|
||||
* should live at least as long as the passed in #scope. May return null.
|
||||
*/
|
||||
virtual const GVArray *get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const = 0;
|
||||
virtual GVArray get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const = 0;
|
||||
|
||||
virtual std::string socket_inspection_name() const;
|
||||
blender::StringRef debug_name() const;
|
||||
@@ -268,9 +268,9 @@ class FieldContext {
|
||||
public:
|
||||
~FieldContext() = default;
|
||||
|
||||
virtual const GVArray *get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const;
|
||||
virtual GVArray get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -289,8 +289,8 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
const FieldContext &context_;
|
||||
const IndexMask mask_;
|
||||
Vector<GField> fields_to_evaluate_;
|
||||
Vector<GVMutableArray *> dst_varrays_;
|
||||
Vector<const GVArray *> evaluated_varrays_;
|
||||
Vector<GVMutableArray> dst_varrays_;
|
||||
Vector<GVArray> evaluated_varrays_;
|
||||
Vector<OutputPointerInfo> output_pointer_infos_;
|
||||
bool is_evaluated_ = false;
|
||||
|
||||
@@ -317,13 +317,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
* \param field: Field to add to the evaluator.
|
||||
* \param dst: Mutable virtual array that the evaluated result for this field is be written into.
|
||||
*/
|
||||
int add_with_destination(GField field, GVMutableArray &dst);
|
||||
int add_with_destination(GField field, GVMutableArray dst);
|
||||
|
||||
/** Same as #add_with_destination but typed. */
|
||||
template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst)
|
||||
template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> dst)
|
||||
{
|
||||
GVMutableArray &varray = scope_.construct<GVMutableArray_For_VMutableArray<T>>(dst);
|
||||
return this->add_with_destination(GField(std::move(field)), varray);
|
||||
return this->add_with_destination(GField(std::move(field)), GVMutableArray(std::move(dst)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,11 +341,10 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
*/
|
||||
template<typename T> int add_with_destination(Field<T> field, MutableSpan<T> dst)
|
||||
{
|
||||
GVMutableArray &varray = scope_.construct<GVMutableArray_For_MutableSpan<T>>(dst);
|
||||
return this->add_with_destination(std::move(field), varray);
|
||||
return this->add_with_destination(std::move(field), VMutableArray<T>::ForSpan(dst));
|
||||
}
|
||||
|
||||
int add(GField field, const GVArray **varray_ptr);
|
||||
int add(GField field, GVArray *varray_ptr);
|
||||
|
||||
/**
|
||||
* \param field: Field to add to the evaluator.
|
||||
@@ -354,14 +352,14 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
* assigned to the given position.
|
||||
* \return Index of the field in the evaluator which can be used in the #get_evaluated methods.
|
||||
*/
|
||||
template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr)
|
||||
template<typename T> int add(Field<T> field, VArray<T> *varray_ptr)
|
||||
{
|
||||
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
|
||||
dst_varrays_.append(nullptr);
|
||||
output_pointer_infos_.append(
|
||||
OutputPointerInfo{varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &scope) {
|
||||
*(const VArray<T> **)dst = &*scope.construct<GVArray_Typed<T>>(varray);
|
||||
}});
|
||||
dst_varrays_.append({});
|
||||
output_pointer_infos_.append(OutputPointerInfo{
|
||||
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
|
||||
*(VArray<T> *)dst = varray.typed<T>();
|
||||
}});
|
||||
return field_index;
|
||||
}
|
||||
|
||||
@@ -378,14 +376,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
const GVArray &get_evaluated(const int field_index) const
|
||||
{
|
||||
BLI_assert(is_evaluated_);
|
||||
return *evaluated_varrays_[field_index];
|
||||
return evaluated_varrays_[field_index];
|
||||
}
|
||||
|
||||
template<typename T> const VArray<T> &get_evaluated(const int field_index)
|
||||
template<typename T> VArray<T> get_evaluated(const int field_index)
|
||||
{
|
||||
const GVArray &varray = this->get_evaluated(field_index);
|
||||
GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(varray);
|
||||
return *typed_varray;
|
||||
return this->get_evaluated(field_index).typed<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,11 +392,11 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
IndexMask get_evaluated_as_mask(const int field_index);
|
||||
};
|
||||
|
||||
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray *> dst_varrays = {});
|
||||
Vector<GVArray> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray> dst_varrays = {});
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility functions for simple field creation and evaluation
|
||||
@@ -429,11 +425,11 @@ class IndexFieldInput final : public FieldInput {
|
||||
public:
|
||||
IndexFieldInput();
|
||||
|
||||
static GVArray *get_index_varray(IndexMask mask, ResourceScope &scope);
|
||||
static GVArray get_index_varray(IndexMask mask, ResourceScope &scope);
|
||||
|
||||
const GVArray *get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final;
|
||||
GVArray get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final;
|
||||
|
||||
uint64_t hash() const override;
|
||||
bool is_equal_to(const fn::FieldNode &other) const override;
|
||||
|
@@ -125,8 +125,7 @@ template<typename T> class GVectorArray_TypedMutableRef {
|
||||
|
||||
void extend(const int64_t index, const VArray<T> &values)
|
||||
{
|
||||
GVArray_For_VArray<T> array{values};
|
||||
this->extend(index, array);
|
||||
vector_array_->extend(index, values);
|
||||
}
|
||||
|
||||
MutableSpan<T> operator[](const int64_t index)
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -100,31 +100,31 @@ class GVVectorArray {
|
||||
}
|
||||
};
|
||||
|
||||
class GVArray_For_GVVectorArrayIndex : public GVArray {
|
||||
class GVArray_For_GVVectorArrayIndex : public GVArrayImpl {
|
||||
private:
|
||||
const GVVectorArray &vector_array_;
|
||||
const int64_t index_;
|
||||
|
||||
public:
|
||||
GVArray_For_GVVectorArrayIndex(const GVVectorArray &vector_array, const int64_t index)
|
||||
: GVArray(vector_array.type(), vector_array.get_vector_size(index)),
|
||||
: GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)),
|
||||
vector_array_(vector_array),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void get_impl(const int64_t index_in_vector, void *r_value) const override;
|
||||
void get_to_uninitialized_impl(const int64_t index_in_vector, void *r_value) const override;
|
||||
void get(const int64_t index_in_vector, void *r_value) const override;
|
||||
void get_to_uninitialized(const int64_t index_in_vector, void *r_value) const override;
|
||||
};
|
||||
|
||||
class GVVectorArray_For_SingleGVArray : public GVVectorArray {
|
||||
private:
|
||||
const GVArray &array_;
|
||||
GVArray varray_;
|
||||
|
||||
public:
|
||||
GVVectorArray_For_SingleGVArray(const GVArray &array, const int64_t size)
|
||||
: GVVectorArray(array.type(), size), array_(array)
|
||||
GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size)
|
||||
: GVVectorArray(varray.type(), size), varray_(std::move(varray))
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -40,7 +40,7 @@ class MFParamsBuilder {
|
||||
const MFSignature *signature_;
|
||||
IndexMask mask_;
|
||||
int64_t min_array_size_;
|
||||
Vector<const GVArray *> virtual_arrays_;
|
||||
Vector<GVArray> virtual_arrays_;
|
||||
Vector<GMutableSpan> mutable_spans_;
|
||||
Vector<const GVVectorArray *> virtual_vector_arrays_;
|
||||
Vector<GVectorArray *> vector_arrays_;
|
||||
@@ -68,24 +68,22 @@ class MFParamsBuilder {
|
||||
template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
|
||||
{
|
||||
this->add_readonly_single_input(
|
||||
scope_.construct<GVArray_For_SingleValueRef>(CPPType::get<T>(), min_array_size_, value),
|
||||
expected_name);
|
||||
GVArray::ForSingleRef(CPPType::get<T>(), min_array_size_, value), expected_name);
|
||||
}
|
||||
void add_readonly_single_input(const GSpan span, StringRef expected_name = "")
|
||||
{
|
||||
this->add_readonly_single_input(scope_.construct<GVArray_For_GSpan>(span), expected_name);
|
||||
this->add_readonly_single_input(GVArray::ForSpan(span), expected_name);
|
||||
}
|
||||
void add_readonly_single_input(GPointer value, StringRef expected_name = "")
|
||||
{
|
||||
this->add_readonly_single_input(
|
||||
scope_.construct<GVArray_For_SingleValueRef>(*value.type(), min_array_size_, value.get()),
|
||||
expected_name);
|
||||
GVArray::ForSingleRef(*value.type(), min_array_size_, value.get()), expected_name);
|
||||
}
|
||||
void add_readonly_single_input(const GVArray &ref, StringRef expected_name = "")
|
||||
void add_readonly_single_input(GVArray varray, StringRef expected_name = "")
|
||||
{
|
||||
this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()), expected_name);
|
||||
BLI_assert(ref.size() >= min_array_size_);
|
||||
virtual_arrays_.append(&ref);
|
||||
this->assert_current_param_type(MFParamType::ForSingleInput(varray.type()), expected_name);
|
||||
BLI_assert(varray.size() >= min_array_size_);
|
||||
virtual_arrays_.append(varray);
|
||||
}
|
||||
|
||||
void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "")
|
||||
@@ -221,16 +219,16 @@ class MFParams {
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> const VArray<T> &readonly_single_input(int param_index, StringRef name = "")
|
||||
template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "")
|
||||
{
|
||||
const GVArray &array = this->readonly_single_input(param_index, name);
|
||||
return builder_->scope_.construct<GVArray_Typed<T>>(array);
|
||||
const GVArray &varray = this->readonly_single_input(param_index, name);
|
||||
return varray.typed<T>();
|
||||
}
|
||||
const GVArray &readonly_single_input(int param_index, StringRef name = "")
|
||||
{
|
||||
this->assert_correct_param(param_index, name, MFParamType::SingleInput);
|
||||
int data_index = builder_->signature_->data_index(param_index);
|
||||
return *builder_->virtual_arrays_[data_index];
|
||||
return builder_->virtual_arrays_[data_index];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -81,19 +81,18 @@ static FieldTreeInfo preprocess_field_tree(Span<GFieldRef> entry_fields)
|
||||
/**
|
||||
* Retrieves the data from the context that is passed as input into the field.
|
||||
*/
|
||||
static Vector<const GVArray *> get_field_context_inputs(
|
||||
static Vector<GVArray> get_field_context_inputs(
|
||||
ResourceScope &scope,
|
||||
const IndexMask mask,
|
||||
const FieldContext &context,
|
||||
const Span<std::reference_wrapper<const FieldInput>> field_inputs)
|
||||
{
|
||||
Vector<const GVArray *> field_context_inputs;
|
||||
Vector<GVArray> field_context_inputs;
|
||||
for (const FieldInput &field_input : field_inputs) {
|
||||
const GVArray *varray = context.get_varray_for_input(field_input, mask, scope);
|
||||
if (varray == nullptr) {
|
||||
GVArray varray = context.get_varray_for_input(field_input, mask, scope);
|
||||
if (!varray) {
|
||||
const CPPType &type = field_input.cpp_type();
|
||||
varray = &scope.construct<GVArray_For_SingleValueRef>(
|
||||
type, mask.min_array_size(), type.default_value());
|
||||
varray = GVArray::ForSingleDefault(type, mask.min_array_size());
|
||||
}
|
||||
field_context_inputs.append(varray);
|
||||
}
|
||||
@@ -105,7 +104,7 @@ static Vector<const GVArray *> get_field_context_inputs(
|
||||
* for different indices.
|
||||
*/
|
||||
static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
|
||||
Span<const GVArray *> field_context_inputs)
|
||||
Span<GVArray> field_context_inputs)
|
||||
{
|
||||
Set<GFieldRef> found_fields;
|
||||
Stack<GFieldRef> fields_to_check;
|
||||
@@ -114,8 +113,8 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
|
||||
* start the tree search at the non-constant input fields and traverse through all fields that
|
||||
* depend on them. */
|
||||
for (const int i : field_context_inputs.index_range()) {
|
||||
const GVArray *varray = field_context_inputs[i];
|
||||
if (varray->is_single()) {
|
||||
const GVArray &varray = field_context_inputs[i];
|
||||
if (varray.is_single()) {
|
||||
continue;
|
||||
}
|
||||
const FieldInput &field_input = field_tree_info.deduplicated_field_inputs[i];
|
||||
@@ -278,29 +277,42 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
|
||||
* \return The computed virtual arrays for each provided field. If #dst_varrays is passed, the
|
||||
* provided virtual arrays are returned.
|
||||
*/
|
||||
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray *> dst_varrays)
|
||||
Vector<GVArray> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray> dst_varrays)
|
||||
{
|
||||
Vector<const GVArray *> r_varrays(fields_to_evaluate.size(), nullptr);
|
||||
Vector<GVArray> r_varrays(fields_to_evaluate.size());
|
||||
Array<bool> is_output_written_to_dst(fields_to_evaluate.size(), false);
|
||||
const int array_size = mask.min_array_size();
|
||||
|
||||
/* Destination arrays are optional. Create a small utility method to access them. */
|
||||
auto get_dst_varray_if_available = [&](int index) -> GVMutableArray * {
|
||||
if (dst_varrays.is_empty()) {
|
||||
return nullptr;
|
||||
if (mask.is_empty()) {
|
||||
for (const int i : fields_to_evaluate.index_range()) {
|
||||
const CPPType &type = fields_to_evaluate[i].cpp_type();
|
||||
r_varrays[i] = GVArray::ForEmpty(type);
|
||||
}
|
||||
BLI_assert(dst_varrays[index] == nullptr || dst_varrays[index]->size() >= array_size);
|
||||
return dst_varrays[index];
|
||||
return r_varrays;
|
||||
}
|
||||
|
||||
/* Destination arrays are optional. Create a small utility method to access them. */
|
||||
auto get_dst_varray = [&](int index) -> GVMutableArray {
|
||||
if (dst_varrays.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
const GVMutableArray &varray = dst_varrays[index];
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
BLI_assert(varray.size() >= array_size);
|
||||
return varray;
|
||||
};
|
||||
|
||||
/* Traverse the field tree and prepare some data that is used in later steps. */
|
||||
FieldTreeInfo field_tree_info = preprocess_field_tree(fields_to_evaluate);
|
||||
|
||||
/* Get inputs that will be passed into the field when evaluated. */
|
||||
Vector<const GVArray *> field_context_inputs = get_field_context_inputs(
|
||||
Vector<GVArray> field_context_inputs = get_field_context_inputs(
|
||||
scope, mask, context, field_tree_info.deduplicated_field_inputs);
|
||||
|
||||
/* Finish fields that output an input varray directly. For those we don't have to do any further
|
||||
@@ -312,7 +324,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
}
|
||||
const FieldInput &field_input = static_cast<const FieldInput &>(field.node());
|
||||
const int field_input_index = field_tree_info.deduplicated_field_inputs.index_of(field_input);
|
||||
const GVArray *varray = field_context_inputs[field_input_index];
|
||||
const GVArray &varray = field_context_inputs[field_input_index];
|
||||
r_varrays[out_index] = varray;
|
||||
}
|
||||
|
||||
@@ -325,7 +337,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
Vector<GFieldRef> constant_fields_to_evaluate;
|
||||
Vector<int> constant_field_indices;
|
||||
for (const int i : fields_to_evaluate.index_range()) {
|
||||
if (r_varrays[i] != nullptr) {
|
||||
if (r_varrays[i]) {
|
||||
/* Already done. */
|
||||
continue;
|
||||
}
|
||||
@@ -357,8 +369,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
MFContextBuilder mf_context;
|
||||
|
||||
/* Provide inputs to the procedure executor. */
|
||||
for (const GVArray *varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(*varray);
|
||||
for (const GVArray &varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(varray);
|
||||
}
|
||||
|
||||
for (const int i : varying_fields_to_evaluate.index_range()) {
|
||||
@@ -367,9 +379,9 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
const int out_index = varying_field_indices[i];
|
||||
|
||||
/* Try to get an existing virtual array that the result should be written into. */
|
||||
GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
|
||||
GVMutableArray dst_varray = get_dst_varray(out_index);
|
||||
void *buffer;
|
||||
if (output_varray == nullptr || !output_varray->is_span()) {
|
||||
if (!dst_varray || !dst_varray.is_span()) {
|
||||
/* Allocate a new buffer for the computed result. */
|
||||
buffer = scope.linear_allocator().allocate(type.size() * array_size, type.alignment());
|
||||
|
||||
@@ -379,14 +391,14 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
[buffer, mask, &type]() { type.destruct_indices(buffer, mask); });
|
||||
}
|
||||
|
||||
r_varrays[out_index] = &scope.construct<GVArray_For_GSpan>(
|
||||
GSpan{type, buffer, array_size});
|
||||
r_varrays[out_index] = GVArray::ForSpan({type, buffer, array_size});
|
||||
}
|
||||
else {
|
||||
/* Write the result into the existing span. */
|
||||
buffer = output_varray->get_internal_span().data();
|
||||
buffer = dst_varray.get_internal_span().data();
|
||||
|
||||
r_varrays[out_index] = output_varray;
|
||||
r_varrays[out_index] = dst_varray;
|
||||
is_output_written_to_dst[out_index] = true;
|
||||
}
|
||||
|
||||
/* Pass output buffer to the procedure executor. */
|
||||
@@ -404,15 +416,12 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
build_multi_function_procedure_for_fields(
|
||||
procedure, scope, field_tree_info, constant_fields_to_evaluate);
|
||||
MFProcedureExecutor procedure_executor{"Procedure", procedure};
|
||||
/* Run the code below even when the mask is empty, so that outputs are properly prepared.
|
||||
* Higher level code can detect this as well and just skip evaluating the field. */
|
||||
const int mask_size = mask.is_empty() ? 0 : 1;
|
||||
MFParamsBuilder mf_params{procedure_executor, mask_size};
|
||||
MFParamsBuilder mf_params{procedure_executor, 1};
|
||||
MFContextBuilder mf_context;
|
||||
|
||||
/* Provide inputs to the procedure executor. */
|
||||
for (const GVArray *varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(*varray);
|
||||
for (const GVArray &varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(varray);
|
||||
}
|
||||
|
||||
for (const int i : constant_fields_to_evaluate.index_range()) {
|
||||
@@ -421,55 +430,52 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
/* Allocate memory where the computed value will be stored in. */
|
||||
void *buffer = scope.linear_allocator().allocate(type.size(), type.alignment());
|
||||
|
||||
if (!type.is_trivially_destructible() && mask_size > 0) {
|
||||
BLI_assert(mask_size == 1);
|
||||
if (!type.is_trivially_destructible()) {
|
||||
/* Destruct value in the end. */
|
||||
scope.add_destruct_call([buffer, &type]() { type.destruct(buffer); });
|
||||
}
|
||||
|
||||
/* Pass output buffer to the procedure executor. */
|
||||
mf_params.add_uninitialized_single_output({type, buffer, mask_size});
|
||||
mf_params.add_uninitialized_single_output({type, buffer, 1});
|
||||
|
||||
/* Create virtual array that can be used after the procedure has been executed below. */
|
||||
const int out_index = constant_field_indices[i];
|
||||
r_varrays[out_index] = &scope.construct<GVArray_For_SingleValueRef>(
|
||||
type, array_size, buffer);
|
||||
r_varrays[out_index] = GVArray::ForSingleRef(type, array_size, buffer);
|
||||
}
|
||||
|
||||
procedure_executor.call(IndexRange(mask_size), mf_params, mf_context);
|
||||
procedure_executor.call(IndexRange(1), mf_params, mf_context);
|
||||
}
|
||||
|
||||
/* Copy data to supplied destination arrays if necessary. In some cases the evaluation above has
|
||||
* written the computed data in the right place already. */
|
||||
/* Copy data to supplied destination arrays if necessary. In some cases the evaluation above
|
||||
* has written the computed data in the right place already. */
|
||||
if (!dst_varrays.is_empty()) {
|
||||
for (const int out_index : fields_to_evaluate.index_range()) {
|
||||
GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
|
||||
if (output_varray == nullptr) {
|
||||
GVMutableArray dst_varray = get_dst_varray(out_index);
|
||||
if (!dst_varray) {
|
||||
/* Caller did not provide a destination for this output. */
|
||||
continue;
|
||||
}
|
||||
const GVArray *computed_varray = r_varrays[out_index];
|
||||
BLI_assert(computed_varray->type() == output_varray->type());
|
||||
if (output_varray == computed_varray) {
|
||||
const GVArray &computed_varray = r_varrays[out_index];
|
||||
BLI_assert(computed_varray.type() == dst_varray.type());
|
||||
if (is_output_written_to_dst[out_index]) {
|
||||
/* The result has been written into the destination provided by the caller already. */
|
||||
continue;
|
||||
}
|
||||
/* Still have to copy over the data in the destination provided by the caller. */
|
||||
if (output_varray->is_span()) {
|
||||
if (dst_varray.is_span()) {
|
||||
/* Materialize into a span. */
|
||||
computed_varray->materialize_to_uninitialized(mask,
|
||||
output_varray->get_internal_span().data());
|
||||
computed_varray.materialize_to_uninitialized(mask, dst_varray.get_internal_span().data());
|
||||
}
|
||||
else {
|
||||
/* Slower materialize into a different structure. */
|
||||
const CPPType &type = computed_varray->type();
|
||||
const CPPType &type = computed_varray.type();
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
for (const int i : mask) {
|
||||
computed_varray->get_to_uninitialized(i, buffer);
|
||||
output_varray->set_by_relocate(i, buffer);
|
||||
computed_varray.get_to_uninitialized(i, buffer);
|
||||
dst_varray.set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
r_varrays[out_index] = output_varray;
|
||||
r_varrays[out_index] = dst_varray;
|
||||
}
|
||||
}
|
||||
return r_varrays;
|
||||
@@ -485,8 +491,8 @@ void evaluate_constant_field(const GField &field, void *r_value)
|
||||
|
||||
ResourceScope scope;
|
||||
FieldContext context;
|
||||
Vector<const GVArray *> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
|
||||
varrays[0]->get_to_uninitialized(0, r_value);
|
||||
Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
|
||||
varrays[0].get_to_uninitialized(0, r_value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,9 +518,9 @@ GField make_field_constant_if_possible(GField field)
|
||||
return GField{operation, 0};
|
||||
}
|
||||
|
||||
const GVArray *FieldContext::get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
GVArray FieldContext::get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
{
|
||||
/* By default ask the field input to create the varray. Another field context might overwrite
|
||||
* the context here. */
|
||||
@@ -526,17 +532,15 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index")
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
GVArray *IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &scope)
|
||||
GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(scope))
|
||||
{
|
||||
auto index_func = [](int i) { return i; };
|
||||
return &scope.construct<
|
||||
fn::GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
|
||||
mask.min_array_size(), mask.min_array_size(), index_func);
|
||||
return VArray<int>::ForFunc(mask.min_array_size(), index_func);
|
||||
}
|
||||
|
||||
const GVArray *IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
{
|
||||
/* TODO: Investigate a similar method to IndexRange::as_span() */
|
||||
return get_index_varray(mask, scope);
|
||||
@@ -631,27 +635,26 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection)
|
||||
return indices;
|
||||
}
|
||||
|
||||
int FieldEvaluator::add_with_destination(GField field, GVMutableArray &dst)
|
||||
int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst)
|
||||
{
|
||||
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
|
||||
dst_varrays_.append(&dst);
|
||||
dst_varrays_.append(dst);
|
||||
output_pointer_infos_.append({});
|
||||
return field_index;
|
||||
}
|
||||
|
||||
int FieldEvaluator::add_with_destination(GField field, GMutableSpan dst)
|
||||
{
|
||||
GVMutableArray &varray = scope_.construct<GVMutableArray_For_GMutableSpan>(dst);
|
||||
return this->add_with_destination(std::move(field), varray);
|
||||
return this->add_with_destination(std::move(field), GVMutableArray::ForSpan(dst));
|
||||
}
|
||||
|
||||
int FieldEvaluator::add(GField field, const GVArray **varray_ptr)
|
||||
int FieldEvaluator::add(GField field, GVArray *varray_ptr)
|
||||
{
|
||||
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
|
||||
dst_varrays_.append(nullptr);
|
||||
output_pointer_infos_.append(OutputPointerInfo{
|
||||
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
|
||||
*(const GVArray **)dst = &varray;
|
||||
*(GVArray *)dst = varray;
|
||||
}});
|
||||
return field_index;
|
||||
}
|
||||
@@ -676,7 +679,7 @@ void FieldEvaluator::evaluate()
|
||||
for (const int i : fields_to_evaluate_.index_range()) {
|
||||
OutputPointerInfo &info = output_pointer_infos_[i];
|
||||
if (info.dst != nullptr) {
|
||||
info.set(info.dst, *evaluated_varrays_[i], scope_);
|
||||
info.set(info.dst, evaluated_varrays_[i], scope_);
|
||||
}
|
||||
}
|
||||
is_evaluated_ = true;
|
||||
@@ -684,17 +687,16 @@ void FieldEvaluator::evaluate()
|
||||
|
||||
IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index)
|
||||
{
|
||||
const GVArray &varray = this->get_evaluated(field_index);
|
||||
GVArray_Typed<bool> typed_varray{varray};
|
||||
VArray<bool> varray = this->get_evaluated(field_index).typed<bool>();
|
||||
|
||||
if (typed_varray->is_single()) {
|
||||
if (typed_varray->get_internal_single()) {
|
||||
return IndexRange(typed_varray.size());
|
||||
if (varray.is_single()) {
|
||||
if (varray.get_internal_single()) {
|
||||
return IndexRange(varray.size());
|
||||
}
|
||||
return IndexRange(0);
|
||||
}
|
||||
|
||||
return scope_.add_value(indices_from_selection(*typed_varray)).as_span();
|
||||
return scope_.add_value(indices_from_selection(varray)).as_span();
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
|
@@ -60,15 +60,14 @@ void GVectorArray::extend(const int64_t index, const GVArray &values)
|
||||
|
||||
void GVectorArray::extend(const int64_t index, const GSpan values)
|
||||
{
|
||||
GVArray_For_GSpan varray{values};
|
||||
this->extend(index, varray);
|
||||
this->extend(index, GVArray::ForSpan(values));
|
||||
}
|
||||
|
||||
void GVectorArray::extend(IndexMask mask, const GVVectorArray &values)
|
||||
{
|
||||
for (const int i : mask) {
|
||||
GVArray_For_GVVectorArrayIndex array{values, i};
|
||||
this->extend(i, array);
|
||||
this->extend(i, GVArray(&array));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,52 +19,10 @@
|
||||
namespace blender::fn {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_ShallowCopy
|
||||
/** \name #GVArrayImpl
|
||||
* \{ */
|
||||
|
||||
class GVArray_For_ShallowCopy : public GVArray {
|
||||
private:
|
||||
const GVArray &varray_;
|
||||
|
||||
public:
|
||||
GVArray_For_ShallowCopy(const GVArray &varray)
|
||||
: GVArray(varray.type(), varray.size()), varray_(varray)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get(index, r_value);
|
||||
}
|
||||
|
||||
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get_to_uninitialized(index, r_value);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
|
||||
{
|
||||
varray_.materialize_to_uninitialized(mask, dst);
|
||||
}
|
||||
};
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray
|
||||
* \{ */
|
||||
|
||||
void GVArray::materialize(void *dst) const
|
||||
{
|
||||
this->materialize(IndexMask(size_), dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
this->materialize_impl(mask, dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_impl(const IndexMask mask, void *dst) const
|
||||
void GVArrayImpl::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
for (const int64_t i : mask) {
|
||||
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
|
||||
@@ -72,18 +30,7 @@ void GVArray::materialize_impl(const IndexMask mask, void *dst) const
|
||||
}
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized(void *dst) const
|
||||
{
|
||||
this->materialize_to_uninitialized(IndexMask(size_), dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized(const IndexMask mask, void *dst) const
|
||||
{
|
||||
BLI_assert(mask.min_array_size() <= size_);
|
||||
this->materialize_to_uninitialized_impl(mask, dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const
|
||||
void GVArrayImpl::materialize_to_uninitialized(const IndexMask mask, void *dst) const
|
||||
{
|
||||
for (const int64_t i : mask) {
|
||||
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
|
||||
@@ -91,83 +38,75 @@ void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst)
|
||||
}
|
||||
}
|
||||
|
||||
void GVArray::get_impl(const int64_t index, void *r_value) const
|
||||
void GVArrayImpl::get(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->destruct(r_value);
|
||||
this->get_to_uninitialized_impl(index, r_value);
|
||||
this->get_to_uninitialized(index, r_value);
|
||||
}
|
||||
|
||||
bool GVArray::is_span_impl() const
|
||||
bool GVArrayImpl::is_span() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GSpan GVArray::get_internal_span_impl() const
|
||||
GSpan GVArrayImpl::get_internal_span() const
|
||||
{
|
||||
BLI_assert(false);
|
||||
return GSpan(*type_);
|
||||
}
|
||||
|
||||
bool GVArray::is_single_impl() const
|
||||
bool GVArrayImpl::is_single() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GVArray::get_internal_single_impl(void *UNUSED(r_value)) const
|
||||
void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const
|
||||
{
|
||||
BLI_assert(false);
|
||||
}
|
||||
|
||||
const void *GVArray::try_get_internal_varray_impl() const
|
||||
bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `std::unique_ptr<GVArray>` based on this `GVArray`.
|
||||
* The lifetime of the returned virtual array must not be longer than the lifetime of this virtual
|
||||
* array.
|
||||
*/
|
||||
GVArrayPtr GVArray::shallow_copy() const
|
||||
bool GVArrayImpl::may_have_ownership() const
|
||||
{
|
||||
if (this->is_span()) {
|
||||
return std::make_unique<GVArray_For_GSpan>(this->get_internal_span());
|
||||
}
|
||||
if (this->is_single()) {
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
|
||||
this->get_internal_single(buffer);
|
||||
std::unique_ptr new_varray = std::make_unique<GVArray_For_SingleValue>(*type_, size_, buffer);
|
||||
type_->destruct(buffer);
|
||||
return new_varray;
|
||||
}
|
||||
return std::make_unique<GVArray_For_ShallowCopy>(*this);
|
||||
/* Use true as default to avoid accidentally creating subclasses that have this set to false but
|
||||
* actually own data. Subclasses should set the to false instead. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVMutableArray
|
||||
/** \name #GVMutableArrayImpl
|
||||
* \{ */
|
||||
|
||||
void GVMutableArray::set_by_copy_impl(const int64_t index, const void *value)
|
||||
GVMutableArrayImpl::GVMutableArrayImpl(const CPPType &type, const int64_t size)
|
||||
: GVArrayImpl(type, size)
|
||||
{
|
||||
}
|
||||
|
||||
void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value)
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
|
||||
type_->copy_construct(value, buffer);
|
||||
this->set_by_move_impl(index, buffer);
|
||||
this->set_by_move(index, buffer);
|
||||
type_->destruct(buffer);
|
||||
}
|
||||
|
||||
void GVMutableArray::set_by_relocate_impl(const int64_t index, void *value)
|
||||
void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value)
|
||||
{
|
||||
this->set_by_move_impl(index, value);
|
||||
this->set_by_move(index, value);
|
||||
type_->destruct(value);
|
||||
}
|
||||
|
||||
void GVMutableArray::set_all_impl(const void *src)
|
||||
void GVMutableArrayImpl::set_all(const void *src)
|
||||
{
|
||||
if (this->is_span()) {
|
||||
const GMutableSpan span = this->get_internal_span();
|
||||
type_->copy_assign_n(src, span.data(), size_);
|
||||
const GSpan span = this->get_internal_span();
|
||||
type_->copy_assign_n(src, const_cast<void *>(span.data()), size_);
|
||||
}
|
||||
else {
|
||||
for (int64_t i : IndexRange(size_)) {
|
||||
@@ -176,149 +115,223 @@ void GVMutableArray::set_all_impl(const void *src)
|
||||
}
|
||||
}
|
||||
|
||||
void *GVMutableArray::try_get_internal_mutable_varray_impl()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GVMutableArray::fill(const void *value)
|
||||
{
|
||||
if (this->is_span()) {
|
||||
const GMutableSpan span = this->get_internal_span();
|
||||
type_->fill_assign_n(value, span.data(), size_);
|
||||
const GSpan span = this->get_internal_span();
|
||||
this->type().fill_assign_n(value, const_cast<void *>(span.data()), this->size());
|
||||
}
|
||||
else {
|
||||
for (int64_t i : IndexRange(size_)) {
|
||||
for (int64_t i : IndexRange(this->size())) {
|
||||
this->set_by_copy(i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_GSpan
|
||||
/** \name #GVArrayImpl_For_GSpan
|
||||
* \{ */
|
||||
|
||||
void GVArray_For_GSpan::get_impl(const int64_t index, void *r_value) const
|
||||
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span)
|
||||
: GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size)
|
||||
: GVArrayImpl(type, size), element_size_(type.size())
|
||||
{
|
||||
}
|
||||
|
||||
void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
void GVArray_For_GSpan::get_to_uninitialized_impl(const int64_t index, void *r_value) const
|
||||
void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
bool GVArray_For_GSpan::is_span_impl() const
|
||||
bool GVArrayImpl_For_GSpan::is_span() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GSpan GVArray_For_GSpan::get_internal_span_impl() const
|
||||
GSpan GVArrayImpl_For_GSpan::get_internal_span() const
|
||||
{
|
||||
return GSpan(*type_, data_, size_);
|
||||
}
|
||||
|
||||
class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan {
|
||||
public:
|
||||
using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan;
|
||||
|
||||
private:
|
||||
bool may_have_ownership() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVMutableArray_For_GMutableSpan
|
||||
/** \name #GVMutableArrayImpl_For_GMutableSpan
|
||||
* \{ */
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::get_impl(const int64_t index, void *r_value) const
|
||||
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span)
|
||||
: GVMutableArrayImpl(span.type(), span.size()),
|
||||
data_(span.data()),
|
||||
element_size_(span.type().size())
|
||||
{
|
||||
}
|
||||
|
||||
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type,
|
||||
const int64_t size)
|
||||
: GVMutableArrayImpl(type, size), element_size_(type.size())
|
||||
{
|
||||
}
|
||||
|
||||
void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::get_to_uninitialized_impl(const int64_t index,
|
||||
void *r_value) const
|
||||
void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index,
|
||||
void *r_value) const
|
||||
{
|
||||
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::set_by_copy_impl(const int64_t index, const void *value)
|
||||
void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value)
|
||||
{
|
||||
type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::set_by_move_impl(const int64_t index, void *value)
|
||||
void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value)
|
||||
{
|
||||
type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::set_by_relocate_impl(const int64_t index, void *value)
|
||||
void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value)
|
||||
{
|
||||
type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
|
||||
}
|
||||
|
||||
bool GVMutableArray_For_GMutableSpan::is_span_impl() const
|
||||
bool GVMutableArrayImpl_For_GMutableSpan::is_span() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GSpan GVMutableArray_For_GMutableSpan::get_internal_span_impl() const
|
||||
GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const
|
||||
{
|
||||
return GSpan(*type_, data_, size_);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
class GVMutableArrayImpl_For_GMutableSpan_final final
|
||||
: public GVMutableArrayImpl_For_GMutableSpan {
|
||||
public:
|
||||
using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_SingleValueRef
|
||||
* \{ */
|
||||
|
||||
void GVArray_For_SingleValueRef::get_impl(const int64_t UNUSED(index), void *r_value) const
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
|
||||
void GVArray_For_SingleValueRef::get_to_uninitialized_impl(const int64_t UNUSED(index),
|
||||
void *r_value) const
|
||||
{
|
||||
type_->copy_construct(value_, r_value);
|
||||
}
|
||||
|
||||
bool GVArray_For_SingleValueRef::is_span_impl() const
|
||||
{
|
||||
return size_ == 1;
|
||||
}
|
||||
|
||||
GSpan GVArray_For_SingleValueRef::get_internal_span_impl() const
|
||||
{
|
||||
return GSpan{*type_, value_, 1};
|
||||
}
|
||||
|
||||
bool GVArray_For_SingleValueRef::is_single_impl() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void GVArray_For_SingleValueRef::get_internal_single_impl(void *r_value) const
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
private:
|
||||
bool may_have_ownership() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_SingleValue
|
||||
/** \name #GVArrayImpl_For_SingleValueRef
|
||||
* \{ */
|
||||
|
||||
GVArray_For_SingleValue::GVArray_For_SingleValue(const CPPType &type,
|
||||
const int64_t size,
|
||||
const void *value)
|
||||
: GVArray_For_SingleValueRef(type, size)
|
||||
{
|
||||
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
|
||||
type.copy_construct(value, (void *)value_);
|
||||
}
|
||||
/* Generic virtual array where each element has the same value. The value is not owned. */
|
||||
class GVArrayImpl_For_SingleValueRef : public GVArrayImpl {
|
||||
protected:
|
||||
const void *value_ = nullptr;
|
||||
|
||||
GVArray_For_SingleValue::~GVArray_For_SingleValue()
|
||||
{
|
||||
type_->destruct((void *)value_);
|
||||
MEM_freeN((void *)value_);
|
||||
}
|
||||
public:
|
||||
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
|
||||
: GVArrayImpl(type, size), value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size)
|
||||
{
|
||||
}
|
||||
|
||||
void get(const int64_t UNUSED(index), void *r_value) const override
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override
|
||||
{
|
||||
type_->copy_construct(value_, r_value);
|
||||
}
|
||||
|
||||
bool is_span() const override
|
||||
{
|
||||
return size_ == 1;
|
||||
}
|
||||
GSpan get_internal_span() const override
|
||||
{
|
||||
return GSpan{*type_, value_, 1};
|
||||
}
|
||||
|
||||
bool is_single() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void get_internal_single(void *r_value) const override
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
};
|
||||
|
||||
class GVArrayImpl_For_SingleValueRef_final final : public GVArrayImpl_For_SingleValueRef {
|
||||
public:
|
||||
using GVArrayImpl_For_SingleValueRef::GVArrayImpl_For_SingleValueRef;
|
||||
|
||||
private:
|
||||
bool may_have_ownership() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArrayImpl_For_SingleValue
|
||||
* \{ */
|
||||
|
||||
/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */
|
||||
class GVArrayImpl_For_SingleValue : public GVArrayImpl_For_SingleValueRef,
|
||||
NonCopyable,
|
||||
NonMovable {
|
||||
public:
|
||||
GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
|
||||
: GVArrayImpl_For_SingleValueRef(type, size)
|
||||
{
|
||||
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
|
||||
type.copy_construct(value, (void *)value_);
|
||||
}
|
||||
|
||||
~GVArrayImpl_For_SingleValue() override
|
||||
{
|
||||
type_->destruct((void *)value_);
|
||||
MEM_freeN((void *)value_);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -326,7 +339,7 @@ GVArray_For_SingleValue::~GVArray_For_SingleValue()
|
||||
/** \name #GVArray_GSpan
|
||||
* \{ */
|
||||
|
||||
GVArray_GSpan::GVArray_GSpan(const GVArray &varray) : GSpan(varray.type()), varray_(varray)
|
||||
GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray))
|
||||
{
|
||||
size_ = varray_.size();
|
||||
if (varray_.is_span()) {
|
||||
@@ -353,8 +366,8 @@ GVArray_GSpan::~GVArray_GSpan()
|
||||
/** \name #GVMutableArray_GSpan
|
||||
* \{ */
|
||||
|
||||
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray &varray, const bool copy_values_to_span)
|
||||
: GMutableSpan(varray.type()), varray_(varray)
|
||||
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span)
|
||||
: GMutableSpan(varray.type()), varray_(std::move(varray))
|
||||
{
|
||||
size_ = varray_.size();
|
||||
if (varray_.is_span()) {
|
||||
@@ -405,48 +418,314 @@ void GVMutableArray_GSpan::disable_not_applied_warning()
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_SlicedGVArray
|
||||
/** \name #GVArrayImpl_For_SlicedGVArray
|
||||
* \{ */
|
||||
|
||||
void GVArray_For_SlicedGVArray::get_impl(const int64_t index, void *r_value) const
|
||||
class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl {
|
||||
protected:
|
||||
GVArray varray_;
|
||||
int64_t offset_;
|
||||
|
||||
public:
|
||||
GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice)
|
||||
: GVArrayImpl(varray.type(), slice.size()),
|
||||
varray_(std::move(varray)),
|
||||
offset_(slice.start())
|
||||
{
|
||||
BLI_assert(slice.one_after_last() <= varray_.size());
|
||||
}
|
||||
|
||||
void get(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get(index + offset_, r_value);
|
||||
}
|
||||
|
||||
void get_to_uninitialized(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get_to_uninitialized(index + offset_, r_value);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArrayCommon
|
||||
* \{ */
|
||||
|
||||
GVArrayCommon::GVArrayCommon() = default;
|
||||
|
||||
GVArrayCommon::GVArrayCommon(const GVArrayCommon &other) : storage_(other.storage_)
|
||||
{
|
||||
varray_.get(index + offset_, r_value);
|
||||
impl_ = this->impl_from_storage();
|
||||
}
|
||||
|
||||
void GVArray_For_SlicedGVArray::get_to_uninitialized_impl(const int64_t index, void *r_value) const
|
||||
GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
|
||||
{
|
||||
varray_.get_to_uninitialized(index + offset_, r_value);
|
||||
impl_ = this->impl_from_storage();
|
||||
other.storage_.reset();
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
|
||||
GVArrayCommon::GVArrayCommon(const GVArrayImpl *impl) : impl_(impl)
|
||||
{
|
||||
storage_ = impl_;
|
||||
}
|
||||
|
||||
GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get())
|
||||
{
|
||||
if (impl) {
|
||||
storage_ = std::move(impl);
|
||||
}
|
||||
}
|
||||
|
||||
GVArrayCommon::~GVArrayCommon() = default;
|
||||
|
||||
void GVArrayCommon::materialize(void *dst) const
|
||||
{
|
||||
this->materialize(IndexMask(impl_->size()), dst);
|
||||
}
|
||||
|
||||
void GVArrayCommon::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
impl_->materialize(mask, dst);
|
||||
}
|
||||
|
||||
void GVArrayCommon::materialize_to_uninitialized(void *dst) const
|
||||
{
|
||||
this->materialize_to_uninitialized(IndexMask(impl_->size()), dst);
|
||||
}
|
||||
|
||||
void GVArrayCommon::materialize_to_uninitialized(const IndexMask mask, void *dst) const
|
||||
{
|
||||
BLI_assert(mask.min_array_size() <= impl_->size());
|
||||
impl_->materialize_to_uninitialized(mask, dst);
|
||||
}
|
||||
|
||||
bool GVArrayCommon::may_have_ownership() const
|
||||
{
|
||||
return impl_->may_have_ownership();
|
||||
}
|
||||
|
||||
void GVArrayCommon::copy_from(const GVArrayCommon &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
storage_ = other.storage_;
|
||||
impl_ = this->impl_from_storage();
|
||||
}
|
||||
|
||||
void GVArrayCommon::move_from(GVArrayCommon &&other) noexcept
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
storage_ = std::move(other.storage_);
|
||||
impl_ = this->impl_from_storage();
|
||||
other.storage_.reset();
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
|
||||
/* Returns true when the virtual array is stored as a span internally. */
|
||||
bool GVArrayCommon::is_span() const
|
||||
{
|
||||
if (this->is_empty()) {
|
||||
return true;
|
||||
}
|
||||
return impl_->is_span();
|
||||
}
|
||||
|
||||
/* Returns the internally used span of the virtual array. This invokes undefined behavior is the
|
||||
* virtual array is not stored as a span internally. */
|
||||
GSpan GVArrayCommon::get_internal_span() const
|
||||
{
|
||||
BLI_assert(this->is_span());
|
||||
if (this->is_empty()) {
|
||||
return GSpan(impl_->type());
|
||||
}
|
||||
return impl_->get_internal_span();
|
||||
}
|
||||
|
||||
/* Returns true when the virtual array returns the same value for every index. */
|
||||
bool GVArrayCommon::is_single() const
|
||||
{
|
||||
if (impl_->size() == 1) {
|
||||
return true;
|
||||
}
|
||||
return impl_->is_single();
|
||||
}
|
||||
|
||||
/* Copies the value that is used for every element into `r_value`, which is expected to point to
|
||||
* initialized memory. This invokes undefined behavior if the virtual array would not return the
|
||||
* same value for every index. */
|
||||
void GVArrayCommon::get_internal_single(void *r_value) const
|
||||
{
|
||||
BLI_assert(this->is_single());
|
||||
if (impl_->size() == 1) {
|
||||
impl_->get(0, r_value);
|
||||
return;
|
||||
}
|
||||
impl_->get_internal_single(r_value);
|
||||
}
|
||||
|
||||
/* Same as `get_internal_single`, but `r_value` points to initialized memory. */
|
||||
void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const
|
||||
{
|
||||
impl_->type().default_construct(r_value);
|
||||
this->get_internal_single(r_value);
|
||||
}
|
||||
|
||||
const GVArrayImpl *GVArrayCommon::impl_from_storage() const
|
||||
{
|
||||
return storage_.extra_info().get_varray(storage_.get());
|
||||
}
|
||||
|
||||
IndexRange GVArrayCommon::index_range() const
|
||||
{
|
||||
return IndexRange(this->size());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_Slice
|
||||
/** \name #GVArray
|
||||
* \{ */
|
||||
|
||||
GVArray_Slice::GVArray_Slice(const GVArray &varray, const IndexRange slice)
|
||||
GVArray::GVArray(const GVArray &other) = default;
|
||||
|
||||
GVArray::GVArray(GVArray &&other) noexcept = default;
|
||||
|
||||
GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl)
|
||||
{
|
||||
if (varray.is_span()) {
|
||||
/* Create a new virtual for the sliced span. */
|
||||
const GSpan span = varray.get_internal_span();
|
||||
const GSpan sliced_span = span.slice(slice.start(), slice.size());
|
||||
varray_span_.emplace(sliced_span);
|
||||
varray_ = &*varray_span_;
|
||||
}
|
||||
else if (varray.is_single()) {
|
||||
/* Can just use the existing virtual array, because it's the same value for the indices in the
|
||||
* slice anyway. */
|
||||
varray_ = &varray;
|
||||
}
|
||||
else {
|
||||
/* Generic version when none of the above method works.
|
||||
* We don't necessarily want to materialize the input varray because there might be
|
||||
* large distances between the required indices. Then we would materialize many elements that
|
||||
* are not accessed later on.
|
||||
*/
|
||||
varray_any_.emplace(varray, slice);
|
||||
varray_ = &*varray_any_;
|
||||
}
|
||||
|
||||
GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_SingleValue>(type, size, value);
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_SingleValueRef_final>(type, size, value);
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size)
|
||||
{
|
||||
return GVArray::ForSingleRef(type, size, type.default_value());
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSpan(GSpan span)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_GSpan_final>(span);
|
||||
}
|
||||
|
||||
class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan {
|
||||
protected:
|
||||
GArray<> array_;
|
||||
|
||||
public:
|
||||
GVArrayImpl_For_GArray(GArray<> array)
|
||||
: GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
GVArray GVArray::ForGArray(GArray<> array)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_GArray>(array);
|
||||
}
|
||||
|
||||
GVArray GVArray::ForEmpty(const CPPType &type)
|
||||
{
|
||||
return GVArray::ForSpan(GSpan(type));
|
||||
}
|
||||
|
||||
GVArray GVArray::slice(IndexRange slice) const
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice);
|
||||
}
|
||||
|
||||
GVArray &GVArray::operator=(const GVArray &other)
|
||||
{
|
||||
this->copy_from(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
GVArray &GVArray::operator=(GVArray &&other) noexcept
|
||||
{
|
||||
this->move_from(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVMutableArray
|
||||
* \{ */
|
||||
|
||||
GVMutableArray::GVMutableArray(const GVMutableArray &other) = default;
|
||||
GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default;
|
||||
|
||||
GVMutableArray::GVMutableArray(GVMutableArrayImpl *impl) : GVArrayCommon(impl)
|
||||
{
|
||||
}
|
||||
|
||||
GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
|
||||
: GVArrayCommon(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
GVMutableArray GVMutableArray::ForSpan(GMutableSpan span)
|
||||
{
|
||||
return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span);
|
||||
}
|
||||
|
||||
GVMutableArray::operator GVArray() const &
|
||||
{
|
||||
GVArray varray;
|
||||
varray.copy_from(*this);
|
||||
return varray;
|
||||
}
|
||||
|
||||
GVMutableArray::operator GVArray() &&noexcept
|
||||
{
|
||||
GVArray varray;
|
||||
varray.move_from(std::move(*this));
|
||||
return varray;
|
||||
}
|
||||
|
||||
GVMutableArray &GVMutableArray::operator=(const GVMutableArray &other)
|
||||
{
|
||||
this->copy_from(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
GVMutableArray &GVMutableArray::operator=(GVMutableArray &&other) noexcept
|
||||
{
|
||||
this->move_from(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
GVMutableArrayImpl *GVMutableArray::get_implementation() const
|
||||
{
|
||||
return this->get_impl();
|
||||
}
|
||||
|
||||
/* Copy the values from the source buffer to all elements in the virtual array. */
|
||||
void GVMutableArray::set_all(const void *src)
|
||||
{
|
||||
this->get_impl()->set_all(src);
|
||||
}
|
||||
|
||||
GMutableSpan GVMutableArray::get_internal_span() const
|
||||
{
|
||||
BLI_assert(this->is_span());
|
||||
const GSpan span = impl_->get_internal_span();
|
||||
return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@@ -18,13 +18,13 @@
|
||||
|
||||
namespace blender::fn {
|
||||
|
||||
void GVArray_For_GVVectorArrayIndex::get_impl(const int64_t index_in_vector, void *r_value) const
|
||||
void GVArray_For_GVVectorArrayIndex::get(const int64_t index_in_vector, void *r_value) const
|
||||
{
|
||||
vector_array_.get_vector_element(index_, index_in_vector, r_value);
|
||||
}
|
||||
|
||||
void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t index_in_vector,
|
||||
void *r_value) const
|
||||
void GVArray_For_GVVectorArrayIndex::get_to_uninitialized(const int64_t index_in_vector,
|
||||
void *r_value) const
|
||||
{
|
||||
type_->default_construct(r_value);
|
||||
vector_array_.get_vector_element(index_, index_in_vector, r_value);
|
||||
@@ -32,14 +32,14 @@ void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t ind
|
||||
|
||||
int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const
|
||||
{
|
||||
return array_.size();
|
||||
return varray_.size();
|
||||
}
|
||||
|
||||
void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t UNUSED(index),
|
||||
const int64_t index_in_vector,
|
||||
void *r_value) const
|
||||
{
|
||||
array_.get(index_in_vector, r_value);
|
||||
varray_.get(index_in_vector, r_value);
|
||||
}
|
||||
|
||||
bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const
|
||||
|
@@ -54,7 +54,6 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
|
||||
const IndexRange input_slice_range{input_slice_start, input_slice_size};
|
||||
|
||||
MFParamsBuilder sub_params{fn_, sub_mask.min_array_size()};
|
||||
ResourceScope &scope = sub_params.resource_scope();
|
||||
|
||||
/* All parameters are sliced so that the wrapped multi-function does not have to take care of
|
||||
* the index offset. */
|
||||
@@ -63,8 +62,7 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
|
||||
switch (param_type.category()) {
|
||||
case MFParamType::SingleInput: {
|
||||
const GVArray &varray = params.readonly_single_input(param_index);
|
||||
const GVArray &sliced_varray = scope.construct<GVArray_Slice>(varray, input_slice_range);
|
||||
sub_params.add_readonly_single_input(sliced_varray);
|
||||
sub_params.add_readonly_single_input(varray.slice(input_slice_range));
|
||||
break;
|
||||
}
|
||||
case MFParamType::SingleMutable: {
|
||||
|
@@ -66,6 +66,7 @@ struct VariableValue_GVArray : public VariableValue {
|
||||
|
||||
VariableValue_GVArray(const GVArray &data) : VariableValue(static_type), data(data)
|
||||
{
|
||||
BLI_assert(data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -756,7 +757,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
|
||||
switch (value_->type) {
|
||||
case ValueType::GVArray: {
|
||||
const GVArray_Typed<bool> varray{this->value_as<VariableValue_GVArray>()->data};
|
||||
const VArray<bool> varray = this->value_as<VariableValue_GVArray>()->data.typed<bool>();
|
||||
for (const int i : mask) {
|
||||
r_indices[varray[i]].append(i);
|
||||
}
|
||||
|
@@ -34,14 +34,12 @@ class IndexFieldInput final : public FieldInput {
|
||||
{
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
auto index_func = [](int i) { return i; };
|
||||
return &scope.construct<
|
||||
GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
|
||||
mask.min_array_size(), mask.min_array_size(), index_func);
|
||||
return VArray<int>::ForFunc(mask.min_array_size(), index_func);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,20 +238,20 @@ TEST(field, TwoFunctionsTwoOutputs)
|
||||
|
||||
FieldContext field_context;
|
||||
FieldEvaluator field_evaluator{field_context, &mask};
|
||||
const VArray<int> *result_1 = nullptr;
|
||||
const VArray<int> *result_2 = nullptr;
|
||||
VArray<int> result_1;
|
||||
VArray<int> result_2;
|
||||
field_evaluator.add(result_field_1, &result_1);
|
||||
field_evaluator.add(result_field_2, &result_2);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
EXPECT_EQ(result_1->get(2), 4);
|
||||
EXPECT_EQ(result_1->get(4), 8);
|
||||
EXPECT_EQ(result_1->get(6), 12);
|
||||
EXPECT_EQ(result_1->get(8), 16);
|
||||
EXPECT_EQ(result_2->get(2), 24);
|
||||
EXPECT_EQ(result_2->get(4), 28);
|
||||
EXPECT_EQ(result_2->get(6), 32);
|
||||
EXPECT_EQ(result_2->get(8), 36);
|
||||
EXPECT_EQ(result_1.get(2), 4);
|
||||
EXPECT_EQ(result_1.get(4), 8);
|
||||
EXPECT_EQ(result_1.get(6), 12);
|
||||
EXPECT_EQ(result_1.get(8), 16);
|
||||
EXPECT_EQ(result_2.get(2), 24);
|
||||
EXPECT_EQ(result_2.get(4), 28);
|
||||
EXPECT_EQ(result_2.get(6), 32);
|
||||
EXPECT_EQ(result_2.get(8), 36);
|
||||
}
|
||||
|
||||
TEST(field, SameFieldTwice)
|
||||
@@ -264,16 +262,16 @@ TEST(field, SameFieldTwice)
|
||||
FieldContext field_context;
|
||||
IndexMask mask{IndexRange(2)};
|
||||
ResourceScope scope;
|
||||
Vector<const GVArray *> results = evaluate_fields(
|
||||
Vector<GVArray> results = evaluate_fields(
|
||||
scope, {constant_field, constant_field}, mask, field_context);
|
||||
|
||||
GVArray_Typed<int> varray1{*results[0]};
|
||||
GVArray_Typed<int> varray2{*results[1]};
|
||||
VArray<int> varray1 = results[0].typed<int>();
|
||||
VArray<int> varray2 = results[1].typed<int>();
|
||||
|
||||
EXPECT_EQ(varray1->get(0), 10);
|
||||
EXPECT_EQ(varray1->get(1), 10);
|
||||
EXPECT_EQ(varray2->get(0), 10);
|
||||
EXPECT_EQ(varray2->get(1), 10);
|
||||
EXPECT_EQ(varray1.get(0), 10);
|
||||
EXPECT_EQ(varray1.get(1), 10);
|
||||
EXPECT_EQ(varray2.get(0), 10);
|
||||
EXPECT_EQ(varray2.get(1), 10);
|
||||
}
|
||||
|
||||
TEST(field, IgnoredOutput)
|
||||
@@ -283,12 +281,12 @@ TEST(field, IgnoredOutput)
|
||||
|
||||
FieldContext field_context;
|
||||
FieldEvaluator field_evaluator{field_context, 10};
|
||||
const VArray<int> *results = nullptr;
|
||||
VArray<int> results;
|
||||
field_evaluator.add(field, &results);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
EXPECT_EQ(results->get(0), 5);
|
||||
EXPECT_EQ(results->get(3), 5);
|
||||
EXPECT_EQ(results.get(0), 5);
|
||||
EXPECT_EQ(results.get(3), 5);
|
||||
}
|
||||
|
||||
} // namespace blender::fn::tests
|
||||
|
@@ -9,6 +9,43 @@
|
||||
|
||||
namespace blender::fn::tests {
|
||||
|
||||
TEST(multi_function_procedure, ConstantOutput)
|
||||
{
|
||||
/**
|
||||
* procedure(int *var2) {
|
||||
* var1 = 5;
|
||||
* var2 = var1 + var1;
|
||||
* }
|
||||
*/
|
||||
|
||||
CustomMF_Constant<int> constant_fn{5};
|
||||
CustomMF_SI_SI_SO<int, int, int> add_fn{"Add", [](int a, int b) { return a + b; }};
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
|
||||
auto [var1] = builder.add_call<1>(constant_fn);
|
||||
auto [var2] = builder.add_call<1>(add_fn, {var1, var1});
|
||||
builder.add_destruct(*var1);
|
||||
builder.add_return();
|
||||
builder.add_output_parameter(*var2);
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor executor{"My Procedure", procedure};
|
||||
|
||||
MFParamsBuilder params{executor, 2};
|
||||
MFContextBuilder context;
|
||||
|
||||
Array<int> output_array(2);
|
||||
params.add_uninitialized_single_output(output_array.as_mutable_span());
|
||||
|
||||
executor.call(IndexRange(2), params, context);
|
||||
|
||||
EXPECT_EQ(output_array[0], 10);
|
||||
EXPECT_EQ(output_array[1], 10);
|
||||
}
|
||||
|
||||
TEST(multi_function_procedure, SimpleTest)
|
||||
{
|
||||
/**
|
||||
|
@@ -50,23 +50,23 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
|
||||
/* Copy builtin control point attributes. */
|
||||
if (source_attribute_ids.contains("tilt")) {
|
||||
const fn::GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
"tilt", ATTR_DOMAIN_POINT, 0.0f);
|
||||
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
copy_attribute_to_points<float>(
|
||||
*tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
|
||||
tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
|
||||
}
|
||||
});
|
||||
source_attribute_ids.remove_contained("tilt");
|
||||
}
|
||||
if (source_attribute_ids.contains("radius")) {
|
||||
const fn::GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
"radius", ATTR_DOMAIN_POINT, 1.0f);
|
||||
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
copy_attribute_to_points<float>(
|
||||
*radius_attribute, point_to_vert_maps[i], splines[i]->radii());
|
||||
radius_attribute, point_to_vert_maps[i], splines[i]->radii());
|
||||
}
|
||||
});
|
||||
source_attribute_ids.remove_contained("radius");
|
||||
@@ -82,7 +82,7 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
continue;
|
||||
}
|
||||
|
||||
const fn::GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(
|
||||
const fn::GVArray mesh_attribute = mesh_component.attribute_try_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_POINT);
|
||||
/* Some attributes might not exist if they were builtin attribute on domains that don't
|
||||
* have any elements, i.e. a face attribute on the output of the line primitive node. */
|
||||
@@ -90,7 +90,7 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
continue;
|
||||
}
|
||||
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type());
|
||||
|
||||
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@@ -101,10 +101,10 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
BLI_assert(spline_attribute);
|
||||
|
||||
/* Copy attribute based on the map for this spline. */
|
||||
attribute_math::convert_to_static_type(mesh_attribute->type(), [&](auto dummy) {
|
||||
attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
copy_attribute_to_points<T>(
|
||||
mesh_attribute->typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
|
||||
mesh_attribute.typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@@ -57,13 +57,8 @@ using fn::GPointer;
|
||||
using fn::GSpan;
|
||||
using fn::GVArray;
|
||||
using fn::GVArray_GSpan;
|
||||
using fn::GVArray_Span;
|
||||
using fn::GVArray_Typed;
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArray;
|
||||
using fn::GVMutableArray_GSpan;
|
||||
using fn::GVMutableArray_Typed;
|
||||
using fn::GVMutableArrayPtr;
|
||||
using geometry_nodes_eval_log::NodeWarningType;
|
||||
|
||||
/**
|
||||
@@ -316,21 +311,21 @@ class GeoNodeExecParams {
|
||||
* \note This will add an error message if the string socket is active and
|
||||
* the input attribute does not exist.
|
||||
*/
|
||||
GVArrayPtr get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const;
|
||||
GVArray get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const;
|
||||
|
||||
template<typename T>
|
||||
GVArray_Typed<T> get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
VArray<T> get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
{
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>());
|
||||
GVArrayPtr varray = this->get_input_attribute(name, component, domain, type, &default_value);
|
||||
return GVArray_Typed<T>(std::move(varray));
|
||||
GVArray varray = this->get_input_attribute(name, component, domain, type, &default_value);
|
||||
return varray.typed<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -21,7 +21,6 @@
|
||||
namespace blender::nodes {
|
||||
|
||||
using fn::CPPType;
|
||||
using fn::GVArray;
|
||||
|
||||
struct ConversionFunctions {
|
||||
const fn::MultiFunction *multi_function;
|
||||
@@ -73,9 +72,9 @@ class DataTypeConversions {
|
||||
const void *from_value,
|
||||
void *to_value) const;
|
||||
|
||||
fn::GVArrayPtr try_convert(fn::GVArrayPtr varray, const CPPType &to_type) const;
|
||||
fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const;
|
||||
|
||||
fn::GVMutableArrayPtr try_convert(fn::GVMutableArrayPtr varray, const CPPType &to_type) const;
|
||||
fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const;
|
||||
};
|
||||
|
||||
const DataTypeConversions &get_implicit_type_conversions();
|
||||
|
@@ -179,9 +179,9 @@ static void align_rotations_on_component(GeometryComponent &component,
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> factors = params.get_input_attribute<float>(
|
||||
VArray<float> factors = params.get_input_attribute<float>(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, 1.0f);
|
||||
GVArray_Typed<float3> vectors = params.get_input_attribute<float3>(
|
||||
VArray<float3> vectors = params.get_input_attribute<float3>(
|
||||
"Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1});
|
||||
|
||||
float3 local_main_axis{0, 0, 0};
|
||||
|
@@ -156,7 +156,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
const AttributeDomain domain = get_result_domain(component, attribute_name, result_name);
|
||||
const int operation = static_cast<int>(storage.operation);
|
||||
|
||||
GVArrayPtr attribute_input = component.attribute_try_get_for_read(
|
||||
GVArray attribute_input = component.attribute_try_get_for_read(
|
||||
attribute_name, domain, data_type);
|
||||
|
||||
OutputAttribute attribute_result = component.attribute_try_get_for_output_only(
|
||||
@@ -185,7 +185,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
}
|
||||
}
|
||||
MutableSpan<float3> results = attribute_result.as_span<float3>();
|
||||
clamp_attribute<float3>(attribute_input->typed<float3>(), results, min, max);
|
||||
clamp_attribute<float3>(attribute_input.typed<float3>(), results, min, max);
|
||||
break;
|
||||
}
|
||||
case CD_PROP_FLOAT: {
|
||||
@@ -193,10 +193,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
const float max = params.get_input<float>("Max_001");
|
||||
MutableSpan<float> results = attribute_result.as_span<float>();
|
||||
if (operation == NODE_CLAMP_RANGE && min > max) {
|
||||
clamp_attribute<float>(attribute_input->typed<float>(), results, max, min);
|
||||
clamp_attribute<float>(attribute_input.typed<float>(), results, max, min);
|
||||
}
|
||||
else {
|
||||
clamp_attribute<float>(attribute_input->typed<float>(), results, min, max);
|
||||
clamp_attribute<float>(attribute_input.typed<float>(), results, min, max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -205,10 +205,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
const int max = params.get_input<int>("Max_002");
|
||||
MutableSpan<int> results = attribute_result.as_span<int>();
|
||||
if (operation == NODE_CLAMP_RANGE && min > max) {
|
||||
clamp_attribute<int>(attribute_input->typed<int>(), results, max, min);
|
||||
clamp_attribute<int>(attribute_input.typed<int>(), results, max, min);
|
||||
}
|
||||
else {
|
||||
clamp_attribute<int>(attribute_input->typed<int>(), results, min, max);
|
||||
clamp_attribute<int>(attribute_input.typed<int>(), results, min, max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -231,7 +231,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
}
|
||||
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
|
||||
clamp_attribute<ColorGeometry4f>(
|
||||
attribute_input->typed<ColorGeometry4f>(), results, min, max);
|
||||
attribute_input.typed<ColorGeometry4f>(), results, min, max);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@@ -85,7 +85,7 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
VArray<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
input_name, result_domain, 0.0f);
|
||||
|
||||
MutableSpan<ColorGeometry4f> results = attribute_result.as_span();
|
||||
|
@@ -95,11 +95,11 @@ static void combine_attributes(GeometryComponent &component, const GeoNodeExecPa
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
}
|
||||
GVArray_Typed<float> attribute_x = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_x = params.get_input_attribute<float>(
|
||||
"X", component, result_domain, 0.0f);
|
||||
GVArray_Typed<float> attribute_y = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_y = params.get_input_attribute<float>(
|
||||
"Y", component, result_domain, 0.0f);
|
||||
GVArray_Typed<float> attribute_z = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_z = params.get_input_attribute<float>(
|
||||
"Z", component, result_domain, 0.0f);
|
||||
|
||||
for (const int i : IndexRange(attribute_result->size())) {
|
||||
|
@@ -257,9 +257,9 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
||||
|
||||
const CustomDataType input_data_type = get_data_type(component, params, *node_storage);
|
||||
|
||||
GVArrayPtr attribute_a = params.get_input_attribute(
|
||||
GVArray attribute_a = params.get_input_attribute(
|
||||
"A", component, result_domain, input_data_type, nullptr);
|
||||
GVArrayPtr attribute_b = params.get_input_attribute(
|
||||
GVArray attribute_b = params.get_input_attribute(
|
||||
"B", component, result_domain, input_data_type, nullptr);
|
||||
|
||||
if (!attribute_a || !attribute_b) {
|
||||
@@ -276,47 +276,47 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
||||
if (operation == NODE_FLOAT_COMPARE_EQUAL) {
|
||||
if (input_data_type == CD_PROP_FLOAT) {
|
||||
do_equal_operation_float(
|
||||
attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
|
||||
attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_FLOAT3) {
|
||||
do_equal_operation_float3(
|
||||
attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
|
||||
attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_COLOR) {
|
||||
do_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
|
||||
attribute_b->typed<ColorGeometry4f>(),
|
||||
do_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
|
||||
attribute_b.typed<ColorGeometry4f>(),
|
||||
threshold,
|
||||
result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_BOOL) {
|
||||
do_equal_operation_bool(
|
||||
attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
|
||||
attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
|
||||
}
|
||||
}
|
||||
else if (operation == NODE_FLOAT_COMPARE_NOT_EQUAL) {
|
||||
if (input_data_type == CD_PROP_FLOAT) {
|
||||
do_not_equal_operation_float(
|
||||
attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
|
||||
attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_FLOAT3) {
|
||||
do_not_equal_operation_float3(
|
||||
attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
|
||||
attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_COLOR) {
|
||||
do_not_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
|
||||
attribute_b->typed<ColorGeometry4f>(),
|
||||
do_not_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
|
||||
attribute_b.typed<ColorGeometry4f>(),
|
||||
threshold,
|
||||
result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_BOOL) {
|
||||
do_not_equal_operation_bool(
|
||||
attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
|
||||
attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
do_math_operation(
|
||||
attribute_a->typed<float>(), attribute_b->typed<float>(), operation, result_span);
|
||||
attribute_a.typed<float>(), attribute_b.typed<float>(), operation, result_span);
|
||||
}
|
||||
|
||||
attribute_result.save();
|
||||
|
@@ -104,7 +104,7 @@ static void attribute_convert_calc(GeometryComponent &component,
|
||||
return;
|
||||
}
|
||||
|
||||
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
|
||||
GVArray source_attribute = component.attribute_try_get_for_read(
|
||||
source_name, result_domain, result_type);
|
||||
if (!source_attribute) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
@@ -118,7 +118,7 @@ static void attribute_convert_calc(GeometryComponent &component,
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_GSpan source_span{*source_attribute};
|
||||
GVArray_GSpan source_span{source_attribute};
|
||||
GMutableSpan result_span = result_attribute.as_span();
|
||||
|
||||
BLI_assert(source_span.size() == result_span.size());
|
||||
|
@@ -136,10 +136,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
switch (result_type) {
|
||||
case CD_PROP_FLOAT: {
|
||||
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
|
||||
GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
VArray<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
input_name, result_domain, float(0.0f));
|
||||
MutableSpan<float> results = attribute_result.as_span<float>();
|
||||
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
|
||||
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
results[i] = BKE_curvemapping_evaluateF(cumap, 3, attribute_in[i]);
|
||||
}
|
||||
@@ -148,10 +148,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
}
|
||||
case CD_PROP_FLOAT3: {
|
||||
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
|
||||
GVArray_Typed<float3> attribute_in = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> attribute_in = component.attribute_get_for_read<float3>(
|
||||
input_name, result_domain, float3(0.0f));
|
||||
MutableSpan<float3> results = attribute_result.as_span<float3>();
|
||||
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
|
||||
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BKE_curvemapping_evaluate3F(cumap, results[i], attribute_in[i]);
|
||||
}
|
||||
@@ -160,11 +160,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
}
|
||||
case CD_PROP_COLOR: {
|
||||
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_rgb;
|
||||
GVArray_Typed<ColorGeometry4f> attribute_in =
|
||||
component.attribute_get_for_read<ColorGeometry4f>(
|
||||
input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
VArray<ColorGeometry4f> attribute_in = component.attribute_get_for_read<ColorGeometry4f>(
|
||||
input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
|
||||
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
|
||||
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BKE_curvemapping_evaluateRGBF(cumap, results[i], attribute_in[i]);
|
||||
}
|
||||
|
@@ -362,7 +362,7 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
|
||||
|
||||
const AttributeDomain domain = get_result_domain(component, input_name, result_name);
|
||||
|
||||
GVArrayPtr attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
|
||||
GVArray attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
|
||||
|
||||
if (!attribute_input) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
@@ -381,12 +381,12 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
|
||||
|
||||
switch (data_type) {
|
||||
case CD_PROP_FLOAT: {
|
||||
map_range_float(attribute_input->typed<float>(), attribute_result.as_span<float>(), params);
|
||||
map_range_float(attribute_input.typed<float>(), attribute_result.as_span<float>(), params);
|
||||
break;
|
||||
}
|
||||
case CD_PROP_FLOAT3: {
|
||||
map_range_float3(
|
||||
attribute_input->typed<float3>(), attribute_result.as_span<float3>(), params);
|
||||
attribute_input.typed<float3>(), attribute_result.as_span<float3>(), params);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@@ -250,7 +250,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> attribute_a = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_a = params.get_input_attribute<float>(
|
||||
"A", component, result_domain, 0.0f);
|
||||
|
||||
MutableSpan<float> result_span = attribute_result.as_span();
|
||||
@@ -258,10 +258,10 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
|
||||
/* Note that passing the data with `get_internal_span<float>()` works
|
||||
* because the attributes were accessed with #CD_PROP_FLOAT. */
|
||||
if (operation_use_input_b(operation)) {
|
||||
GVArray_Typed<float> attribute_b = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_b = params.get_input_attribute<float>(
|
||||
"B", component, result_domain, 0.0f);
|
||||
if (operation_use_input_c(operation)) {
|
||||
GVArray_Typed<float> attribute_c = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_c = params.get_input_attribute<float>(
|
||||
"C", component, result_domain, 0.0f);
|
||||
do_math_operation(attribute_a, attribute_b, attribute_c, result_span, operation);
|
||||
}
|
||||
|
@@ -144,25 +144,28 @@ static void do_mix_operation(const CustomDataType result_type,
|
||||
GVMutableArray &attribute_result)
|
||||
{
|
||||
if (result_type == CD_PROP_FLOAT) {
|
||||
VMutableArray<float> result = attribute_result.typed<float>();
|
||||
do_mix_operation_float(blend_mode,
|
||||
attribute_factor,
|
||||
attribute_a.typed<float>(),
|
||||
attribute_b.typed<float>(),
|
||||
attribute_result.typed<float>());
|
||||
result);
|
||||
}
|
||||
else if (result_type == CD_PROP_FLOAT3) {
|
||||
VMutableArray<float3> result = attribute_result.typed<float3>();
|
||||
do_mix_operation_float3(blend_mode,
|
||||
attribute_factor,
|
||||
attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_result.typed<float3>());
|
||||
result);
|
||||
}
|
||||
else if (result_type == CD_PROP_COLOR) {
|
||||
VMutableArray<ColorGeometry4f> result = attribute_result.typed<ColorGeometry4f>();
|
||||
do_mix_operation_color4f(blend_mode,
|
||||
attribute_factor,
|
||||
attribute_a.typed<ColorGeometry4f>(),
|
||||
attribute_b.typed<ColorGeometry4f>(),
|
||||
attribute_result.typed<ColorGeometry4f>());
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,19 +206,19 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> attribute_factor = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_factor = params.get_input_attribute<float>(
|
||||
"Factor", component, result_domain, 0.5f);
|
||||
GVArrayPtr attribute_a = params.get_input_attribute(
|
||||
GVArray attribute_a = params.get_input_attribute(
|
||||
"A", component, result_domain, result_type, nullptr);
|
||||
GVArrayPtr attribute_b = params.get_input_attribute(
|
||||
GVArray attribute_b = params.get_input_attribute(
|
||||
"B", component, result_domain, result_type, nullptr);
|
||||
|
||||
do_mix_operation(result_type,
|
||||
node_storage->blend_type,
|
||||
attribute_factor,
|
||||
*attribute_a,
|
||||
*attribute_b,
|
||||
*attribute_result);
|
||||
attribute_a,
|
||||
attribute_b,
|
||||
attribute_result.varray());
|
||||
attribute_result.save();
|
||||
}
|
||||
|
||||
|
@@ -153,7 +153,7 @@ static void attribute_calc_proximity(GeometryComponent &component,
|
||||
if (!position_attribute || (!distance_attribute && !location_attribute)) {
|
||||
return;
|
||||
}
|
||||
GVArray_Typed<float3> positions{*position_attribute.varray};
|
||||
VArray<float3> positions = position_attribute.varray.typed<float3>();
|
||||
const NodeGeometryAttributeProximity &storage =
|
||||
*(const NodeGeometryAttributeProximity *)params.node().storage;
|
||||
|
||||
|
@@ -180,13 +180,13 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo
|
||||
const int domain_size = component.attribute_domain_size(domain);
|
||||
|
||||
/* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */
|
||||
GVArrayPtr hash_attribute = component.attribute_try_get_for_read("id", domain);
|
||||
GVArray hash_attribute = component.attribute_try_get_for_read("id", domain);
|
||||
Array<uint32_t> hashes(domain_size);
|
||||
if (hash_attribute) {
|
||||
BLI_assert(hashes.size() == hash_attribute->size());
|
||||
const CPPType &cpp_type = hash_attribute->type();
|
||||
BLI_assert(hashes.size() == hash_attribute.size());
|
||||
const CPPType &cpp_type = hash_attribute.type();
|
||||
BLI_assert(cpp_type.is_hashable());
|
||||
GVArray_GSpan items{*hash_attribute};
|
||||
GVArray_GSpan items{hash_attribute};
|
||||
threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
hashes[i] = cpp_type.hash(items[i]);
|
||||
|
@@ -82,7 +82,7 @@ static void execute_on_component(GeometryComponent &component, const GeoNodeExec
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float3> mapping_attribute = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> mapping_attribute = component.attribute_get_for_read<float3>(
|
||||
mapping_name, result_domain, {0, 0, 0});
|
||||
|
||||
MutableSpan<ColorGeometry4f> colors = attribute_out.as_span();
|
||||
|
@@ -106,9 +106,9 @@ static void separate_attribute(GeometryComponent &component, const GeoNodeExecPa
|
||||
const AttributeDomain result_domain = get_result_domain(
|
||||
component, params, result_name_x, result_name_y, result_name_z);
|
||||
|
||||
GVArray_Typed<float3> attribute_input = params.get_input_attribute<float3>(
|
||||
VArray<float3> attribute_input = params.get_input_attribute<float3>(
|
||||
"Vector", component, result_domain, {0, 0, 0});
|
||||
VArray_Span<float3> input_span{*attribute_input};
|
||||
VArray_Span<float3> input_span{attribute_input};
|
||||
|
||||
OutputAttribute_Typed<float> attribute_result_x =
|
||||
component.attribute_try_get_for_output_only<float>(result_name_x, result_domain);
|
||||
|
@@ -407,13 +407,13 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
|
||||
if (pointcloud_distances_sq[i] < mesh_distances_sq[i]) {
|
||||
/* Point-cloud point is closer. */
|
||||
const int index = pointcloud_indices[i];
|
||||
pointcloud_src_attribute.varray->get(index, buffer);
|
||||
pointcloud_src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
else {
|
||||
/* Mesh element is closer. */
|
||||
const int index = mesh_indices[i];
|
||||
mesh_src_attribute.varray->get(index, buffer);
|
||||
mesh_src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
@@ -424,7 +424,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
|
||||
src_name, data_type);
|
||||
for (const int i : IndexRange(tot_samples)) {
|
||||
const int index = pointcloud_indices[i];
|
||||
src_attribute.varray->get(index, buffer);
|
||||
src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
@@ -434,7 +434,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
|
||||
data_type);
|
||||
for (const int i : IndexRange(tot_samples)) {
|
||||
const int index = mesh_indices[i];
|
||||
src_attribute.varray->get(index, buffer);
|
||||
src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
@@ -460,7 +460,7 @@ static void transfer_attribute(const GeoNodeExecParams ¶ms,
|
||||
const AttributeDomain dst_domain = (input_domain == ATTR_DOMAIN_AUTO) ? auto_domain :
|
||||
input_domain;
|
||||
|
||||
GVArray_Typed<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
|
||||
VArray<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
|
||||
"position", dst_domain, {0, 0, 0});
|
||||
|
||||
switch (mapping) {
|
||||
|
@@ -187,7 +187,7 @@ static void geo_node_attribute_vector_math_update(bNodeTree *UNUSED(ntree), bNod
|
||||
|
||||
static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -218,7 +218,7 @@ static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
const VArray<float3> &input_c,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -251,7 +251,7 @@ static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
const VArray<float> &input_c,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -283,7 +283,7 @@ static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
|
||||
static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
VMutableArray<float> &result,
|
||||
const VMutableArray<float> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -313,7 +313,7 @@ static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
|
||||
|
||||
static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float> &input_b,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -342,7 +342,7 @@ static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
}
|
||||
|
||||
static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -369,7 +369,7 @@ static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
}
|
||||
|
||||
static void do_math_operation_fl3_to_fl(const VArray<float3> &input_a,
|
||||
VMutableArray<float> &result,
|
||||
const VMutableArray<float> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -437,13 +437,13 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
||||
const AttributeDomain result_domain = get_result_domain(
|
||||
component, params, operation, result_name);
|
||||
|
||||
GVArrayPtr attribute_a = params.get_input_attribute(
|
||||
GVArray attribute_a = params.get_input_attribute(
|
||||
"A", component, result_domain, read_type_a, nullptr);
|
||||
if (!attribute_a) {
|
||||
return;
|
||||
}
|
||||
GVArrayPtr attribute_b;
|
||||
GVArrayPtr attribute_c;
|
||||
GVArray attribute_b;
|
||||
GVArray attribute_c;
|
||||
if (use_input_b) {
|
||||
attribute_b = params.get_input_attribute("B", component, result_domain, read_type_b, nullptr);
|
||||
if (!attribute_b) {
|
||||
@@ -476,26 +476,26 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
||||
case NODE_VECTOR_MATH_MODULO:
|
||||
case NODE_VECTOR_MATH_MINIMUM:
|
||||
case NODE_VECTOR_MATH_MAXIMUM:
|
||||
do_math_operation_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||
case NODE_VECTOR_MATH_DISTANCE:
|
||||
do_math_operation_fl3_fl3_to_fl(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_result->typed<float>(),
|
||||
do_math_operation_fl3_fl3_to_fl(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_result.varray().typed<float>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_LENGTH:
|
||||
do_math_operation_fl3_to_fl(
|
||||
attribute_a->typed<float3>(), attribute_result->typed<float>(), operation);
|
||||
attribute_a.typed<float3>(), attribute_result.varray().typed<float>(), operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_SCALE:
|
||||
do_math_operation_fl3_fl_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_NORMALIZE:
|
||||
@@ -507,22 +507,22 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
||||
case NODE_VECTOR_MATH_COSINE:
|
||||
case NODE_VECTOR_MATH_TANGENT:
|
||||
do_math_operation_fl3_to_fl3(
|
||||
attribute_a->typed<float3>(), attribute_result->typed<float3>(), operation);
|
||||
attribute_a.typed<float3>(), attribute_result.varray().typed<float3>(), operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_WRAP:
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
||||
do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_c->typed<float3>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_c.typed<float3>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
do_math_operation_fl3_fl3_fl_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_c->typed<float>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl3_fl_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_c.typed<float>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
}
|
||||
|
@@ -220,12 +220,12 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
const AttributeDomain result_domain = get_result_domain(component, params, result_name);
|
||||
const bool invert = params.get_input<bool>("Invert");
|
||||
|
||||
GVArrayPtr attribute_vector = params.get_input_attribute(
|
||||
GVArray attribute_vector = params.get_input_attribute(
|
||||
"Vector", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_vector) {
|
||||
return;
|
||||
}
|
||||
GVArrayPtr attribute_center = params.get_input_attribute(
|
||||
GVArray attribute_center = params.get_input_attribute(
|
||||
"Center", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_center) {
|
||||
return;
|
||||
@@ -238,21 +238,21 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
}
|
||||
|
||||
if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
|
||||
GVArrayPtr attribute_rotation = params.get_input_attribute(
|
||||
GVArray attribute_rotation = params.get_input_attribute(
|
||||
"Rotation", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_rotation) {
|
||||
return;
|
||||
}
|
||||
do_vector_rotate_euler(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
attribute_rotation->typed<float3>(),
|
||||
do_vector_rotate_euler(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
attribute_rotation.typed<float3>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
attribute_result.save();
|
||||
return;
|
||||
}
|
||||
|
||||
GVArrayPtr attribute_angle = params.get_input_attribute(
|
||||
GVArray attribute_angle = params.get_input_attribute(
|
||||
"Angle", component, result_domain, CD_PROP_FLOAT, nullptr);
|
||||
if (!attribute_angle) {
|
||||
return;
|
||||
@@ -260,40 +260,40 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
|
||||
switch (mode) {
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS: {
|
||||
GVArrayPtr attribute_axis = params.get_input_attribute(
|
||||
GVArray attribute_axis = params.get_input_attribute(
|
||||
"Axis", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_axis) {
|
||||
return;
|
||||
}
|
||||
do_vector_rotate_around_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
attribute_axis->typed<float3>(),
|
||||
attribute_angle->typed<float>(),
|
||||
do_vector_rotate_around_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
attribute_axis.typed<float3>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
} break;
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X:
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
float3(1.0f, 0.0f, 0.0f),
|
||||
attribute_angle->typed<float>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
break;
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
float3(0.0f, 1.0f, 0.0f),
|
||||
attribute_angle->typed<float>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
|
||||
break;
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
float3(0.0f, 0.0f, 1.0f),
|
||||
attribute_angle->typed<float>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
|
||||
|
@@ -61,7 +61,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
|
||||
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
|
||||
return true;
|
||||
}
|
||||
GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
|
||||
GVArray spline_attribute = curve_component.attribute_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
|
||||
|
||||
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
|
||||
@@ -70,7 +70,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
|
||||
|
||||
/* Only copy the attributes of splines in the offsets. */
|
||||
for (const int i : offsets.index_range()) {
|
||||
spline_attribute->get(offsets[i], result[i]);
|
||||
spline_attribute.get(offsets[i], result[i]);
|
||||
}
|
||||
|
||||
result_attribute.save();
|
||||
@@ -130,7 +130,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
|
||||
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]);
|
||||
spline_span.type().copy_assign(spline_span[0], point_span[i]);
|
||||
}
|
||||
|
||||
for (const auto item : end_data.point_attributes.items()) {
|
||||
@@ -139,7 +139,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
|
||||
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]);
|
||||
spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -44,7 +44,7 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
||||
MutableSpan<SplinePtr> splines = curve.splines();
|
||||
|
||||
const std::string selection_name = params.extract_input<std::string>("Selection");
|
||||
GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
|
||||
VArray<bool> selection = curve_component.attribute_get_for_read(
|
||||
selection_name, ATTR_DOMAIN_CURVE, true);
|
||||
|
||||
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
|
||||
|
@@ -84,7 +84,7 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
|
||||
MutableSpan<SplinePtr> splines = curve.splines();
|
||||
|
||||
const std::string selection_name = params.extract_input<std::string>("Selection");
|
||||
GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
|
||||
VArray<bool> selection = curve_component.attribute_get_for_read(
|
||||
selection_name, ATTR_DOMAIN_POINT, true);
|
||||
|
||||
const BezierSpline::HandleType new_handle_type = handle_type_from_input_type(type);
|
||||
|
@@ -255,7 +255,7 @@ static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params)
|
||||
const CurveEval &curve = *curve_component->get_for_read();
|
||||
|
||||
const std::string selection_name = params.extract_input<std::string>("Selection");
|
||||
GVArray_Typed<bool> selection = curve_component->attribute_get_for_read(
|
||||
VArray<bool> selection = curve_component->attribute_get_for_read(
|
||||
selection_name, ATTR_DOMAIN_CURVE, true);
|
||||
|
||||
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
|
||||
|
@@ -25,10 +25,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_Span;
|
||||
using blender::fn::GVArray_Typed;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
|
||||
@@ -363,14 +359,13 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
|
||||
}
|
||||
|
||||
const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
|
||||
GVArray_Typed<int> cuts = params.get_input_attribute<int>(
|
||||
"Cuts", component, ATTR_DOMAIN_POINT, 0);
|
||||
if (cuts->is_single() && cuts->get_internal_single() < 1) {
|
||||
VArray<int> cuts = params.get_input_attribute<int>("Cuts", component, ATTR_DOMAIN_POINT, 0);
|
||||
if (cuts.is_single() && cuts.get_internal_single() < 1) {
|
||||
params.set_output("Geometry", geometry_set);
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), *cuts);
|
||||
std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts);
|
||||
|
||||
params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release()));
|
||||
}
|
||||
|
@@ -121,7 +121,7 @@ static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &poin
|
||||
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
|
||||
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
|
||||
BLI_assert(attribute);
|
||||
return attribute.varray->get_internal_span();
|
||||
return attribute.varray.get_internal_span();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -177,8 +177,8 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
|
||||
const int size = offsets[i + 1] - offsets[i];
|
||||
|
||||
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
|
||||
spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.tilts())->materialize(data.tilts.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.tilts()).materialize(data.tilts.slice(offset, size));
|
||||
|
||||
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
|
||||
const AttributeIDRef attribute_id = item.key;
|
||||
@@ -188,7 +188,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.interpolate_to_evaluated(spline_span)
|
||||
->materialize(point_span.slice(offset, size).data());
|
||||
.materialize(point_span.slice(offset, size).data());
|
||||
}
|
||||
|
||||
data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents());
|
||||
@@ -230,7 +230,7 @@ static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines,
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
|
||||
spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
|
||||
uniform_samples,
|
||||
point_span.slice(offset, size));
|
||||
}
|
||||
@@ -263,20 +263,20 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
|
||||
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
|
||||
return true;
|
||||
}
|
||||
GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
|
||||
GVArray spline_attribute = curve_component.attribute_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
|
||||
const CPPType &type = spline_attribute->type();
|
||||
const CPPType &type = spline_attribute.type();
|
||||
|
||||
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
|
||||
attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type);
|
||||
GMutableSpan result = result_attribute.as_span();
|
||||
|
||||
for (const int i : IndexRange(spline_attribute->size())) {
|
||||
for (const int i : spline_attribute.index_range()) {
|
||||
const int offset = offsets[i];
|
||||
const int size = offsets[i + 1] - offsets[i];
|
||||
if (size != 0) {
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
spline_attribute->get(i, buffer);
|
||||
spline_attribute.get(i, buffer);
|
||||
type.fill_assign_n(buffer, result[offset], size);
|
||||
}
|
||||
}
|
||||
|
@@ -137,7 +137,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
|
||||
Vector<int64_t> copied_splines;
|
||||
|
||||
if (input_curve.attributes.get_for_read(name)) {
|
||||
GVArray_Typed<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
|
||||
VArray<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
|
||||
for (const int i : input_splines.index_range()) {
|
||||
if (selection[i] == invert) {
|
||||
output_curve->add_spline(input_splines[i]->copy());
|
||||
@@ -151,7 +151,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
|
||||
|
||||
for (const int i : input_splines.index_range()) {
|
||||
const Spline &spline = *input_splines[i];
|
||||
GVArray_Typed<bool> selection = spline.attributes.get_for_read<bool>(name, false);
|
||||
VArray<bool> selection = spline.attributes.get_for_read<bool>(name, false);
|
||||
|
||||
indices_to_copy.clear();
|
||||
for (const int i_point : IndexRange(spline.size())) {
|
||||
@@ -202,7 +202,7 @@ static void delete_point_cloud_selection(const PointCloudComponent &in_component
|
||||
const StringRef selection_name,
|
||||
const bool invert)
|
||||
{
|
||||
const GVArray_Typed<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
|
||||
const VArray<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
|
||||
selection_name, ATTR_DOMAIN_POINT, false);
|
||||
VArray_Span<bool> selection{selection_attribute};
|
||||
|
||||
@@ -590,7 +590,7 @@ static void delete_mesh_selection(MeshComponent &component,
|
||||
const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name);
|
||||
|
||||
/* This already checks if the attribute exists, and displays a warning in that case. */
|
||||
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
|
||||
VArray<bool> selection = component.attribute_get_for_read<bool>(
|
||||
selection_name, selection_domain, false);
|
||||
|
||||
/* Check if there is anything to delete. */
|
||||
|
@@ -72,7 +72,7 @@ static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params)
|
||||
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
||||
Mesh *mesh = mesh_component.get_for_write();
|
||||
if (mesh != nullptr) {
|
||||
GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
|
||||
VArray<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
|
||||
mask_name, ATTR_DOMAIN_FACE, true);
|
||||
assign_material_to_faces(*mesh, face_mask, material);
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
TIP_("No attribute with name \"") + selection_name + "\"");
|
||||
}
|
||||
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
|
||||
VArray<bool> selection = component.attribute_get_for_read<bool>(
|
||||
selection_name, ATTR_DOMAIN_EDGE, true);
|
||||
|
||||
Vector<int64_t> selected_edge_indices;
|
||||
|
@@ -106,9 +106,9 @@ static void sample_mesh_surface(const Mesh &mesh,
|
||||
|
||||
float looptri_density_factor = 1.0f;
|
||||
if (density_factors != nullptr) {
|
||||
const float v0_density_factor = std::max(0.0f, density_factors->get(v0_loop));
|
||||
const float v1_density_factor = std::max(0.0f, density_factors->get(v1_loop));
|
||||
const float v2_density_factor = std::max(0.0f, density_factors->get(v2_loop));
|
||||
const float v0_density_factor = std::max(0.0f, (*density_factors)[v0_loop]);
|
||||
const float v1_density_factor = std::max(0.0f, (*density_factors)[v1_loop]);
|
||||
const float v2_density_factor = std::max(0.0f, (*density_factors)[v2_loop]);
|
||||
looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f;
|
||||
}
|
||||
const float area = area_tri_v3(v0_pos, v1_pos, v2_pos);
|
||||
@@ -315,7 +315,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
||||
}
|
||||
|
||||
const AttributeDomain source_domain = attribute_info->domain;
|
||||
GVArrayPtr source_attribute = source_component.attribute_get_for_read(
|
||||
GVArray source_attribute = source_component.attribute_get_for_read(
|
||||
attribute_id, source_domain, output_data_type, nullptr);
|
||||
if (!source_attribute) {
|
||||
i_instance += set_group.transforms.size();
|
||||
@@ -329,7 +329,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
||||
|
||||
GMutableSpan instance_span = out_span.slice(offset, bary_coords.size());
|
||||
interpolate_attribute(
|
||||
mesh, bary_coords, looptri_indices, source_domain, *source_attribute, instance_span);
|
||||
mesh, bary_coords, looptri_indices, source_domain, source_attribute, instance_span);
|
||||
|
||||
i_instance++;
|
||||
}
|
||||
@@ -337,7 +337,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
||||
attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
GVArray_Span<T> source_span{*source_attribute};
|
||||
VArray_Span source_span{source_attribute.typed<T>()};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
|
||||
for (const GeometryInstanceGroup &set_group : set_groups) {
|
||||
const GeometrySet &set = set_group.geometry_set;
|
||||
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
|
||||
GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
|
||||
VArray<float> density_factors = component.attribute_get_for_read<float>(
|
||||
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
|
||||
const Mesh &mesh = *component.get_for_read();
|
||||
for (const float4x4 &transform : set_group.transforms) {
|
||||
@@ -455,7 +455,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
|
||||
sample_mesh_surface(mesh,
|
||||
transform,
|
||||
density,
|
||||
&*density_factors,
|
||||
&density_factors,
|
||||
seed,
|
||||
positions,
|
||||
bary_coords,
|
||||
@@ -514,7 +514,7 @@ static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_group
|
||||
const GeometrySet &set = set_group.geometry_set;
|
||||
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
|
||||
const Mesh &mesh = *component.get_for_read();
|
||||
const GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
|
||||
const VArray<float> density_factors = component.attribute_get_for_read<float>(
|
||||
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
|
||||
|
||||
for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
|
||||
|
@@ -171,13 +171,12 @@ static void add_instances_from_component(InstancesComponent &instances,
|
||||
|
||||
const int domain_size = src_geometry.attribute_domain_size(domain);
|
||||
|
||||
GVArray_Typed<float3> positions = src_geometry.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = src_geometry.attribute_get_for_read<float3>(
|
||||
"position", domain, {0, 0, 0});
|
||||
GVArray_Typed<float3> rotations = src_geometry.attribute_get_for_read<float3>(
|
||||
VArray<float3> rotations = src_geometry.attribute_get_for_read<float3>(
|
||||
"rotation", domain, {0, 0, 0});
|
||||
GVArray_Typed<float3> scales = src_geometry.attribute_get_for_read<float3>(
|
||||
"scale", domain, {1, 1, 1});
|
||||
GVArray_Typed<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
|
||||
VArray<float3> scales = src_geometry.attribute_get_for_read<float3>("scale", domain, {1, 1, 1});
|
||||
VArray<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
|
||||
|
||||
/* The initial size of the component might be non-zero if there are two component types. */
|
||||
const int start_len = instances.instances_amount();
|
||||
|
@@ -169,9 +169,9 @@ static void point_rotate_on_component(GeometryComponent &component,
|
||||
const int domain_size = rotations.size();
|
||||
|
||||
if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) {
|
||||
GVArray_Typed<float3> axis = params.get_input_attribute<float3>(
|
||||
VArray<float3> axis = params.get_input_attribute<float3>(
|
||||
"Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1});
|
||||
GVArray_Typed<float> angles = params.get_input_attribute<float>(
|
||||
VArray<float> angles = params.get_input_attribute<float>(
|
||||
"Angle", component, ATTR_DOMAIN_POINT, 0);
|
||||
|
||||
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
|
||||
@@ -182,7 +182,7 @@ static void point_rotate_on_component(GeometryComponent &component,
|
||||
}
|
||||
}
|
||||
else {
|
||||
GVArray_Typed<float3> eulers = params.get_input_attribute<float3>(
|
||||
VArray<float3> eulers = params.get_input_attribute<float3>(
|
||||
"Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
|
||||
|
@@ -78,7 +78,7 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
||||
const CustomDataType data_type = (input_type == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ? CD_PROP_FLOAT :
|
||||
CD_PROP_FLOAT3;
|
||||
|
||||
GVArrayPtr attribute = params.get_input_attribute(
|
||||
GVArray attribute = params.get_input_attribute(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, data_type, nullptr);
|
||||
if (!attribute) {
|
||||
return;
|
||||
@@ -86,13 +86,13 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
||||
|
||||
MutableSpan<float3> scale_span = scale_attribute.as_span();
|
||||
if (data_type == CD_PROP_FLOAT) {
|
||||
GVArray_Typed<float> factors{*attribute};
|
||||
VArray<float> factors = attribute.typed<float>();
|
||||
for (const int i : scale_span.index_range()) {
|
||||
scale_span[i] = scale_span[i] * factors[i];
|
||||
}
|
||||
}
|
||||
else if (data_type == CD_PROP_FLOAT3) {
|
||||
GVArray_Typed<float3> factors{*attribute};
|
||||
VArray<float3> factors = attribute.typed<float3>();
|
||||
for (const int i : scale_span.index_range()) {
|
||||
scale_span[i] = scale_span[i] * factors[i];
|
||||
}
|
||||
|
@@ -55,7 +55,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
|
||||
{
|
||||
for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) {
|
||||
ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id);
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
|
||||
|
||||
/* Only copy point attributes. Theoretically this could interpolate attributes on other
|
||||
* domains to the point domain, but that would conflict with attributes that are built-in
|
||||
@@ -69,7 +69,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Span<T> span{*attribute.varray};
|
||||
VArray_Span span{attribute.varray.typed<T>()};
|
||||
MutableSpan<T> out_span = result_attribute.as_span<T>();
|
||||
copy_data_based_on_mask(span, masks, invert, out_span);
|
||||
});
|
||||
@@ -103,7 +103,7 @@ static void separate_points_from_component(const GeometryComponent &in_component
|
||||
return;
|
||||
}
|
||||
|
||||
const GVArray_Typed<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
|
||||
const VArray<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
|
||||
mask_name, ATTR_DOMAIN_POINT, false);
|
||||
VArray_Span<bool> masks{mask_attribute};
|
||||
|
||||
|
@@ -43,10 +43,10 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
||||
if (!position_attribute) {
|
||||
return;
|
||||
}
|
||||
GVArray_Typed<float3> attribute = params.get_input_attribute<float3>(
|
||||
VArray<float3> attribute = params.get_input_attribute<float3>(
|
||||
"Translation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
for (const int i : IndexRange(attribute.size())) {
|
||||
for (const int i : attribute.index_range()) {
|
||||
position_attribute->set(i, position_attribute->get(i) + attribute[i]);
|
||||
}
|
||||
|
||||
|
@@ -172,12 +172,12 @@ static void gather_point_data_from_component(const GeoNodeExecParams ¶ms,
|
||||
Vector<float3> &r_positions,
|
||||
Vector<float> &r_radii)
|
||||
{
|
||||
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = component.attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
GVArray_Typed<float> radii = params.get_input_attribute<float>(
|
||||
VArray<float> radii = params.get_input_attribute<float>(
|
||||
"Radius", component, ATTR_DOMAIN_POINT, 0.0f);
|
||||
|
||||
for (const int i : IndexRange(positions.size())) {
|
||||
for (const int i : positions.index_range()) {
|
||||
r_positions.append(positions[i]);
|
||||
r_radii.append(radii[i]);
|
||||
}
|
||||
|
@@ -197,11 +197,11 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms,
|
||||
(GeometryNodeRaycastMapMode)storage.mapping);
|
||||
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
|
||||
|
||||
GVArray_Typed<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
|
||||
VArray<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
|
||||
"position", result_domain, {0, 0, 0});
|
||||
GVArray_Typed<float3> ray_directions = params.get_input_attribute<float3>(
|
||||
VArray<float3> ray_directions = params.get_input_attribute<float3>(
|
||||
"Ray Direction", dst_component, result_domain, {0, 0, 0});
|
||||
GVArray_Typed<float> ray_lengths = params.get_input_attribute<float>(
|
||||
VArray<float> ray_lengths = params.get_input_attribute<float>(
|
||||
"Ray Length", dst_component, result_domain, 0);
|
||||
|
||||
OutputAttribute_Typed<bool> hit_attribute =
|
||||
@@ -218,10 +218,10 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms,
|
||||
Array<int> hit_indices;
|
||||
Array<float3> hit_positions_internal;
|
||||
if (!hit_attribute_names.is_empty()) {
|
||||
hit_indices.reinitialize(ray_origins->size());
|
||||
hit_indices.reinitialize(ray_origins.size());
|
||||
|
||||
if (!hit_position_attribute) {
|
||||
hit_positions_internal.reinitialize(ray_origins->size());
|
||||
hit_positions_internal.reinitialize(ray_origins.size());
|
||||
}
|
||||
}
|
||||
const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>();
|
||||
|
@@ -169,10 +169,10 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
|
||||
span_count++;
|
||||
const PointCloudComponent *component =
|
||||
geometry_set.get_component_for_read<PointCloudComponent>();
|
||||
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
|
||||
VArray<float3> varray = component->attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
total_size += varray->size();
|
||||
positions_span = varray->get_internal_span();
|
||||
total_size += varray.size();
|
||||
positions_span = varray.get_internal_span();
|
||||
}
|
||||
|
||||
if (geometry_set.has_curve()) {
|
||||
@@ -200,18 +200,18 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
|
||||
|
||||
if (geometry_set.has_mesh()) {
|
||||
const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>();
|
||||
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
|
||||
VArray<float3> varray = component->attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
offset += varray.size();
|
||||
}
|
||||
|
||||
if (geometry_set.has_pointcloud()) {
|
||||
const PointCloudComponent *component =
|
||||
geometry_set.get_component_for_read<PointCloudComponent>();
|
||||
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
|
||||
VArray<float3> varray = component->attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
offset += varray.size();
|
||||
}
|
||||
|
||||
@@ -235,16 +235,16 @@ static void read_positions(const GeometryComponent &component,
|
||||
Span<float4x4> transforms,
|
||||
Vector<float3> *r_coords)
|
||||
{
|
||||
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = component.attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
/* NOTE: could use convex hull operation here to
|
||||
* cut out some vertices, before accumulating,
|
||||
* but can also be done by the user beforehand. */
|
||||
|
||||
r_coords->reserve(r_coords->size() + positions.size() * transforms.size());
|
||||
r_coords->reserve(r_coords->size() + positions->size() * transforms.size());
|
||||
for (const float4x4 &transform : transforms) {
|
||||
for (const int i : positions.index_range()) {
|
||||
for (const int i : positions->index_range()) {
|
||||
const float3 position = positions[i];
|
||||
const float3 transformed_position = transform * position;
|
||||
r_coords->append(transformed_position);
|
||||
|
@@ -64,9 +64,9 @@ class EndpointFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -111,9 +111,9 @@ class EndpointFieldInput final : public fn::FieldInput {
|
||||
}
|
||||
current_point += spline->size();
|
||||
}
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
|
||||
return VArray<bool>::ForContainer(std::move(selection));
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
};
|
||||
|
||||
uint64_t hash() const override
|
||||
|
@@ -59,10 +59,10 @@ struct FilletParam {
|
||||
GeometryNodeCurveFilletMode mode;
|
||||
|
||||
/* Number of points to be added. */
|
||||
const VArray<int> *counts;
|
||||
VArray<int> counts;
|
||||
|
||||
/* Radii for fillet arc at all vertices. */
|
||||
const VArray<float> *radii;
|
||||
VArray<float> radii;
|
||||
|
||||
/* Whether or not fillets are allowed to overlap. */
|
||||
bool limit_radius;
|
||||
@@ -160,7 +160,7 @@ static Array<int> calculate_counts(const FilletParam &fillet_param,
|
||||
Array<int> counts(size, 1);
|
||||
if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) {
|
||||
for (const int i : IndexRange(size)) {
|
||||
counts[i] = (*fillet_param.counts)[spline_offset + i];
|
||||
counts[i] = fillet_param.counts[spline_offset + i];
|
||||
}
|
||||
}
|
||||
if (!cyclic) {
|
||||
@@ -178,12 +178,12 @@ static Array<float> calculate_radii(const FilletParam &fillet_param,
|
||||
Array<float> radii(size, 0.0f);
|
||||
if (fillet_param.limit_radius) {
|
||||
for (const int i : IndexRange(size)) {
|
||||
radii[i] = std::max((*fillet_param.radii)[spline_offset + i], 0.0f);
|
||||
radii[i] = std::max(fillet_param.radii[spline_offset + i], 0.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : IndexRange(size)) {
|
||||
radii[i] = (*fillet_param.radii)[spline_offset + i];
|
||||
radii[i] = fillet_param.radii[spline_offset + i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,13 +590,13 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
|
||||
|
||||
field_evaluator.evaluate();
|
||||
|
||||
fillet_param.radii = &field_evaluator.get_evaluated<float>(0);
|
||||
if (fillet_param.radii->is_single() && fillet_param.radii->get_internal_single() < 0.0f) {
|
||||
fillet_param.radii = field_evaluator.get_evaluated<float>(0);
|
||||
if (fillet_param.radii.is_single() && fillet_param.radii.get_internal_single() < 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GEO_NODE_CURVE_FILLET_POLY) {
|
||||
fillet_param.counts = &field_evaluator.get_evaluated<int>(1);
|
||||
fillet_param.counts = field_evaluator.get_evaluated<int>(1);
|
||||
}
|
||||
|
||||
fillet_param.limit_radius = limit_radius;
|
||||
|
@@ -96,9 +96,9 @@ class HandleTypeFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -106,22 +106,22 @@ class HandleTypeFieldInput final : public fn::FieldInput {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
|
||||
const CurveEval *curve = curve_component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<bool> selection(mask.min_array_size());
|
||||
select_by_handle_type(*curve, type_, mode_, selection);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
|
||||
return VArray<bool>::ForContainer(std::move(selection));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
};
|
||||
|
||||
uint64_t hash() const override
|
||||
|
@@ -130,22 +130,22 @@ static Array<float> curve_parameter_point_domain(const CurveEval &curve)
|
||||
return parameters;
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
static GVArray construct_curve_parameter_gvarray(const CurveEval &curve,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<float> parameters = curve_parameter_point_domain(curve);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(parameters));
|
||||
return VArray<float>::ForContainer(std::move(parameters));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float> parameters = curve_parameter_spline_domain(curve, mask);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(parameters));
|
||||
return VArray<float>::ForContainer(std::move(parameters));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
class CurveParameterFieldInput final : public fn::FieldInput {
|
||||
@@ -155,9 +155,9 @@ class CurveParameterFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -173,7 +173,7 @@ class CurveParameterFieldInput final : public fn::FieldInput {
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
@@ -26,10 +26,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_Span;
|
||||
using blender::fn::GVArray_Typed;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_resample_declare(NodeDeclarationBuilder &b)
|
||||
@@ -122,7 +118,7 @@ static SplinePtr resample_spline(const Spline &src, const int count)
|
||||
std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write(
|
||||
attribute_id);
|
||||
if (output_attribute) {
|
||||
src.sample_with_index_factors(*src.interpolate_to_evaluated(*input_attribute),
|
||||
src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute),
|
||||
uniform_samples,
|
||||
*output_attribute);
|
||||
return true;
|
||||
@@ -145,8 +141,8 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
|
||||
|
||||
dst->positions().copy_from(src.evaluated_positions());
|
||||
dst->positions().copy_from(src.evaluated_positions());
|
||||
src.interpolate_to_evaluated(src.radii())->materialize(dst->radii());
|
||||
src.interpolate_to_evaluated(src.tilts())->materialize(dst->tilts());
|
||||
src.interpolate_to_evaluated(src.radii()).materialize(dst->radii());
|
||||
src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts());
|
||||
|
||||
src.attributes.foreach_attribute(
|
||||
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
|
||||
@@ -154,7 +150,7 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
|
||||
if (dst->attributes.create(attribute_id, meta_data.data_type)) {
|
||||
std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id);
|
||||
if (dst_attribute) {
|
||||
src.interpolate_to_evaluated(*src_attribute)->materialize(dst_attribute->data());
|
||||
src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -25,10 +25,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_Span;
|
||||
using blender::fn::GVArray_Typed;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
|
||||
|
@@ -113,7 +113,7 @@ static GMutableSpan ensure_point_attribute(PointCloudComponent &points,
|
||||
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
|
||||
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
|
||||
BLI_assert(attribute);
|
||||
return attribute.varray->get_internal_span();
|
||||
return attribute.varray.get_internal_span();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -194,7 +194,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
|
||||
const int size = offsets[i + 1] - offsets[i];
|
||||
|
||||
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
|
||||
spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
|
||||
|
||||
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
|
||||
const AttributeIDRef attribute_id = item.key;
|
||||
@@ -203,7 +203,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.interpolate_to_evaluated(spline_span)->materialize(dst.slice(offset, size).data());
|
||||
spline.interpolate_to_evaluated(spline_span).materialize(dst.slice(offset, size).data());
|
||||
}
|
||||
|
||||
if (!data.tangents.is_empty()) {
|
||||
@@ -233,7 +233,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
|
||||
|
||||
spline.sample_with_index_factors<float3>(
|
||||
spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, size));
|
||||
spline.sample_with_index_factors<float>(*spline.interpolate_to_evaluated(spline.radii()),
|
||||
spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()),
|
||||
uniform_samples,
|
||||
data.radii.slice(offset, size));
|
||||
|
||||
@@ -244,7 +244,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
|
||||
spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
|
||||
uniform_samples,
|
||||
dst.slice(offset, size));
|
||||
}
|
||||
|
@@ -216,9 +216,9 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
|
||||
|
||||
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
linear_trim_to_output_data<T>(
|
||||
start, end, eval_data->get_internal_span(), dst->typed<T>());
|
||||
start, end, eval_data.get_internal_span(), dst->typed<T>());
|
||||
});
|
||||
return true;
|
||||
},
|
||||
@@ -227,13 +227,13 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
|
||||
linear_trim_to_output_data<float3>(
|
||||
start, end, spline.evaluated_positions(), new_spline.positions());
|
||||
|
||||
GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
linear_trim_to_output_data<float>(
|
||||
start, end, evaluated_radii->get_internal_span(), new_spline.radii());
|
||||
start, end, evaluated_radii.get_internal_span(), new_spline.radii());
|
||||
|
||||
GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
linear_trim_to_output_data<float>(
|
||||
start, end, evaluated_tilts->get_internal_span(), new_spline.tilts());
|
||||
start, end, evaluated_tilts.get_internal_span(), new_spline.tilts());
|
||||
|
||||
return new_spline;
|
||||
}
|
||||
@@ -427,8 +427,8 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
|
||||
std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(attribute_id);
|
||||
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
to_single_point_data<T>(trim, eval_data->get_internal_span(), dst->typed<T>());
|
||||
VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
to_single_point_data<T>(trim, eval_data.get_internal_span(), dst->typed<T>());
|
||||
});
|
||||
return true;
|
||||
},
|
||||
@@ -436,11 +436,11 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
|
||||
|
||||
to_single_point_data<float3>(trim, spline.evaluated_positions(), new_spline.positions());
|
||||
|
||||
GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
to_single_point_data<float>(trim, evaluated_radii->get_internal_span(), new_spline.radii());
|
||||
VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
to_single_point_data<float>(trim, evaluated_radii.get_internal_span(), new_spline.radii());
|
||||
|
||||
GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
to_single_point_data<float>(trim, evaluated_tilts->get_internal_span(), new_spline.tilts());
|
||||
VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
to_single_point_data<float>(trim, evaluated_tilts.get_internal_span(), new_spline.tilts());
|
||||
|
||||
return new_spline;
|
||||
}
|
||||
|
@@ -138,7 +138,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
|
||||
if (!domains.contains(attribute.domain)) {
|
||||
continue;
|
||||
}
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
|
||||
|
||||
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
|
||||
attribute_id, attribute.domain, data_type);
|
||||
@@ -149,7 +149,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Span<T> span{*attribute.varray};
|
||||
VArray_Span<T> span{attribute.varray.typed<T>()};
|
||||
MutableSpan<T> out_span = result_attribute.as_span<T>();
|
||||
out_span.copy_from(span);
|
||||
});
|
||||
@@ -178,7 +178,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
|
||||
if (domain != attribute.domain) {
|
||||
continue;
|
||||
}
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
|
||||
|
||||
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
|
||||
attribute_id, attribute.domain, data_type);
|
||||
@@ -189,7 +189,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Span<T> span{*attribute.varray};
|
||||
VArray_Span<T> span{attribute.varray.typed<T>()};
|
||||
MutableSpan<T> out_span = result_attribute.as_span<T>();
|
||||
copy_data(span, out_span, mask);
|
||||
});
|
||||
|
@@ -311,14 +311,14 @@ BLI_NOINLINE static void propagate_existing_attributes(
|
||||
}
|
||||
|
||||
const AttributeDomain source_domain = attribute_info->domain;
|
||||
GVArrayPtr source_attribute = mesh_component.attribute_get_for_read(
|
||||
GVArray source_attribute = mesh_component.attribute_get_for_read(
|
||||
attribute_id, source_domain, output_data_type, nullptr);
|
||||
if (!source_attribute) {
|
||||
continue;
|
||||
}
|
||||
|
||||
interpolate_attribute(
|
||||
mesh, bary_coords, looptri_indices, source_domain, *source_attribute, out_span);
|
||||
mesh, bary_coords, looptri_indices, source_domain, source_attribute, out_span);
|
||||
|
||||
attribute_out.save();
|
||||
}
|
||||
|
@@ -31,19 +31,18 @@ static void geo_node_input_normal_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Vector>(N_("Normal")).field_source();
|
||||
}
|
||||
|
||||
static GVArrayPtr mesh_face_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
static VArray<float3> mesh_face_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
{
|
||||
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
|
||||
if (!(mesh.runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh.pdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<fn::GVArray_For_Span<float3>>(
|
||||
Span<float3>((const float3 *)data, polys.size()));
|
||||
return VArray<float3>::ForSpan({(const float3 *)data, polys.size()});
|
||||
}
|
||||
|
||||
auto normal_fn = [verts, polys, loops](const int i) -> float3 {
|
||||
@@ -53,24 +52,21 @@ static GVArrayPtr mesh_face_normals(const Mesh &mesh,
|
||||
return normal;
|
||||
};
|
||||
|
||||
return std::make_unique<
|
||||
fn::GVArray_For_EmbeddedVArray<float3, VArray_For_Func<float3, decltype(normal_fn)>>>(
|
||||
mask.min_array_size(), mask.min_array_size(), normal_fn);
|
||||
return VArray<float3>::ForFunc(mask.min_array_size(), normal_fn);
|
||||
}
|
||||
|
||||
static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
static VArray<float3> mesh_vertex_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
{
|
||||
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
|
||||
if (!(mesh.runtime.cd_dirty_vert & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh.vdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<fn::GVArray_For_Span<float3>>(
|
||||
Span<float3>((const float3 *)data, mesh.totvert));
|
||||
return VArray<float3>::ForSpan({(const float3 *)data, mesh.totvert});
|
||||
}
|
||||
|
||||
/* If the normals are dirty, they must be recalculated for the output of this node's field
|
||||
@@ -91,14 +87,14 @@ static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
|
||||
nullptr,
|
||||
(float(*)[3])normals.data());
|
||||
|
||||
return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
|
||||
static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
|
||||
const Mesh &mesh,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
Span<MVert> verts{mesh.mvert, mesh.totvert};
|
||||
Span<MEdge> edges{mesh.medge, mesh.totedge};
|
||||
@@ -107,18 +103,18 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
return scope.add_value(mesh_face_normals(mesh, verts, polys, loops, mask)).get();
|
||||
return mesh_face_normals(mesh, verts, polys, loops, mask);
|
||||
}
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
return scope.add_value(mesh_vertex_normals(mesh, verts, polys, loops, mask)).get();
|
||||
return mesh_vertex_normals(mesh, verts, polys, loops, mask);
|
||||
}
|
||||
case ATTR_DOMAIN_EDGE: {
|
||||
/* In this case, start with vertex normals and convert to the edge domain, since the
|
||||
* conversion from edges to vertices is very simple. Use the full mask since the edges
|
||||
* might use the vertex normal from any index. */
|
||||
GVArrayPtr vert_normals = mesh_vertex_normals(
|
||||
GVArray vert_normals = mesh_vertex_normals(
|
||||
mesh, verts, polys, loops, IndexRange(verts.size()));
|
||||
Span<float3> vert_normals_span = vert_normals->get_internal_span().typed<float3>();
|
||||
Span<float3> vert_normals_span = vert_normals.get_internal_span().typed<float3>();
|
||||
Array<float3> edge_normals(mask.min_array_size());
|
||||
|
||||
/* Use "manual" domain interpolation instead of the GeometryComponent API to avoid
|
||||
@@ -130,23 +126,21 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
|
||||
.normalized();
|
||||
}
|
||||
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(
|
||||
std::move(edge_normals));
|
||||
return VArray<float3>::ForContainer(std::move(edge_normals));
|
||||
}
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
/* The normals on corners are just the mesh's face normals, so start with the face normal
|
||||
* array and copy the face normal for each of its corners. */
|
||||
GVArrayPtr face_normals = mesh_face_normals(
|
||||
VArray<float3> face_normals = mesh_face_normals(
|
||||
mesh, verts, polys, loops, IndexRange(polys.size()));
|
||||
|
||||
/* In this case using the mesh component's generic domain interpolation is fine, the data
|
||||
* will still be normalized, since the face normal is just copied to every corner. */
|
||||
GVArrayPtr loop_normals = mesh_component.attribute_try_adapt_domain(
|
||||
return mesh_component.attribute_try_adapt_domain<float3>(
|
||||
std::move(face_normals), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
|
||||
return scope.add_value(std::move(loop_normals)).get();
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,9 +198,9 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve)
|
||||
return normals;
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_normal_gvarray(const CurveComponent &component,
|
||||
static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
const CurveEval *curve = component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
@@ -220,20 +214,18 @@ static const GVArray *construct_curve_normal_gvarray(const CurveComponent &compo
|
||||
* This is only possible when there is only one poly spline. */
|
||||
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
|
||||
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
|
||||
return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_normals());
|
||||
return VArray<float3>::ForSpan(spline.evaluated_normals());
|
||||
}
|
||||
|
||||
Array<float3> normals = curve_normal_point_domain(*curve);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float3> point_normals = curve_normal_point_domain(*curve);
|
||||
GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
|
||||
std::move(point_normals));
|
||||
GVArrayPtr spline_normals = component.attribute_try_adapt_domain(
|
||||
std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
|
||||
return scope.add_value(std::move(spline_normals)).get();
|
||||
VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
|
||||
return component.attribute_try_adapt_domain<float3>(
|
||||
std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -246,9 +238,9 @@ class NormalFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -260,7 +252,7 @@ class NormalFieldInput final : public fn::FieldInput {
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
if (mesh == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain, scope);
|
||||
@@ -270,7 +262,7 @@ class NormalFieldInput final : public fn::FieldInput {
|
||||
return construct_curve_normal_gvarray(curve_component, domain, scope);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
@@ -25,31 +25,25 @@ static void geo_node_input_spline_length_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Float>(N_("Length")).field_source();
|
||||
}
|
||||
|
||||
static const GVArray *construct_spline_length_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
static VArray<float> construct_spline_length_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
const CurveEval *curve = component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
Span<SplinePtr> splines = curve->splines();
|
||||
auto length_fn = [splines](int i) { return splines[i]->length(); };
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
return &scope.construct<
|
||||
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
|
||||
splines.size(), splines.size(), length_fn);
|
||||
return VArray<float>::ForFunc(splines.size(), length_fn);
|
||||
}
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
GVArrayPtr length = std::make_unique<
|
||||
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
|
||||
splines.size(), splines.size(), length_fn);
|
||||
return scope
|
||||
.add_value(component.attribute_try_adapt_domain(
|
||||
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT))
|
||||
.get();
|
||||
VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn);
|
||||
return component.attribute_try_adapt_domain<float>(
|
||||
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -62,9 +56,9 @@ class SplineLengthFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -76,7 +70,7 @@ class SplineLengthFieldInput final : public fn::FieldInput {
|
||||
return construct_spline_length_gvarray(curve_component, domain, scope);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
@@ -84,9 +84,9 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
|
||||
return tangents;
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &component,
|
||||
static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
const CurveEval *curve = component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
@@ -100,20 +100,19 @@ static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &comp
|
||||
* This is only possible when there is only one poly spline. */
|
||||
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
|
||||
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
|
||||
return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_tangents());
|
||||
return VArray<float3>::ForSpan(spline.evaluated_tangents());
|
||||
}
|
||||
|
||||
Array<float3> tangents = curve_tangent_point_domain(*curve);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(tangents));
|
||||
return VArray<float3>::ForContainer(std::move(tangents));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float3> point_tangents = curve_tangent_point_domain(*curve);
|
||||
GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
|
||||
std::move(point_tangents));
|
||||
GVArrayPtr spline_tangents = component.attribute_try_adapt_domain(
|
||||
std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
|
||||
return scope.add_value(std::move(spline_tangents)).get();
|
||||
return component.attribute_try_adapt_domain<float3>(
|
||||
VArray<float3>::ForContainer(std::move(point_tangents)),
|
||||
ATTR_DOMAIN_POINT,
|
||||
ATTR_DOMAIN_CURVE);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -126,9 +125,9 @@ class TangentFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -141,7 +140,7 @@ class TangentFieldInput final : public fn::FieldInput {
|
||||
return construct_curve_tangent_gvarray(curve_component, domain, scope);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
@@ -80,10 +80,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
select_len);
|
||||
|
||||
FieldEvaluator field_evaluator{field_context, domain_size};
|
||||
const VArray<bool> *pick_instance = nullptr;
|
||||
const VArray<int> *indices = nullptr;
|
||||
const VArray<float3> *rotations = nullptr;
|
||||
const VArray<float3> *scales = nullptr;
|
||||
VArray<bool> pick_instance;
|
||||
VArray<int> indices;
|
||||
VArray<float3> rotations;
|
||||
VArray<float3> scales;
|
||||
/* The evaluator could use the component's stable IDs as a destination directly, but only the
|
||||
* selected indices should be copied. */
|
||||
field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
|
||||
@@ -92,7 +92,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
GVArray_Typed<float3> positions = src_component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = src_component.attribute_get_for_read<float3>(
|
||||
"position", domain, {0, 0, 0});
|
||||
|
||||
const InstancesComponent *src_instances = instance.get_component_for_read<InstancesComponent>();
|
||||
@@ -101,7 +101,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
Array<int> handle_mapping;
|
||||
/* Only fill #handle_mapping when it may be used below. */
|
||||
if (src_instances != nullptr &&
|
||||
(!pick_instance->is_single() || pick_instance->get_internal_single())) {
|
||||
(!pick_instance.is_single() || pick_instance.get_internal_single())) {
|
||||
Span<InstanceReference> src_references = src_instances->references();
|
||||
handle_mapping.reinitialize(src_references.size());
|
||||
for (const int src_instance_handle : src_references.index_range()) {
|
||||
@@ -121,17 +121,16 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
|
||||
/* Compute base transform for every instances. */
|
||||
float4x4 &dst_transform = dst_transforms[range_i];
|
||||
dst_transform = float4x4::from_loc_eul_scale(
|
||||
positions[i], rotations->get(i), scales->get(i));
|
||||
dst_transform = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
|
||||
|
||||
/* Reference that will be used by this new instance. */
|
||||
int dst_handle = empty_reference_handle;
|
||||
|
||||
const bool use_individual_instance = pick_instance->get(i);
|
||||
const bool use_individual_instance = pick_instance[i];
|
||||
if (use_individual_instance) {
|
||||
if (src_instances != nullptr) {
|
||||
const int src_instances_amount = src_instances->instances_amount();
|
||||
const int original_index = indices->get(i);
|
||||
const int original_index = indices[i];
|
||||
/* Use #mod_i instead of `%` to get the desirable wrap around behavior where -1
|
||||
* refers to the last element. */
|
||||
const int index = mod_i(original_index, std::max(src_instances_amount, 1));
|
||||
@@ -155,10 +154,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
}
|
||||
});
|
||||
|
||||
GVArrayPtr id_attribute = src_component.attribute_try_get_for_read(
|
||||
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
|
||||
if (id_attribute) {
|
||||
GVArray_Typed<int> ids{*id_attribute};
|
||||
VArray<int> ids = src_component
|
||||
.attribute_try_get_for_read("id", ATTR_DOMAIN_POINT, CD_PROP_INT32)
|
||||
.typed<int>();
|
||||
if (ids) {
|
||||
VArray_Span<int> ids_span{ids};
|
||||
MutableSpan<int> dst_ids = dst_component.instance_ids_ensure();
|
||||
for (const int64_t i : selection.index_range()) {
|
||||
@@ -166,8 +165,8 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
}
|
||||
}
|
||||
|
||||
if (pick_instance->is_single()) {
|
||||
if (pick_instance->get_internal_single()) {
|
||||
if (pick_instance.is_single()) {
|
||||
if (pick_instance.get_internal_single()) {
|
||||
if (instance.has_realized_data()) {
|
||||
params.error_message_add(
|
||||
NodeWarningType::Info,
|
||||
|
@@ -27,8 +27,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
|
||||
@@ -190,10 +188,10 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components,
|
||||
if (domain_size == 0) {
|
||||
continue;
|
||||
}
|
||||
GVArrayPtr read_attribute = component->attribute_get_for_read(
|
||||
GVArray read_attribute = component->attribute_get_for_read(
|
||||
attribute_id, domain, data_type, nullptr);
|
||||
|
||||
GVArray_GSpan src_span{*read_attribute};
|
||||
GVArray_GSpan src_span{read_attribute};
|
||||
const void *src_buffer = src_span.data();
|
||||
void *dst_buffer = dst_span[offset];
|
||||
cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size);
|
||||
@@ -319,8 +317,7 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
|
||||
spline->size() * type.size(), type.alignment(), __func__);
|
||||
|
||||
const DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions();
|
||||
conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), type)
|
||||
->materialize(converted_buffer);
|
||||
conversions.try_convert(GVArray::ForSpan(*attribute), type).materialize(converted_buffer);
|
||||
|
||||
spline->attributes.remove(attribute_id);
|
||||
spline->attributes.create_by_move(attribute_id, data_type, converted_buffer);
|
||||
@@ -333,14 +330,14 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
|
||||
/* In this case the attribute did not exist, but there is a spline domain attribute
|
||||
* we can retrieve a value from, as a spline to point domain conversion. So fill the
|
||||
* new attribute with the value for this spline. */
|
||||
GVArrayPtr current_curve_attribute = current_curve->attributes.get_for_read(
|
||||
GVArray current_curve_attribute = current_curve->attributes.get_for_read(
|
||||
attribute_id, data_type, nullptr);
|
||||
|
||||
BLI_assert(spline->attributes.get_for_read(attribute_id));
|
||||
std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(attribute_id);
|
||||
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
current_curve_attribute->get(spline_index_in_component, buffer);
|
||||
current_curve_attribute.get(spline_index_in_component, buffer);
|
||||
type.fill_assign_n(buffer, new_attribute->data(), new_attribute->size());
|
||||
}
|
||||
}
|
||||
@@ -376,8 +373,8 @@ static void ensure_spline_attribute(const AttributeIDRef &attribute_id,
|
||||
if (size == 0) {
|
||||
continue;
|
||||
}
|
||||
GVArrayPtr read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
|
||||
GVArray_GSpan src_span{*read_attribute};
|
||||
GVArray read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
|
||||
GVArray_GSpan src_span{read_attribute};
|
||||
|
||||
const void *src_buffer = src_span.data();
|
||||
type.copy_assign_n(src_buffer, result_attribute[offset], size);
|
||||
|
@@ -64,36 +64,33 @@ class MaterialSelectionFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
if (component.type() != GEO_COMPONENT_TYPE_MESH) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
if (mesh == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_FACE) {
|
||||
Array<bool> selection(mask.min_array_size());
|
||||
select_mesh_by_material(*mesh, material_, mask, selection);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
|
||||
return VArray<bool>::ForContainer(std::move(selection));
|
||||
}
|
||||
|
||||
Array<bool> selection(mesh->totpoly);
|
||||
select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection);
|
||||
GVArrayPtr face_selection = std::make_unique<fn::GVArray_For_ArrayContainer<Array<bool>>>(
|
||||
std::move(selection));
|
||||
GVArrayPtr final_selection = mesh_component.attribute_try_adapt_domain(
|
||||
std::move(face_selection), ATTR_DOMAIN_FACE, domain);
|
||||
return scope.add_value(std::move(final_selection)).get();
|
||||
return mesh_component.attribute_try_adapt_domain<bool>(
|
||||
VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@@ -113,14 +113,14 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
|
||||
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
|
||||
const AttributeIDRef attribute_id = entry.key;
|
||||
const CustomDataType data_type = entry.value.data_type;
|
||||
GVArrayPtr src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
|
||||
GVArray src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
|
||||
OutputAttribute dst = point_component.attribute_try_get_for_output_only(
|
||||
attribute_id, ATTR_DOMAIN_POINT, data_type);
|
||||
if (dst && src) {
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> src_typed{*src};
|
||||
copy_attribute_to_points(*src_typed, selection, dst.as_span().typed<T>());
|
||||
VArray<T> src_typed = src.typed<T>();
|
||||
copy_attribute_to_points(src_typed, selection, dst.as_span().typed<T>());
|
||||
});
|
||||
dst.save();
|
||||
}
|
||||
|
@@ -74,15 +74,15 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set,
|
||||
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
|
||||
const AttributeIDRef attribute_id = entry.key;
|
||||
const CustomDataType data_type = entry.value.data_type;
|
||||
GVArrayPtr src = point_component->attribute_get_for_read(
|
||||
GVArray src = point_component->attribute_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_POINT, data_type);
|
||||
OutputAttribute dst = mesh_component.attribute_try_get_for_output_only(
|
||||
attribute_id, ATTR_DOMAIN_POINT, data_type);
|
||||
if (dst && src) {
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> src_typed{*src};
|
||||
VArray_Span<T> src_typed_span{*src_typed};
|
||||
VArray<T> src_typed = src.typed<T>();
|
||||
VArray_Span<T> src_typed_span{src_typed};
|
||||
copy_attribute_to_vertices(src_typed_span, selection, dst.as_span().typed<T>());
|
||||
});
|
||||
dst.save();
|
||||
|
@@ -165,7 +165,7 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms,
|
||||
Vector<float3> &r_positions,
|
||||
Vector<float> &r_radii)
|
||||
{
|
||||
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = component.attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
Field<float> radius_field = params.get_input<Field<float>>("Radius");
|
||||
@@ -173,7 +173,7 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms,
|
||||
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
|
||||
|
||||
r_positions.resize(r_positions.size() + domain_size);
|
||||
positions->materialize(r_positions.as_mutable_span().take_back(domain_size));
|
||||
positions.materialize(r_positions.as_mutable_span().take_back(domain_size));
|
||||
|
||||
r_radii.resize(r_radii.size() + domain_size);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
|
@@ -540,10 +540,10 @@ class NearestTransferFunction : public fn::MultiFunction {
|
||||
attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if (use_mesh_ && use_points_) {
|
||||
GVArray_Typed<T> src_mesh{*mesh_data_};
|
||||
GVArray_Typed<T> src_point{*point_data_};
|
||||
copy_with_indices_and_comparison(*src_mesh,
|
||||
*src_point,
|
||||
VArray<T> src_mesh = mesh_data_->typed<T>();
|
||||
VArray<T> src_point = point_data_->typed<T>();
|
||||
copy_with_indices_and_comparison(src_mesh,
|
||||
src_point,
|
||||
mesh_distances,
|
||||
point_distances,
|
||||
mask,
|
||||
@@ -552,12 +552,12 @@ class NearestTransferFunction : public fn::MultiFunction {
|
||||
dst.typed<T>());
|
||||
}
|
||||
else if (use_points_) {
|
||||
GVArray_Typed<T> src_point{*point_data_};
|
||||
copy_with_indices(*src_point, mask, point_indices, dst.typed<T>());
|
||||
VArray<T> src_point = point_data_->typed<T>();
|
||||
copy_with_indices(src_point, mask, point_indices, dst.typed<T>());
|
||||
}
|
||||
else if (use_mesh_) {
|
||||
GVArray_Typed<T> src_mesh{*mesh_data_};
|
||||
copy_with_indices(*src_mesh, mask, mesh_indices, dst.typed<T>());
|
||||
VArray<T> src_mesh = mesh_data_->typed<T>();
|
||||
copy_with_indices(src_mesh, mask, mesh_indices, dst.typed<T>());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -640,14 +640,14 @@ class IndexTransferFieldInput : public FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const FieldContext &context,
|
||||
const IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const FieldContext &context,
|
||||
const IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context);
|
||||
if (geometry_context == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
FieldEvaluator index_evaluator{*geometry_context, &mask};
|
||||
@@ -661,7 +661,7 @@ class IndexTransferFieldInput : public FieldInput {
|
||||
const GeometryComponent *component = find_best_match_component(
|
||||
src_geometry_, geometry_context->geometry_component().type(), domain_);
|
||||
if (component == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
GeometryComponentFieldContext target_context{*component, domain_};
|
||||
@@ -676,11 +676,11 @@ class IndexTransferFieldInput : public FieldInput {
|
||||
|
||||
attribute_math::convert_to_static_type(src_data.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> src{src_data};
|
||||
copy_with_indices_clamped(*src, mask, indices, dst.as_mutable_span().typed<T>());
|
||||
copy_with_indices_clamped(
|
||||
src_data.typed<T>(), mask, indices, dst.as_mutable_span().typed<T>());
|
||||
});
|
||||
|
||||
return &scope.construct<fn::GVArray_For_GArray>(std::move(dst));
|
||||
return GVArray::ForGArray(std::move(dst));
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -113,11 +113,11 @@ const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const
|
||||
GVArray GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const
|
||||
{
|
||||
const bNodeSocket *found_socket = this->find_available_socket(name);
|
||||
BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */
|
||||
@@ -129,13 +129,13 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
}
|
||||
|
||||
if (found_socket == nullptr) {
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
|
||||
}
|
||||
|
||||
if (found_socket->type == SOCK_STRING) {
|
||||
const std::string name = this->get_input<std::string>(found_socket->identifier);
|
||||
/* Try getting the attribute without the default value. */
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, type);
|
||||
GVArray attribute = component.attribute_try_get_for_read(name, domain, type);
|
||||
if (attribute) {
|
||||
return attribute;
|
||||
}
|
||||
@@ -147,36 +147,36 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
this->error_message_add(NodeWarningType::Error,
|
||||
TIP_("No attribute with name \"") + name + "\"");
|
||||
}
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
|
||||
}
|
||||
const DataTypeConversions &conversions = get_implicit_type_conversions();
|
||||
if (found_socket->type == SOCK_FLOAT) {
|
||||
const float value = this->get_input<float>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(CPPType::get<float>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
if (found_socket->type == SOCK_INT) {
|
||||
const int value = this->get_input<int>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(CPPType::get<int>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
if (found_socket->type == SOCK_VECTOR) {
|
||||
const float3 value = this->get_input<float3>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(CPPType::get<float3>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
if (found_socket->type == SOCK_RGBA) {
|
||||
const ColorGeometry4f value = this->get_input<ColorGeometry4f>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(
|
||||
CPPType::get<ColorGeometry4f>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
BLI_assert(false);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
|
||||
}
|
||||
|
||||
CustomDataType GeoNodeExecParams::get_input_attribute_data_type(
|
||||
|
@@ -24,9 +24,6 @@
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArray;
|
||||
using fn::GVMutableArrayPtr;
|
||||
using fn::MFDataType;
|
||||
|
||||
template<typename From, typename To, To (*ConversionF)(const From &)>
|
||||
@@ -242,107 +239,108 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
|
||||
functions->convert_single_to_uninitialized(from_value, to_value);
|
||||
}
|
||||
|
||||
class GVArray_For_ConvertedGVArray : public GVArray {
|
||||
class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl {
|
||||
private:
|
||||
GVArrayPtr varray_;
|
||||
fn::GVArray varray_;
|
||||
const CPPType &from_type_;
|
||||
ConversionFunctions old_to_new_conversions_;
|
||||
|
||||
public:
|
||||
GVArray_For_ConvertedGVArray(GVArrayPtr varray,
|
||||
GVArray_For_ConvertedGVArray(fn::GVArray varray,
|
||||
const CPPType &to_type,
|
||||
const DataTypeConversions &conversions)
|
||||
: GVArray(to_type, varray->size()), varray_(std::move(varray)), from_type_(varray_->type())
|
||||
: fn::GVArrayImpl(to_type, varray.size()),
|
||||
varray_(std::move(varray)),
|
||||
from_type_(varray_.type())
|
||||
{
|
||||
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(const int64_t index, void *r_value) const override
|
||||
void get(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
|
||||
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
|
||||
void get_to_uninitialized(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArray {
|
||||
class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl {
|
||||
private:
|
||||
GVMutableArrayPtr varray_;
|
||||
fn::GVMutableArray varray_;
|
||||
const CPPType &from_type_;
|
||||
ConversionFunctions old_to_new_conversions_;
|
||||
ConversionFunctions new_to_old_conversions_;
|
||||
|
||||
public:
|
||||
GVMutableArray_For_ConvertedGVMutableArray(GVMutableArrayPtr varray,
|
||||
GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray,
|
||||
const CPPType &to_type,
|
||||
const DataTypeConversions &conversions)
|
||||
: GVMutableArray(to_type, varray->size()),
|
||||
: fn::GVMutableArrayImpl(to_type, varray.size()),
|
||||
varray_(std::move(varray)),
|
||||
from_type_(varray_->type())
|
||||
from_type_(varray_.type())
|
||||
{
|
||||
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
|
||||
new_to_old_conversions_ = *conversions.get_conversion_functions(to_type, from_type_);
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(const int64_t index, void *r_value) const override
|
||||
void get(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
|
||||
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
|
||||
void get_to_uninitialized(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
|
||||
void set_by_move_impl(const int64_t index, void *value) override
|
||||
void set_by_move(const int64_t index, void *value) override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
new_to_old_conversions_.convert_single_to_uninitialized(value, buffer);
|
||||
varray_->set_by_relocate(index, buffer);
|
||||
varray_.set_by_relocate(index, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
fn::GVArrayPtr DataTypeConversions::try_convert(fn::GVArrayPtr varray,
|
||||
const CPPType &to_type) const
|
||||
fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const
|
||||
{
|
||||
const CPPType &from_type = varray->type();
|
||||
const CPPType &from_type = varray.type();
|
||||
if (from_type == to_type) {
|
||||
return varray;
|
||||
}
|
||||
if (!this->is_convertible(from_type, to_type)) {
|
||||
return {};
|
||||
}
|
||||
return std::make_unique<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
|
||||
return fn::GVArray::For<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
|
||||
}
|
||||
|
||||
fn::GVMutableArrayPtr DataTypeConversions::try_convert(fn::GVMutableArrayPtr varray,
|
||||
const CPPType &to_type) const
|
||||
fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray,
|
||||
const CPPType &to_type) const
|
||||
{
|
||||
const CPPType &from_type = varray->type();
|
||||
const CPPType &from_type = varray.type();
|
||||
if (from_type == to_type) {
|
||||
return varray;
|
||||
}
|
||||
if (!this->is_convertible(from_type, to_type)) {
|
||||
return {};
|
||||
}
|
||||
return std::make_unique<GVMutableArray_For_ConvertedGVMutableArray>(
|
||||
return fn::GVMutableArray::For<GVMutableArray_For_ConvertedGVMutableArray>(
|
||||
std::move(varray), to_type, *this);
|
||||
}
|
||||
|
||||
|
@@ -199,28 +199,28 @@ class MusgraveFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_detail = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_detail = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Detail");
|
||||
};
|
||||
auto get_dimension = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_dimension = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Dimension");
|
||||
};
|
||||
auto get_lacunarity = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_lacunarity = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Lacunarity");
|
||||
};
|
||||
auto get_offset = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_offset = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Offset");
|
||||
};
|
||||
auto get_gain = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_gain = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Gain");
|
||||
};
|
||||
|
||||
|
@@ -220,22 +220,22 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_smoothness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_smoothness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Smoothness");
|
||||
};
|
||||
auto get_exponent = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_exponent = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Exponent");
|
||||
};
|
||||
auto get_randomness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_randomness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Randomness");
|
||||
};
|
||||
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
|
||||
@@ -651,19 +651,19 @@ class VoronoiMetricFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_smoothness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_smoothness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Smoothness");
|
||||
};
|
||||
auto get_randomness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_randomness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Randomness");
|
||||
};
|
||||
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
|
||||
@@ -1153,16 +1153,16 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_randomness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_randomness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Randomness");
|
||||
};
|
||||
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
|
||||
|
Reference in New Issue
Block a user