Blender V4.5
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
135void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node)
136{
138 if (wm == nullptr) {
139 return;
140 }
141 for (bNode *iter_node : snode.edittree->all_nodes()) {
142 if (iter_node->type_legacy == GEO_NODE_VIEWER) {
143 SET_FLAG_FROM_TEST(iter_node->flag, iter_node == &node, NODE_DO_OUTPUT);
144 }
145 }
146 ViewerPath new_viewer_path{};
147 BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&new_viewer_path); });
148 if (snode.id != nullptr && GS(snode.id->name) == ID_OB) {
149 viewer_path_for_geometry_node(snode, node, new_viewer_path);
150 }
151
152 bool found_view3d_with_enabled_viewer = false;
153 View3D *any_view3d_without_viewer = nullptr;
154 LISTBASE_FOREACH (wmWindow *, window, &wm->windows) {
155 WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook);
156 bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
157 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
158 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
159 if (sl->spacetype == SPACE_SPREADSHEET) {
160 SpaceSpreadsheet &sspreadsheet = *reinterpret_cast<SpaceSpreadsheet *>(sl);
161 if (!(sspreadsheet.flag & SPREADSHEET_FLAG_PINNED)) {
163 }
164 }
165 else if (sl->spacetype == SPACE_VIEW3D) {
166 View3D &v3d = *reinterpret_cast<View3D *>(sl);
167 if (v3d.flag2 & V3D_SHOW_VIEWER) {
168 found_view3d_with_enabled_viewer = true;
169 }
170 else {
171 any_view3d_without_viewer = &v3d;
172 }
173 }
174 }
175
176 /* Enable viewer in one viewport if it is disabled in all of them. */
177 if (!found_view3d_with_enabled_viewer && any_view3d_without_viewer != nullptr) {
178 any_view3d_without_viewer->flag2 |= V3D_SHOW_VIEWER;
179 }
180
182 BKE_viewer_path_copy(&workspace->viewer_path, &new_viewer_path);
183
184 /* Make sure the viewed data becomes available. */
187 }
188}
189
191{
192 if (BLI_listbase_count(&viewer_path.path) != 1) {
193 return nullptr;
194 }
195 const ViewerPathElem *elem = static_cast<ViewerPathElem *>(viewer_path.path.first);
196 if (elem->type != VIEWER_PATH_ELEM_TYPE_ID) {
197 return nullptr;
198 }
199 ID *id = reinterpret_cast<const IDViewerPathElem *>(elem)->id;
200 if (id == nullptr) {
201 return nullptr;
202 }
203 if (GS(id->name) != ID_OB) {
204 return nullptr;
205 }
206 return reinterpret_cast<Object *>(id);
207}
208
209std::optional<ViewerPathForGeometryNodesViewer> parse_geometry_nodes_viewer(
210 const ViewerPath &viewer_path)
211{
213 LISTBASE_FOREACH (const ViewerPathElem *, item, &viewer_path.path) {
214 elems_vec.append(item);
215 }
216
217 if (elems_vec.size() < 3) {
218 /* Need at least the object, modifier and viewer node name. */
219 return std::nullopt;
220 }
221 Span<const ViewerPathElem *> remaining_elems = elems_vec;
222 const ViewerPathElem &id_elem = *remaining_elems[0];
223 if (id_elem.type != VIEWER_PATH_ELEM_TYPE_ID) {
224 return std::nullopt;
225 }
226 ID *root_id = reinterpret_cast<const IDViewerPathElem &>(id_elem).id;
227 if (root_id == nullptr) {
228 return std::nullopt;
229 }
230 if (GS(root_id->name) != ID_OB) {
231 return std::nullopt;
232 }
233 Object *root_ob = reinterpret_cast<Object *>(root_id);
234 remaining_elems = remaining_elems.drop_front(1);
235 const ViewerPathElem &modifier_elem = *remaining_elems[0];
236 if (modifier_elem.type != VIEWER_PATH_ELEM_TYPE_MODIFIER) {
237 return std::nullopt;
238 }
239 const int modifier_uid =
240 reinterpret_cast<const ModifierViewerPathElem &>(modifier_elem).modifier_uid;
241
242 remaining_elems = remaining_elems.drop_front(1);
244 for (const ViewerPathElem *elem : remaining_elems.drop_back(1)) {
245 if (!ELEM(elem->type,
251 {
252 return std::nullopt;
253 }
254 node_path.append(elem);
255 }
256 const ViewerPathElem *last_elem = remaining_elems.last();
257 if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) {
258 return std::nullopt;
259 }
260 const int32_t viewer_node_id =
261 reinterpret_cast<const ViewerNodeViewerPathElem *>(last_elem)->node_id;
262 return ViewerPathForGeometryNodesViewer{root_ob, modifier_uid, node_path, viewer_node_id};
263}
264
266{
267 const NodesModifierData *modifier = nullptr;
268 LISTBASE_FOREACH (const ModifierData *, md, &parsed_viewer_path.object->modifiers) {
269 if (md->type != eModifierType_Nodes) {
270 continue;
271 }
272 if (md->persistent_uid != parsed_viewer_path.modifier_uid) {
273 continue;
274 }
275 modifier = reinterpret_cast<const NodesModifierData *>(md);
276 break;
277 }
278 if (modifier == nullptr) {
279 return false;
280 }
281 if (modifier->node_group == nullptr) {
282 return false;
283 }
284 const bNodeTree *ngroup = modifier->node_group;
285 const bNodeTreeZone *zone = nullptr;
286 for (const ViewerPathElem *path_elem : parsed_viewer_path.node_path) {
287 ngroup->ensure_topology_cache();
288 const bNodeTreeZones *tree_zones = ngroup->zones();
289 switch (path_elem->type) {
291 const auto &typed_elem = *reinterpret_cast<const SimulationZoneViewerPathElem *>(
292 path_elem);
293 const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
294 typed_elem.sim_output_node_id);
295 if (next_zone == nullptr) {
296 return false;
297 }
298 if (next_zone->parent_zone != zone) {
299 return false;
300 }
301 zone = next_zone;
302 break;
303 }
305 const auto &typed_elem = *reinterpret_cast<const RepeatZoneViewerPathElem *>(path_elem);
306 const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
307 typed_elem.repeat_output_node_id);
308 if (next_zone == nullptr) {
309 return false;
310 }
311 if (next_zone->parent_zone != zone) {
312 return false;
313 }
314 zone = next_zone;
315 break;
316 }
318 const auto &typed_elem =
319 *reinterpret_cast<const ForeachGeometryElementZoneViewerPathElem *>(path_elem);
320 const bNodeTreeZone *next_zone = tree_zones->get_zone_by_node(
321 typed_elem.zone_output_node_id);
322 if (next_zone == nullptr) {
323 return false;
324 }
325 if (next_zone->parent_zone != zone) {
326 return false;
327 }
328 zone = next_zone;
329 break;
330 }
332 const auto &typed_elem = *reinterpret_cast<const GroupNodeViewerPathElem *>(path_elem);
333 const bNode *group_node = ngroup->node_by_id(typed_elem.node_id);
334 if (group_node == nullptr) {
335 return false;
336 }
337 const bNodeTreeZone *parent_zone = tree_zones->get_zone_by_node(typed_elem.node_id);
338 if (parent_zone != zone) {
339 return false;
340 }
341 if (group_node->id == nullptr) {
342 return false;
343 }
344 ngroup = reinterpret_cast<const bNodeTree *>(group_node->id);
345 zone = nullptr;
346 break;
347 }
349 const auto &typed_elem = *reinterpret_cast<const EvaluateClosureNodeViewerPathElem *>(
350 path_elem);
351 const bNode *evaluate_node = ngroup->node_by_id(typed_elem.evaluate_node_id);
352 if (evaluate_node == nullptr) {
353 return false;
354 }
355 const bNodeTreeZone *parent_zone = tree_zones->get_zone_by_node(
356 typed_elem.evaluate_node_id);
357 if (parent_zone != zone) {
358 return false;
359 }
360 if (!typed_elem.source_node_tree) {
361 return false;
362 }
363 const bNode *closure_output_node = typed_elem.source_node_tree->node_by_id(
364 typed_elem.source_output_node_id);
365 if (!closure_output_node) {
366 return false;
367 }
368 ngroup = typed_elem.source_node_tree;
369 const bNodeTreeZones *closure_tree_zones = typed_elem.source_node_tree->zones();
370 if (!closure_tree_zones) {
371 return false;
372 }
373 zone = closure_tree_zones->get_zone_by_node(typed_elem.source_output_node_id);
374 break;
375 }
376 default: {
378 }
379 }
380 }
381
382 const bNode *viewer_node = ngroup->node_by_id(parsed_viewer_path.viewer_node_id);
383 if (viewer_node == nullptr) {
384 return false;
385 }
386 const bNodeTreeZones *tree_zones = ngroup->zones();
387 if (tree_zones == nullptr) {
388 return false;
389 }
390 if (tree_zones->get_zone_by_node(viewer_node->identifier) != zone) {
391 return false;
392 }
393 return true;
394}
395
398{
401 }
402 const ViewerPathElem *last_elem = static_cast<ViewerPathElem *>(viewer_path.path.last);
403 if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) {
405 }
406 const int32_t viewer_node_id =
407 reinterpret_cast<const ViewerNodeViewerPathElem *>(last_elem)->node_id;
408
409 const Main *bmain = CTX_data_main(&C);
410 const wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
411 if (wm == nullptr) {
413 }
414 LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
415 const bScreen *active_screen = BKE_workspace_active_screen_get(window->workspace_hook);
416 Vector<const bScreen *> screens = {active_screen};
417 if (ELEM(active_screen->state, SCREENMAXIMIZED, SCREENFULL)) {
418 const ScrArea *area = static_cast<ScrArea *>(active_screen->areabase.first);
419 screens.append(area->full);
420 }
421 for (const bScreen *screen : screens) {
422 LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
423 const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
424 if (sl == nullptr) {
425 continue;
426 }
427 if (sl->spacetype != SPACE_NODE) {
428 continue;
429 }
430 const SpaceNode &snode = *reinterpret_cast<const SpaceNode *>(sl);
431 if (snode.edittree == nullptr) {
432 continue;
433 }
434 if (snode.edittree->type != NTREE_GEOMETRY) {
435 continue;
436 }
437 if (!snode.id) {
438 continue;
439 }
440 snode.edittree->ensure_topology_cache();
441 const bNode *viewer_node = snode.edittree->node_by_id(viewer_node_id);
442 if (viewer_node == nullptr) {
443 continue;
444 }
445 if (!(viewer_node->flag & NODE_DO_OUTPUT)) {
446 continue;
447 }
448 ViewerPath tmp_viewer_path{};
449 BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&tmp_viewer_path); });
450 viewer_path_for_geometry_node(snode, *viewer_node, tmp_viewer_path);
453 {
454 continue;
455 }
456 if (!BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) {
457 std::swap(viewer_path, tmp_viewer_path);
458 /* Make sure the viewed data becomes available. */
461 }
464 {
465 /* Only swap, without triggering a depsgraph update.*/
466 std::swap(viewer_path, tmp_viewer_path);
468 }
470 }
471 }
472 }
474}
475
477{
478 /* Viewer path is only valid if the context object is set. */
479 if (snode.id == nullptr || GS(snode.id->name) != ID_OB) {
480 return nullptr;
481 }
482
483 const std::optional<ViewerPathForGeometryNodesViewer> parsed_viewer_path =
485 if (!parsed_viewer_path.has_value()) {
486 return nullptr;
487 }
488
489 snode.edittree->ensure_topology_cache();
490 bNode *possible_viewer = snode.edittree->node_by_id(parsed_viewer_path->viewer_node_id);
491 if (possible_viewer == nullptr) {
492 return nullptr;
493 }
494 ViewerPath tmp_viewer_path;
495 BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&tmp_viewer_path); });
496 viewer_path_for_geometry_node(snode, *possible_viewer, tmp_viewer_path);
497
498 if (BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) {
499 return possible_viewer;
500 }
501 return nullptr;
502}
503
505 const ViewerPathElem &elem_generic,
506 bke::ComputeContextCache &compute_context_cache,
507 const ComputeContext *parent_compute_context)
508{
509 switch (ViewerPathElemType(elem_generic.type)) {
512 return nullptr;
513 }
515 const auto &elem = reinterpret_cast<const ModifierViewerPathElem &>(elem_generic);
516 return &compute_context_cache.for_modifier(parent_compute_context, elem.modifier_uid);
517 }
519 const auto &elem = reinterpret_cast<const GroupNodeViewerPathElem &>(elem_generic);
520 return &compute_context_cache.for_group_node(parent_compute_context, elem.node_id);
521 }
523 const auto &elem = reinterpret_cast<const SimulationZoneViewerPathElem &>(elem_generic);
524 return &compute_context_cache.for_simulation_zone(parent_compute_context,
525 elem.sim_output_node_id);
526 }
528 const auto &elem = reinterpret_cast<const RepeatZoneViewerPathElem &>(elem_generic);
529 return &compute_context_cache.for_repeat_zone(
530 parent_compute_context, elem.repeat_output_node_id, elem.iteration);
531 }
533 const auto &elem = reinterpret_cast<const ForeachGeometryElementZoneViewerPathElem &>(
534 elem_generic);
535 return &compute_context_cache.for_foreach_geometry_element_zone(
536 parent_compute_context, elem.zone_output_node_id, elem.index);
537 }
539 const auto &elem = reinterpret_cast<const EvaluateClosureNodeViewerPathElem &>(elem_generic);
540 std::optional<nodes::ClosureSourceLocation> source_location;
541 if (elem.source_node_tree) {
542 source_location = nodes::ClosureSourceLocation{
543 elem.source_node_tree,
544 elem.source_output_node_id,
545 parent_compute_context ? parent_compute_context->hash() : ComputeContextHash{}};
546 }
547 return &compute_context_cache.for_evaluate_closure(
548 parent_compute_context, elem.evaluate_node_id, nullptr, source_location);
549 }
550 }
551 return nullptr;
552}
553
554} // 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:612
WorkSpace * BKE_workspace_active_get(WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:561
#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:982
@ ID_OB
@ eModifierType_Nodes
@ NTREE_GEOMETRY
@ NODE_DO_OUTPUT
@ SCREENFULL
@ SCREENMAXIMIZED
@ SPACE_NODE
@ SPACE_SPREADSHEET
@ SPACE_VIEW3D
@ SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE
@ SPREADSHEET_FLAG_PINNED
@ 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 C
Definition RandGen.cpp:29
#define NC_VIEWER_PATH
Definition WM_types.hh:403
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(a)
std::string node_label(const bNodeTree &ntree, const bNode &node)
Definition node.cc:5242
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)
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)
void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node)
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:404
char name[66]
Definition DNA_ID.h:415
void * first
ListBase wm
Definition BKE_main.hh:276
ListBase modifiers
bScreen * full
struct bNodeTree * edittree
struct ID * id
SpreadsheetTableIDGeometry geometry_id
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)