28#include "RNA_prototypes.hh"
45 b.use_custom_socket_order();
46 b.allow_any_socket_order();
49 const bNode *node =
b.node_or_null();
50 if (node ==
nullptr) {
59 StructureType::Single :
60 StructureType::Dynamic;
61 StructureType menu_structure_type = value_structure_type;
66 if (is_single_compositor_type) {
67 value_structure_type = StructureType::Single;
69 menu_structure_type = StructureType::Single;
72 auto &
output =
b.add_output(data_type,
"Output");
73 if (supports_fields) {
74 output.dependent_field().reference_pass_all();
80 output.reference_pass_all();
82 output.structure_type(value_structure_type);
84 b.add_default_layout();
87 if (supports_fields) {
88 menu.supports_field();
91 menu.optional_label();
95 auto &
input =
b.add_input(data_type, enum_item.name, identifier)
99 .description(
"Becomes the output value if it is chosen by the menu input");
100 if (supports_fields) {
101 input.supports_field();
105 input.structure_type(value_structure_type);
106 auto &item_output =
b.add_output<
decl::Bool>(enum_item.name, std::move(identifier))
107 .align_with_previous()
108 .
description(
"True if this item is chosen by the menu input");
109 if (supports_fields) {
110 item_output.dependent_field({menu.index()});
111 item_output.structure_type(menu_structure_type);
116 .structure_type(StructureType::Dynamic)
120 PointerRNA op_ptr = layout.
op(
"node.enum_definition_item_add",
"", ICON_ADD);
134 data->enum_definition.next_identifier = 0;
135 data->enum_definition.items_array =
nullptr;
136 data->enum_definition.items_num = 0;
153 dst_node->
storage = dst_storage;
164 bNode &node =
params.add_node(
"GeometryNodeMenuSwitch");
165 params.update_and_connect_available_socket(node,
"Menu");
172 bNode &node =
params.add_node(
"GeometryNodeMenuSwitch");
173 node_storage(node).data_type =
params.socket.type;
174 params.update_and_connect_available_socket(node,
"Output");
187 mf::Signature signature_;
191 : enum_def_(enum_def), type_(type)
193 mf::SignatureBuilder builder{
"Menu Switch", signature_};
195 for (
const NodeEnumItem &enum_item : enum_def.items()) {
196 builder.single_input(enum_item.name, type);
198 builder.single_output(
"Output", type, mf::ParamFlag::SupportsUnusedOutput);
200 builder.single_output<bool>(item.name, mf::ParamFlag::SupportsUnusedOutput);
203 this->set_signature(&signature_);
208 const int value_inputs_start = 1;
209 const int inputs_num = enum_def_.items_num;
212 const int invalid_index = inputs_num;
214 GMutableSpan value_output =
params.uninitialized_single_output_if_required(1 + inputs_num,
218 for (
const int item_i :
IndexRange(inputs_num)) {
219 const int param_index = 2 + inputs_num + item_i;
220 item_mask_outputs[item_i] =
params.uninitialized_single_output_if_required<
bool>(
224 auto find_item_index = [&](
const MenuValue value) ->
int {
225 for (
const int i : enum_def_.items().index_range()) {
231 return invalid_index;
234 if (
const std::optional<MenuValue> value = values.
get_if_single()) {
235 const int index = find_item_index(*value);
236 if (index < inputs_num) {
241 for (
const int item_i :
IndexRange(inputs_num)) {
250 type_.fill_construct_indices(type_.default_value(), value_output.
data(),
mask);
252 for (
const int item_i :
IndexRange(inputs_num)) {
265 mask, memory, [&](
const int64_t i) {
return find_item_index(values[
i]); }, masks);
267 for (
const int item_i :
IndexRange(inputs_num)) {
268 const IndexMask &mask_for_index = masks[item_i];
271 inputs.materialize_to_uninitialized(mask_for_index, value_output.
data());
275 if (
mask.size() != mask_for_index.
size()) {
283 type_.fill_construct_indices(type_.default_value(), value_output.
data(), masks[invalid_index]);
290 bool can_be_field_ =
false;
292 const CPPType *field_base_type_;
297 : node_(node), enum_def_(node_storage(node).enum_definition)
308 lf_index_by_bsocket[node.input_socket(0).index_in_tree()] =
inputs_.append_and_get_index_as(
310 for (
const int i : enum_def_.items().index_range()) {
312 lf_index_by_bsocket[node.input_socket(
i + 1).index_in_tree()] =
313 inputs_.append_and_get_index_as(
316 lf_index_by_bsocket[node.output_socket(0).index_in_tree()] =
outputs_.append_and_get_index_as(
318 for (
const int i : enum_def_.items().index_range()) {
320 lf_index_by_bsocket[node.output_socket(
i + 1).index_in_tree()] =
338 for (
const int i :
IndexRange(enum_def_.items_num)) {
340 const int input_index =
i + 1;
345 if (value_to_forward ==
nullptr) {
350 params.set_output(0, std::move(*value_to_forward));
353 params.set_input_unused(input_index);
355 if (!
params.output_was_set(
i + 1)) {
367 const int values_num = this->enum_def_.
items_num;
370 const int input_index =
i + 1;
373 if (input_values.
as_span().contains(
nullptr)) {
379 item_fields[0] = std::move(condition);
380 for (
const int i :
IndexRange(enum_def_.items_num)) {
381 item_fields[
i + 1] = input_values[
i]->extract<
GField>();
383 std::unique_ptr<MultiFunction> multi_function = std::make_unique<MenuSwitchFn>(
384 enum_def_, *field_base_type_);
386 std::move(item_fields));
389 for (
const int item_i :
IndexRange(enum_def_.items_num)) {
405 : enum_def_(node_storage(node).enum_definition)
409 for (
const int i :
IndexRange(enum_def_.items_num)) {
410 const NodeEnumItem &enum_item = enum_def_.items()[i];
411 outputs_.append_as(enum_item.name, CPPType::get<bool>());
419 for (
const int i :
IndexRange(enum_def_.items_num)) {
425 for (
const int i :
IndexRange(enum_def_.items_num)) {
444 bool found_item =
false;
446 for (
const int i :
IndexRange(enum_definition.items_num)) {
450 const bool is_selected = enum_item.
identifier == menu_identifier.
value;
485 C, panel,
tree, node);
488 panel->use_property_split_set(
true);
489 panel->use_property_decorate_set(
false);
490 panel->prop(item_ptr,
"description",
UI_ITEM_NONE, std::nullopt, ICON_NONE);
526 return &node.input_socket(1);
595 return std::make_unique<LazyFunctionForMenuSwitchNode>(node, lf_graph_info);
602 return std::make_unique<LazyFunctionForMenuSwitchSocketUsage>(node);
#define NODE_CLASS_CONVERTER
#define NODE_STORAGE_FUNCS(StorageT)
#define GEO_NODE_MENU_SWITCH
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)
#define NOD_storage_enum_accessors(member)
BMesh const char void * data
Span< T > as_span() const
static const CPPType & get()
static void from_groups(const IndexMask &universe, IndexMaskMemory &memory, Fn &&get_group_index, MutableSpan< IndexMask > r_masks)
constexpr bool is_empty() const
std::optional< T > get_if_single() const
bool is_context_dependent_field() const
const bNode & bnode() const
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Result & get_input(StringRef identifier) const
void share_data(const Result &source)
static bool is_single_value_only_type(ResultType type)
void set_single_value(const T &value)
void allocate_single_value()
const T & get_single_value() const
Vector< Output > outputs_
static std::shared_ptr< FieldOperation > from(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
StructureType structure_type
static SocketValueVariant From(T &&value)
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)
bNodeSocketType * node_socket_type_find_static(int type, int subtype=0)
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))
ResultType socket_data_type_to_result_type(const eNodeSocketDatatype data_type, const std::optional< int > dimensions=std::nullopt)
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
void make_common_operators()
static void draw_items_list_with_operators(const bContext *C, uiLayout *layout, const bNodeTree &tree, const bNode &node)
static void draw_active_item_props(const bNodeTree &tree, const bNode &node, const FunctionRef< void(PointerRNA *item_ptr)> draw_item)
void blend_write(BlendWriter *writer, const bNode &node)
Accessor::ItemT * add_item_with_name(bNode &node, const char *name)
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)
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)
std::unique_ptr< LazyFunction > get_menu_switch_node_socket_usage_lazy_function(const bNode &node)
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)
std::unique_ptr< LazyFunction > get_menu_switch_node_lazy_function(const bNode &node, GeometryNodesLazyFunctionGraphInfo &lf_graph_info)
const EnumPropertyItem * enum_items_filter(const EnumPropertyItem *original_item_array, FunctionRef< bool(const EnumPropertyItem &item)> fn)
void common_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[]
bNodeTreeTypeHandle * typeinfo
const blender::CPPType * base_cpp_type
bool(* valid_socket_type)(bNodeTreeType *ntreetype, bNodeSocketType *socket_type)
NodeInternallyLinkedInputFunction internally_linked_input
NodeBlendWriteFunction blend_write_storage_content
std::string ui_description
NodeBlendDataReadFunction blend_data_read_storage_content
NodeGetCompositorOperationFunction get_compositor_operation
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
PanelLayout panel(const bContext *C, blender::StringRef idname, bool default_closed)
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)