Blender V5.0
ed_viewer_path.cc
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#include "ED_viewer_path.hh"
6#include "ED_node.hh"
7#include "ED_screen.hh"
8
11#include "BKE_context.hh"
12#include "BKE_lib_id.hh"
13#include "BKE_main.hh"
15#include "BKE_node_runtime.hh"
17#include "BKE_viewer_path.hh"
18#include "BKE_workspace.hh"
19
20#include "BLI_listbase.h"
21#include "BLI_string.h"
22#include "BLI_vector.hh"
23
24#include "DNA_modifier_types.h"
25#include "DNA_node_types.h"
27
28#include "DEG_depsgraph.hh"
30
31#include "WM_api.hh"
32
34
35using bke::bNodeTreeZone;
36using bke::bNodeTreeZones;
37
39{
40 if (const auto *context = dynamic_cast<const bke::ModifierComputeContext *>(&compute_context)) {
42 elem->modifier_uid = context->modifier_uid();
43 if (const NodesModifierData *nmd = context->nmd()) {
44 elem->base.ui_name = BLI_strdup(nmd->modifier.name);
45 }
46 return &elem->base;
47 }
48 if (const auto *context = dynamic_cast<const bke::GroupNodeComputeContext *>(&compute_context)) {
50 elem->node_id = context->node_id();
51 if (const bNode *caller_node = context->node()) {
52 if (const bNodeTree *group = reinterpret_cast<const bNodeTree *>(caller_node->id)) {
53 elem->base.ui_name = BLI_strdup(BKE_id_name(group->id));
54 }
55 }
56 return &elem->base;
57 }
58 if (const auto *context = dynamic_cast<const bke::SimulationZoneComputeContext *>(
59 &compute_context))
60 {
62 elem->sim_output_node_id = context->output_node_id();
63 return &elem->base;
64 }
65 if (const auto *context = dynamic_cast<const bke::RepeatZoneComputeContext *>(&compute_context))
66 {
68 elem->repeat_output_node_id = context->output_node_id();
69 elem->iteration = context->iteration();
70 return &elem->base;
71 }
72 if (const auto *context = dynamic_cast<const bke::ForeachGeometryElementZoneComputeContext *>(
73 &compute_context))
74 {
77 elem->zone_output_node_id = context->output_node_id();
78 elem->index = context->index();
79 return &elem->base;
80 }
81 if (const auto *context = dynamic_cast<const bke::EvaluateClosureComputeContext *>(
82 &compute_context))
83 {
85 elem->evaluate_node_id = context->node_id();
86 if (const std::optional<nodes::ClosureSourceLocation> &source =
87 context->closure_source_location())
88 {
89 elem->source_output_node_id = source->closure_output_node_id;
90 BLI_assert(DEG_is_original(source->tree));
91 elem->source_node_tree = const_cast<bNodeTree *>(source->tree);
92 }
93 return &elem->base;
94 }
95 return nullptr;
96}
97
99 const bNode &node,
100 ViewerPath &r_dst)
101{
102 /* Only valid if the node space has a context object. */
103 BLI_assert(snode.id != nullptr && GS(snode.id->name) == ID_OB);
104 snode.edittree->ensure_topology_cache();
105
106 BKE_viewer_path_init(&r_dst);
107
108 bke::ComputeContextCache compute_context_cache;
110 snode, compute_context_cache, node.input_socket(0));
111 if (!socket_context) {
112 return;
113 }
114
115 Object *ob = reinterpret_cast<Object *>(snode.id);
117 id_elem->id = &ob->id;
118 BLI_addhead(&r_dst.path, id_elem);
119
120 for (const ComputeContext *context = socket_context; context; context = context->parent()) {
122 if (!elem) {
123 BKE_viewer_path_clear(&r_dst);
124 return;
125 }
126 BLI_insertlinkafter(&r_dst.path, id_elem, elem);
127 }
128
130 viewer_node_elem->node_id = node.identifier;
131 viewer_node_elem->base.ui_name = BLI_strdup(bke::node_label(*snode.edittree, node).c_str());
132 BLI_addtail(&r_dst.path, viewer_node_elem);
133}
134
136 SpaceNode &snode,
137 bNode &node,
138 std::optional<int> item_identifier)
139{
141 if (wm == nullptr) {
142 return;
143 }
144 for (bNode *iter_node : snode.edittree->all_nodes()) {
145 if (iter_node->type_legacy == GEO_NODE_VIEWER) {
146 SET_FLAG_FROM_TEST(iter_node->flag, iter_node == &node, NODE_DO_OUTPUT);
147 }
148 }
149 ViewerPath new_viewer_path{};
150 BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&new_viewer_path); });
151 if (snode.id != nullptr && GS(snode.id->name) == ID_OB) {
152 viewer_path_for_geometry_node(snode, node, new_viewer_path);
153 }
154
155 bool found_view3d_with_enabled_viewer = false;
156 View3D *any_view3d_without_viewer = nullptr;
157 LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
158 WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook);
159 bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
160 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
161 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
162 if (sl->spacetype == SPACE_SPREADSHEET) {
163 SpaceSpreadsheet &sspreadsheet = *reinterpret_cast<SpaceSpreadsheet *>(sl);
164 if (!(sspreadsheet.flag & SPREADSHEET_FLAG_PINNED)) {
165 SpreadsheetTableIDGeometry &table_id = sspreadsheet.geometry_id;
167 if (item_identifier) {
168 table_id.viewer_item_identifier = *item_identifier;
169 }
170 MEM_SAFE_FREE(table_id.bundle_path);
171 table_id.bundle_path_num = 0;
173 }
174 }
175 else if (sl->spacetype == SPACE_VIEW3D) {
176 View3D &v3d = *reinterpret_cast<View3D *>(sl);
177 if (v3d.flag2 & V3D_SHOW_VIEWER) {
178 found_view3d_with_enabled_viewer = true;
179 }
180 else {
181 any_view3d_without_viewer = &v3d;
182 }
183 }
184 }
185
186 /* Enable viewer in one viewport if it is disabled in all of them. */
187 if (!found_view3d_with_enabled_viewer && any_view3d_without_viewer != nullptr) {
188 any_view3d_without_viewer->flag2 |= V3D_SHOW_VIEWER;
189 }
190
192 BKE_viewer_path_copy(&workspace->viewer_path, &new_viewer_path);
193
194 /* Make sure the viewed data becomes available. */
197 }
198}
199
201{
202 if (BLI_listbase_count(&viewer_path.path) != 1) {
203 return nullptr;
204 }
205 const ViewerPathElem *elem = static_cast<ViewerPathElem *>(viewer_path.path.first);
206 if (elem->type != VIEWER_PATH_ELEM_TYPE_ID) {
207 return nullptr;
208 }
209 ID *id = reinterpret_cast<const IDViewerPathElem *>(elem)->id;
210 if (id == nullptr) {
211 return nullptr;
212 }
213 if (GS(id->name) != ID_OB) {
214 return nullptr;
215 }
216 return reinterpret_cast<Object *>(id);
217}
218
219std::optional<ViewerPathForGeometryNodesViewer> parse_geometry_nodes_viewer(
220 const ViewerPath &viewer_path)
221{
223 LISTBASE_FOREACH (const ViewerPathElem *, item, &viewer_path.path) {
224 elems_vec.append(item);
225 }
226
227 if (elems_vec.size() < 3) {
228 /* Need at least the object, modifier and viewer node name. */
229 return std::nullopt;
230 }
231 Span<const ViewerPathElem *> remaining_elems = elems_vec;
232 const ViewerPathElem &id_elem = *remaining_elems[0];
233 if (id_elem.type != VIEWER_PATH_ELEM_TYPE_ID) {
234 return std::nullopt;
235 }
236 ID *root_id = reinterpret_cast<const IDViewerPathElem &>(id_elem).id;
237 if (root_id == nullptr) {
238 return std::nullopt;
239 }
240 if (GS(root_id->name) != ID_OB) {
241 return std::nullopt;
242 }
243 Object *root_ob = reinterpret_cast<Object *>(root_id);
244 remaining_elems = remaining_elems.drop_front(1);
245 const ViewerPathElem &modifier_elem = *remaining_elems[0];
246 if (modifier_elem.type != VIEWER_PATH_ELEM_TYPE_MODIFIER) {
247 return std::nullopt;
248 }
249 const int modifier_uid =
250 reinterpret_cast<const ModifierViewerPathElem &>(modifier_elem).modifier_uid;
251
252 remaining_elems = remaining_elems.drop_front(1);
254 for (const ViewerPathElem *elem : remaining_elems.drop_back(1)) {
255 if (!ELEM(elem->type,
261 {
262 return std::nullopt;
263 }
264 node_path.append(elem);
265 }
266 const ViewerPathElem *last_elem = remaining_elems.last();
267 if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) {
268 return std::nullopt;
269 }
270 const int32_t viewer_node_id =
271 reinterpret_cast<const ViewerNodeViewerPathElem *>(last_elem)->node_id;
272 return ViewerPathForGeometryNodesViewer{root_ob, modifier_uid, node_path, viewer_node_id};
273}
274
276{
277 const NodesModifierData *modifier = nullptr;
278 LISTBASE_FOREACH (const ModifierData *, md, &parsed_viewer_path.object->modifiers) {
279 if (md->type != eModifierType_Nodes) {
280 continue;
281 }
282 if (md->persistent_uid != parsed_viewer_path.modifier_uid) {
283 continue;
284 }
285 modifier = reinterpret_cast<const NodesModifierData *>(md);
286 break;
287 }
288 if (modifier == nullptr) {
289 return false;
290 }
291 if (modifier->node_group == nullptr) {
292 return false;
293 }
294 const bNodeTree *ngroup = modifier->node_group;
295 const bNodeTreeZone *zone = nullptr;
296 for (const ViewerPathElem *path_elem : parsed_viewer_path.node_path) {
297 ngroup->ensure_topology_cache();
298 const bNodeTreeZones *tree_zones = ngroup->zones();
299 switch (path_elem->type) {
301 const auto &typed_elem = *reinterpret_cast<const SimulationZoneViewerPathElem *>(
302 path_elem);
303 const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
304 typed_elem.sim_output_node_id);
305 if (next_zone == nullptr) {
306 return false;
307 }
308 if (next_zone->parent_zone != zone) {
309 return false;
310 }
311 zone = next_zone;
312 break;
313 }
315 const auto &typed_elem = *reinterpret_cast<const RepeatZoneViewerPathElem *>(path_elem);
316 const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
317 typed_elem.repeat_output_node_id);
318 if (next_zone == nullptr) {
319 return false;
320 }
321 if (next_zone->parent_zone != zone) {
322 return false;
323 }
324 zone = next_zone;
325 break;
326 }
328 const auto &typed_elem =
329 *reinterpret_cast<const ForeachGeometryElementZoneViewerPathElem *>(path_elem);
330 const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
331 typed_elem.zone_output_node_id);
332 if (next_zone == nullptr) {
333 return false;
334 }
335 if (next_zone->parent_zone != zone) {
336 return false;
337 }
338 zone = next_zone;
339 break;
340 }
342 const auto &typed_elem = *reinterpret_cast<const GroupNodeViewerPathElem *>(path_elem);
343 const bNode *group_node = ngroup->node_by_id(typed_elem.node_id);
344 if (group_node == nullptr) {
345 return false;
346 }
347 const bNodeTreeZone *parent_zone = tree_zones->get_zone_by_node(typed_elem.node_id);
348 if (parent_zone != zone) {
349 return false;
350 }
351 if (group_node->id == nullptr) {
352 return false;
353 }
354 ngroup = reinterpret_cast<const bNodeTree *>(group_node->id);
355 zone = nullptr;
356 break;
357 }
359 const auto &typed_elem = *reinterpret_cast<const EvaluateClosureNodeViewerPathElem *>(
360 path_elem);
361 const bNode *evaluate_node = ngroup->node_by_id(typed_elem.evaluate_node_id);
362 if (evaluate_node == nullptr) {
363 return false;
364 }
365 const bNodeTreeZone *parent_zone = tree_zones->get_zone_by_node(
366 typed_elem.evaluate_node_id);
367 if (parent_zone != zone) {
368 return false;
369 }
370 if (!typed_elem.source_node_tree) {
371 return false;
372 }
373 const bNode *closure_output_node = typed_elem.source_node_tree->node_by_id(
374 typed_elem.source_output_node_id);
375 if (!closure_output_node) {
376 return false;
377 }
378 ngroup = typed_elem.source_node_tree;
379 const bNodeTreeZones *closure_tree_zones = typed_elem.source_node_tree->zones();
380 if (!closure_tree_zones) {
381 return false;
382 }
383 zone = closure_tree_zones->get_zone_by_node(typed_elem.source_output_node_id);
384 break;
385 }
386 default: {
388 }
389 }
390 }
391
392 const bNode *viewer_node = ngroup->node_by_id(parsed_viewer_path.viewer_node_id);
393 if (viewer_node == nullptr) {
394 return false;
395 }
396 const bNodeTreeZones *tree_zones = ngroup->zones();
397 if (tree_zones == nullptr) {
398 return false;
399 }
400 if (tree_zones->get_zone_by_node(viewer_node->identifier) != zone) {
401 return false;
402 }
403 return true;
404}
405
408{
411 }
412 const ViewerPathElem *last_elem = static_cast<ViewerPathElem *>(viewer_path.path.last);
413 if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) {
415 }
416 const int32_t viewer_node_id =
417 reinterpret_cast<const ViewerNodeViewerPathElem *>(last_elem)->node_id;
418
419 const Main *bmain = CTX_data_main(&C);
420 const wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
421 if (wm == nullptr) {
423 }
424 LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
425 const bScreen *active_screen = BKE_workspace_active_screen_get(window->workspace_hook);
426 Vector<const bScreen *> screens = {active_screen};
427 if (ELEM(active_screen->state, SCREENMAXIMIZED, SCREENFULL)) {
428 const ScrArea *area = static_cast<ScrArea *>(active_screen->areabase.first);
429 screens.append(area->full);
430 }
431 for (const bScreen *screen : screens) {
432 LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
433 const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
434 if (sl == nullptr) {
435 continue;
436 }
437 if (sl->spacetype != SPACE_NODE) {
438 continue;
439 }
440 const SpaceNode &snode = *reinterpret_cast<const SpaceNode *>(sl);
441 if (snode.edittree == nullptr) {
442 continue;
443 }
444 if (snode.edittree->type != NTREE_GEOMETRY) {
445 continue;
446 }
447 if (!snode.id) {
448 continue;
449 }
450 snode.edittree->ensure_topology_cache();
451 const bNode *viewer_node = snode.edittree->node_by_id(viewer_node_id);
452 if (viewer_node == nullptr) {
453 continue;
454 }
455 if (!(viewer_node->flag & NODE_DO_OUTPUT)) {
456 continue;
457 }
458 ViewerPath tmp_viewer_path{};
459 BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&tmp_viewer_path); });
460 viewer_path_for_geometry_node(snode, *viewer_node, tmp_viewer_path);
463 {
464 continue;
465 }
466 if (!BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) {
467 std::swap(viewer_path, tmp_viewer_path);
468 /* Make sure the viewed data becomes available. */
471 }
474 {
475 /* Only swap, without triggering a depsgraph update. */
476 std::swap(viewer_path, tmp_viewer_path);
478 }
480 }
481 }
482 }
484}
485
487{
488 /* Viewer path is only valid if the context object is set. */
489 if (snode.id == nullptr || GS(snode.id->name) != ID_OB) {
490 return nullptr;
491 }
492
493 const std::optional<ViewerPathForGeometryNodesViewer> parsed_viewer_path =
495 if (!parsed_viewer_path.has_value()) {
496 return nullptr;
497 }
498
499 snode.edittree->ensure_topology_cache();
500 bNode *possible_viewer = snode.edittree->node_by_id(parsed_viewer_path->viewer_node_id);
501 if (possible_viewer == nullptr) {
502 return nullptr;
503 }
504 ViewerPath tmp_viewer_path;
505 BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&tmp_viewer_path); });
506 viewer_path_for_geometry_node(snode, *possible_viewer, tmp_viewer_path);
507
508 if (BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) {
509 return possible_viewer;
510 }
511 return nullptr;
512}
513
515 const ViewerPathElem &elem_generic,
516 bke::ComputeContextCache &compute_context_cache,
517 const ComputeContext *parent_compute_context)
518{
519 switch (ViewerPathElemType(elem_generic.type)) {
522 return nullptr;
523 }
525 const auto &elem = reinterpret_cast<const ModifierViewerPathElem &>(elem_generic);
526 return &compute_context_cache.for_modifier(parent_compute_context, elem.modifier_uid);
527 }
529 const auto &elem = reinterpret_cast<const GroupNodeViewerPathElem &>(elem_generic);
530 return &compute_context_cache.for_group_node(parent_compute_context, elem.node_id);
531 }
533 const auto &elem = reinterpret_cast<const SimulationZoneViewerPathElem &>(elem_generic);
534 return &compute_context_cache.for_simulation_zone(parent_compute_context,
535 elem.sim_output_node_id);
536 }
538 const auto &elem = reinterpret_cast<const RepeatZoneViewerPathElem &>(elem_generic);
539 return &compute_context_cache.for_repeat_zone(
540 parent_compute_context, elem.repeat_output_node_id, elem.iteration);
541 }
543 const auto &elem = reinterpret_cast<const ForeachGeometryElementZoneViewerPathElem &>(
544 elem_generic);
545 return &compute_context_cache.for_foreach_geometry_element_zone(
546 parent_compute_context, elem.zone_output_node_id, elem.index);
547 }
549 const auto &elem = reinterpret_cast<const EvaluateClosureNodeViewerPathElem &>(elem_generic);
550 std::optional<nodes::ClosureSourceLocation> source_location;
551 if (elem.source_node_tree) {
552 source_location = nodes::ClosureSourceLocation{
553 elem.source_node_tree,
554 elem.source_output_node_id,
555 parent_compute_context ? parent_compute_context->hash() : ComputeContextHash{}};
556 }
557 return &compute_context_cache.for_evaluate_closure(
558 parent_compute_context, elem.evaluate_node_id, nullptr, source_location);
559 }
560 }
561 return nullptr;
562}
563
564} // namespace blender::ed::viewer_path
Main * CTX_data_main(const bContext *C)
const char * BKE_id_name(const ID &id)
#define GEO_NODE_VIEWER
void BKE_viewer_path_copy(ViewerPath *dst, const ViewerPath *src)
EvaluateClosureNodeViewerPathElem * BKE_viewer_path_elem_new_evaluate_closure()
ViewerNodeViewerPathElem * BKE_viewer_path_elem_new_viewer_node()
@ VIEWER_PATH_EQUAL_FLAG_IGNORE_ITERATION
@ VIEWER_PATH_EQUAL_FLAG_CONSIDER_UI_NAME
void BKE_viewer_path_clear(ViewerPath *viewer_path)
void BKE_viewer_path_init(ViewerPath *viewer_path)
SimulationZoneViewerPathElem * BKE_viewer_path_elem_new_simulation_zone()
ForeachGeometryElementZoneViewerPathElem * BKE_viewer_path_elem_new_foreach_geometry_element_zone()
GroupNodeViewerPathElem * BKE_viewer_path_elem_new_group_node()
IDViewerPathElem * BKE_viewer_path_elem_new_id()
ModifierViewerPathElem * BKE_viewer_path_elem_new_modifier()
RepeatZoneViewerPathElem * BKE_viewer_path_elem_new_repeat_zone()
bool BKE_viewer_path_equal(const ViewerPath *a, const ViewerPath *b, ViewerPathEqualFlag flag=ViewerPathEqualFlag(0))
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:614
WorkSpace * BKE_workspace_active_get(WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:563
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
#define BLI_SCOPED_DEFER(function_to_defer)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
bool DEG_is_original(const T *id)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ ID_OB
@ eModifierType_Nodes
@ NODE_DO_OUTPUT
@ NTREE_GEOMETRY
@ SCREENFULL
@ SCREENMAXIMIZED
@ SPACE_NODE
@ SPACE_SPREADSHEET
@ SPACE_VIEW3D
@ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE
@ SPREADSHEET_FLAG_PINNED
@ SPREADSHEET_CLOSURE_NONE
@ V3D_SHOW_VIEWER
@ VIEWER_PATH_ELEM_TYPE_GROUP_NODE
@ VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE
@ VIEWER_PATH_ELEM_TYPE_FOREACH_GEOMETRY_ELEMENT_ZONE
@ VIEWER_PATH_ELEM_TYPE_VIEWER_NODE
@ VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE
@ VIEWER_PATH_ELEM_TYPE_MODIFIER
@ VIEWER_PATH_ELEM_TYPE_EVALUATE_CLOSURE
@ VIEWER_PATH_ELEM_TYPE_ID
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
#define NC_VIEWER_PATH
Definition WM_types.hh:406
const ComputeContextHash & hash() const
constexpr Span drop_front(int64_t n) const
Definition BLI_span.hh:171
constexpr Span drop_back(int64_t n) const
Definition BLI_span.hh:182
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:325
int64_t size() const
void append(const T &value)
const EvaluateClosureComputeContext & for_evaluate_closure(const ComputeContext *parent, int32_t node_id, const bNodeTree *tree=nullptr, const std::optional< nodes::ClosureSourceLocation > &closure_source_location=std::nullopt)
const ModifierComputeContext & for_modifier(const ComputeContext *parent, const NodesModifierData &nmd)
const GroupNodeComputeContext & for_group_node(const ComputeContext *parent, int32_t node_id, const bNodeTree *tree=nullptr)
const ForeachGeometryElementZoneComputeContext & for_foreach_geometry_element_zone(const ComputeContext *parent, int32_t output_node_id, int index)
const RepeatZoneComputeContext & for_repeat_zone(const ComputeContext *parent, int32_t output_node_id, int iteration)
const SimulationZoneComputeContext & for_simulation_zone(const ComputeContext *parent, int output_node_id)
Vector< bNodeTreeZone * > zones
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
#define GS(x)
std::string node_label(const bNodeTree &ntree, const bNode &node)
Definition node.cc:4970
const ComputeContext * compute_context_for_edittree_socket(const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache, const bNodeSocket &socket)
ViewerPathElem * viewer_path_elem_for_compute_context(const ComputeContext &compute_context)
void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node, std::optional< int > item_identifier=std::nullopt)
Object * parse_object_only(const ViewerPath &viewer_path)
UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const bContext &C, ViewerPath &viewer_path)
std::optional< ViewerPathForGeometryNodesViewer > parse_geometry_nodes_viewer(const ViewerPath &viewer_path)
static void viewer_path_for_geometry_node(const SpaceNode &snode, const bNode &node, ViewerPath &r_dst)
bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed_viewer_path)
const ComputeContext * compute_context_for_viewer_path_elem(const ViewerPathElem &elem, bke::ComputeContextCache &compute_context_cache, const ComputeContext *parent_compute_context)
bNode * find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode)
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * first
ListBase wm
Definition BKE_main.hh:307
ListBase modifiers
bScreen * full
struct bNodeTree * edittree
struct ID * id
SpreadsheetTableIDGeometry geometry_id
SpreadsheetBundlePathElem * bundle_path
ViewerPath viewer_path
struct ID * id
int32_t identifier
ListBase areabase
blender::Vector< const ViewerPathElem * > node_path
void WM_main_add_notifier(uint type, void *reference)