30 const bNode *node =
b.node_or_null();
31 b.use_custom_socket_order();
32 b.allow_any_socket_order();
34 b.add_default_layout();
37 b.add_output<
decl::Geometry>(
"Geometry").propagate_all().align_with_previous();
38 if (node !=
nullptr) {
44 const std::string input_identifier =
46 const std::string output_identifier =
48 b.add_input(data_type, item.name, input_identifier)
51 b.add_output(data_type, item.name, output_identifier).field_on_all().align_with_previous();
57 .align_with_previous();
70 data->domain = int8_t(AttrDomain::Point);
82 C,
"capture_attribute_items",
false,
IFACE_(
"Capture Items")))
84 socket_items::ui::draw_items_list_with_operators<CaptureAttributeItemsAccessor>(
85 C, panel, tree, node);
86 socket_items::ui::draw_active_item_props<CaptureAttributeItemsAccessor>(
90 panel->prop(item_ptr,
"data_type",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
105 if (!attributes.has_value()) {
123 for (
const std::string &unused_id : unused_ids) {
124 attributes->remove(unused_id);
135 TIP_(
"The attribute output cannot be used without the geometry output"));
150 const std::string input_identifier =
152 const std::string output_identifier =
159 used_attribute_ids_set.
add(*attribute_id);
161 attribute_id_ptrs.
append(std::move(*attribute_id));
173 attribute_ids[
i] = attribute_id_ptrs[
i];
185 if (domain == AttrDomain::Instance) {
192 GeometryComponent::Type::PointCloud,
193 GeometryComponent::Type::Curve,
194 GeometryComponent::Type::GreasePencil};
198 if (geometry_set.
has(type)) {
211 *ntree, *node, *node, *link);
224 __func__, src_storage);
225 dst_node->
storage = dst_storage;
235 bNode &node = params.
add_node(
"GeometryNodeCaptureAttribute");
244 bNode &node = params.add_node(
"GeometryNodeCaptureAttribute");
246 node, type, params.socket.name);
247 params.update_and_connect_available_socket(node, params.socket.name);
255 return &node.input_socket(output_socket.index());
272 ntype.
ui_name =
"Capture Attribute";
274 "Store the result of a field on a geometry and output the data as a node socket. Allows "
275 "remembering or interpolating data as the geometry changes, such as positions before "
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_ATTRIBUTE
#define GEO_NODE_CAPTURE_ATTRIBUTE
void BLO_read_string(BlendDataReader *reader, char **ptr_p)
void BLO_write_string(BlendWriter *writer, const char *data_ptr)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
BMesh const char void * data
bool contains(const Key &key) const
void append(const T &value)
IndexRange index_range() const
virtual std::optional< MutableAttributeAccessor > attributes_for_write()
void add_item(std::string socket_name, SocketLinkOperation::LinkSocketFn fn, int weight=0)
const bNodeSocket & other_socket() const
T extract_input(StringRef identifier)
void error_message_add(const NodeWarningType type, StringRef message) const
void set_output(StringRef identifier, T &&value)
bool output_is_required(StringRef identifier) const
std::optional< std::string > get_output_anonymous_attribute_id_if_needed(const StringRef output_identifier, const bool force_create=false)
const bNode & node() const
void set_default_remaining_outputs()
NodeAttributeFilter get_attribute_filter(const StringRef output_identifier) const
void connect_available_socket(bNode &new_node, StringRef socket_name)
bNode & add_node(StringRef idname)
StructureType structure_type
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
bool attribute_name_is_anonymous(const StringRef name)
void node_register_type(bNodeType &ntype)
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)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
static void node_operators()
static void node_free_storage(bNode *node)
static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void node_init(bNodeTree *, bNode *node)
static void clean_unused_attributes(const AttributeFilter &attribute_filter, const Set< StringRef > &keep, GeometryComponent &component)
static void node_blend_read(bNodeTree &, bNode &node, BlendDataReader &reader)
static void node_blend_write(const bNodeTree &, const bNode &node, BlendWriter &writer)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void node_register()
static bool node_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
static const bNodeSocket * node_internally_linked_input(const bNodeTree &, const bNode &node, const bNodeSocket &output_socket)
static void node_copy_storage(bNodeTree *, bNode *dst_node, const bNode *src_node)
void make_common_operators()
void blend_write(BlendWriter *writer, const bNode &node)
void destruct_array(bNode &node)
void blend_read_data(BlendDataReader *reader, bNode &node)
void copy_array(const bNode &src_node, bNode &dst_node)
Accessor::ItemT * add_item_with_socket_type_and_name(bNode &node, const eNodeSocketDatatype socket_type, const char *name)
bool try_add_item_via_any_extend_socket(bNodeTree &ntree, bNode &extend_node, bNode &storage_node, bNodeLink &link, const std::optional< StringRef > socket_identifier=std::nullopt)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
NodeGeometryAttributeCaptureItem * capture_items
bool allow_skip(const StringRef name) const
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
bool has(const GeometryComponent::Type component_type) const
bool has_instances() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
NodeInternallyLinkedInputFunction internally_linked_input
NodeBlendWriteFunction blend_write_storage_content
bool(*) insert_link(bNodeTree *ntree, bNode *node, bNodeLink *link)
void(*) register_operators()
std::string ui_description
NodeBlendDataReadFunction blend_data_read_storage_content
void(*) draw_buttons(uiLayout *, bContext *C, PointerRNA *ptr)
NodeGeometryExecFunction geometry_node_execute
void(*) initfunc(bNodeTree *ntree, bNode *node)
const char * enum_name_legacy
void(*) draw_buttons_ex(uiLayout *, bContext *C, PointerRNA *ptr)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare
static StructRNA * item_srna
NodeGeometryAttributeCaptureItem ItemT
static bool supports_socket_type(const eNodeSocketDatatype socket_type)
static std::string input_socket_identifier_for_item(const NodeGeometryAttributeCaptureItem &item)
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
static std::string output_socket_identifier_for_item(const NodeGeometryAttributeCaptureItem &item)
static void blend_write_item(BlendWriter *writer, const ItemT &item)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)