From b20e2fe2d10a8021046da40809929c32a4c5dab4 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Fri, 8 Sep 2023 18:18:11 +0300 Subject: [PATCH 01/15] init --- source/blender/blenkernel/BKE_node.hh | 2 ++ source/blender/blenkernel/BKE_node_runtime.hh | 5 +++ source/blender/blenkernel/intern/node.cc | 6 ++++ .../blenkernel/intern/node_tree_update.cc | 32 +++++++++++++++++++ .../blender/editors/space_node/node_draw.cc | 8 +++-- source/blender/makesdna/DNA_node_types.h | 5 +++ .../blender/makesrna/intern/rna_nodetree.cc | 6 ++++ 7 files changed, 62 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.hh b/source/blender/blenkernel/BKE_node.hh index fa8234d2488..277e2cd0416 100644 --- a/source/blender/blenkernel/BKE_node.hh +++ b/source/blender/blenkernel/BKE_node.hh @@ -122,6 +122,8 @@ bool nodeLinkIsSelected(const bNodeLink *link); void nodeInternalRelink(bNodeTree *ntree, bNode *node); +bool node_is_viewer_group(const bNode &node); + float2 nodeToView(const bNode *node, float2 loc); float2 nodeFromView(const bNode *node, float2 view_loc); diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index 57035fcc184..1c339ec847f 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -564,6 +564,11 @@ inline blender::Span bNodeTree::interface_items() cons return this->runtime->interface_cache.items; } +inline bool bNodeTree::is_viewer() const +{ + return this->flag & NTREE_IS_VIEWER; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 69f0937e7f3..3bac63c4ea7 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -3665,6 +3665,12 @@ void nodeSetActive(bNodeTree *ntree, bNode *node) namespace blender::bke { +bool node_is_viewer_group(const bNode &node) +{ + const bNodeTree *tree = reinterpret_cast(node.id); + return node.is_group() && (tree != nullptr) && tree->is_viewer(); +} + void nodeSetSocketAvailability(bNodeTree *ntree, bNodeSocket *sock, const bool is_available) { if (is_available == sock->is_available()) { diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index 9694d665649..846cc6764cd 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -480,6 +480,8 @@ class NodeTreeMainUpdater { this->remove_unused_previews_when_necessary(ntree); this->make_node_previews_dirty(ntree); + this->propagate_viewers(ntree); + this->propagate_runtime_flags(ntree); if (ntree.type == NTREE_GEOMETRY) { if (node_field_inferencing::update_field_inferencing(ntree)) { @@ -737,6 +739,36 @@ class NodeTreeMainUpdater { } } + void propagate_viewers(bNodeTree &ntree) + { + ntree.ensure_topology_cache(); + ntree.flag &= ~NTREE_IS_VIEWER; + if (!ntree.interface_outputs().is_empty()) { + return; + } + + const Span viewers = ntree.nodes_by_type("GeometryNodeViewer"); + const Span groups = ntree.group_nodes(); + + const bNode *viewer_node = viewers.size() != 1 ? nullptr : viewers.first(); + const bNode *viewer_group = [&]() -> bNode * { + bNode *viewer_group = nullptr; + for (bNode *group_node : groups) { + if (bke::node_is_viewer_group(*group_node)) { + if (viewer_group != nullptr) { + return nullptr; + } + viewer_group = group_node; + } + } + return viewer_group; + }(); + + if ((viewer_node == nullptr) != (viewer_group == nullptr)) { + ntree.flag |= NTREE_IS_VIEWER; + } + } + void propagate_runtime_flags(const bNodeTree &ntree) { ntree.ensure_topology_cache(); diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 2a4cef0b10d..f0d6e77e827 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -795,8 +795,12 @@ static int node_get_colorid(TreeDrawContext &tree_draw_ctx, const bNode &node) return TH_NODE_VECTOR; case NODE_CLASS_OP_FILTER: return TH_NODE_FILTER; - case NODE_CLASS_GROUP: + case NODE_CLASS_GROUP: { + if (bke::node_is_viewer_group(node)) { + return &node == tree_draw_ctx.active_geometry_nodes_viewer ? TH_NODE_OUTPUT : TH_NODE; + } return TH_NODE_GROUP; + } case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE; case NODE_CLASS_MATTE: @@ -2650,7 +2654,7 @@ static void node_draw_basis(const bContext &C, ""); UI_block_emboss_set(&block, UI_EMBOSS); } - if (node.type == GEO_NODE_VIEWER) { + if (node.type == GEO_NODE_VIEWER || bke::node_is_viewer_group(node)) { const bool is_active = &node == tree_draw_ctx.active_geometry_nodes_viewer; iconofs -= iconbutw; UI_block_emboss_set(&block, UI_EMBOSS_NONE); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index ca227d2a3a9..749c213f4c4 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -712,6 +712,8 @@ typedef struct bNodeTree { [[nodiscard]] bool node_id_path_from_nested_node_ref(const int32_t nested_node_id, blender::Vector &r_node_ids) const; + bool is_viewer() const; + /** * Update a run-time cache for the node tree based on it's current state. This makes many methods * available which allow efficient lookup for topology information (like neighboring sockets). @@ -804,6 +806,9 @@ enum { * NOTE: DEPRECATED, use (id->tag & LIB_TAG_LOCALIZED) instead. */ // NTREE_IS_LOCALIZED = 1 << 5, + + /** Viuwer subtype of node tree. */ + NTREE_IS_VIEWER, }; /* tree->execution_mode */ diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 38c2d4ee572..60b0ecc6073 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -10099,6 +10099,12 @@ static void rna_def_nodetree(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil data-block"); RNA_def_property_update(prop, NC_NODE, nullptr); + prop = RNA_def_property(srna, "is_viewer", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "flag", NTREE_IS_VIEWER); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Is Viewer Group", "Node Group can be used as Viewer node"); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, nullptr); + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, static_type_items); -- 2.30.2 From bbc0e50abd5cd1cbe67dacf8fbb02db92e5230f5 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Fri, 8 Sep 2023 21:56:41 +0300 Subject: [PATCH 02/15] progress --- source/blender/blenkernel/BKE_viewer_path.h | 1 + .../blender/blenkernel/intern/viewer_path.cc | 29 +++++++++++++++++++ .../blender/editors/space_node/node_edit.cc | 22 +++++--------- .../blender/editors/space_node/node_select.cc | 7 +++++ source/blender/editors/util/ed_viewer_path.cc | 5 +++- source/blender/makesdna/DNA_node_types.h | 2 +- .../blender/makesdna/DNA_viewer_path_types.h | 8 +++++ 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/BKE_viewer_path.h b/source/blender/blenkernel/BKE_viewer_path.h index fa871166ece..2139c523d1b 100644 --- a/source/blender/blenkernel/BKE_viewer_path.h +++ b/source/blender/blenkernel/BKE_viewer_path.h @@ -50,6 +50,7 @@ ModifierViewerPathElem *BKE_viewer_path_elem_new_modifier(void); GroupNodeViewerPathElem *BKE_viewer_path_elem_new_group_node(void); SimulationZoneViewerPathElem *BKE_viewer_path_elem_new_simulation_zone(void); ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node(void); +ViewerNodeGroupViewerPathElem *BKE_viewer_path_elem_new_viewer_node_group(void); RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone(void); ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src); bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b); diff --git a/source/blender/blenkernel/intern/viewer_path.cc b/source/blender/blenkernel/intern/viewer_path.cc index 2c3783631ad..d6b89e9c05f 100644 --- a/source/blender/blenkernel/intern/viewer_path.cc +++ b/source/blender/blenkernel/intern/viewer_path.cc @@ -78,6 +78,11 @@ void BKE_viewer_path_blend_write(BlendWriter *writer, const ViewerPath *viewer_p BLO_write_struct(writer, GroupNodeViewerPathElem, typed_elem); break; } + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { + const auto *typed_elem = reinterpret_cast(elem); + BLO_write_struct(writer, ViewerNodeGroupViewerPathElem, typed_elem); + break; + } case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { const auto *typed_elem = reinterpret_cast(elem); BLO_write_struct(writer, SimulationZoneViewerPathElem, typed_elem); @@ -107,6 +112,7 @@ void BKE_viewer_path_blend_read_data(BlendDataReader *reader, ViewerPath *viewer case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: case VIEWER_PATH_ELEM_TYPE_ID: { break; @@ -131,6 +137,7 @@ void BKE_viewer_path_foreach_id(LibraryForeachIDData *data, ViewerPath *viewer_p } case VIEWER_PATH_ELEM_TYPE_MODIFIER: case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: { @@ -151,6 +158,7 @@ void BKE_viewer_path_id_remap(ViewerPath *viewer_path, const IDRemapper *mapping } case VIEWER_PATH_ELEM_TYPE_MODIFIER: case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: { @@ -179,6 +187,9 @@ ViewerPathElem *BKE_viewer_path_elem_new(const ViewerPathElemType type) case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: { return &make_elem(type)->base; } + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { + return &make_elem(type)->base; + } case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { return &make_elem(type)->base; } @@ -222,6 +233,12 @@ ViewerNodeViewerPathElem *BKE_viewer_path_elem_new_viewer_node() BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_VIEWER_NODE)); } +ViewerNodeGroupViewerPathElem *BKE_viewer_path_elem_new_viewer_node_group() +{ + return reinterpret_cast( + BKE_viewer_path_elem_new(VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP)); +} + RepeatZoneViewerPathElem *BKE_viewer_path_elem_new_repeat_zone() { return reinterpret_cast( @@ -255,6 +272,12 @@ ViewerPathElem *BKE_viewer_path_elem_copy(const ViewerPathElem *src) new_elem->node_id = old_elem->node_id; break; } + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { + const auto *old_elem = reinterpret_cast(src); + auto *new_elem = reinterpret_cast(dst); + new_elem->node_id = old_elem->node_id; + break; + } case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { const auto *old_elem = reinterpret_cast(src); auto *new_elem = reinterpret_cast(dst); @@ -299,6 +322,11 @@ bool BKE_viewer_path_elem_equal(const ViewerPathElem *a, const ViewerPathElem *b const auto *b_elem = reinterpret_cast(b); return a_elem->node_id == b_elem->node_id; } + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { + const auto *a_elem = reinterpret_cast(a); + const auto *b_elem = reinterpret_cast(b); + return a_elem->node_id == b_elem->node_id; + } case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { const auto *a_elem = reinterpret_cast(a); const auto *b_elem = reinterpret_cast(b); @@ -324,6 +352,7 @@ void BKE_viewer_path_elem_free(ViewerPathElem *elem) switch (ViewerPathElemType(elem->type)) { case VIEWER_PATH_ELEM_TYPE_ID: case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: { diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 661369d284d..f067271b77c 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -696,7 +696,7 @@ void ED_node_set_active( } nodeSetActive(ntree, node); - if (node->type == NODE_GROUP) { + if (node->is_group() && !blender::bke::node_is_viewer_group(*node)) { return; } @@ -818,10 +818,10 @@ void ED_node_set_active( } } else if (ntree->type == NTREE_GEOMETRY) { - if (node->type == GEO_NODE_VIEWER) { + if (node->type == GEO_NODE_VIEWER || blender::bke::node_is_viewer_group(*node)) { if ((node->flag & NODE_DO_OUTPUT) == 0) { for (bNode *node_iter : ntree->all_nodes()) { - if (node_iter->type == GEO_NODE_VIEWER) { + if (node_iter->type == GEO_NODE_VIEWER || blender::bke::node_is_viewer_group(*node)) { node_iter->flag &= ~NODE_DO_OUTPUT; } } @@ -1701,19 +1701,11 @@ static int node_deactivate_viewer_exec(bContext *C, wmOperator * /*op*/) bNode *active_viewer = viewer_path::find_geometry_nodes_viewer(workspace.viewer_path, snode); - for (bNode *node : snode.edittree->all_nodes()) { - if (node->type != GEO_NODE_VIEWER) { - continue; - } - if (!(node->flag & SELECT)) { - continue; - } - if (node == active_viewer) { - node->flag &= ~NODE_DO_OUTPUT; - BKE_ntree_update_tag_node_property(snode.edittree, node); - } + if (active_viewer == nullptr) { + return OPERATOR_FINISHED; } - + active_viewer->flag &= ~NODE_DO_OUTPUT; + BKE_ntree_update_tag_node_property(snode.edittree, active_viewer); ED_node_tree_propagate_change(C, CTX_data_main(C), snode.edittree); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 387f65e83fc..c29ce9538a5 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -6,6 +6,8 @@ * \ingroup spnode */ +#include + #include #include @@ -687,14 +689,18 @@ static bool node_mouse_select(bContext *C, return false; } + std::cout << __func__ << std::endl; + bool active_texture_changed = false; bool viewer_node_changed = false; if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) { viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed); + std::cout << __LINE__ << std::endl; } else if (node != nullptr && node->type == GEO_NODE_VIEWER) { viewer_path::activate_geometry_node(bmain, snode, *node); + std::cout << __LINE__ << std::endl; } ED_node_set_active_viewer_key(&snode); node_sort(node_tree); @@ -702,6 +708,7 @@ static bool node_mouse_select(bContext *C, viewer_node_changed) { DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE); + std::cout << __LINE__ << std::endl; } WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index a80248f0f91..1186cb5fb14 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -2,8 +2,10 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "ED_viewer_path.hh" +#include + #include "ED_screen.hh" +#include "ED_viewer_path.hh" #include "BKE_context.h" #include "BKE_main.h" @@ -137,6 +139,7 @@ static void viewer_path_for_geometry_node(const SpaceNode &snode, void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node) { + std::cout << __func__ << ": " << node.name << std::endl; wmWindowManager *wm = (wmWindowManager *)bmain.wm.first; if (wm == nullptr) { return; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 749c213f4c4..e7410805834 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -807,7 +807,7 @@ enum { */ // NTREE_IS_LOCALIZED = 1 << 5, - /** Viuwer subtype of node tree. */ + /** Viewer subtype of node tree. */ NTREE_IS_VIEWER, }; diff --git a/source/blender/makesdna/DNA_viewer_path_types.h b/source/blender/makesdna/DNA_viewer_path_types.h index 0c942962bb8..3de46b6b0e2 100644 --- a/source/blender/makesdna/DNA_viewer_path_types.h +++ b/source/blender/makesdna/DNA_viewer_path_types.h @@ -16,6 +16,7 @@ typedef enum ViewerPathElemType { VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE = 3, VIEWER_PATH_ELEM_TYPE_VIEWER_NODE = 4, VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE = 5, + VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP = 6, } ViewerPathElemType; typedef struct ViewerPathElem { @@ -42,6 +43,13 @@ typedef struct GroupNodeViewerPathElem { char _pad1[4]; } GroupNodeViewerPathElem; +typedef struct ViewerNodeGroupViewerPathElem { + ViewerPathElem base; + + int32_t node_id; + char _pad1[4]; +} ViewerNodeGroupViewerPathElem; + typedef struct SimulationZoneViewerPathElem { ViewerPathElem base; -- 2.30.2 From 5a26bf0d7cc277da1fe1c4a5ac59ab97174390b3 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sat, 9 Sep 2023 03:41:33 +0300 Subject: [PATCH 03/15] progress --- .../editors/screen/workspace_listen.cc | 3 + source/blender/editors/util/ed_viewer_path.cc | 40 +- source/blender/modifiers/intern/MOD_nodes.cc | 425 +++++++++++++----- .../intern/geometry_nodes_lazy_function.cc | 1 + .../nodes/intern/geometry_nodes_log.cc | 90 ++++ 5 files changed, 439 insertions(+), 120 deletions(-) diff --git a/source/blender/editors/screen/workspace_listen.cc b/source/blender/editors/screen/workspace_listen.cc index 8da2e451649..7358b34049c 100644 --- a/source/blender/editors/screen/workspace_listen.cc +++ b/source/blender/editors/screen/workspace_listen.cc @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include + #include "BKE_context.h" #include "ED_screen.hh" @@ -24,6 +26,7 @@ static void validate_viewer_paths(bContext &C, WorkSpace &workspace) /* The current viewer path is still valid and active. */ return; } + std::cout << __func__ << std::endl; /* Reset inactive viewer path. */ BKE_viewer_path_clear(&workspace.viewer_path); WM_event_add_notifier(&C, NC_VIEWER_PATH, nullptr); diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index 1186cb5fb14..705238da070 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -131,10 +131,20 @@ static void viewer_path_for_geometry_node(const SpaceNode &snode, BLI_addtail(&r_dst.path, zone_elem); } - ViewerNodeViewerPathElem *viewer_node_elem = BKE_viewer_path_elem_new_viewer_node(); - viewer_node_elem->node_id = node.identifier; - viewer_node_elem->base.ui_name = BLI_strdup(node.name); - BLI_addtail(&r_dst.path, viewer_node_elem); + if (node.type == GEO_NODE_VIEWER) { + ViewerNodeViewerPathElem *viewer_node_elem = BKE_viewer_path_elem_new_viewer_node(); + viewer_node_elem->node_id = node.identifier; + viewer_node_elem->base.ui_name = BLI_strdup(node.name); + BLI_addtail(&r_dst.path, viewer_node_elem); + } + + if (bke::node_is_viewer_group(node)) { + ViewerNodeGroupViewerPathElem *viewer_node_group_elem = + BKE_viewer_path_elem_new_viewer_node_group(); + viewer_node_group_elem->node_id = node.identifier; + viewer_node_group_elem->base.ui_name = BLI_strdup(node.name); + BLI_addtail(&r_dst.path, viewer_node_group_elem); + } } void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node) @@ -260,16 +270,23 @@ std::optional parse_geometry_nodes_viewer( node_path.append(elem); } const ViewerPathElem *last_elem = remaining_elems.last(); - if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) { - return std::nullopt; + if (last_elem->type == VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) { + const int32_t viewer_node_id = + reinterpret_cast(last_elem)->node_id; + return ViewerPathForGeometryNodesViewer{root_ob, modifier_name, node_path, viewer_node_id}; } - const int32_t viewer_node_id = - reinterpret_cast(last_elem)->node_id; - return ViewerPathForGeometryNodesViewer{root_ob, modifier_name, node_path, viewer_node_id}; + if (last_elem->type == VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP) { + const int32_t viewer_node_group_id = + reinterpret_cast(last_elem)->node_id; + return ViewerPathForGeometryNodesViewer{ + root_ob, modifier_name, node_path, viewer_node_group_id}; + } + return std::nullopt; } bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed_viewer_path) { + // TODO const NodesModifierData *modifier = nullptr; LISTBASE_FOREACH (const ModifierData *, md, &parsed_viewer_path.object->modifiers) { if (md->type != eModifierType_Nodes) { @@ -363,7 +380,10 @@ bool is_active_geometry_nodes_viewer(const bContext &C, const ViewerPath &viewer return false; } const ViewerPathElem *last_elem = static_cast(viewer_path.path.last); - if (last_elem->type != VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) { + if (!ELEM(last_elem->type, + VIEWER_PATH_ELEM_TYPE_VIEWER_NODE, + VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP)) + { return false; } const int32_t viewer_node_id = diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 8a55c8b257a..968575ded3c 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -417,6 +417,312 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd) namespace blender { +/* TODO: Validate viewer path zones / groups stack (next_zone->parent_zone != zone, ...) IDK WHY + * THIS CAN BE BUT... */ + +using SideEffectNodes = MultiValueMap; + +static bool side_effects_for_simulation( + const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info, + const bke::bNodeTreeZones &tree_zones, + const bNode &simulation_output, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + const bke::bNodeTreeZone *simulation_zone = tree_zones.get_zone_by_node( + simulation_output.identifier); + if (simulation_zone == nullptr) { + return false; + } + const lf::FunctionNode *lf_zone_node = lf_graph_info.mapping.zone_node_map.lookup_default( + simulation_zone, nullptr); + if (lf_zone_node == nullptr) { + return false; + } + local_side_effect_nodes.add(compute_context_builder.hash(), lf_zone_node); + compute_context_builder.push(*simulation_zone->output_node); + return true; +} + +static bool side_effects_for_repeat(const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info, + const bke::bNodeTreeZones &tree_zones, + const bNode &repeat_output, + const int iteration, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + const bke::bNodeTreeZone *repeat_zone = tree_zones.get_zone_by_node(repeat_output.identifier); + if (repeat_zone == nullptr) { + return false; + } + const lf::FunctionNode *lf_zone_node = lf_graph_info.mapping.zone_node_map.lookup_default( + repeat_zone, nullptr); + if (lf_zone_node == nullptr) { + return false; + } + local_side_effect_nodes.add(compute_context_builder.hash(), lf_zone_node); + compute_context_builder.push(*repeat_zone->output_node, + iteration); + return true; +} + +static bool side_effects_for_group(const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info, + const bNode &node, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + if (node.id == nullptr) { + return false; + } + if (node.is_muted()) { + return false; + } + const lf::FunctionNode *lf_group_node = lf_graph_info.mapping.group_node_map.lookup_default( + &node, nullptr); + if (lf_group_node == nullptr) { + return false; + } + local_side_effect_nodes.add(compute_context_builder.hash(), lf_group_node); + compute_context_builder.push(node); + return true; +} + +static bool side_effects_for_viewer(const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info, + const bNode &viewer, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + const lf::FunctionNode *lf_viewer_node = lf_graph_info.mapping.viewer_node_map.lookup_default( + &viewer, nullptr); + if (lf_viewer_node == nullptr) { + return false; + } + local_side_effect_nodes.add(compute_context_builder.hash(), lf_viewer_node); + return true; +} + +static bool side_effects_for_group_viewer( + const nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info, + const bNode &viewer, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + BLI_assert(bke::node_is_viewer_group(viewer)); + const bNodeTree *iter_node_tree = reinterpret_cast(viewer.id); + const lf::FunctionNode *lf_viewer_group = lf_graph_info.mapping.group_node_map.lookup_default( + &viewer, nullptr); + if (lf_viewer_group == nullptr) { + return false; + } + local_side_effect_nodes.add(compute_context_builder.hash(), lf_viewer_group); + compute_context_builder.push(viewer); + + const auto lookup_viewer = [&](const bNodeTree &tree) -> const bNode * { + BLI_assert(tree.is_viewer()); + tree.ensure_topology_cache(); + const Span viewers = tree.nodes_by_type("GeometryNodeViewer"); + const Span groups = tree.group_nodes(); + if (viewers.size() == 1) { + return viewers.first(); + } + for (const bNode *group_node : groups) { + if (bke::node_is_viewer_group(*group_node)) { + return group_node; + } + } + return nullptr; + }; + + while (const bNode *viewer = lookup_viewer(*iter_node_tree)) { + const bke::bNodeTreeZones *tree_zones = iter_node_tree->zones(); + const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*iter_node_tree); + if (ELEM(nullptr, tree_zones, lf_graph_info)) { + return false; + } + for (const bke::bNodeTreeZone *zone : tree_zones->get_zone_stack_for_node(viewer->identifier)) + { + if (zone->output_node == nullptr) { + return false; + } + const bNode &zone_output = *zone->output_node; + switch (zone_output.type) { + case GEO_NODE_SIMULATION_OUTPUT: { + if (!side_effects_for_simulation(*lf_graph_info, + *tree_zones, + zone_output, + compute_context_builder, + local_side_effect_nodes)) + { + return false; + } + break; + } + case GEO_NODE_REPEAT_OUTPUT: { + if (!side_effects_for_repeat(*lf_graph_info, + *tree_zones, + zone_output, + 0, + compute_context_builder, + local_side_effect_nodes)) + { + return false; + } + break; + } + default: { + BLI_assert_unreachable(); + } + } + } + if (viewer->type == GEO_NODE_VIEWER) { + if (!side_effects_for_viewer( + *lf_graph_info, *viewer, compute_context_builder, local_side_effect_nodes)) + { + return false; + } + return true; + } + if (!side_effects_for_group( + *lf_graph_info, *viewer, compute_context_builder, local_side_effect_nodes)) + { + return false; + } + iter_node_tree = reinterpret_cast(viewer->id); + if (iter_node_tree == nullptr) { + return false; + } + } + + return true; +} + +static bool side_effects_for_viewer_path(const Span node_path, + const bNodeTree &root_group, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + const bNodeTree *iter_group = &root_group; + for (const ViewerPathElem *elem : node_path) { + const bke::bNodeTreeZones *tree_zones = iter_group->zones(); + const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*iter_group); + if (ELEM(nullptr, tree_zones, lf_graph_info)) { + return false; + } + switch (elem->type) { + case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { + const auto &typed_elem = *reinterpret_cast(elem); + const bNode *simulation_output = iter_group->node_by_id(typed_elem.sim_output_node_id); + if (simulation_output == nullptr) { + return false; + } + if (!side_effects_for_simulation(*lf_graph_info, + *tree_zones, + *simulation_output, + compute_context_builder, + local_side_effect_nodes)) + { + return false; + } + break; + } + case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: { + const auto &typed_elem = *reinterpret_cast(elem); + const bNode *repeat_output = iter_group->node_by_id(typed_elem.repeat_output_node_id); + const int iteration = typed_elem.iteration; + if (repeat_output == nullptr) { + return false; + } + if (!side_effects_for_repeat(*lf_graph_info, + *tree_zones, + *repeat_output, + iteration, + compute_context_builder, + local_side_effect_nodes)) + { + return false; + } + break; + } + case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: { + const auto &typed_elem = *reinterpret_cast(elem); + const bNode *node_group = iter_group->node_by_id(typed_elem.node_id); + if (node_group == nullptr) { + return false; + } + if (!side_effects_for_group( + *lf_graph_info, *node_group, compute_context_builder, local_side_effect_nodes)) + { + return false; + } + iter_group = reinterpret_cast(node_group->id); + break; + } + default: { + BLI_assert_unreachable(); + return false; + } + } + } + return true; +} + +static const bNodeTree *top_tree_from_viewer_path( + const ed::viewer_path::ViewerPathForGeometryNodesViewer &path, const bNodeTree &root_node_tree) +{ + const bNodeTree *iter_node_tree = &root_node_tree; + for (const ViewerPathElem *elem : path.node_path) { + if (elem->type == VIEWER_PATH_ELEM_TYPE_GROUP_NODE) { + const auto &typed_elem = *reinterpret_cast(elem); + const bNode *node_group = iter_node_tree->node_by_id(typed_elem.node_id); + if (node_group != nullptr && node_group->id != nullptr) { + iter_node_tree = reinterpret_cast(node_group->id); + continue; + } + return nullptr; + } + } + return iter_node_tree; +} + +static bool side_effects_for_path(const ed::viewer_path::ViewerPathForGeometryNodesViewer &path, + const bNodeTree &root_node_tree, + ComputeContextBuilder &compute_context_builder, + SideEffectNodes &local_side_effect_nodes) +{ + if (!side_effects_for_viewer_path( + path.node_path, root_node_tree, compute_context_builder, local_side_effect_nodes)) + { + return false; + } + const bNodeTree *group = top_tree_from_viewer_path(path, root_node_tree); + if (group == nullptr) { + return false; + } + const bNode *viewer = group->node_by_id(path.viewer_node_id); + const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*group); + if (ELEM(nullptr, viewer, lf_graph_info)) { + return false; + } + std::cout << "AAA: " << viewer->name << std::endl; + if (viewer->type == GEO_NODE_VIEWER) { + if (!side_effects_for_viewer( + *lf_graph_info, *viewer, compute_context_builder, local_side_effect_nodes)) + { + return false; + } + } + if (bke::node_is_viewer_group(*viewer)) { + std::cout << "BBBBB!" << std::endl; + if (!side_effects_for_group_viewer( + *lf_graph_info, *viewer, compute_context_builder, local_side_effect_nodes)) + { + return false; + } + } + + return true; +} + static void find_side_effect_nodes_for_viewer_path( const ViewerPath &viewer_path, const NodesModifierData &nmd, @@ -434,122 +740,21 @@ static void find_side_effect_nodes_for_viewer_path( if (parsed_path->modifier_name != nmd.modifier.name) { return; } - - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(parsed_path->modifier_name); + if (nmd.node_group == nullptr) { + return; + } /* Write side effect nodes to a new map and only if everything succeeds, move the nodes to the * caller. This is easier than changing r_side_effect_nodes directly and then undoing changes in * case of errors. */ - MultiValueMap local_side_effect_nodes; - - const bNodeTree *group = nmd.node_group; - const bke::bNodeTreeZone *zone = nullptr; - for (const ViewerPathElem *elem : parsed_path->node_path) { - const bke::bNodeTreeZones *tree_zones = group->zones(); - if (tree_zones == nullptr) { - return; - } - const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*group); - if (lf_graph_info == nullptr) { - return; - } - switch (elem->type) { - case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { - const auto &typed_elem = *reinterpret_cast(elem); - const bke::bNodeTreeZone *next_zone = tree_zones->get_zone_by_node( - typed_elem.sim_output_node_id); - if (next_zone == nullptr) { - return; - } - if (next_zone->parent_zone != zone) { - return; - } - const lf::FunctionNode *lf_zone_node = lf_graph_info->mapping.zone_node_map.lookup_default( - next_zone, nullptr); - if (lf_zone_node == nullptr) { - return; - } - local_side_effect_nodes.add(compute_context_builder.hash(), lf_zone_node); - compute_context_builder.push(*next_zone->output_node); - zone = next_zone; - break; - } - case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: { - const auto &typed_elem = *reinterpret_cast(elem); - const bke::bNodeTreeZone *next_zone = tree_zones->get_zone_by_node( - typed_elem.repeat_output_node_id); - if (next_zone == nullptr) { - return; - } - if (next_zone->parent_zone != zone) { - return; - } - const lf::FunctionNode *lf_zone_node = lf_graph_info->mapping.zone_node_map.lookup_default( - next_zone, nullptr); - if (lf_zone_node == nullptr) { - return; - } - local_side_effect_nodes.add(compute_context_builder.hash(), lf_zone_node); - compute_context_builder.push(*next_zone->output_node, - typed_elem.iteration); - zone = next_zone; - break; - } - case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: { - const auto &typed_elem = *reinterpret_cast(elem); - const bNode *node = group->node_by_id(typed_elem.node_id); - if (node == nullptr) { - return; - } - if (node->id == nullptr) { - return; - } - if (node->is_muted()) { - return; - } - if (zone != tree_zones->get_zone_by_node(node->identifier)) { - return; - } - const lf::FunctionNode *lf_group_node = - lf_graph_info->mapping.group_node_map.lookup_default(node, nullptr); - if (lf_group_node == nullptr) { - return; - } - local_side_effect_nodes.add(compute_context_builder.hash(), lf_group_node); - compute_context_builder.push(*node); - group = reinterpret_cast(node->id); - zone = nullptr; - break; - } - default: { - BLI_assert_unreachable(); - return; - } - } - } - - const bNode *found_viewer_node = group->node_by_id(parsed_path->viewer_node_id); - if (found_viewer_node == nullptr) { + SideEffectNodes local_side_effect_nodes; + ComputeContextBuilder compute_context_builder; + compute_context_builder.push(parsed_path->modifier_name); + if (!side_effects_for_path( + *parsed_path, *nmd.node_group, compute_context_builder, local_side_effect_nodes)) + { return; } - const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*group); - if (lf_graph_info == nullptr) { - return; - } - const bke::bNodeTreeZones *tree_zones = group->zones(); - if (tree_zones == nullptr) { - return; - } - if (tree_zones->get_zone_by_node(found_viewer_node->identifier) != zone) { - return; - } - const lf::FunctionNode *lf_viewer_node = lf_graph_info->mapping.viewer_node_map.lookup_default( - found_viewer_node, nullptr); - if (lf_viewer_node == nullptr) { - return; - } - local_side_effect_nodes.add(compute_context_builder.hash(), lf_viewer_node); /* Successfully found all compute contexts for the viewer. */ for (const auto item : local_side_effect_nodes.items()) { diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 591eceb6f67..1b398dec8a1 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -778,6 +778,7 @@ class LazyFunctionForViewerNode : public LazyFunction { void execute_impl(lf::Params ¶ms, const lf::Context &context) const override { + std::cout << __func__ << std::endl; const auto &local_user_data = *static_cast(context.local_user_data); if (local_user_data.tree_logger == nullptr) { return; diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index e531fe4ca00..d529af228de 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -629,6 +629,24 @@ Map GeoModifierLog::get_tree_log_by_zone_fo return log_by_zone; } +static const bNodeTree *top_tree_from_viewer_path(const Span node_path, + const bNodeTree &root_node_tree) +{ + const bNodeTree *iter_node_tree = &root_node_tree; + for (const ViewerPathElem *elem : node_path) { + if (elem->type == VIEWER_PATH_ELEM_TYPE_GROUP_NODE) { + const auto &typed_elem = *reinterpret_cast(elem); + const bNode *node_group = iter_node_tree->node_by_id(typed_elem.node_id); + if (node_group != nullptr && node_group->id != nullptr) { + iter_node_tree = reinterpret_cast(node_group->id); + continue; + } + return nullptr; + } + } + return iter_node_tree; +} + const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerPath &viewer_path) { const std::optional parsed_path = @@ -680,6 +698,78 @@ const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerP } } } + + { + const bNodeTree *iter_node_tree = top_tree_from_viewer_path(parsed_path->node_path, + *nmd->node_group); + std::cout << "Name: " << nmd->node_group->id.name << std::endl; + const bNode *viewer_node = iter_node_tree->node_by_id(parsed_path->viewer_node_id); + if (bke::node_is_viewer_group(*viewer_node)) { + compute_context_builder.push(parsed_path->viewer_node_id); + + const auto lookup_viewer = [&](const bNodeTree &tree) -> const bNode * { + BLI_assert(tree.is_viewer()); + tree.ensure_topology_cache(); + const Span viewers = tree.nodes_by_type("GeometryNodeViewer"); + const Span groups = tree.group_nodes(); + if (viewers.size() == 1) { + return viewers.first(); + } + for (const bNode *group_node : groups) { + if (bke::node_is_viewer_group(*group_node)) { + return group_node; + } + } + return nullptr; + }; + + iter_node_tree = iter_node_tree = reinterpret_cast(viewer_node->id); + while (const bNode *viewer = lookup_viewer(*iter_node_tree)) { + std::cout << "Step\n"; + const bke::bNodeTreeZones *tree_zones = iter_node_tree->zones(); + if (tree_zones == nullptr) { + return nullptr; + } + for (const bke::bNodeTreeZone *zone : + tree_zones->get_zone_stack_for_node(viewer->identifier)) { + if (zone->output_node == nullptr) { + return nullptr; + } + const bNode &zone_output = *zone->output_node; + switch (zone_output.type) { + case GEO_NODE_SIMULATION_OUTPUT: { + compute_context_builder.push( + zone_output.identifier); + break; + } + case GEO_NODE_REPEAT_OUTPUT: { + compute_context_builder.push(zone_output.identifier, + 0); + break; + } + default: { + BLI_assert_unreachable(); + } + } + } + if (viewer->type == GEO_NODE_VIEWER) { + const ComputeContextHash context_hash = compute_context_builder.hash(); + nodes::geo_eval_log::GeoTreeLog &tree_log = modifier_log->get_tree_log(context_hash); + tree_log.ensure_viewer_node_logs(); + + const ViewerNodeLog *viewer_log = tree_log.viewer_node_logs.lookup_default( + viewer->identifier, nullptr); + return viewer_log; + } + compute_context_builder.push(viewer->identifier); + iter_node_tree = reinterpret_cast(viewer->id); + if (iter_node_tree == nullptr) { + return nullptr; + } + } + } + } + const ComputeContextHash context_hash = compute_context_builder.hash(); nodes::geo_eval_log::GeoTreeLog &tree_log = modifier_log->get_tree_log(context_hash); tree_log.ensure_viewer_node_logs(); -- 2.30.2 From b0eb2dad8402b453870d0ec45e3ec47df910840b Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sat, 9 Sep 2023 22:54:03 +0300 Subject: [PATCH 04/15] progress --- scripts/startup/bl_ui/node_add_menu.py | 47 ++++++++++++------- .../startup/bl_ui/node_add_menu_geometry.py | 5 +- source/blender/makesrna/intern/rna_space.cc | 19 ++++++++ .../nodes/intern/geometry_nodes_log.cc | 1 - 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/scripts/startup/bl_ui/node_add_menu.py b/scripts/startup/bl_ui/node_add_menu.py index ae23abd92fb..5bb066e53c5 100644 --- a/scripts/startup/bl_ui/node_add_menu.py +++ b/scripts/startup/bl_ui/node_add_menu.py @@ -25,33 +25,48 @@ def add_node_type(layout, node_type, *, label=None, poll=None): return props -def draw_node_group_add_menu(context, layout): - """Add items to the layout used for interacting with node groups.""" +def node_groups(context): + """All node groups allowed in current context.""" space_node = context.space_data node_tree = space_node.edit_tree all_node_groups = context.blend_data.node_groups + if node_tree is None: + return None + def group_allowed_in_context(group): + if group.bl_idname is node_tree.bl_idname: + return False + if group.name.startswith('.'): + return False + if group.contains_tree(node_tree): + return False + return True + + return [group for group in all_node_groups if group_allowed_in_context(group)] + + +def draw_node_group_add_menu(context, layout, groups = None): + """Add items to the layout used for interacting with node groups.""" + space_node = context.space_data + node_tree = space_node.edit_tree + if groups is None: + groups = node_groups(context) + + all_node_groups = context.blend_data.node_groups if node_tree in all_node_groups.values(): layout.separator() add_node_type(layout, "NodeGroupInput") add_node_type(layout, "NodeGroupOutput") - if node_tree: + if node_tree and groups: from nodeitems_builtins import node_tree_group_type - groups = [ - group for group in context.blend_data.node_groups - if (group.bl_idname == node_tree.bl_idname and - not group.contains_tree(node_tree) and - not group.name.startswith('.')) - ] - if groups: - layout.separator() - for group in groups: - props = add_node_type(layout, node_tree_group_type[group.bl_idname], label=group.name) - ops = props.settings.add() - ops.name = "node_tree" - ops.value = "bpy.data.node_groups[%r]" % group.name + layout.separator() + for group in groups: + props = add_node_type(layout, node_tree_group_type[group.bl_idname], label=group.name) + ops = props.settings.add() + ops.name = "node_tree" + ops.value = "bpy.data.node_groups[%r]" % group.name def draw_assets_for_catalog(layout, catalog_path): diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index 718a57dd001..2470c4da4eb 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -453,10 +453,13 @@ class NODE_MT_category_GEO_OUTPUT(Menu): bl_idname = "NODE_MT_category_GEO_OUTPUT" bl_label = "Output" - def draw(self, _context): + def draw(self, context): layout = self.layout node_add_menu.add_node_type(layout, "NodeGroupOutput") node_add_menu.add_node_type(layout, "GeometryNodeViewer") + groups = node_add_menu.node_groups(context) + groups = [group for group in groups if group.is_viewer] + node_add_menu.draw_node_group_add_menu(context, layout, groups) node_add_menu.draw_assets_for_catalog(layout, self.bl_label) diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc index 7ebd27ea184..6722d4d0e4f 100644 --- a/source/blender/makesrna/intern/rna_space.cc +++ b/source/blender/makesrna/intern/rna_space.cc @@ -3323,6 +3323,8 @@ static StructRNA *rna_viewer_path_elem_refine(PointerRNA *ptr) return &RNA_ModifierViewerPathElem; case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: return &RNA_GroupNodeViewerPathElem; + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: + return &RNA_ViewerNodeGroupViewerPathElem; case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: return &RNA_SimulationZoneViewerPathElem; case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: @@ -8073,6 +8075,11 @@ static const EnumPropertyItem viewer_path_elem_type_items[] = { {VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE, "SIMULATION_ZONE", ICON_NONE, "Simulation Zone", ""}, {VIEWER_PATH_ELEM_TYPE_VIEWER_NODE, "VIEWER_NODE", ICON_NONE, "Viewer Node", ""}, {VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE, "REPEAT_ZONE", ICON_NONE, "Repeat", ""}, + {VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP, + "VIEWER_NODE_GROUP", + ICON_NONE, + "Viewer Node Group", + ""}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -8162,6 +8169,17 @@ static void rna_def_viewer_node_viewer_path_elem(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Node ID", ""); } +static void rna_def_viewer_node_group_viewer_path_elem(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "ViewerNodeGroupViewerPathElem", "ViewerPathElem"); + + prop = RNA_def_property(srna, "node_id", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Node ID", ""); +} + static void rna_def_viewer_path(BlenderRNA *brna) { StructRNA *srna; @@ -8174,6 +8192,7 @@ static void rna_def_viewer_path(BlenderRNA *brna) rna_def_simulation_zone_viewer_path_elem(brna); rna_def_repeat_zone_viewer_path_elem(brna); rna_def_viewer_node_viewer_path_elem(brna); + rna_def_viewer_node_group_viewer_path_elem(brna); srna = RNA_def_struct(brna, "ViewerPath", nullptr); RNA_def_struct_ui_text(srna, "Viewer Path", "Path to data that is viewed"); diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index d529af228de..dfe04723bd0 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -725,7 +725,6 @@ const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerP iter_node_tree = iter_node_tree = reinterpret_cast(viewer_node->id); while (const bNode *viewer = lookup_viewer(*iter_node_tree)) { - std::cout << "Step\n"; const bke::bNodeTreeZones *tree_zones = iter_node_tree->zones(); if (tree_zones == nullptr) { return nullptr; -- 2.30.2 From e092d827ddee08b0271e997974a0d1fc5fabb16b Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sat, 9 Sep 2023 23:27:54 +0300 Subject: [PATCH 05/15] propagate updates --- source/blender/blenkernel/intern/node_tree_update.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index 846cc6764cd..867bb81e42f 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -928,6 +928,9 @@ class NodeTreeMainUpdater { if (node.typeinfo->nclass == NODE_CLASS_OUTPUT) { return true; } + if (bke::node_is_viewer_group(node)) { + return true; + } if (node.type == NODE_GROUP_OUTPUT) { return true; } -- 2.30.2 From 2501ad5e0243bd43a000fca025733a1387d11b19 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sun, 10 Sep 2023 03:47:26 +0300 Subject: [PATCH 06/15] progress fast connection reimplementing --- source/blender/blenkernel/BKE_node.hh | 2 + .../blenkernel/intern/node_tree_update.cc | 20 +-- .../editors/space_node/node_relationships.cc | 134 ++++++++++++------ 3 files changed, 104 insertions(+), 52 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.hh b/source/blender/blenkernel/BKE_node.hh index 277e2cd0416..9d595b6c4e8 100644 --- a/source/blender/blenkernel/BKE_node.hh +++ b/source/blender/blenkernel/BKE_node.hh @@ -124,6 +124,8 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node); bool node_is_viewer_group(const bNode &node); +int get_internal_link_type_priority(const bNodeSocketType &from, const bNodeSocketType &to); + float2 nodeToView(const bNode *node, float2 loc); float2 nodeFromView(const bNode *node, float2 view_loc); diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index 867bb81e42f..d0c44a63c38 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -83,11 +83,11 @@ namespace blender::bke { * `< 0`: never connect these types. * `>= 0`: priority of connection (higher values chosen first). */ -static int get_internal_link_type_priority(const bNodeSocketType *from, const bNodeSocketType *to) +int get_internal_link_type_priority(const bNodeSocketType &from, const bNodeSocketType &to) { - switch (to->type) { + switch (to.type) { case SOCK_RGBA: - switch (from->type) { + switch (from.type) { case SOCK_RGBA: return 4; case SOCK_FLOAT: @@ -99,7 +99,7 @@ static int get_internal_link_type_priority(const bNodeSocketType *from, const bN } return -1; case SOCK_VECTOR: - switch (from->type) { + switch (from.type) { case SOCK_VECTOR: return 4; case SOCK_FLOAT: @@ -111,7 +111,7 @@ static int get_internal_link_type_priority(const bNodeSocketType *from, const bN } return -1; case SOCK_FLOAT: - switch (from->type) { + switch (from.type) { case SOCK_FLOAT: return 5; case SOCK_INT: @@ -125,7 +125,7 @@ static int get_internal_link_type_priority(const bNodeSocketType *from, const bN } return -1; case SOCK_INT: - switch (from->type) { + switch (from.type) { case SOCK_INT: return 5; case SOCK_FLOAT: @@ -139,7 +139,7 @@ static int get_internal_link_type_priority(const bNodeSocketType *from, const bN } return -1; case SOCK_BOOLEAN: - switch (from->type) { + switch (from.type) { case SOCK_BOOLEAN: return 5; case SOCK_INT: @@ -156,7 +156,7 @@ static int get_internal_link_type_priority(const bNodeSocketType *from, const bN /* The rest of the socket types only allow an internal link if both the input and output socket * have the same type. If the sockets are custom, we check the idname instead. */ - if (to->type == from->type && (to->type != SOCK_CUSTOM || STREQ(to->idname, from->idname))) { + if (to.type == from.type && (to.type != SOCK_CUSTOM || STREQ(to.idname, from.idname))) { return 1; } @@ -669,8 +669,8 @@ class NodeTreeMainUpdater { if (input_socket->flag & SOCK_NO_INTERNAL_LINK) { continue; } - const int priority = get_internal_link_type_priority(input_socket->typeinfo, - output_socket->typeinfo); + const int priority = get_internal_link_type_priority(*input_socket->typeinfo, + *output_socket->typeinfo); if (priority < 0) { continue; } diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index be6113bd322..c0ff2722277 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -413,6 +413,28 @@ namespace viewer_linking { /** \name Link Viewer Operator * \{ */ +/* Find index of socket int viewer that the best to connect to a to_viewer. */ +static std::optional best_socket_of_viewer(const bNode &viewer, const bNodeSocket &to_viewer) +{ + const Span inputs = viewer.input_sockets(); + if (inputs.is_empty()) { + return std::nullopt; + } + + int max_value = 0; + std::optional index_of_max; + for (const int index : inputs.index_range()) { + const bNodeSocket &socket = *inputs[index]; + const int priority = bke::get_internal_link_type_priority(*to_viewer.typeinfo, + *socket.typeinfo); + if (priority > max_value) { + max_value = priority; + index_of_max.emplace(index); + } + } + return index_of_max; +} + /* Depending on the node tree type, different socket types are supported by viewer nodes. */ static bool socket_can_be_viewed(const bNodeSocket &socket) { @@ -425,14 +447,7 @@ static bool socket_can_be_viewed(const bNodeSocket &socket) if (socket.owner_tree().type != NTREE_GEOMETRY) { return true; } - return ELEM(socket.typeinfo->type, - SOCK_GEOMETRY, - SOCK_FLOAT, - SOCK_VECTOR, - SOCK_INT, - SOCK_BOOLEAN, - SOCK_ROTATION, - SOCK_RGBA); + return true; } static eCustomDataType socket_type_to_custom_data_type(const eNodeSocketDatatype socket_type) @@ -475,7 +490,7 @@ static bNodeSocket *node_link_viewer_get_socket(bNodeTree &ntree, } NodeGeometryViewer *storage = (NodeGeometryViewer *)viewer_node.storage; const eCustomDataType data_type = socket_type_to_custom_data_type( - (eNodeSocketDatatype)src_socket.type); + eNodeSocketDatatype(src_socket.type)); BLI_assert(data_type != CD_AUTO_FROM_NAME); storage->data_type = data_type; viewer_node.typeinfo->updatefunc(&ntree, &viewer_node); @@ -487,7 +502,8 @@ static bNodeSocket *node_link_viewer_get_socket(bNodeTree &ntree, static bool is_viewer_node(const bNode &node) { - return ELEM(node.type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER); + return ELEM(node.type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER, GEO_NODE_VIEWER) || + bke::node_is_viewer_group(node); } static bool is_viewer_socket_in_viewer(const bNodeSocket &socket) @@ -614,16 +630,64 @@ static void finalize_viewer_link(const bContext &C, ED_node_tree_propagate_change(&C, bmain, snode.edittree); } -static int view_socket(const bContext &C, - SpaceNode &snode, - bNodeTree &btree, - bNode &bnode_to_view, - bNodeSocket &bsocket_to_view) +static Array all_view_nodes(const bNodeTree &tree) { + return {}; +} + +static Array all_connected_viewer(const bNodeTree &tree, const bNode &bnode_to_view) +{ + return {}; +} + +static const bNode *active_viewer_in_tree(const bNodeTree &tree) +{ + return {}; +} + +static int link_view_sockets(const bContext &C, + SpaceNode &snode, + bNodeTree &btree, + bNodeSocket &bsocket_to_view, + bNodeSocket &bsocket_of_viewer) +{ + return {}; + /* + bNodeSocket *viewer_bsocket = node_link_viewer_get_socket(btree, *viewer_node, bsocket_to_view); + if (viewer_bsocket == nullptr) { + return OPERATOR_CANCELLED; + } + bNodeLink *viewer_link = nullptr; + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &btree.links) { + if (link->tosock == viewer_bsocket) { + viewer_link = link; + break; + } + } + if (viewer_link == nullptr) { + viewer_link = nodeAddLink( + &btree, &bnode_to_view, &bsocket_to_view, viewer_node, viewer_bsocket); + } + else { + viewer_link->fromnode = &bnode_to_view; + viewer_link->fromsock = &bsocket_to_view; + BKE_ntree_update_tag_link_changed(&btree); + } + finalize_viewer_link(C, snode, *viewer_node, *viewer_link); + return OPERATOR_CANCELLED;*/ +} + +static bNodeSocket *best_view_socket_find_or_new(const bNodeTree &btree, + const bNodeSocket &bsocket_to_view, + const Span viewers, + const Span connected_viewers, + const bNode *active_viewer) +{ + return {}; + /* bNode *viewer_node = nullptr; - /* Try to find a viewer that is already active. */ for (bNode *node : btree.all_nodes()) { - if (is_viewer_node(*node)) { + if (is_viewer_node(*node) || bke::node_is_viewer_group(*node)) { if (node->flag & NODE_DO_OUTPUT) { viewer_node = node; break; @@ -631,7 +695,6 @@ static int view_socket(const bContext &C, } } - /* Try to reactivate existing viewer connection. */ for (bNodeLink *link : bsocket_to_view.directly_linked_links()) { bNodeSocket &target_socket = *link->tosock; bNode &target_node = *link->tonode; @@ -656,29 +719,7 @@ static int view_socket(const bContext &C, socket_location.y / UI_SCALE_FAC}; viewer_node = add_static_node(C, viewer_type, location); } - - bNodeSocket *viewer_bsocket = node_link_viewer_get_socket(btree, *viewer_node, bsocket_to_view); - if (viewer_bsocket == nullptr) { - return OPERATOR_CANCELLED; - } - bNodeLink *viewer_link = nullptr; - LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &btree.links) { - if (link->tosock == viewer_bsocket) { - viewer_link = link; - break; - } - } - if (viewer_link == nullptr) { - viewer_link = nodeAddLink( - &btree, &bnode_to_view, &bsocket_to_view, viewer_node, viewer_bsocket); - } - else { - viewer_link->fromnode = &bnode_to_view; - viewer_link->fromsock = &bsocket_to_view; - BKE_ntree_update_tag_link_changed(&btree); - } - finalize_viewer_link(C, snode, *viewer_node, *viewer_link); - return OPERATOR_CANCELLED; + */ } static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket *bsocket_to_view) @@ -687,6 +728,10 @@ static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket bNodeTree *btree = snode.edittree; btree->ensure_topology_cache(); + const Array viewers = all_view_nodes(*btree); + const Array connected_viewers = all_connected_viewer(*btree, bnode_to_view); + const bNode *active_viewer = active_viewer_in_tree(*btree); + if (bsocket_to_view == nullptr) { bsocket_to_view = determine_socket_to_view(bnode_to_view); } @@ -695,7 +740,12 @@ static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket return OPERATOR_CANCELLED; } - return view_socket(C, snode, *btree, bnode_to_view, *bsocket_to_view); + bNodeSocket *target_viewer_socket = best_view_socket_find_or_new( + *btree, *bsocket_to_view, viewers, connected_viewers, active_viewer); + if (target_viewer_socket == nullptr) { + return OPERATOR_CANCELLED; + } + return link_view_sockets(C, snode, *btree, *bsocket_to_view, *target_viewer_socket); } /** \} */ -- 2.30.2 From 72fdd7be4daf875a89531d36741e30bb9126d8ac Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sat, 30 Sep 2023 02:38:34 +0300 Subject: [PATCH 07/15] progres --- .../blender/editors/space_node/CMakeLists.txt | 1 + .../editors/space_node/node_connection.cc | 247 ++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 source/blender/editors/space_node/node_connection.cc diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index fac04776f25..b88d91dd915 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -35,6 +35,7 @@ set(SRC drawnode.cc link_drag_search.cc node_add.cc + node_connection.cc node_context_path.cc node_draw.cc node_edit.cc diff --git a/source/blender/editors/space_node/node_connection.cc b/source/blender/editors/space_node/node_connection.cc new file mode 100644 index 00000000000..817f2b93a3d --- /dev/null +++ b/source/blender/editors/space_node/node_connection.cc @@ -0,0 +1,247 @@ +/* SPDX-FileCopyrightText: 2008 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup spnode + */ + +#include "DNA_node_types.h" + +#include "BKE_node_runtime.hh" + +#include "NOD_node_declaration.hh" + +namespace blender::ed::space_node::connection { + +class RealNode; + +//#if (0) + +class Context { + public: + bNodeTree *tree; + std::unique_ptr target_node; + int index; + bool side_is_input; +}; + +class Node { + public: + virtual ~Node() = default; + + IndexRange index_range() const + { + return IndexRange(this->size()); + } + + std::optional first_connection(const Context &context) const + { + for (const int index : this->index_range()) { + if (this->is_connected(context, index)) { + return index; + } + } + return std::nullopt; + } + + virtual int size(const Context &context) const = 0; + + virtual bool is_connected(const Context &context, int socket_index) const = 0; + virtual eNodeSocketDatatype type(const Context &context, int socket_index) const = 0; + + virtual StringRef name(const Context &context, int socket_index) const = 0; + virtual bool single_value(const Context &context, int socket_index) const = 0; + + //TODO: std::pair to_connect(Context &context, int socket_index) const = 0; +}; + +using NodePtr = std::unique_ptr; + +class RealNode : public Node { + private: + const bNode &node_; + public: + RealNode(const bNode &node) : node_(node) {} + + int size(const Context &context) const final + { + return int(context.side_is_input ? node_.input_sockets().size() : node_.output_sockets().size()); + } + + bool is_connected(const Context &context, const int socket_index) const override + { + BLI_assert(&node_ != &context.target_node->node_); + const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + for (const bNodeSocket *other_socket : sockets[socket_index]->logically_linked_sockets()) { + if (&other_socket->owner_node() == &context.target_node->node_) { + return true; + } + } + return false; + } + + eNodeSocketDatatype type(const Context &context, int socket_index) const override + { + const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + return eNodeSocketDatatype(sockets[socket_index]->type); + } + + StringRef name(const Context &context, int socket_index) const override + { + const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + return sockets[socket_index]->name; + } + + bool single_value(const Context &context, int socket_index) const override + { + BLI_assert(context.tree != nullptr); + const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + if (context.side_is_input) { + return nodes::InputSocketFieldType::None == sockets[socket_index]->runtime->declaration->input_field_type; + } + return nodes::OutputSocketFieldType::None == sockets[socket_index]->runtime->declaration->output_field_dependency.field_type(); + } +}; + +class VirtualNode : public Node { + public: + bool is_connected(const Context &/*context*/, const int /*socket_index*/) const final + { + return false; + } +}; + +class ViewerNode : public VirtualNode { + private: + const eNodeSocketDatatype data_type_; + public: + ViewerNode(const eNodeSocketDatatype data_type) : data_type_(data_type) {} + + int size(const Context &context) const final + { + return 2; + } + + eNodeSocketDatatype type(const Context &/*context*/, int socket_index) const override + { + if (socket_index == 0) { + return SOCK_GEOMETRY; + } + return data_type_; + } + + StringRef name(const Context &/*context*/, int socket_index) const override + { + if (socket_index == 0) { + return "Geometry"; + } + return "Value"; + } + + bool single_value(const Context &/*context*/, int socket_index) const override + { + if (socket_index == 0) { + return true; + } + return false; + } +}; + +class GroupNode : public VirtualNode { + private: + const bNodeTree &group_; + public: + GroupNode(const bNodeTree &group) : group_(group) + { + group_.ensure_topology_cache(); + group_.ensure_interface_cache(); + } + + int size(const Context &context) const final + { + const Span sockets = context.side_is_input ? group_.interface_inputs() : group_.interface_outputs(); + return int(context.side_is_input ? group_.interface_inputs().size() : group_.interface_outputs().size()); + } + + eNodeSocketDatatype type(const Context &context, int socket_index) const override + { + const Span sockets = context.side_is_input ? group_.interface_inputs() : group_.interface_outputs(); + return eNodeSocketDatatype(sockets[socket_index]->socket_typeinfo()->type); + } + + StringRef name(const Context &context, int socket_index) const override + { + const Span sockets = context.side_is_input ? group_.interface_inputs() : group_.interface_outputs(); + return sockets[socket_index]->name; + } + + bool single_value(const Context &context, int socket_index) const override + { + const nodes::FieldInferencingInterface &interface = *group_.runtime->field_inferencing_interface; + if (context.side_is_input) { + return nodes::InputSocketFieldType::None == interface.inputs[socket_index]; + } + return nodes::OutputSocketFieldType::None == interface.outputs[socket_index].field_type(); + } + + const bNodeTree &group() const + { + return group_; + } +}; + +class ViewerGroupNode : public GroupNode { + public: + ViewerGroupNode(const bNodeTree &group) : GroupNode(group) + { + BLI_assert(this->group().is_viewer()); + } +}; + +/* +static void (const Context &context, const Span nodes) +{ + const NodePtr target = context.target_node; + for (const NodePtr &node : nodes) { + std::optional index = node->first_connection(context); + if (!index.has_value()) { + continue; + } + for (const int i : target->index_range()) { + if (target->type(i) != node->type(*index)) { + continue; + } + + } + for (const int i : target->index_range()) { + if (target->type(i) == node->type(*index)) { + continue; + } + + } + } + for (const NodePtr &node : nodes) { + if (node->first_connection(context).has_value()) { + continue; + } + + } +} +*/ + +//#endif + +struct ConnectWeight { + bool connected; + std::optional first_index; + bool same_name; + int type_conversion; + int field_interfacing_conversion; + + ConnectWeight(const Context &context, const Node &node, const int index) : + connected(node->first_connection(context).has_value()), + same_name(node->name() ) +}; + +} -- 2.30.2 From a7c603f674f9d7a6ec9d4510cb4ba8ad9587178b Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sun, 1 Oct 2023 23:09:15 +0300 Subject: [PATCH 08/15] progress --- .../editors/space_node/node_connection.cc | 229 +++++++++++++++--- 1 file changed, 197 insertions(+), 32 deletions(-) diff --git a/source/blender/editors/space_node/node_connection.cc b/source/blender/editors/space_node/node_connection.cc index 817f2b93a3d..a7dd435fb7c 100644 --- a/source/blender/editors/space_node/node_connection.cc +++ b/source/blender/editors/space_node/node_connection.cc @@ -8,20 +8,28 @@ #include "DNA_node_types.h" +#include "BLI_offset_indices.hh" + #include "BKE_node_runtime.hh" #include "NOD_node_declaration.hh" namespace blender::ed::space_node::connection { -class RealNode; - //#if (0) +enum class SocketState : int8_t { + ConnectedToTarger, + ConnectedToOther, + Free, +}; + +class TargetSocketNode; + class Context { public: - bNodeTree *tree; - std::unique_ptr target_node; + bNodeTree &tree; + TargetSocketNode &target_node; int index; bool side_is_input; }; @@ -30,14 +38,14 @@ class Node { public: virtual ~Node() = default; - IndexRange index_range() const + IndexRange index_range(const Context &context) const { - return IndexRange(this->size()); + return IndexRange(this->size(context)); } std::optional first_connection(const Context &context) const { - for (const int index : this->index_range()) { + for (const int index : this->index_range(context)) { if (this->is_connected(context, index)) { return index; } @@ -53,26 +61,29 @@ class Node { virtual StringRef name(const Context &context, int socket_index) const = 0; virtual bool single_value(const Context &context, int socket_index) const = 0; - //TODO: std::pair to_connect(Context &context, int socket_index) const = 0; + // TODO: std::pair to_connect(Context &context, int socket_index) const = + // 0; }; -using NodePtr = std::unique_ptr; - class RealNode : public Node { private: const bNode &node_; + public: RealNode(const bNode &node) : node_(node) {} int size(const Context &context) const final { - return int(context.side_is_input ? node_.input_sockets().size() : node_.output_sockets().size()); + /* TODO: Do not count hide sockets! */ + return int(context.side_is_input ? node_.input_sockets().size() : + node_.output_sockets().size()); } bool is_connected(const Context &context, const int socket_index) const override { - BLI_assert(&node_ != &context.target_node->node_); - const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + BLI_assert(&node_ != &context.target_node); + const Span sockets = context.side_is_input ? node_.input_sockets() : + node_.output_sockets(); for (const bNodeSocket *other_socket : sockets[socket_index]->logically_linked_sockets()) { if (&other_socket->owner_node() == &context.target_node->node_) { return true; @@ -83,30 +94,71 @@ class RealNode : public Node { eNodeSocketDatatype type(const Context &context, int socket_index) const override { - const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + const Span sockets = context.side_is_input ? node_.input_sockets() : + node_.output_sockets(); return eNodeSocketDatatype(sockets[socket_index]->type); } StringRef name(const Context &context, int socket_index) const override { - const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + const Span sockets = context.side_is_input ? node_.input_sockets() : + node_.output_sockets(); return sockets[socket_index]->name; } bool single_value(const Context &context, int socket_index) const override { BLI_assert(context.tree != nullptr); - const Span sockets = context.side_is_input ? node_.input_sockets() : node_.output_sockets(); + const Span sockets = context.side_is_input ? node_.input_sockets() : + node_.output_sockets(); if (context.side_is_input) { - return nodes::InputSocketFieldType::None == sockets[socket_index]->runtime->declaration->input_field_type; + return nodes::InputSocketFieldType::None == + sockets[socket_index]->runtime->declaration->input_field_type; } - return nodes::OutputSocketFieldType::None == sockets[socket_index]->runtime->declaration->output_field_dependency.field_type(); + return nodes::OutputSocketFieldType::None == + sockets[socket_index]->runtime->declaration->output_field_dependency.field_type(); + } +}; + +class TargetSocketNode : public Node { + private: + const eNodeSocketDatatype type_; + const StringRef name_; + + public: + TargetSocketNode(const eNodeSocketDatatype type, const StringRef name) : type_(type), name_(name) + { + } + + int size(const Context & /*context*/) const final + { + return 1; + } + + bool is_connected(const Context &context, int socket_index) const final + { + return false; + } + + eNodeSocketDatatype type(const Context &context, int socket_index) const final + { + return type_; + } + + StringRef name(const Context &context, int socket_index) const final + { + return name; + } + + bool single_value(const Context &context, int socket_index) const final + { + return false; } }; class VirtualNode : public Node { public: - bool is_connected(const Context &/*context*/, const int /*socket_index*/) const final + bool is_connected(const Context & /*context*/, const int /*socket_index*/) const final { return false; } @@ -115,15 +167,16 @@ class VirtualNode : public Node { class ViewerNode : public VirtualNode { private: const eNodeSocketDatatype data_type_; + public: ViewerNode(const eNodeSocketDatatype data_type) : data_type_(data_type) {} - int size(const Context &context) const final + int size(const Context & /*context*/) const final { return 2; } - eNodeSocketDatatype type(const Context &/*context*/, int socket_index) const override + eNodeSocketDatatype type(const Context & /*context*/, int socket_index) const override { if (socket_index == 0) { return SOCK_GEOMETRY; @@ -131,7 +184,7 @@ class ViewerNode : public VirtualNode { return data_type_; } - StringRef name(const Context &/*context*/, int socket_index) const override + StringRef name(const Context & /*context*/, int socket_index) const override { if (socket_index == 0) { return "Geometry"; @@ -139,7 +192,7 @@ class ViewerNode : public VirtualNode { return "Value"; } - bool single_value(const Context &/*context*/, int socket_index) const override + bool single_value(const Context & /*context*/, int socket_index) const override { if (socket_index == 0) { return true; @@ -151,6 +204,7 @@ class ViewerNode : public VirtualNode { class GroupNode : public VirtualNode { private: const bNodeTree &group_; + public: GroupNode(const bNodeTree &group) : group_(group) { @@ -160,25 +214,33 @@ class GroupNode : public VirtualNode { int size(const Context &context) const final { - const Span sockets = context.side_is_input ? group_.interface_inputs() : group_.interface_outputs(); - return int(context.side_is_input ? group_.interface_inputs().size() : group_.interface_outputs().size()); + const Span sockets = context.side_is_input ? + group_.interface_inputs() : + group_.interface_outputs(); + return int(context.side_is_input ? group_.interface_inputs().size() : + group_.interface_outputs().size()); } eNodeSocketDatatype type(const Context &context, int socket_index) const override { - const Span sockets = context.side_is_input ? group_.interface_inputs() : group_.interface_outputs(); + const Span sockets = context.side_is_input ? + group_.interface_inputs() : + group_.interface_outputs(); return eNodeSocketDatatype(sockets[socket_index]->socket_typeinfo()->type); } StringRef name(const Context &context, int socket_index) const override { - const Span sockets = context.side_is_input ? group_.interface_inputs() : group_.interface_outputs(); + const Span sockets = context.side_is_input ? + group_.interface_inputs() : + group_.interface_outputs(); return sockets[socket_index]->name; } bool single_value(const Context &context, int socket_index) const override { - const nodes::FieldInferencingInterface &interface = *group_.runtime->field_inferencing_interface; + const nodes::FieldInferencingInterface &interface = + *group_.runtime->field_inferencing_interface; if (context.side_is_input) { return nodes::InputSocketFieldType::None == interface.inputs[socket_index]; } @@ -212,26 +274,93 @@ static void (const Context &context, const Span nodes) if (target->type(i) != node->type(*index)) { continue; } - + } for (const int i : target->index_range()) { if (target->type(i) == node->type(*index)) { continue; } - + } } for (const NodePtr &node : nodes) { if (node->first_connection(context).has_value()) { continue; } - + } } */ //#endif +/* + +class Socket { + private: + const NodePtr own_node_; + const int index_; + const SocketState state_; + + public: + + bool operator > (const Socket &other) const + { + return false; + } +}; + +*/ + +/* + +using NodeFilter = FunctionRef nodes)>; + +static bool node_state_filter(const MutableSpan nodes, const NodeFilter next_filter) +{ + Vector connected; + Vector exist; + Vector other; + + for (NodePtr &node : nodes) { + if (node->first_connection()) { + connected.append(std::move(node)); + continue; + } + if (dynamic_cast(&*node)) { + exist.append(std::move(node)); + continue; + } + other.append(std::move(node)); + } + + return next_filter(connected) || next_filter(exist) || next_filter(other); +} + +static bool socket_state_filter(const MutableSpan nodes, const NodeFilter next_filter) +{ + Vector targer; + Vector exist; + Vector other; + + for (NodePtr &node : nodes) { + if (node->first_connection()) { + connected.append(std::move(node)); + continue; + } + if (dynamic_cast(&*node)) { + exist.append(std::move(node)); + continue; + } + other.append(std::move(node)); + } + + return next_filter(connected) || next_filter(exist) || next_filter(other); +} + +*/ + +/* struct ConnectWeight { bool connected; std::optional first_index; @@ -241,7 +370,43 @@ struct ConnectWeight { ConnectWeight(const Context &context, const Node &node, const int index) : connected(node->first_connection(context).has_value()), - same_name(node->name() ) + same_name(node->name() ); +}; +*/ + +class Socket { + // const NodePtr &node; }; +static bool sockets_cmp(const Socket &a, const Socket b) +{ + return false; } + +static std::optional lookup_socket_for_context(const Span nodes, + const Context context) +{ + Array accumulate_sockets(nodes.size() + 1, 0); + for (const int index : nodes.index_range()) { + accumulate_sockets[index] = nodes[index]->size(context); + } + OffsetIndices sockets_offset = offset_indices::accumulate_counts_to_offsets( + accumulate_sockets); + Array sockets(sockets_offset.total_size()); + for (const int node_index : nodes.index_range()) { + const NodePtr &node = nodes[node_index]; + IndexRange node_sockets = sockets_offset[node_index]; + for (const int index : node_sockets.index_range()) { + sockets[node_sockets[index]]; // = Socket(context, node); + } + } + + const Socket *socket = std::max_element(sockets.begin(), sockets.end(), sockets_cmp); + if (socket == sockets.end()) { + return std::nullopt; + } + + return *socket; +} + +} // namespace blender::ed::space_node::connection -- 2.30.2 From 030976df06a409107b048b8948ece1876563ff4f Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Fri, 3 Nov 2023 15:19:03 +0300 Subject: [PATCH 09/15] merge conflict fix finally --- .../blenkernel/BKE_compute_contexts.hh | 2 +- source/blender/modifiers/intern/MOD_nodes.cc | 29 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_compute_contexts.hh b/source/blender/blenkernel/BKE_compute_contexts.hh index 3537a615040..13ff2951f9f 100644 --- a/source/blender/blenkernel/BKE_compute_contexts.hh +++ b/source/blender/blenkernel/BKE_compute_contexts.hh @@ -64,7 +64,7 @@ class NodeGroupComputeContext : public ComputeContext { void print_current_in_line(std::ostream &stream) const override; }; -class NodeViewerGroupComputeContext : public NodeGroupComputeContext { +class NodeViewerGroupComputeContext : public ComputeContext { private: static constexpr const char *s_static_type = "NODE_GROUP"; diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 44d1a59a1a9..29144025a4d 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -14,6 +14,7 @@ #include "MEM_guardedalloc.h" #include "BLI_array.hh" +#include "BLI_linear_allocator.hh" #include "BLI_listbase.h" #include "BLI_math_vector_types.hh" #include "BLI_multi_value_map.hh" @@ -470,7 +471,7 @@ static const bNodeTree *try_add_side_effect_node_for_path( if (const auto *compute_context = dynamic_cast( compute_context_generic)) { - const bNode *group_node = current_tree->node_by_id(compute_context->node_id()); + const bNode *group_node = start_tree->node_by_id(compute_context->node_id()); if (group_node == nullptr) { return nullptr; } @@ -537,6 +538,10 @@ static void try_add_side_effect_node(const ComputeContext &final_compute_context return; } + int final_node_id_ = final_node_id; + + LinearAllocator scope; + if (const auto *compute_context = dynamic_cast( compute_context_vec.last())) { @@ -545,7 +550,7 @@ static void try_add_side_effect_node(const ComputeContext &final_compute_context while (true) { result_tree->ensure_topology_cache(); result_tree->node_by_id(compute_context->node_id()); - const Span viewers = ntree.nodes_by_type("GeometryNodeViewer"); + const Span viewers = result_tree->nodes_by_type("GeometryNodeViewer"); const bNode *viewer_node = viewers.size() != 1 ? nullptr : viewers.first(); const bNode *viewer_group = [&]() -> const bNode * { @@ -558,21 +563,27 @@ static void try_add_side_effect_node(const ComputeContext &final_compute_context }(); if (viewer_node != nullptr) { + final_node_id_ = viewer_node->identifier; break; } - if (viewer_group == nullptr) { + if (viewer_group == nullptr || viewer_group->id == nullptr) { return; } - for (const bNodeTreeZone *zone : - viewer_group->zones()->get_zone_stack_for_node(viewer_group->identifier)) + const bNodeTree *tree_f = reinterpret_cast(viewer_group->id); + + for (const bke::bNodeTreeZone *zone : + tree_f->zones()->get_zone_stack_for_node(viewer_group->identifier)) { - viewer_group_context_list.append_as( - /*parent_context*/, zone->output_node->identifier); + auto *simulation_context = scope.allocate(); + new (simulation_context) + bke::SimulationZoneComputeContext(parent_context, zone->output_node->identifier); + viewer_group_context_list.append(simulation_context); } - viewer_group_context_list.append_as(/*parent_context*/, - viewer_group->identifier); + auto *group_context = scope.allocate(); + new (group_context) bke::NodeGroupComputeContext(parent_context, viewer_group->identifier); + viewer_group_context_list.append(group_context); result_tree = reinterpret_cast(viewer_group->id); if (result_tree == nullptr) { -- 2.30.2 From e0b9e4c6e25d78783fe1e17cc96e684fdb37fc74 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sat, 4 Nov 2023 12:53:04 +0300 Subject: [PATCH 10/15] first attempt to get it works --- source/blender/editors/util/ed_viewer_path.cc | 11 +- source/blender/modifiers/intern/MOD_nodes.cc | 213 +++++++----------- 2 files changed, 89 insertions(+), 135 deletions(-) diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index c18a7ccfbe9..a1068c49988 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -264,6 +264,7 @@ std::optional parse_geometry_nodes_viewer( Vector node_path; for (const ViewerPathElem *elem : remaining_elems.drop_back(1)) { if (!ELEM(elem->type, + VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP, VIEWER_PATH_ELEM_TYPE_GROUP_NODE, VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE, VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE)) @@ -496,11 +497,6 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod compute_context_builder.push(elem.node_id); return true; } - case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { - const auto &elem = reinterpret_cast(elem_generic); - compute_context_builder.push(elem.node_id); - return true; - } case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { const auto &elem = reinterpret_cast(elem_generic); compute_context_builder.push(elem.sim_output_node_id); @@ -512,6 +508,11 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod elem.iteration); return true; } + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { + const auto &elem = reinterpret_cast(elem_generic); + compute_context_builder.push(elem.node_id); + return true; + } } return false; } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 29144025a4d..f523eb826c6 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -14,7 +14,6 @@ #include "MEM_guardedalloc.h" #include "BLI_array.hh" -#include "BLI_linear_allocator.hh" #include "BLI_listbase.h" #include "BLI_math_vector_types.hh" #include "BLI_multi_value_map.hh" @@ -424,77 +423,6 @@ const NodesModifierBake *NodesModifierData::find_bake(const int id) const namespace blender { -static const bNodeTree *try_add_side_effect_node_for_path( - const Span context_path, - const bNodeTree *start_tree, - nodes::GeoNodesSideEffectNodes &local_side_effect_nodes) -{ - for (const ComputeContext *compute_context_generic : context_path) { - BLI_assert(start_tree != nullptr); - const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*start_tree); - if (lf_graph_info == nullptr) { - return nullptr; - } - const bke::bNodeTreeZones *current_zones = start_tree->zones(); - const ComputeContextHash &parent_compute_context_hash = - compute_context_generic->parent()->hash(); - - if (const auto *compute_context = dynamic_cast( - compute_context_generic)) - { - const bke::bNodeTreeZone *simulation_zone = current_zones->get_zone_by_node( - compute_context->output_node_id()); - const lf::FunctionNode *lf_zone_node = lf_graph_info->mapping.zone_node_map.lookup_default( - simulation_zone, nullptr); - if (lf_zone_node == nullptr) { - return nullptr; - } - local_side_effect_nodes.nodes_by_context.add(parent_compute_context_hash, lf_zone_node); - continue; - } - if (const auto *compute_context = dynamic_cast( - compute_context_generic)) - { - const bke::bNodeTreeZone *repeat_zone = current_zones->get_zone_by_node( - compute_context->output_node_id()); - const lf::FunctionNode *lf_zone_node = lf_graph_info->mapping.zone_node_map.lookup_default( - repeat_zone, nullptr); - if (lf_zone_node == nullptr) { - return nullptr; - } - local_side_effect_nodes.nodes_by_context.add(parent_compute_context_hash, lf_zone_node); - local_side_effect_nodes.iterations_by_repeat_zone.add( - {parent_compute_context_hash, compute_context->output_node_id()}, - compute_context->iteration()); - continue; - } - if (const auto *compute_context = dynamic_cast( - compute_context_generic)) - { - const bNode *group_node = start_tree->node_by_id(compute_context->node_id()); - if (group_node == nullptr) { - return nullptr; - } - if (group_node->id == nullptr) { - return nullptr; - } - if (group_node->is_muted()) { - return nullptr; - } - const lf::FunctionNode *lf_group_node = lf_graph_info->mapping.group_node_map.lookup_default( - group_node, nullptr); - if (lf_group_node == nullptr) { - return nullptr; - } - local_side_effect_nodes.nodes_by_context.add(parent_compute_context_hash, lf_group_node); - start_tree = reinterpret_cast(group_node->id); - continue; - } - return nullptr; - } - return start_tree; -} - /** * Setup side effects nodes so that the given node in the given compute context will be executed. * To make sure that it is executed, all parent group nodes and zones have to be set to have side @@ -531,78 +459,103 @@ static void try_add_side_effect_node(const ComputeContext &final_compute_context * caller. This is easier than changing r_side_effect_nodes directly and then undoing changes in * case of errors. */ nodes::GeoNodesSideEffectNodes local_side_effect_nodes; - const bNodeTree *result_tree = nullptr; - result_tree = try_add_side_effect_node_for_path( - compute_context_vec.as_span().drop_front(1), current_tree, local_side_effect_nodes); - if (result_tree == nullptr) { - return; - } - - int final_node_id_ = final_node_id; - - LinearAllocator scope; - - if (const auto *compute_context = dynamic_cast( - compute_context_vec.last())) + for (const ComputeContext *compute_context_generic : compute_context_vec.as_span().drop_front(1)) { - Vector viewer_group_context_list; - const ComputeContext *parent_context = compute_context; - while (true) { - result_tree->ensure_topology_cache(); - result_tree->node_by_id(compute_context->node_id()); - const Span viewers = result_tree->nodes_by_type("GeometryNodeViewer"); - - const bNode *viewer_node = viewers.size() != 1 ? nullptr : viewers.first(); - const bNode *viewer_group = [&]() -> const bNode * { - for (const bNode *group_node : result_tree->group_nodes()) { - if (bke::node_is_viewer_group(*group_node)) { - return group_node; - } - } - return nullptr; - }(); - - if (viewer_node != nullptr) { - final_node_id_ = viewer_node->identifier; - break; - } - if (viewer_group == nullptr || viewer_group->id == nullptr) { + const bke::bNodeTreeZones *current_zones = current_tree->zones(); + if (current_zones == nullptr) { + return; + } + const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*current_tree); + if (lf_graph_info == nullptr) { + return; + } + const ComputeContextHash &parent_compute_context_hash = + compute_context_generic->parent()->hash(); + if (const auto *compute_context = dynamic_cast( + compute_context_generic)) + { + const bke::bNodeTreeZone *simulation_zone = current_zones->get_zone_by_node( + compute_context->output_node_id()); + if (simulation_zone == nullptr) { return; } - - const bNodeTree *tree_f = reinterpret_cast(viewer_group->id); - - for (const bke::bNodeTreeZone *zone : - tree_f->zones()->get_zone_stack_for_node(viewer_group->identifier)) - { - auto *simulation_context = scope.allocate(); - new (simulation_context) - bke::SimulationZoneComputeContext(parent_context, zone->output_node->identifier); - viewer_group_context_list.append(simulation_context); + if (simulation_zone->parent_zone != current_zone) { + return; } - - auto *group_context = scope.allocate(); - new (group_context) bke::NodeGroupComputeContext(parent_context, viewer_group->identifier); - viewer_group_context_list.append(group_context); - - result_tree = reinterpret_cast(viewer_group->id); - if (result_tree == nullptr) { - break; + const lf::FunctionNode *lf_zone_node = lf_graph_info->mapping.zone_node_map.lookup_default( + simulation_zone, nullptr); + if (lf_zone_node == nullptr) { + return; } + local_side_effect_nodes.nodes_by_context.add(parent_compute_context_hash, lf_zone_node); + current_zone = simulation_zone; } - - result_tree = try_add_side_effect_node_for_path( - viewer_group_context_list, result_tree, local_side_effect_nodes); - if (result_tree == nullptr) { + else if (const auto *compute_context = dynamic_cast( + compute_context_generic)) + { + const bke::bNodeTreeZone *repeat_zone = current_zones->get_zone_by_node( + compute_context->output_node_id()); + if (repeat_zone == nullptr) { + return; + } + if (repeat_zone->parent_zone != current_zone) { + return; + } + const lf::FunctionNode *lf_zone_node = lf_graph_info->mapping.zone_node_map.lookup_default( + repeat_zone, nullptr); + if (lf_zone_node == nullptr) { + return; + } + local_side_effect_nodes.nodes_by_context.add(parent_compute_context_hash, lf_zone_node); + local_side_effect_nodes.iterations_by_repeat_zone.add( + {parent_compute_context_hash, compute_context->output_node_id()}, + compute_context->iteration()); + current_zone = repeat_zone; + } + else if (const auto *compute_context = dynamic_cast( + compute_context_generic)) + { + const bNode *group_node = current_tree->node_by_id(compute_context->node_id()); + if (group_node == nullptr) { + return; + } + if (group_node->id == nullptr) { + return; + } + if (group_node->is_muted()) { + return; + } + if (current_zone != current_zones->get_zone_by_node(group_node->identifier)) { + return; + } + const lf::FunctionNode *lf_group_node = lf_graph_info->mapping.group_node_map.lookup_default( + group_node, nullptr); + if (lf_group_node == nullptr) { + return; + } + local_side_effect_nodes.nodes_by_context.add(parent_compute_context_hash, lf_group_node); + current_tree = reinterpret_cast(group_node->id); + current_zone = nullptr; + } + else { return; } } - const bNode *final_node = current_tree->node_by_id(final_node_id); + if (final_node == nullptr) { + return; + } const auto *lf_graph_info = nodes::ensure_geometry_nodes_lazy_function_graph(*current_tree); if (lf_graph_info == nullptr) { return; } + const bke::bNodeTreeZones *tree_zones = current_tree->zones(); + if (tree_zones == nullptr) { + return; + } + if (tree_zones->get_zone_by_node(final_node_id) != current_zone) { + return; + } const lf::FunctionNode *lf_node = lf_graph_info->mapping.possible_side_effect_node_map.lookup_default(final_node, nullptr); if (lf_node == nullptr) { -- 2.30.2 From 449126c0f75656e9e3eb36ab36820e9460e87f4f Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sat, 4 Nov 2023 16:57:36 +0300 Subject: [PATCH 11/15] progress --- .../blender/editors/include/ED_viewer_path.hh | 9 +- .../space_spreadsheet/space_spreadsheet.cc | 7 +- source/blender/editors/util/ed_viewer_path.cc | 101 +++++++++++++++++- source/blender/modifiers/intern/MOD_nodes.cc | 3 +- .../nodes/intern/geometry_nodes_log.cc | 3 +- 5 files changed, 114 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/include/ED_viewer_path.hh b/source/blender/editors/include/ED_viewer_path.hh index fb4ebb47453..fbcc64b1353 100644 --- a/source/blender/editors/include/ED_viewer_path.hh +++ b/source/blender/editors/include/ED_viewer_path.hh @@ -43,12 +43,19 @@ struct ViewerPathForGeometryNodesViewer { int32_t viewer_node_id; }; +struct ViewerPathMemory { + ViewerPath viewer_group_path; + + ViewerPathMemory(); + ~ViewerPathMemory(); +}; + /** * Parses a #ViewerPath into a #ViewerPathForGeometryNodesViewer or returns none if that does not * work. */ std::optional parse_geometry_nodes_viewer( - const ViewerPath &viewer_path); + const ViewerPath &viewer_path, ViewerPathMemory &memory); /** * Finds the node referenced by the #ViewerPath within the provided editor. If no node is diff --git a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc index 83dbd8f9727..fc0008b447f 100644 --- a/source/blender/editors/space_spreadsheet/space_spreadsheet.cc +++ b/source/blender/editors/space_spreadsheet/space_spreadsheet.cc @@ -255,8 +255,10 @@ static void spreadsheet_update_context(const bContext *C) case SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE: { WorkSpace *workspace = CTX_wm_workspace(C); if (sspreadsheet->flag & SPREADSHEET_FLAG_PINNED) { + ed::viewer_path::ViewerPathMemory memory; const std::optional parsed_path = - blender::ed::viewer_path::parse_geometry_nodes_viewer(sspreadsheet->viewer_path); + blender::ed::viewer_path::parse_geometry_nodes_viewer(sspreadsheet->viewer_path, + memory); if (parsed_path.has_value()) { if (blender::ed::viewer_path::exists_geometry_nodes_viewer(*parsed_path)) { /* The pinned path is still valid, do nothing. */ @@ -271,8 +273,9 @@ static void spreadsheet_update_context(const bContext *C) } } /* Now try to update the viewer path from the workspace. */ + ed::viewer_path::ViewerPathMemory memory; const std::optional workspace_parsed_path = - blender::ed::viewer_path::parse_geometry_nodes_viewer(workspace->viewer_path); + blender::ed::viewer_path::parse_geometry_nodes_viewer(workspace->viewer_path, memory); if (workspace_parsed_path.has_value()) { if (BKE_viewer_path_equal(&sspreadsheet->viewer_path, &workspace->viewer_path)) { /* Nothing changed. */ diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index a1068c49988..43640c284d1 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -10,6 +10,7 @@ #include "BKE_compute_contexts.hh" #include "BKE_context.h" #include "BKE_main.h" +#include "BKE_modifier.h" #include "BKE_node_runtime.hh" #include "BKE_node_tree_zones.hh" #include "BKE_workspace.h" @@ -226,7 +227,7 @@ Object *parse_object_only(const ViewerPath &viewer_path) } std::optional parse_geometry_nodes_viewer( - const ViewerPath &viewer_path) + const ViewerPath &viewer_path, ViewerPathMemory &memory) { Vector elems_vec; LISTBASE_FOREACH (const ViewerPathElem *, item, &viewer_path.path) { @@ -262,7 +263,7 @@ std::optional parse_geometry_nodes_viewer( } remaining_elems = remaining_elems.drop_front(1); Vector node_path; - for (const ViewerPathElem *elem : remaining_elems.drop_back(1)) { + for (const ViewerPathElem *elem : remaining_elems) { if (!ELEM(elem->type, VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP, VIEWER_PATH_ELEM_TYPE_GROUP_NODE, @@ -280,8 +281,89 @@ std::optional parse_geometry_nodes_viewer( return ViewerPathForGeometryNodesViewer{root_ob, modifier_name, node_path, viewer_node_id}; } if (last_elem->type == VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP) { + const ModifierData *md = BKE_modifiers_findby_name(reinterpret_cast(root_id), + modifier_name); + const NodesModifierData &nmd = *reinterpret_cast(md); + + const bNodeTree *tree = nmd.node_group; + for (const ViewerPathElem *elem : node_path) { + if (tree == nullptr) { + return std::nullopt; + } + switch (ViewerPathElemType(elem->type)) { + case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: { + const auto &group_elem = *reinterpret_cast(elem); + tree->ensure_topology_cache(); + const bNode &node = *tree->node_by_id(group_elem.node_id); + BLI_assert(node.is_group()); + tree = reinterpret_cast(node.id); + break; + } + case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { + const auto &group_elem = *reinterpret_cast(elem); + tree->ensure_topology_cache(); + const bNode &node = *tree->node_by_id(group_elem.node_id); + BLI_assert(node.is_group()); + tree = reinterpret_cast(node.id); + break; + } + default: + break; + } + } + + while (true) { + tree->ensure_topology_cache(); + BLI_assert(tree->is_viewer()); + + const int32_t local_viewer = [&]() -> int32_t { + const Span viewers = tree->nodes_by_type("GeometryNodeViewer"); + if (viewers.size() == 1) { + return viewers.first()->identifier; + } + BLI_assert(viewers.is_empty()); + const Span groups = tree->group_nodes(); + const bNode &viewer_group = **std::find_if( + groups.begin(), groups.end(), [](const bNode *node) -> bool { + return bke::node_is_viewer_group(*node); + }); + return viewer_group.identifier; + }(); + + const bke::bNodeTreeZones *zones = tree->zones(); + + for (const bNodeTreeZone *zone : zones->get_zone_stack_for_node(local_viewer)) { + ViewerPathElem *zone_elem = viewer_path_elem_for_zone(*zone); + BLI_addtail(&memory.viewer_group_path.path, zone_elem); + node_path.append(zone_elem); + } + + const bNode &viewer = *tree->node_by_id(local_viewer); + if (bke::node_is_viewer_group(viewer)) { + GroupNodeViewerPathElem *group_elem = BKE_viewer_path_elem_new_group_node(); + group_elem->node_id = local_viewer; + ViewerPathElem *elem = reinterpret_cast(group_elem); + + tree = reinterpret_cast(viewer.id); + BLI_assert(tree != nullptr); + + BLI_addtail(&memory.viewer_group_path.path, elem); + node_path.append(elem); + } + else { + /* Regualr Viewer node. */ + ViewerNodeViewerPathElem *viewer_elem = BKE_viewer_path_elem_new_viewer_node(); + viewer_elem->node_id = local_viewer; + ViewerPathElem *elem = reinterpret_cast(viewer_elem); + + BLI_addtail(&memory.viewer_group_path.path, elem); + node_path.append(elem); + break; + } + } + const int32_t viewer_node_group_id = - reinterpret_cast(last_elem)->node_id; + reinterpret_cast(node_path.last())->node_id; return ViewerPathForGeometryNodesViewer{ root_ob, modifier_name, node_path, viewer_node_group_id}; } @@ -458,8 +540,9 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod return nullptr; } + ViewerPathMemory memory; const std::optional parsed_viewer_path = - parse_geometry_nodes_viewer(viewer_path); + parse_geometry_nodes_viewer(viewer_path, memory); if (!parsed_viewer_path.has_value()) { return nullptr; } @@ -517,4 +600,14 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod return false; } +ViewerPathMemory::ViewerPathMemory() +{ + BKE_viewer_path_init(&viewer_group_path); +} + +ViewerPathMemory::~ViewerPathMemory() +{ + BKE_viewer_path_clear(&viewer_group_path); +} + } // namespace blender::ed::viewer_path diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index f523eb826c6..ce001b68fb5 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -578,8 +578,9 @@ static void find_side_effect_nodes_for_viewer_path( const ModifierEvalContext &ctx, nodes::GeoNodesSideEffectNodes &r_side_effect_nodes) { + ed::viewer_path::ViewerPathMemory memory; const std::optional parsed_path = - ed::viewer_path::parse_geometry_nodes_viewer(viewer_path); + ed::viewer_path::parse_geometry_nodes_viewer(viewer_path, memory); if (!parsed_path.has_value()) { return; } diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index b363e8d8c5b..8d4dbd6d8a7 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -571,8 +571,9 @@ static const bNodeTree *top_tree_from_viewer_path(const Span parsed_path = - ed::viewer_path::parse_geometry_nodes_viewer(viewer_path); + ed::viewer_path::parse_geometry_nodes_viewer(viewer_path, memory); if (!parsed_path.has_value()) { return nullptr; } -- 2.30.2 From fd70096825a6b21358986ff226fb7b57827256c0 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sun, 5 Nov 2023 14:59:38 +0300 Subject: [PATCH 12/15] progress --- .../blender/editors/include/ED_viewer_path.hh | 4 +- .../blender/editors/space_node/node_draw.cc | 2 +- .../blender/editors/space_node/node_edit.cc | 3 +- source/blender/editors/util/ed_viewer_path.cc | 77 +++++++++++-------- source/blender/modifiers/intern/MOD_nodes.cc | 3 +- .../nodes/intern/geometry_nodes_log.cc | 16 +++- 6 files changed, 63 insertions(+), 42 deletions(-) diff --git a/source/blender/editors/include/ED_viewer_path.hh b/source/blender/editors/include/ED_viewer_path.hh index fbcc64b1353..633dc4c1a59 100644 --- a/source/blender/editors/include/ED_viewer_path.hh +++ b/source/blender/editors/include/ED_viewer_path.hh @@ -40,7 +40,7 @@ struct ViewerPathForGeometryNodesViewer { blender::StringRefNull modifier_name; /* Contains only group node and simulation zone elements. */ blender::Vector node_path; - int32_t viewer_node_id; + Vector node_ids; }; struct ViewerPathMemory { @@ -62,7 +62,7 @@ std::optional parse_geometry_nodes_viewer( * referenced, null is returned. When two different editors show the same node group but in a * different context, it's possible that the same node is active in one editor but not the other. */ -bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode); +bNode *find_geometry_nodes_viewer_in_space(const ViewerPath &viewer_path, SpaceNode &snode); /** * Checks if the node referenced by the viewer path and its entire context still exists. The node diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 80b9cb8e170..576c4749e69 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -4112,7 +4112,7 @@ static void draw_nodetree(const bContext &C, log->ensure_node_run_time(); } const WorkSpace *workspace = CTX_wm_workspace(&C); - tree_draw_ctx.active_geometry_nodes_viewer = viewer_path::find_geometry_nodes_viewer( + tree_draw_ctx.active_geometry_nodes_viewer = viewer_path::find_geometry_nodes_viewer_in_space( workspace->viewer_path, *snode); } else if (ntree.type == NTREE_COMPOSIT) { diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 6602516b049..a080c21ddbf 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -1684,7 +1684,8 @@ static int node_deactivate_viewer_exec(bContext *C, wmOperator * /*op*/) SpaceNode &snode = *CTX_wm_space_node(C); WorkSpace &workspace = *CTX_wm_workspace(C); - bNode *active_viewer = viewer_path::find_geometry_nodes_viewer(workspace.viewer_path, snode); + bNode *active_viewer = viewer_path::find_geometry_nodes_viewer_in_space(workspace.viewer_path, + snode); if (active_viewer == nullptr) { return OPERATOR_FINISHED; diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index 43640c284d1..8fb30c3b963 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -264,6 +264,9 @@ std::optional parse_geometry_nodes_viewer( remaining_elems = remaining_elems.drop_front(1); Vector node_path; for (const ViewerPathElem *elem : remaining_elems) { + if (ELEM(elem->type, VIEWER_PATH_ELEM_TYPE_VIEWER_NODE)) { + continue; + } if (!ELEM(elem->type, VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP, VIEWER_PATH_ELEM_TYPE_GROUP_NODE, @@ -278,9 +281,11 @@ std::optional parse_geometry_nodes_viewer( if (last_elem->type == VIEWER_PATH_ELEM_TYPE_VIEWER_NODE) { const int32_t viewer_node_id = reinterpret_cast(last_elem)->node_id; - return ViewerPathForGeometryNodesViewer{root_ob, modifier_name, node_path, viewer_node_id}; + return ViewerPathForGeometryNodesViewer{root_ob, modifier_name, node_path, {viewer_node_id}}; } if (last_elem->type == VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP) { + Vector viewer_groups; + const ModifierData *md = BKE_modifiers_findby_name(reinterpret_cast(root_id), modifier_name); const NodesModifierData &nmd = *reinterpret_cast(md); @@ -294,17 +299,24 @@ std::optional parse_geometry_nodes_viewer( case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: { const auto &group_elem = *reinterpret_cast(elem); tree->ensure_topology_cache(); - const bNode &node = *tree->node_by_id(group_elem.node_id); - BLI_assert(node.is_group()); - tree = reinterpret_cast(node.id); + const bNode *node = tree->node_by_id(group_elem.node_id); + if (node == nullptr) { + return std::nullopt; + } + BLI_assert(node->is_group()); + tree = reinterpret_cast(node->id); break; } case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP: { const auto &group_elem = *reinterpret_cast(elem); tree->ensure_topology_cache(); - const bNode &node = *tree->node_by_id(group_elem.node_id); - BLI_assert(node.is_group()); - tree = reinterpret_cast(node.id); + const bNode *node = tree->node_by_id(group_elem.node_id); + if (node == nullptr) { + return std::nullopt; + } + viewer_groups.append(group_elem.node_id); + BLI_assert(node->is_group()); + tree = reinterpret_cast(node->id); break; } default: @@ -338,34 +350,27 @@ std::optional parse_geometry_nodes_viewer( node_path.append(zone_elem); } - const bNode &viewer = *tree->node_by_id(local_viewer); - if (bke::node_is_viewer_group(viewer)) { - GroupNodeViewerPathElem *group_elem = BKE_viewer_path_elem_new_group_node(); - group_elem->node_id = local_viewer; - ViewerPathElem *elem = reinterpret_cast(group_elem); - - tree = reinterpret_cast(viewer.id); - BLI_assert(tree != nullptr); - - BLI_addtail(&memory.viewer_group_path.path, elem); - node_path.append(elem); + const bNode *viewer = tree->node_by_id(local_viewer); + if (viewer == nullptr) { + return std::nullopt; } - else { - /* Regualr Viewer node. */ - ViewerNodeViewerPathElem *viewer_elem = BKE_viewer_path_elem_new_viewer_node(); - viewer_elem->node_id = local_viewer; - ViewerPathElem *elem = reinterpret_cast(viewer_elem); - - BLI_addtail(&memory.viewer_group_path.path, elem); - node_path.append(elem); + viewer_groups.append(viewer->identifier); + if (!bke::node_is_viewer_group(*viewer)) { break; } + GroupNodeViewerPathElem *group_elem = BKE_viewer_path_elem_new_group_node(); + group_elem->node_id = local_viewer; + ViewerPathElem *elem = reinterpret_cast(group_elem); + + tree = reinterpret_cast(viewer->id); + BLI_assert(tree != nullptr); + + BLI_addtail(&memory.viewer_group_path.path, elem); + node_path.append(elem); } - const int32_t viewer_node_group_id = - reinterpret_cast(node_path.last())->node_id; return ViewerPathForGeometryNodesViewer{ - root_ob, modifier_name, node_path, viewer_node_group_id}; + root_ob, modifier_name, node_path, std::move(viewer_groups)}; } return std::nullopt; } @@ -446,7 +451,7 @@ bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed } } - const bNode *viewer_node = ngroup->node_by_id(parsed_viewer_path.viewer_node_id); + const bNode *viewer_node = ngroup->node_by_id(parsed_viewer_path.node_ids.last()); if (viewer_node == nullptr) { return false; } @@ -533,7 +538,7 @@ UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const return UpdateActiveGeometryNodesViewerResult::NotActive; } -bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode) +bNode *find_geometry_nodes_viewer_in_space(const ViewerPath &viewer_path, SpaceNode &snode) { /* Viewer path is only valid if the context object is set. */ if (snode.id == nullptr || GS(snode.id->name) != ID_OB) { @@ -548,7 +553,15 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod } snode.edittree->ensure_topology_cache(); - bNode *possible_viewer = snode.edittree->node_by_id(parsed_viewer_path->viewer_node_id); + bNode *possible_viewer = [&]() -> bNode * { + for (const int32_t identifier : parsed_viewer_path->node_ids) { + if (bNode *viewer = snode.edittree->node_by_id(identifier)) { + return viewer; + } + } + return nullptr; + }(); + if (possible_viewer == nullptr) { return nullptr; } diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index ce001b68fb5..49ce7489529 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -593,7 +593,6 @@ static void find_side_effect_nodes_for_viewer_path( ComputeContextBuilder compute_context_builder; compute_context_builder.push(parsed_path->modifier_name); - for (const ViewerPathElem *elem : parsed_path->node_path) { if (!ed::viewer_path::add_compute_context_for_viewer_path_elem(*elem, compute_context_builder)) { @@ -602,7 +601,7 @@ static void find_side_effect_nodes_for_viewer_path( } try_add_side_effect_node( - *compute_context_builder.current(), parsed_path->viewer_node_id, nmd, r_side_effect_nodes); + *compute_context_builder.current(), parsed_path->node_ids.last(), nmd, r_side_effect_nodes); } static void find_side_effect_nodes(const NodesModifierData &nmd, diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index 8d4dbd6d8a7..a50909b2151 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -565,6 +565,15 @@ static const bNodeTree *top_tree_from_viewer_path(const Spantype == VIEWER_PATH_ELEM_TYPE_VIEWER_NODE_GROUP) { + const auto &typed_elem = *reinterpret_cast(elem); + const bNode *node_group = iter_node_tree->node_by_id(typed_elem.node_id); + if (node_group != nullptr && node_group->id != nullptr) { + iter_node_tree = reinterpret_cast(node_group->id); + continue; + } + return nullptr; + } } return iter_node_tree; } @@ -606,10 +615,9 @@ const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerP { const bNodeTree *iter_node_tree = top_tree_from_viewer_path(parsed_path->node_path, *nmd->node_group); - std::cout << "Name: " << nmd->node_group->id.name << std::endl; - const bNode *viewer_node = iter_node_tree->node_by_id(parsed_path->viewer_node_id); + const bNode *viewer_node = iter_node_tree->node_by_id(parsed_path->node_ids.last()); if (bke::node_is_viewer_group(*viewer_node)) { - compute_context_builder.push(parsed_path->viewer_node_id); + compute_context_builder.push(parsed_path->node_ids.last()); const auto lookup_viewer = [&](const bNodeTree &tree) -> const bNode * { BLI_assert(tree.is_viewer()); @@ -678,7 +686,7 @@ const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerP tree_log.ensure_viewer_node_logs(); const ViewerNodeLog *viewer_log = tree_log.viewer_node_logs.lookup_default( - parsed_path->viewer_node_id, nullptr); + parsed_path->node_ids.last(), nullptr); return viewer_log; } -- 2.30.2 From 4eb6331a26e9e1358c8b70820840c462ff980e3a Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Sun, 5 Nov 2023 21:37:28 +0300 Subject: [PATCH 13/15] progress --- .../blender/editors/space_node/CMakeLists.txt | 1 - .../editors/space_node/node_connection.cc | 416 ------------------ .../editors/space_node/node_relationships.cc | 146 +++++- 3 files changed, 123 insertions(+), 440 deletions(-) delete mode 100644 source/blender/editors/space_node/node_connection.cc diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index b88d91dd915..fac04776f25 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -35,7 +35,6 @@ set(SRC drawnode.cc link_drag_search.cc node_add.cc - node_connection.cc node_context_path.cc node_draw.cc node_edit.cc diff --git a/source/blender/editors/space_node/node_connection.cc b/source/blender/editors/space_node/node_connection.cc deleted file mode 100644 index 814c2da29f4..00000000000 --- a/source/blender/editors/space_node/node_connection.cc +++ /dev/null @@ -1,416 +0,0 @@ -/* SPDX-FileCopyrightText: 2008 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup spnode - */ - -#if (0) - -# include "DNA_node_types.h" - -# include "BLI_offset_indices.hh" - -# include "BKE_node_runtime.hh" - -# include "NOD_node_declaration.hh" - -namespace blender::ed::space_node::connection { - -//#if (0) - -enum class SocketState : int8_t { - ConnectedToTarger, - ConnectedToOther, - Free, -}; - -class TargetSocketNode; - -class Context { - public: - bNodeTree &tree; - TargetSocketNode &target_node; - int index; - bool side_is_input; -}; - -class Node { - public: - virtual ~Node() = default; - - IndexRange index_range(const Context &context) const - { - return IndexRange(this->size(context)); - } - - std::optional first_connection(const Context &context) const - { - for (const int index : this->index_range(context)) { - if (this->is_connected(context, index)) { - return index; - } - } - return std::nullopt; - } - - virtual int size(const Context &context) const = 0; - - virtual bool is_connected(const Context &context, int socket_index) const = 0; - virtual eNodeSocketDatatype type(const Context &context, int socket_index) const = 0; - - virtual StringRef name(const Context &context, int socket_index) const = 0; - virtual bool single_value(const Context &context, int socket_index) const = 0; - - // TODO: std::pair to_connect(Context &context, int socket_index) const = - // 0; -}; - -class RealNode : public Node { - private: - const bNode &node_; - - public: - RealNode(const bNode &node) : node_(node) {} - - int size(const Context &context) const final - { - /* TODO: Do not count hide sockets! */ - return int(context.side_is_input ? node_.input_sockets().size() : - node_.output_sockets().size()); - } - - bool is_connected(const Context &context, const int socket_index) const override - { - BLI_assert(&node_ != &context.target_node); - const Span sockets = context.side_is_input ? node_.input_sockets() : - node_.output_sockets(); - for (const bNodeSocket *other_socket : sockets[socket_index]->logically_linked_sockets()) { - if (&other_socket->owner_node() == &context.target_node->node_) { - return true; - } - } - return false; - } - - eNodeSocketDatatype type(const Context &context, int socket_index) const override - { - const Span sockets = context.side_is_input ? node_.input_sockets() : - node_.output_sockets(); - return eNodeSocketDatatype(sockets[socket_index]->type); - } - - StringRef name(const Context &context, int socket_index) const override - { - const Span sockets = context.side_is_input ? node_.input_sockets() : - node_.output_sockets(); - return sockets[socket_index]->name; - } - - bool single_value(const Context &context, int socket_index) const override - { - BLI_assert(context.tree != nullptr); - const Span sockets = context.side_is_input ? node_.input_sockets() : - node_.output_sockets(); - if (context.side_is_input) { - return nodes::InputSocketFieldType::None == - sockets[socket_index]->runtime->declaration->input_field_type; - } - return nodes::OutputSocketFieldType::None == - sockets[socket_index]->runtime->declaration->output_field_dependency.field_type(); - } -}; - -class TargetSocketNode : public Node { - private: - const eNodeSocketDatatype type_; - const StringRef name_; - - public: - TargetSocketNode(const eNodeSocketDatatype type, const StringRef name) : type_(type), name_(name) - { - } - - int size(const Context & /*context*/) const final - { - return 1; - } - - bool is_connected(const Context &context, int socket_index) const final - { - return false; - } - - eNodeSocketDatatype type(const Context &context, int socket_index) const final - { - return type_; - } - - StringRef name(const Context &context, int socket_index) const final - { - return name; - } - - bool single_value(const Context &context, int socket_index) const final - { - return false; - } -}; - -class VirtualNode : public Node { - public: - bool is_connected(const Context & /*context*/, const int /*socket_index*/) const final - { - return false; - } -}; - -class ViewerNode : public VirtualNode { - private: - const eNodeSocketDatatype data_type_; - - public: - ViewerNode(const eNodeSocketDatatype data_type) : data_type_(data_type) {} - - int size(const Context & /*context*/) const final - { - return 2; - } - - eNodeSocketDatatype type(const Context & /*context*/, int socket_index) const override - { - if (socket_index == 0) { - return SOCK_GEOMETRY; - } - return data_type_; - } - - StringRef name(const Context & /*context*/, int socket_index) const override - { - if (socket_index == 0) { - return "Geometry"; - } - return "Value"; - } - - bool single_value(const Context & /*context*/, int socket_index) const override - { - if (socket_index == 0) { - return true; - } - return false; - } -}; - -class GroupNode : public VirtualNode { - private: - const bNodeTree &group_; - - public: - GroupNode(const bNodeTree &group) : group_(group) - { - group_.ensure_topology_cache(); - group_.ensure_interface_cache(); - } - - int size(const Context &context) const final - { - const Span sockets = context.side_is_input ? - group_.interface_inputs() : - group_.interface_outputs(); - return int(context.side_is_input ? group_.interface_inputs().size() : - group_.interface_outputs().size()); - } - - eNodeSocketDatatype type(const Context &context, int socket_index) const override - { - const Span sockets = context.side_is_input ? - group_.interface_inputs() : - group_.interface_outputs(); - return eNodeSocketDatatype(sockets[socket_index]->socket_typeinfo()->type); - } - - StringRef name(const Context &context, int socket_index) const override - { - const Span sockets = context.side_is_input ? - group_.interface_inputs() : - group_.interface_outputs(); - return sockets[socket_index]->name; - } - - bool single_value(const Context &context, int socket_index) const override - { - const nodes::FieldInferencingInterface &interface = - *group_.runtime->field_inferencing_interface; - if (context.side_is_input) { - return nodes::InputSocketFieldType::None == interface.inputs[socket_index]; - } - return nodes::OutputSocketFieldType::None == interface.outputs[socket_index].field_type(); - } - - const bNodeTree &group() const - { - return group_; - } -}; - -class ViewerGroupNode : public GroupNode { - public: - ViewerGroupNode(const bNodeTree &group) : GroupNode(group) - { - BLI_assert(this->group().is_viewer()); - } -}; - -/* -static void (const Context &context, const Span nodes) -{ - const NodePtr target = context.target_node; - for (const NodePtr &node : nodes) { - std::optional index = node->first_connection(context); - if (!index.has_value()) { - continue; - } - for (const int i : target->index_range()) { - if (target->type(i) != node->type(*index)) { - continue; - } - - } - for (const int i : target->index_range()) { - if (target->type(i) == node->type(*index)) { - continue; - } - - } - } - for (const NodePtr &node : nodes) { - if (node->first_connection(context).has_value()) { - continue; - } - - } -} -*/ - -//#endif - -/* - -class Socket { - private: - const NodePtr own_node_; - const int index_; - const SocketState state_; - - public: - - bool operator > (const Socket &other) const - { - return false; - } -}; - -*/ - -/* - -using NodeFilter = FunctionRef nodes)>; - -static bool node_state_filter(const MutableSpan nodes, const NodeFilter next_filter) -{ - Vector connected; - Vector exist; - Vector other; - - for (NodePtr &node : nodes) { - if (node->first_connection()) { - connected.append(std::move(node)); - continue; - } - if (dynamic_cast(&*node)) { - exist.append(std::move(node)); - continue; - } - other.append(std::move(node)); - } - - return next_filter(connected) || next_filter(exist) || next_filter(other); -} - -static bool socket_state_filter(const MutableSpan nodes, const NodeFilter next_filter) -{ - Vector targer; - Vector exist; - Vector other; - - for (NodePtr &node : nodes) { - if (node->first_connection()) { - connected.append(std::move(node)); - continue; - } - if (dynamic_cast(&*node)) { - exist.append(std::move(node)); - continue; - } - other.append(std::move(node)); - } - - return next_filter(connected) || next_filter(exist) || next_filter(other); -} - -*/ - -/* -struct ConnectWeight { - bool connected; - std::optional first_index; - bool same_name; - int type_conversion; - int field_interfacing_conversion; - - ConnectWeight(const Context &context, const Node &node, const int index) : - connected(node->first_connection(context).has_value()), - same_name(node->name() ); -}; -*/ - -class Socket { - // const NodePtr &node; -}; - -static bool sockets_cmp(const Socket &a, const Socket b) -{ - return false; -} - -static std::optional lookup_socket_for_context(const Span nodes, - const Context context) -{ - Array accumulate_sockets(nodes.size() + 1, 0); - for (const int index : nodes.index_range()) { - accumulate_sockets[index] = nodes[index]->size(context); - } - OffsetIndices sockets_offset = offset_indices::accumulate_counts_to_offsets( - accumulate_sockets); - Array sockets(sockets_offset.total_size()); - for (const int node_index : nodes.index_range()) { - const NodePtr &node = nodes[node_index]; - IndexRange node_sockets = sockets_offset[node_index]; - for (const int index : node_sockets.index_range()) { - sockets[node_sockets[index]]; // = Socket(context, node); - } - } - - const Socket *socket = std::max_element(sockets.begin(), sockets.end(), sockets_cmp); - if (socket == sockets.end()) { - return std::nullopt; - } - - return *socket; -} - -} // namespace blender::ed::space_node::connection - -#endif \ No newline at end of file diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index b4787b6c28c..5e94f5f7554 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -50,6 +50,7 @@ #include "BLT_translation.h" #include "NOD_node_declaration.hh" +#include "NOD_socket.hh" #include "NOD_socket_declarations.hh" #include "NOD_socket_declarations_geometry.hh" @@ -453,6 +454,7 @@ static bool socket_can_be_viewed(const bNode &node, const bNodeSocket &socket) /** * Find the socket to link to in a viewer node. */ + static bNodeSocket *node_link_viewer_get_socket(bNodeTree &ntree, bNode &viewer_node, bNodeSocket &src_socket) @@ -630,30 +632,26 @@ static int link_view_sockets(const bContext &C, bNodeSocket &bsocket_to_view, bNodeSocket &bsocket_of_viewer) { - return {}; - /* - bNodeSocket *viewer_bsocket = node_link_viewer_get_socket(btree, *viewer_node, bsocket_to_view); - if (viewer_bsocket == nullptr) { - return OPERATOR_CANCELLED; - } + bNode &node = bsocket_to_view.owner_node(); + bNode &viewer = bsocket_of_viewer.owner_node(); + bNodeLink *viewer_link = nullptr; - LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &btree.links) { - if (link->tosock == viewer_bsocket) { + for (bNodeLink *link : btree.all_links()) { + if (link->tosock == &bsocket_of_viewer) { viewer_link = link; break; } } if (viewer_link == nullptr) { - viewer_link = nodeAddLink( - &btree, &bnode_to_view, &bsocket_to_view, viewer_node, viewer_bsocket); + viewer_link = nodeAddLink(&btree, &node, &bsocket_to_view, &viewer, &bsocket_of_viewer); } else { - viewer_link->fromnode = &bnode_to_view; + viewer_link->fromnode = &node; viewer_link->fromsock = &bsocket_to_view; BKE_ntree_update_tag_link_changed(&btree); } - finalize_viewer_link(C, snode, *viewer_node, *viewer_link); - return OPERATOR_CANCELLED;*/ + finalize_viewer_link(C, snode, viewer, *viewer_link); + return OPERATOR_CANCELLED; } static bNodeSocket *best_view_socket_find_or_new(const bNodeTree &btree, @@ -701,30 +699,132 @@ static bNodeSocket *best_view_socket_find_or_new(const bNodeTree &btree, */ } -static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket *bsocket_to_view) +struct ViewerSocketTrait { + std::function(bNodeTree &)> finalize; + + eCustomDataType type; + StringRef socket_name; + StringRef node_name; +}; + +static void traits_for_viewers(const Span viewers, + Vector &r_traits) +{ + static const Array viewer_types = {CD_PROP_FLOAT, + CD_PROP_BOOL, + CD_PROP_INT32, + CD_PROP_FLOAT3, + CD_PROP_COLOR, + CD_PROP_QUATERNION}; + for (const bNode *viewer : viewers) { + for (const eCustomDataType data_type : viewer_types) { + ViewerSocketTrait trait; + trait.type = data_type; + trait.socket_name = "Value"; + trait.node_name = viewer->name; + + const int32_t identifiers = viewer->identifier; + trait.finalize = [=](bNodeTree &tree) -> std::pair { + tree.ensure_topology_cache(); + bNode &viewer = *tree.node_by_id(identifiers); + for (bNodeSocket *socket : viewer.input_sockets().drop_front(1)) { + const eNodeSocketDatatype socket_type = eNodeSocketDatatype(socket->type); + if (*bke::socket_type_to_custom_data_type(socket_type) == data_type) { + NodeGeometryViewer &storage = *static_cast(viewer.storage); + storage.data_type = data_type; + viewer.typeinfo->updatefunc(&tree, &viewer); + return {&viewer, socket}; + } + } + BLI_assert_unreachable(); + return {}; + }; + + r_traits.append(std::move(trait)); + } + } +} + +static void traits_for_groups(Main &bmain, Vector &r_traits) +{ + LISTBASE_FOREACH (bNodeTree *, group, &bmain.nodetrees) { + if (!group->is_viewer()) { + continue; + } + + group->ensure_topology_cache(); + group->ensure_interface_cache(); + + const Span inputs = group->interface_inputs(); + for (const int index : inputs.index_range()) { + const bNodeTreeInterfaceSocket &input = *inputs[index]; + + ViewerSocketTrait trait; + trait.type = CD_PROP_INT32; + trait.socket_name = input.name; + trait.node_name = group->id.name; + + trait.finalize = [=](bNodeTree &tree) -> std::pair { + tree.ensure_topology_cache(); + + bNode *node_group = nodeAddStaticNode(nullptr, &tree, NODE_GROUP); + node_group->id = &group->id; + id_us_plus(&group->id); + tree.ensure_topology_cache(); + bke::node_field_inferencing::update_field_inferencing(*group); + nodes::update_node_declaration_and_sockets(tree, *node_group); + tree.ensure_topology_cache(); + + return {node_group, node_group->input_sockets()[index]}; + }; + + r_traits.append(std::move(trait)); + } + } +} + +static void traits_for_exist_groups(const Span groups, + Vector &r_traits) +{ +} + +static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket *node_socket) { SpaceNode &snode = *CTX_wm_space_node(&C); bNodeTree *btree = snode.edittree; btree->ensure_topology_cache(); - const Array viewers = all_view_nodes(*btree); - const Array connected_viewers = all_connected_viewer(*btree, bnode_to_view); + const Span viewers = btree->nodes_by_type("GeometryNodeViewer"); + const Span groups = btree->group_nodes(); + // const Array connected_viewers = all_connected_viewer(*btree, bnode_to_view); const bNode *active_viewer = active_viewer_in_tree(*btree); - if (bsocket_to_view == nullptr) { - bsocket_to_view = determine_socket_to_view(bnode_to_view); + if (node_socket == nullptr) { + node_socket = determine_socket_to_view(bnode_to_view); } - if (bsocket_to_view == nullptr) { + if (node_socket == nullptr) { return OPERATOR_CANCELLED; } - bNodeSocket *target_viewer_socket = best_view_socket_find_or_new( - *btree, *bsocket_to_view, viewers, connected_viewers, active_viewer); - if (target_viewer_socket == nullptr) { + Vector traits; + traits_for_viewers(viewers, traits); + // traits_for_viewers({active_viewer}, traits); + traits_for_exist_groups(groups, traits); + traits_for_groups(*CTX_data_main(&C), traits); + + if (traits.is_empty()) { return OPERATOR_CANCELLED; } - return link_view_sockets(C, snode, *btree, *bsocket_to_view, *target_viewer_socket); + + const ViewerSocketTrait &viewer_trait = *std::max_element( + traits.begin(), + traits.end(), + [&](const ViewerSocketTrait &a, const ViewerSocketTrait &b) -> bool { return false; }); + + auto [viewer_node, viewer_socket] = viewer_trait.finalize(*btree); + btree->ensure_topology_cache(); + return link_view_sockets(C, snode, *btree, *node_socket, *viewer_socket); } /** \} */ -- 2.30.2 From 7b5b0d4ee8acf9bcb61f7710c05fdb72171c6efd Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Mon, 6 Nov 2023 18:18:35 +0300 Subject: [PATCH 14/15] progress --- .../editors/space_node/node_relationships.cc | 157 ++++++++++++++++-- 1 file changed, 143 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 5e94f5f7554..c3211c21974 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -702,36 +702,58 @@ static bNodeSocket *best_view_socket_find_or_new(const bNodeTree &btree, struct ViewerSocketTrait { std::function(bNodeTree &)> finalize; - eCustomDataType type; + eNodeSocketDatatype type; StringRef socket_name; StringRef node_name; + + bool node_is_connected = false; + + float prioriti = 1.0f; }; static void traits_for_viewers(const Span viewers, Vector &r_traits) { - static const Array viewer_types = {CD_PROP_FLOAT, - CD_PROP_BOOL, - CD_PROP_INT32, - CD_PROP_FLOAT3, - CD_PROP_COLOR, - CD_PROP_QUATERNION}; + static const Array viewer_types = { + SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_INT, SOCK_ROTATION, SOCK_VECTOR}; for (const bNode *viewer : viewers) { - for (const eCustomDataType data_type : viewer_types) { + ViewerSocketTrait trait; + trait.type = SOCK_GEOMETRY; + trait.socket_name = "Geometry"; + trait.node_name = viewer->name; + trait.prioriti = 1.0f; + + const int32_t identifiers = viewer->identifier; + trait.finalize = [=](bNodeTree &tree) -> std::pair { + tree.ensure_topology_cache(); + bNode &viewer = *tree.node_by_id(identifiers); + return {&viewer, viewer.input_sockets().first()}; + }; + + r_traits.append(std::move(trait)); + + for (const eNodeSocketDatatype socket_type : viewer_types) { ViewerSocketTrait trait; - trait.type = data_type; + trait.type = socket_type; trait.socket_name = "Value"; trait.node_name = viewer->name; + trait.prioriti = 1.0f; const int32_t identifiers = viewer->identifier; + NodeGeometryViewer &storage = *static_cast(viewer->storage); + + if (storage.data_type == *bke::socket_type_to_custom_data_type(socket_type)) { + trait.prioriti = 2.0f; + } + trait.finalize = [=](bNodeTree &tree) -> std::pair { tree.ensure_topology_cache(); bNode &viewer = *tree.node_by_id(identifiers); for (bNodeSocket *socket : viewer.input_sockets().drop_front(1)) { - const eNodeSocketDatatype socket_type = eNodeSocketDatatype(socket->type); - if (*bke::socket_type_to_custom_data_type(socket_type) == data_type) { + const eNodeSocketDatatype other_socket_type = eNodeSocketDatatype(socket->type); + if (socket_type == other_socket_type) { NodeGeometryViewer &storage = *static_cast(viewer.storage); - storage.data_type = data_type; + storage.data_type = *bke::socket_type_to_custom_data_type(other_socket_type); viewer.typeinfo->updatefunc(&tree, &viewer); return {&viewer, socket}; } @@ -760,7 +782,7 @@ static void traits_for_groups(Main &bmain, Vector &r_traits) const bNodeTreeInterfaceSocket &input = *inputs[index]; ViewerSocketTrait trait; - trait.type = CD_PROP_INT32; + trait.type = SOCK_INT; trait.socket_name = input.name; trait.node_name = group->id.name; @@ -788,6 +810,96 @@ static void traits_for_exist_groups(const Span groups, { } +int get_link_type_priority(const eNodeSocketDatatype from, const eNodeSocketDatatype to) +{ + switch (to) { + case SOCK_RGBA: + switch (from) { + case SOCK_RGBA: + return 4; + case SOCK_FLOAT: + return 3; + case SOCK_INT: + return 2; + case SOCK_BOOLEAN: + return 1; + default: + break; + } + return -1; + case SOCK_VECTOR: + switch (from) { + case SOCK_VECTOR: + return 4; + case SOCK_FLOAT: + return 3; + case SOCK_INT: + return 2; + case SOCK_BOOLEAN: + return 1; + default: + break; + } + return -1; + case SOCK_FLOAT: + switch (from) { + case SOCK_FLOAT: + return 5; + case SOCK_INT: + return 4; + case SOCK_BOOLEAN: + return 3; + case SOCK_RGBA: + return 2; + case SOCK_VECTOR: + return 1; + default: + break; + } + return -1; + case SOCK_INT: + switch (from) { + case SOCK_INT: + return 5; + case SOCK_FLOAT: + return 4; + case SOCK_BOOLEAN: + return 3; + case SOCK_RGBA: + return 2; + case SOCK_VECTOR: + return 1; + default: + break; + } + return -1; + case SOCK_BOOLEAN: + switch (from) { + case SOCK_BOOLEAN: + return 5; + case SOCK_INT: + return 4; + case SOCK_FLOAT: + return 3; + case SOCK_RGBA: + return 2; + case SOCK_VECTOR: + return 1; + default: + break; + } + return -1; + default: + break; + } + + if (to == from) { + return 1; + } + + return -1; +} + static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket *node_socket) { SpaceNode &snode = *CTX_wm_space_node(&C); @@ -820,7 +932,24 @@ static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket const ViewerSocketTrait &viewer_trait = *std::max_element( traits.begin(), traits.end(), - [&](const ViewerSocketTrait &a, const ViewerSocketTrait &b) -> bool { return false; }); + [&](const ViewerSocketTrait &a, const ViewerSocketTrait &b) -> bool { + const bool to_connected = a.node_is_connected != b.node_is_connected; + const bool connected_node = b.node_is_connected; + + const int a_type_priority = get_link_type_priority(a.type, + eNodeSocketDatatype(node_socket->type)); + const int b_type_priority = get_link_type_priority(b.type, + eNodeSocketDatatype(node_socket->type)); + if (ELEM(-1, a_type_priority, b_type_priority)) { + return a_type_priority < b_type_priority; + } + /* Avoid conversions if possible. */ + if (ELEM(4, a_type_priority, b_type_priority) && a_type_priority != b_type_priority) { + return a_type_priority < b_type_priority; + } + + return a.prioriti < b.prioriti; + }); auto [viewer_node, viewer_socket] = viewer_trait.finalize(*btree); btree->ensure_topology_cache(); -- 2.30.2 From b5451cd5df44707f2358fcb857ff38ab117a1204 Mon Sep 17 00:00:00 2001 From: Iliya Katueshenock Date: Mon, 6 Nov 2023 21:30:40 +0300 Subject: [PATCH 15/15] progress --- .../editors/space_node/node_relationships.cc | 165 ++++++++++++++---- 1 file changed, 129 insertions(+), 36 deletions(-) diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index c3211c21974..f83f2a1c029 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -711,59 +711,127 @@ struct ViewerSocketTrait { float prioriti = 1.0f; }; +static void traits_for_viewer(Vector &r_traits) +{ + static const Array viewer_types = { + SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_INT, SOCK_ROTATION, SOCK_VECTOR}; + + static const auto new_viewer = [](bNodeTree &tree) -> bNode & { + return *nodeAddStaticNode(nullptr, &tree, GEO_NODE_VIEWER); + }; + + ViewerSocketTrait trait; + trait.type = SOCK_GEOMETRY; + trait.socket_name = "Geometry"; + trait.node_name = "Viewer"; + trait.prioriti = 1.0f; + + trait.finalize = [=](bNodeTree &tree) -> std::pair { + bNode &viewer = new_viewer(tree); + tree.ensure_topology_cache(); + return {&viewer, viewer.input_sockets().first()}; + }; + + r_traits.append(std::move(trait)); + + for (const eNodeSocketDatatype socket_type : viewer_types) { + ViewerSocketTrait trait; + trait.type = socket_type; + trait.socket_name = "Value"; + trait.node_name = "Viewer"; + trait.prioriti = 0.5f; + + trait.finalize = [=](bNodeTree &tree) -> std::pair { + bNode &viewer = new_viewer(tree); + tree.ensure_topology_cache(); + + for (bNodeSocket *socket : viewer.input_sockets().drop_front(1)) { + const eNodeSocketDatatype other_socket_type = eNodeSocketDatatype(socket->type); + if (socket_type == other_socket_type) { + NodeGeometryViewer &storage = *static_cast(viewer.storage); + storage.data_type = *bke::socket_type_to_custom_data_type(other_socket_type); + viewer.typeinfo->updatefunc(&tree, &viewer); + return {&viewer, socket}; + } + } + + BLI_assert_unreachable(); + return {}; + }; + + r_traits.append(std::move(trait)); + } +} + static void traits_for_viewers(const Span viewers, + const Span depend_on_node, Vector &r_traits) { static const Array viewer_types = { SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_INT, SOCK_ROTATION, SOCK_VECTOR}; for (const bNode *viewer : viewers) { - ViewerSocketTrait trait; - trait.type = SOCK_GEOMETRY; - trait.socket_name = "Geometry"; - trait.node_name = viewer->name; - trait.prioriti = 1.0f; - const int32_t identifiers = viewer->identifier; - trait.finalize = [=](bNodeTree &tree) -> std::pair { - tree.ensure_topology_cache(); - bNode &viewer = *tree.node_by_id(identifiers); - return {&viewer, viewer.input_sockets().first()}; - }; - - r_traits.append(std::move(trait)); - - for (const eNodeSocketDatatype socket_type : viewer_types) { + if (!viewer->input_sockets().first()->is_directly_linked()) { ViewerSocketTrait trait; - trait.type = socket_type; - trait.socket_name = "Value"; + trait.type = SOCK_GEOMETRY; + trait.socket_name = "Geometry"; trait.node_name = viewer->name; trait.prioriti = 1.0f; + trait.node_is_connected = depend_on_node[viewer->index()]; + const int32_t identifiers = viewer->identifier; - NodeGeometryViewer &storage = *static_cast(viewer->storage); - - if (storage.data_type == *bke::socket_type_to_custom_data_type(socket_type)) { - trait.prioriti = 2.0f; - } - trait.finalize = [=](bNodeTree &tree) -> std::pair { tree.ensure_topology_cache(); bNode &viewer = *tree.node_by_id(identifiers); - for (bNodeSocket *socket : viewer.input_sockets().drop_front(1)) { - const eNodeSocketDatatype other_socket_type = eNodeSocketDatatype(socket->type); - if (socket_type == other_socket_type) { - NodeGeometryViewer &storage = *static_cast(viewer.storage); - storage.data_type = *bke::socket_type_to_custom_data_type(other_socket_type); - viewer.typeinfo->updatefunc(&tree, &viewer); - return {&viewer, socket}; - } - } - BLI_assert_unreachable(); - return {}; + return {&viewer, viewer.input_sockets().first()}; }; r_traits.append(std::move(trait)); } + + bool value_is_linked = false; + + for (const bNodeSocket *socket : viewer->input_sockets().drop_front(1)) { + value_is_linked |= socket->is_directly_linked(); + } + + if (!value_is_linked) { + for (const eNodeSocketDatatype socket_type : viewer_types) { + ViewerSocketTrait trait; + trait.type = socket_type; + trait.socket_name = "Value"; + trait.node_name = viewer->name; + trait.prioriti = 1.0f; + + trait.node_is_connected = depend_on_node[viewer->index()]; + + const int32_t identifiers = viewer->identifier; + NodeGeometryViewer &storage = *static_cast(viewer->storage); + + if (storage.data_type == *bke::socket_type_to_custom_data_type(socket_type)) { + trait.prioriti = 2.0f; + } + + trait.finalize = [=](bNodeTree &tree) -> std::pair { + tree.ensure_topology_cache(); + bNode &viewer = *tree.node_by_id(identifiers); + for (bNodeSocket *socket : viewer.input_sockets().drop_front(1)) { + const eNodeSocketDatatype other_socket_type = eNodeSocketDatatype(socket->type); + if (socket_type == other_socket_type) { + NodeGeometryViewer &storage = *static_cast(viewer.storage); + storage.data_type = *bke::socket_type_to_custom_data_type(other_socket_type); + viewer.typeinfo->updatefunc(&tree, &viewer); + return {&viewer, socket}; + } + } + BLI_assert_unreachable(); + return {}; + }; + + r_traits.append(std::move(trait)); + } + } } } @@ -782,9 +850,10 @@ static void traits_for_groups(Main &bmain, Vector &r_traits) const bNodeTreeInterfaceSocket &input = *inputs[index]; ViewerSocketTrait trait; - trait.type = SOCK_INT; + trait.type = eNodeSocketDatatype(input.socket_typeinfo()->type); trait.socket_name = input.name; trait.node_name = group->id.name; + trait.prioriti = 3.0f; trait.finalize = [=](bNodeTree &tree) -> std::pair { tree.ensure_topology_cache(); @@ -919,8 +988,23 @@ static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket return OPERATOR_CANCELLED; } + const Span left_to_right = btree->toposort_left_to_right(); + Array depend_on_node(left_to_right.size(), false); + for (const bNode *node : left_to_right) { + for (const bNodeSocket *input : node->input_sockets()) { + for (const bNodeSocket *output_socket : input->directly_linked_sockets()) { + const bNode &other = output_socket->owner_node(); + if (&other == &bnode_to_view) { + depend_on_node[node->index()] = true; + } + depend_on_node[node->index()] |= depend_on_node[other.index()]; + } + } + } + Vector traits; - traits_for_viewers(viewers, traits); + traits_for_viewer(traits); + traits_for_viewers(viewers, depend_on_node, traits); // traits_for_viewers({active_viewer}, traits); traits_for_exist_groups(groups, traits); traits_for_groups(*CTX_data_main(&C), traits); @@ -948,9 +1032,18 @@ static int node_link_viewer(const bContext &C, bNode &bnode_to_view, bNodeSocket return a_type_priority < b_type_priority; } + if (to_connected) { + const float connection_factor = connected_node ? 5.0f : 0.2f; + return a.prioriti < b.prioriti * connection_factor; + } + return a.prioriti < b.prioriti; }); + if (-1 == get_link_type_priority(viewer_trait.type, eNodeSocketDatatype(node_socket->type))) { + return OPERATOR_CANCELLED; + } + auto [viewer_node, viewer_socket] = viewer_trait.finalize(*btree); btree->ensure_topology_cache(); return link_view_sockets(C, snode, *btree, *node_socket, *viewer_socket); -- 2.30.2