20#include <fmt/format.h>
52 if (drawing->strokes().attributes().domain_supported(this->domain())) {
54 return curves_field_input->get_varray_for_context(context,
mask, scope);
64 : geometry_(other.geometry_),
67 curves_id_(other.curves_id_),
68 grease_pencil_layer_index_(other.grease_pencil_layer_index_)
93 switch (component.
type()) {
94 case GeometryComponent::Type::Mesh: {
95 const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
96 geometry_ = mesh_component.get();
100 const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
101 const Curves *curves = curve_component.get();
102 geometry_ = curves ? &curves->geometry.wrap() : nullptr;
103 curves_id_ = curve_component.get();
107 const PointCloudComponent &pointcloud_component = static_cast<const PointCloudComponent &>(
109 geometry_ = pointcloud_component.get();
113 const GreasePencilComponent &grease_pencil_component =
114 static_cast<const GreasePencilComponent &>(component);
115 geometry_ = grease_pencil_component.get();
117 BLI_assert(domain == AttrDomain::Layer);
121 const InstancesComponent &instances_component = static_cast<const InstancesComponent &>(
123 geometry_ = instances_component.get();
160 const int layer_index)
164 grease_pencil_layer_index_(layer_index)
177 return mesh->attributes();
180 return curves->attributes();
192 return drawing->strokes().attributes();
232 this->
grease_pencil()->layer(this->grease_pencil_layer_index_));
240 return &drawing->strokes();
251 static_cast<const Instances *
>(geometry_) :
269 if (
const Curves *curves_id = curve_context->curves_id()) {
288 grease_pencil_context->domain(),
289 grease_pencil_context->layer_index()},
313 if (
const Mesh *
mesh = geometry_context->mesh()) {
360 if (
const PointCloud *pointcloud = geometry_context->pointcloud()) {
379 if (
const Instances *instances = geometry_context->instances()) {
396 if (
const GreasePencil *grease_pencil = context.grease_pencil()) {
399 return *layer_attributes.
lookup(name_, data_type);
402 const int layer_index = context.grease_pencil_layer_index();
412 reader.varray.get_to_uninitialized(layer_index, value);
413 const int domain_size = curves_attributes.
domain_size(domain);
422 else if (
auto attributes = context.attributes()) {
423 return *attributes->lookup(name_, domain, data_type);
434 const AttributeAccessor layer_attributes = context.grease_pencil()->attributes();
436 const bool exists = layer_attributes.
contains(name_);
442 const bool exists = layer_attributes.
contains(name_) || curve_attributes.
contains(name_);
443 const int domain_size = curve_attributes.
domain_size(domain);
446 const bool exists = context.attributes()->contains(name_);
447 const int domain_size = context.attributes()->domain_size(domain);
453 if (socket_inspection_name_) {
454 return *socket_inspection_name_;
456 return fmt::format(fmt::runtime(
TIP_(
"\"{}\" attribute from geometry")), name_);
467 return name_ == other_typed->name_ &&
type_ == other_typed->type_;
475 const std::optional<AttributeAccessor> attributes = component.
attributes();
476 if (!attributes.has_value()) {
479 const std::optional<AttributeMetaData> meta_data = attributes->lookup_meta_data(name_);
480 if (!meta_data.has_value()) {
483 return meta_data->domain;
502 if (
auto attributes = context.attributes()) {
503 if (
GVArray attribute = *attributes->lookup<
int>(
name, context.domain())) {
514 return TIP_(
"ID / Index");
538 const GreasePencil &grease_pencil = *context.grease_pencil();
539 if (!context.grease_pencil()) {
543 auto layer_is_selected = [selection_name =
StringRef(layer_name_),
545 size =
mask.min_array_size()](
const int layer_i) {
546 if (layer_i < 0 || layer_i >= grease_pencil.layers().size()) {
549 const Layer &layer = grease_pencil.layer(layer_i);
550 return layer.name() == selection_name;
554 const int layer_i = context.grease_pencil_layer_index();
555 const bool selected = layer_is_selected(layer_i);
572 return layer_name_ == other_named_layer->layer_name_;
609 using T = decltype(dummy);
610 copy_with_checked_indices(src.typed<T>(), indices, mask, dst.typed<T>());
618 index_field_(std::move(index_field)),
619 value_field_(std::move(value_field)),
620 value_field_domain_(value_field_domain)
627 const std::optional<AttributeAccessor> attributes = context.attributes();
633 fn::FieldEvaluator value_evaluator{value_context, attributes->domain_size(value_field_domain_)};
634 value_evaluator.
add(value_field_);
639 index_evaluator.
add(index_field_);
650 src_field_(std::move(field)),
658 const AttrDomain dst_domain = context.domain();
659 const int dst_domain_size = context.attributes()->domain_size(dst_domain);
668 const int layer_index = context.grease_pencil_layer_index();
672 value_evaluator.
add(src_field_);
700 src_field_.node().for_each_field_input_recursive(
fn);
720 if (
const Mesh *
mesh = context.mesh()) {
722 *
mesh,
mask, context.domain(), legacy_corner_normals_, true_normals_);
732 return true_normals_ ?
TIP_(
"True Normal") :
TIP_(
"Normal");
743 return legacy_corner_normals_ == other_typed->legacy_corner_normals_ &&
744 true_normals_ == other_typed->true_normals_;
752 return field->attribute_name();
777 const std::optional<AttributeMetaData> meta_data = attributes.
lookup_meta_data(*field_id);
792 return attributes.
add(id_to_create, domain, data_type,
init);
805 return varray_info.
data == attribute_info.
data;
810 const int domain_size,
827 old_attribute.varray.materialize(buffer);
841 const int domain_size = attributes.
domain_size(domain);
842 if (domain_size == 0) {
843 bool all_added =
true;
872 for (
const int input_index : attribute_ids.
index_range()) {
873 const StringRef id = attribute_ids[input_index];
874 const CPPType &type = fields[input_index].cpp_type();
878 if (
const std::optional<AttributeDomainAndType> meta_data =
892 if (dst.domain == domain && dst.varray.type() == field.
cpp_type()) {
893 const int evaluator_index = evaluator.
add(field);
894 results_to_store.
append({input_index, evaluator_index});
899 if (!validator && selection_is_full) {
908 if (!selection_is_full) {
914 results_to_add.
append({input_index, evaluator_index, buffer});
920 for (
const StoreResult &
result : results_to_store) {
931 for (
const AddResult &
result : results_to_add) {
960 GreasePencil *grease_pencil = grease_pencil_component.get_for_write();
961 if (grease_pencil ==
nullptr) {
964 bool any_success =
false;
966 for (const int layer_index : range) {
967 if (greasepencil::Drawing *drawing = grease_pencil->get_eval_drawing(
968 grease_pencil->layer(layer_index)))
970 const GeometryFieldContext field_context{*grease_pencil, domain, layer_index};
971 const bool success = try_capture_fields_on_geometry(
972 drawing->strokes_for_write().attributes_for_write(),
978 if (success & !any_success) {
991 MutableAttributeAccessor attributes = *component.attributes_for_write();
992 const GeometryFieldContext field_context{component, domain};
994 attributes, field_context, attribute_ids, domain, selection, fields);
1019 const std::shared_ptr<const fn::FieldInputs> &field_inputs = field.
node().
field_inputs();
1020 if (!field_inputs) {
1021 return std::nullopt;
1023 std::optional<AttrDomain> output_domain;
1024 auto handle_domain = [&](
const std::optional<AttrDomain> domain) {
1025 if (!domain.has_value()) {
1028 if (output_domain.has_value()) {
1029 if (*output_domain != *domain) {
1034 output_domain = domain;
1040 if (
mesh ==
nullptr) {
1041 return std::nullopt;
1043 for (
const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) {
1047 if (!handle_domain(geometry_field_input->preferred_domain(component))) {
1048 return std::nullopt;
1051 else if (
const auto *mesh_field_input =
dynamic_cast<const MeshFieldInput *
>(&field_input)) {
1052 if (!handle_domain(mesh_field_input->preferred_domain(*
mesh))) {
1053 return std::nullopt;
1057 return std::nullopt;
1065 return std::nullopt;
1067 for (
const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) {
1071 if (!handle_domain(geometry_field_input->preferred_domain(component))) {
1072 return std::nullopt;
1075 else if (
const auto *curves_field_input =
dynamic_cast<const CurvesFieldInput *
>(
1078 if (!handle_domain(curves_field_input->preferred_domain(
curves->geometry.wrap()))) {
1079 return std::nullopt;
1083 return std::nullopt;
1087 return output_domain;
Low-level operations for curves.
Low-level operations for grease pencil.
#define BLI_assert_unreachable()
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
#define BLI_SCOPED_DEFER(function_to_defer)
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void destruct_n(void *ptr, int64_t n) const
void fill_construct_n(const void *value, void *dst, int64_t n) const
const void * default_value() const
GMutableSpan as_mutable_span()
const void * data() const
CommonVArrayInfo common_info() const
GSpan get_internal_span() const
const CPPType & type() const
void get_to_uninitialized(int64_t index, void *r_value) const
static GVArray from_single_default(const CPPType &type, int64_t size)
static GVArray from_garray(GArray<> array)
static GVArray from_single(const CPPType &type, int64_t size, const void *value)
constexpr bool contains(int64_t value) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
IndexRange index_range() const
static VArray from_single(T value, const int64_t size)
static VArray from_func(const int64_t size, GetFunc get_func)
void append(const T &value)
bool is_builtin(const StringRef attribute_id) const
std::optional< AttributeDomainAndType > get_builtin_domain_and_type(const StringRef name) const
AttributeValidator lookup_validator(const StringRef attribute_id) const
GPointer get_builtin_default(const StringRef attribute_id) const
bool contains(StringRef attribute_id) const
GVArray adapt_domain(const GVArray &varray, const AttrDomain from_domain, const AttrDomain to_domain) const
GAttributeReader lookup(const StringRef attribute_id) const
int domain_size(const AttrDomain domain) const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
const Curves * get() const
const Curves * curves_id() const
const CurvesGeometry & curves() const
CurvesFieldContext(const CurvesGeometry &curves, AttrDomain domain)
AttrDomain domain() const
AttributeAccessor attributes() const
std::optional< AttrDomain > preferred_domain(const GeometryComponent &) const override
void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) const override
EvaluateOnDomainInput(fn::GField field, AttrDomain domain)
GVArray get_varray_for_context(const bke::GeometryFieldContext &context, const IndexMask &) const final
virtual std::optional< AttributeAccessor > attributes() const
const CurvesGeometry * curves() const
std::optional< AttributeAccessor > attributes() const
AttrDomain domain() const
const Mesh * mesh() const
int grease_pencil_layer_index() const
const Instances * instances() const
const PointCloud * pointcloud() const
GeometryFieldContext(const GeometryFieldContext &other, AttrDomain domain)
const greasepencil::Drawing * grease_pencil_layer_drawing() const
const void * geometry() const
const GreasePencil * grease_pencil() const
const CurvesGeometry * curves_or_strokes() const
GeometryComponent::Type type() const
const Curves * curves_id() const
const GreasePencil & grease_pencil() const
AttrDomain domain() const
GVArray get_varray_for_input(const fn::FieldInput &field_input, const IndexMask &mask, ResourceScope &scope) const override
const Mesh & mesh() const
AttrDomain domain() const
MeshFieldContext(const Mesh &mesh, AttrDomain domain)
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
const bke::CurvesGeometry & strokes() const
void set_selection(Field< bool > selection)
int add(GField field, GVArray *varray_ptr)
IndexMask get_evaluated_selection_as_mask() const
int add_with_destination(GField field, GVMutableArray dst)
const GVArray & get_evaluated(const int field_index) const
bool depends_on_input() const
const std::shared_ptr< const FieldInputs > & field_inputs() const
const CPPType & cpp_type() const
const FieldNode & node() const
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
static bool attribute_data_matches_varray(const GAttributeReader &attribute, const GVArray &varray)
std::optional< AttrDomain > try_detect_field_domain(const GeometryComponent &component, const fn::GField &field)
void copy_with_checked_indices(const GVArray &src, const VArray< int > &indices, const IndexMask &mask, GMutableSpan dst)
VArray< float3 > curve_normals_varray(const CurvesGeometry &curves, AttrDomain domain)
static std::optional< StringRefNull > try_get_field_direct_attribute_id(const fn::GField &any_field)
VArray< float3 > mesh_normals_varray(const Mesh &mesh, const IndexMask &mask, AttrDomain domain, bool no_corner_normals=false, bool true_normals=false)
VArray< float3 > instance_position_varray(const Instances &instances)
static bool try_add_shared_field_attribute(MutableAttributeAccessor attributes, const StringRef id_to_create, const AttrDomain domain, const fn::GField &field)
static void initialize_new_data(MutableAttributeAccessor &attributes, const AttrDomain domain, const int domain_size, const StringRef name, const CPPType &type, const bke::AttrType data_type, void *buffer)
static bool attribute_kind_matches(const AttributeMetaData meta_data, const AttrDomain domain, const bke::AttrType data_type)
static StringRef get_random_id_attribute_name(const AttrDomain domain)
bool try_capture_fields_on_geometry(MutableAttributeAccessor attributes, const fn::FieldContext &field_context, Span< StringRef > attribute_ids, AttrDomain domain, const fn::Field< bool > &selection, Span< fn::GField > fields)
AttrType cpp_type_to_attribute_type(const CPPType &type)
GField make_constant_field(const CPPType &type, const void *value)
void evaluate_constant_field(const GField &field, void *r_value)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void devirtualize_varray2(const VArray< T1 > &varray1, const VArray< T2 > &varray2, const Func &func, bool enable=true)
uint64_t get_default_hash(const T &v, const Args &...args)
float wrap(float value, float max, float min)
static void init(bNodeTree *, bNode *node)
fn::GField validate_field_if_necessary(const fn::GField &field) const
const ImplicitSharingInfo * sharing_info