20#include <fmt/format.h>
25 : mesh_(
mesh), domain_(domain)
31 : curves_(curves), domain_(domain)
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_)
75 const int grease_pencil_layer_index)
76 : geometry_(geometry),
79 grease_pencil_layer_index_(grease_pencil_layer_index)
91 : type_(component.type()), domain_(domain)
93 switch (component.
type()) {
96 geometry_ = mesh_component.
get();
102 geometry_ =
curves ? &
curves->geometry.wrap() :
nullptr;
103 curves_id_ = curve_component.
get();
109 geometry_ = pointcloud_component.
get();
115 geometry_ = grease_pencil_component.
get();
123 geometry_ = instances_component.
get();
142 : geometry_(&curves_id.geometry.
wrap()),
145 curves_id_(&curves_id)
153 : geometry_(&grease_pencil),
160 const int layer_index)
161 : geometry_(&grease_pencil),
164 grease_pencil_layer_index_(layer_index)
168 : geometry_(&instances),
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()) {
335 if (
const CurvesGeometry *curves = geometry_context->curves_or_strokes()) {
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()) {
514 return TIP_(
"ID / Index");
532 using namespace bke::greasepencil;
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_);
635 value_evaluator.evaluate();
636 const GVArray &values = value_evaluator.get_evaluated(0);
639 index_evaluator.add(index_field_);
640 index_evaluator.evaluate();
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_);
673 value_evaluator.evaluate();
675 const GVArray &values = value_evaluator.get_evaluated(0);
693 value_evaluator.evaluate();
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;
816 const int domain_size = attributes.
domain_size(domain);
817 if (domain_size == 0) {
818 bool all_added =
true;
827 evaluator.set_selection(selection);
847 for (
const int input_index : attribute_ids.
index_range()) {
848 const StringRef id = attribute_ids[input_index];
849 const CPPType &type = fields[input_index].cpp_type();
853 if (
const std::optional<AttributeDomainAndType> meta_data =
867 if (dst.domain == domain && dst.varray.type() == field.
cpp_type()) {
868 const int evaluator_index = evaluator.add(field);
869 results_to_store.
append({input_index, evaluator_index});
874 if (!validator && selection_is_full) {
883 if (!selection_is_full) {
889 const int evaluator_index = evaluator.add_with_destination(field, dst);
890 results_to_add.
append({input_index, evaluator_index, buffer});
893 evaluator.evaluate();
894 const IndexMask &
mask = evaluator.get_evaluated_selection_as_mask();
896 for (
const StoreResult &
result : results_to_store) {
898 const GVArray &result_data = evaluator.get_evaluated(
result.evaluator_index);
907 for (
const AddResult &
result : results_to_add) {
936 GreasePencil *grease_pencil = grease_pencil_component.get_for_write();
937 if (grease_pencil ==
nullptr) {
940 bool any_success =
false;
942 for (const int layer_index : range) {
943 if (greasepencil::Drawing *drawing = grease_pencil->get_eval_drawing(
944 grease_pencil->layer(layer_index)))
946 const GeometryFieldContext field_context{*grease_pencil, domain, layer_index};
947 const bool success = try_capture_fields_on_geometry(
948 drawing->strokes_for_write().attributes_for_write(),
954 if (success & !any_success) {
967 MutableAttributeAccessor attributes = *component.attributes_for_write();
968 const GeometryFieldContext field_context{component, domain};
970 attributes, field_context, attribute_ids, domain, selection, fields);
986 if (component_type == GeometryComponent::Type::PointCloud) {
987 return AttrDomain::Point;
989 if (component_type == GeometryComponent::Type::GreasePencil) {
990 return AttrDomain::Layer;
992 if (component_type == GeometryComponent::Type::Instance) {
993 return AttrDomain::Instance;
995 const std::shared_ptr<const fn::FieldInputs> &field_inputs = field.
node().
field_inputs();
999 std::optional<AttrDomain> output_domain;
1000 auto handle_domain = [&](
const std::optional<AttrDomain> domain) {
1001 if (!domain.has_value()) {
1004 if (output_domain.has_value()) {
1005 if (*output_domain != *domain) {
1010 output_domain = domain;
1013 if (component_type == GeometryComponent::Type::Mesh) {
1016 if (
mesh ==
nullptr) {
1017 return std::nullopt;
1019 for (
const fn::FieldInput &field_input : field_inputs->deduplicated_nodes) {
1023 if (!handle_domain(geometry_field_input->preferred_domain(component))) {
1024 return std::nullopt;
1027 else if (
const auto *mesh_field_input =
dynamic_cast<const MeshFieldInput *
>(&field_input)) {
1028 if (!handle_domain(mesh_field_input->preferred_domain(*
mesh))) {
1029 return std::nullopt;
1033 return std::nullopt;
1037 if (component_type == GeometryComponent::Type::Curve) {
1039 const Curves *curves = curve_component.
get();
1040 if (curves ==
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 *curves_field_input =
dynamic_cast<const CurvesFieldInput *
>(
1054 if (!handle_domain(curves_field_input->preferred_domain(curves->
geometry.wrap()))) {
1055 return std::nullopt;
1059 return std::nullopt;
1063 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)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
void destruct_n(void *ptr, int64_t n) const
void destruct(void *ptr) 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
void materialize(void *dst) const
static GVArray ForGArray(GArray<> array)
static GVArray ForSingleDefault(const CPPType &type, int64_t size)
static GVArray ForSingle(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 ForSingle(T value, const int64_t size)
static VArray ForFunc(const int64_t size, GetFunc get_func)
void append(const T &value)
std::optional< AttributeDomainAndType > get_builtin_domain_and_type(const StringRef name) const
AttributeValidator lookup_validator(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
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
bool domain_supported(const AttrDomain domain) 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
const Instances * instances() const
const PointCloud * pointcloud() const
GeometryFieldContext(const GeometryFieldContext &other, AttrDomain domain)
const greasepencil::Drawing * grease_pencil_layer_drawing() const
const GreasePencil * grease_pencil() const
const CurvesGeometry * curves_or_strokes() const
GeometryComponent::Type type() const
const Curves * curves_id() const
const GreasePencil * get() 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 Instances * get() const
bke::AttributeAccessor attributes() const
const Mesh & mesh() const
MeshFieldContext(const Mesh &mesh, AttrDomain domain)
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
const PointCloud * get() const
const bke::CurvesGeometry & strokes() const
int add(GField field, GVArray *varray_ptr)
int add_with_destination(GField field, GVMutableArray dst)
virtual void for_each_field_input_recursive(FunctionRef< void(const FieldInput &)> fn) 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_kind_matches(const AttributeMetaData meta_data, const AttrDomain domain, const eCustomDataType data_type)
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)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
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 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)
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)
unsigned __int64 uint64_t
fn::GField validate_field_if_necessary(const fn::GField &field) const
const ImplicitSharingInfo * sharing_info