21#include "RNA_prototypes.hh"
34 if (!
params.menu_switch_source_by_index_switch) {
35 params.draw_standard(params.layout);
38 const bNode *menu_switch_node =
params.menu_switch_source_by_index_switch->lookup_default(
40 if (!menu_switch_node) {
44 const auto &menu_switch_storage = *
static_cast<const NodeMenuSwitch *
>(
45 menu_switch_node->storage);
48 for (
const int i :
IndexRange(menu_switch_storage.enum_definition.items_num)) {
49 const NodeEnumItem &item = menu_switch_storage.enum_definition.items_array[
i];
50 const bNodeSocket &menu_switch_input_socket = menu_switch_node->input_socket(1 +
i);
51 if (menu_switch_input_socket.is_directly_linked()) {
57 if (menu_switch_input_socket_value.value == index) {
70 const std::string label = fmt::format(
"{}: {}", index, found_item->
name);
76 const bNode *node =
b.node_or_null();
85 StructureType::Single :
86 StructureType::Dynamic;
89 auto &index =
b.add_input<
decl::Int>(
"Index").
min(0).max(std::max<int>(0, items.
size() - 1));
90 if (supports_fields) {
91 index.supports_field().structure_type(structure_type);
96 auto &
input =
b.add_input(data_type, std::to_string(
i), std::move(identifier));
99 if (supports_fields) {
100 input.supports_field();
104 input.structure_type(structure_type);
107 auto &
output =
b.add_output(data_type,
"Output");
108 if (supports_fields) {
109 output.dependent_field().reference_pass_all();
115 output.reference_pass_all();
117 output.structure_type(structure_type);
122 PointerRNA op_ptr = layout.
op(
"node.index_switch_item_add",
"", ICON_ADD);
137 panel->op(
"node.index_switch_item_add",
IFACE_(
"Add Item"), ICON_ADD);
141 row->
label(node.input_socket(
i + 1).
name, ICON_NONE);
142 PointerRNA op_ptr = row->
op(
"node.index_switch_item_remove",
"", ICON_REMOVE);
151 ot,
"Add Item", __func__,
"Add an item to the index switch");
157 ot,
"Remove Item", __func__,
"Remove an item from the index switch");
170 data->next_identifier = 0;
173 const int default_items_num = 2;
175 for (
const int i :
IndexRange(default_items_num)) {
176 data->items[
i].identifier =
data->next_identifier++;
178 data->items_num = default_items_num;
187 bNode &node =
params.add_node(
"GeometryNodeIndexSwitch");
188 node_storage(node).data_type =
params.socket.type;
189 params.update_and_connect_available_socket(node,
"Output");
194 if (
params.node_tree().typeinfo->validate_link(other_type,
SOCK_INT)) {
196 bNode &node =
params.add_node(
"GeometryNodeIndexSwitch");
197 params.update_and_connect_available_socket(node,
"Index");
206 mf::Signature signature_;
212 mf::SignatureBuilder builder{
"Index Switch", signature_};
213 builder.single_input<
int>(
"Index");
214 debug_names_.reinitialize(items_num);
216 debug_names_[
i] = std::to_string(
i);
217 builder.single_input(debug_names_[
i].c_str(), type);
219 builder.single_output(
"Output", type);
225 const int inputs_num = signature_.params.size() - 2;
229 signature_.params.index_range().last(),
"Output");
232 if (
const std::optional<int>
i =
indices.get_if_single()) {
244 const int invalid_index = inputs_num;
257 if (!masks[
i].is_empty()) {
259 inputs.materialize_to_uninitialized(masks[
i],
output.data());
277 bool can_be_field_ =
false;
278 const CPPType *field_base_type_;
287 const bNodeSocket &index_socket = node.input_socket(0);
288 const bNodeSocket &output_socket = node.output_socket(0);
293 field_base_type_ = output_socket.
typeinfo->base_cpp_type;
297 lf_index_by_bsocket[index_socket.index_in_tree()] =
inputs_.append_and_get_index_as(
299 lf_index_by_bsocket[output_socket.index_in_tree()] =
outputs_.append_and_get_index_as(
302 for (
const int i : storage.items_span().index_range()) {
304 lf_index_by_bsocket[
input.index_in_tree()] =
inputs_.append_and_get_index_as(
342 if (value_to_forward ==
nullptr) {
347 void *output_ptr =
params.get_output_data_ptr(0);
360 if (input_values.
as_span().contains(
nullptr)) {
370 std::unique_ptr<mf::MultiFunction> switch_fn = std::make_unique<IndexSwitchFunction>(
374 void *output_ptr =
params.get_output_data_ptr(0);
425 dst_node->
storage = dst_storage;
455 return &node.input_socket(1);
463 ntype.
ui_name =
"Index Switch";
464 ntype.
ui_description =
"Choose between an arbitrary number of values with an index";
494 return std::make_unique<LazyFunctionForIndexSwitchNode>(node, lf_graph_info);
#define NODE_CLASS_CONVERTER
#define NODE_STORAGE_FUNCS(StorageT)
#define GEO_NODE_INDEX_SWITCH
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
__forceinline float extract(const int4 &b)
BMesh const char void * data
Span< T > as_span() const
static const CPPType & get()
void fill_construct_indices(const void *value, void *dst, const IndexMask &mask) const
const void * default_value() const
void move_construct(void *src, void *dst) const
static void from_groups(const IndexMask &universe, IndexMaskMemory &memory, Fn &&get_group_index, MutableSpan< IndexMask > r_masks)
constexpr bool contains(int64_t value) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
bool is_context_dependent_field() const
Vector< Output > outputs_
void set_signature(const Signature *signature)
static std::shared_ptr< FieldOperation > from(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
static SocketValueVariant & ConstructIn(void *ptr, T &&value)
IndexSwitchFunction(const CPPType &type, const int items_num)
ExecutionHints get_execution_hints() const override
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
void execute_single(const int index, lf::Params ¶ms) const
void execute_field(Field< int > index, lf::Params ¶ms) const
LazyFunctionForIndexSwitchNode(const bNode &node, GeometryNodesLazyFunctionGraphInfo &lf_graph_info)
void execute_impl(lf::Params ¶ms, const lf::Context &) const override
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
bool can_contain_reference(eNodeSocketDatatype socket_type)
bool can_contain_referenced_data(eNodeSocketDatatype socket_type)
void node_register_type(bNodeType &ntype)
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_copy_storage(bNodeTree *, bNode *dst_node, const bNode *src_node)
static void node_init(bNodeTree *, bNode *node)
static void node_blend_read(bNodeTree &, bNode &node, BlendDataReader &reader)
static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
static void NODE_OT_index_switch_item_add(wmOperatorType *ot)
static void NODE_OT_index_switch_item_remove(wmOperatorType *ot)
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
static void node_declare(NodeDeclarationBuilder &b)
static void register_node()
static void node_rna(StructRNA *srna)
static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_operators()
static void node_blend_write(const bNodeTree &, const bNode &node, BlendWriter &writer)
constexpr int value_inputs_start
static void draw_item_socket(CustomSocketDrawParams ¶ms, const int index)
static void node_free_storage(bNode *node)
static const bNodeSocket * node_internally_linked_input(const bNodeTree &, const bNode &node, const bNodeSocket &)
void remove_item_by_index(wmOperatorType *ot, const char *name, const char *idname, const char *description)
void add_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
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)
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, typename Accessor::ItemT **r_new_item=nullptr)
std::unique_ptr< LazyFunction > get_index_switch_node_lazy_function(const bNode &node, GeometryNodesLazyFunctionGraphInfo &lf_graph_info)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
void set_default_remaining_node_outputs(lf::Params ¶ms, const bNode &node)
bool socket_type_always_single(const eNodeSocketDatatype socket_type)
const EnumPropertyItem * enum_items_filter(const EnumPropertyItem *original_item_array, FunctionRef< bool(const EnumPropertyItem &item)> fn)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
static blender::bke::bNodeSocketTemplate inputs[]
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
const EnumPropertyItem rna_enum_node_socket_data_type_items[]
bNodeSocketTypeHandle * typeinfo
NodeInternallyLinkedInputFunction internally_linked_input
NodeBlendWriteFunction blend_write_storage_content
std::string ui_description
NodeBlendDataReadFunction blend_data_read_storage_content
void(* initfunc)(bNodeTree *ntree, bNode *node)
void(* draw_buttons_ex)(uiLayout *, bContext *C, PointerRNA *ptr)
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
bool(* insert_link)(NodeInsertLinkParams ¶ms)
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
NodeDeclareFunction declare
void(* register_operators)()
bool ignore_inferred_input_socket_visibility
Array< int > lf_index_by_bsocket
GeometryNodeLazyFunctionGraphMapping mapping
static StructRNA * item_srna
static std::string socket_identifier_for_item(const IndexSwitchItem &item)
static void blend_read_data_item(BlendDataReader *reader, ItemT &item)
static void blend_write_item(BlendWriter *writer, const ItemT &item)
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
void label(blender::StringRef name, int icon)
void emboss_set(blender::ui::EmbossType emboss)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
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)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))