Blender V4.3
NOD_socket_items_ops.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include "NOD_socket_items.hh"
8
9#include "WM_api.hh"
10
11#include "BKE_context.hh"
14
15#include "RNA_access.hh"
16#include "RNA_define.hh"
17#include "RNA_prototypes.hh"
18
19#include "ED_node.hh"
20
21#include "DNA_space_types.h"
22
24
25inline PointerRNA get_active_node_to_operate_on(bContext *C, const int node_type)
26{
27 SpaceNode *snode = CTX_wm_space_node(C);
28 if (!snode) {
29 return PointerRNA_NULL;
30 }
31 if (!snode->edittree) {
32 return PointerRNA_NULL;
33 }
34 if (!ID_IS_EDITABLE(snode->edittree)) {
35 return PointerRNA_NULL;
36 }
37 const bke::bNodeTreeZones *zones = snode->edittree->zones();
38 if (!zones) {
39 return PointerRNA_NULL;
40 }
41 bNode *active_node = bke::node_get_active(snode->edittree);
42 if (!active_node) {
43 return PointerRNA_NULL;
44 }
45 if (const bke::bNodeTreeZone *zone = zones->get_zone_by_node(active_node->identifier)) {
46 if (zone->input_node == active_node) {
47 /* Assume the data is generally stored on the output and not the input node. */
48 active_node = const_cast<bNode *>(zone->output_node);
49 }
50 }
51 if (active_node->type != node_type) {
52 return PointerRNA_NULL;
53 }
54 return RNA_pointer_create(&snode->edittree->id, &RNA_Node, active_node);
55}
56
57inline void update_after_node_change(bContext *C, const PointerRNA node_ptr)
58{
59 bNode *node = static_cast<bNode *>(node_ptr.data);
60 bNodeTree *ntree = reinterpret_cast<bNodeTree *>(node_ptr.owner_id);
61
65}
66
67template<typename Accessor> inline bool editable_node_active_poll(bContext *C)
68{
69 return get_active_node_to_operate_on(C, Accessor::node_type).data != nullptr;
70}
71
72template<typename Accessor>
74 const char *name,
75 const char *idname,
76 const char *description)
77{
78 ot->name = name;
79 ot->idname = idname;
80 ot->description = description;
82
83 ot->exec = [](bContext *C, wmOperator * /*op*/) -> int {
84 PointerRNA node_ptr = get_active_node_to_operate_on(C, Accessor::node_type);
85 bNode &node = *static_cast<bNode *>(node_ptr.data);
86 SocketItemsRef ref = Accessor::get_items_from_node(node);
87 if (*ref.items_num > 0) {
89 ref.items, ref.items_num, ref.active_index, *ref.active_index, Accessor::destruct_item);
90 update_after_node_change(C, node_ptr);
91 }
92 return OPERATOR_FINISHED;
93 };
94}
95
96template<typename Accessor>
98 const char *name,
99 const char *idname,
100 const char *description)
101{
102 ot->name = name;
103 ot->idname = idname;
104 ot->description = description;
106
107 ot->exec = [](bContext *C, wmOperator *op) -> int {
108 PointerRNA node_ptr = get_active_node_to_operate_on(C, Accessor::node_type);
109 bNode &node = *static_cast<bNode *>(node_ptr.data);
110 const int index_to_remove = RNA_int_get(op->ptr, "index");
111 SocketItemsRef ref = Accessor::get_items_from_node(node);
113 ref.items, ref.items_num, ref.active_index, index_to_remove, Accessor::destruct_item);
114
115 update_after_node_change(C, node_ptr);
116 return OPERATOR_FINISHED;
117 };
118
119 RNA_def_int(ot->srna, "index", 0, 0, INT32_MAX, "Index", "Index to remove", 0, INT32_MAX);
120}
121
122template<typename Accessor>
124 const char *name,
125 const char *idname,
126 const char *description)
127{
128 ot->name = name;
129 ot->idname = idname;
130 ot->description = description;
132
133 ot->exec = [](bContext *C, wmOperator * /*op*/) -> int {
134 PointerRNA node_ptr = get_active_node_to_operate_on(C, Accessor::node_type);
135 bNode &node = *static_cast<bNode *>(node_ptr.data);
136 SocketItemsRef ref = Accessor::get_items_from_node(node);
137 const typename Accessor::ItemT *active_item = nullptr;
138 int dst_index = *ref.items_num;
139 if (ref.active_index) {
140 const int old_active_index = *ref.active_index;
141 if (old_active_index >= 0 && old_active_index < *ref.items_num) {
142 active_item = &(*ref.items)[old_active_index];
143 dst_index = active_item ? old_active_index + 1 : *ref.items_num;
144 }
145 }
146
147 if constexpr (Accessor::has_type && Accessor::has_name) {
149 node,
150 active_item ?
151 Accessor::get_socket_type(*active_item) :
152 (Accessor::supports_socket_type(SOCK_GEOMETRY) ? SOCK_GEOMETRY : SOCK_FLOAT),
153 /* Empty name so it is based on the type. */
154 active_item ? active_item->name : "");
155 }
156 else if constexpr (!Accessor::has_type && Accessor::has_name) {
157 socket_items::add_item_with_name<Accessor>(node, active_item ? active_item->name : "");
158 }
159 else if constexpr (!Accessor::has_type && !Accessor::has_name) {
161 }
162 else {
164 }
165
166 dna::array::move_index(*ref.items, *ref.items_num, *ref.items_num - 1, dst_index);
167 if (ref.active_index) {
168 *ref.active_index = dst_index;
169 }
170
171 update_after_node_change(C, node_ptr);
172 return OPERATOR_FINISHED;
173 };
174}
175
176enum class MoveDirection {
177 Up = 0,
178 Down = 1,
179};
180
181template<typename Accessor>
183 const char *name,
184 const char *idname,
185 const char *description)
186{
187 ot->name = name;
188 ot->idname = idname;
189 ot->description = description;
191
192 ot->exec = [](bContext *C, wmOperator *op) -> int {
193 PointerRNA node_ptr = get_active_node_to_operate_on(C, Accessor::node_type);
194 bNode &node = *static_cast<bNode *>(node_ptr.data);
195 const MoveDirection direction = MoveDirection(RNA_enum_get(op->ptr, "direction"));
196
197 SocketItemsRef ref = Accessor::get_items_from_node(node);
198 const int old_active_index = *ref.active_index;
199 if (direction == MoveDirection::Up && old_active_index > 0) {
200 dna::array::move_index(*ref.items, *ref.items_num, old_active_index, old_active_index - 1);
201 *ref.active_index -= 1;
202 }
203 else if (direction == MoveDirection::Down && old_active_index < *ref.items_num - 1) {
204 dna::array::move_index(*ref.items, *ref.items_num, old_active_index, old_active_index + 1);
205 *ref.active_index += 1;
206 }
207
208 update_after_node_change(C, node_ptr);
209 return OPERATOR_FINISHED;
210 };
211
212 static const EnumPropertyItem direction_items[] = {
213 {int(MoveDirection::Up), "UP", 0, "Up", ""},
214 {int(MoveDirection::Down), "DOWN", 0, "Down", ""},
215 {0, nullptr, 0, nullptr, nullptr},
216 };
217
218 RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Move direction");
219}
220
221} // namespace blender::nodes::socket_items::ops
SpaceNode * CTX_wm_space_node(const bContext *C)
Main * CTX_data_main(const bContext *C)
void BKE_ntree_update_tag_node_property(bNodeTree *ntree, bNode *node)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
@ SOCK_FLOAT
@ SOCK_GEOMETRY
void ED_node_tree_propagate_change(const bContext *C, Main *bmain, bNodeTree *ntree)
Definition node_edit.cc:492
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
#define C
Definition RandGen.cpp:29
#define NC_NODE
Definition WM_types.hh:361
#define NA_EDITED
Definition WM_types.hh:550
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
bNode * node_get_active(bNodeTree *ntree)
Definition node.cc:3849
void remove_index(T **items, int *items_num, int *active_index, const int index, void(*destruct_item)(T *))
void move_index(T *items, const int items_num, const int from_index, const int to_index)
void remove_item_by_index(wmOperatorType *ot, const char *name, const char *idname, const char *description)
void move_active_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
void remove_active_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
PointerRNA get_active_node_to_operate_on(bContext *C, const int node_type)
void update_after_node_change(bContext *C, const PointerRNA node_ptr)
void add_item(wmOperatorType *ot, const char *name, const char *idname, const char *description)
Accessor::ItemT * add_item_with_name(bNode &node, const char *name)
Accessor::ItemT * add_item(bNode &node)
Accessor::ItemT * add_item_with_socket_type_and_name(bNode &node, const eNodeSocketDatatype socket_type, const char *name)
int RNA_int_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
#define INT32_MAX
Definition stdint.h:137
ID * owner_id
Definition RNA_types.hh:40
void * data
Definition RNA_types.hh:42
struct bNodeTree * edittree
int32_t identifier
int16_t type
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
void WM_main_add_notifier(uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125