WIP: Geometry Nodes: Viewer Node Group #112152

Draft
Iliya Katushenock wants to merge 24 commits from mod_moder/blender:group_viewer_branch into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 62 additions and 2 deletions
Showing only changes of commit b20e2fe2d1 - Show all commits

View File

@ -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);

View File

@ -564,6 +564,11 @@ inline blender::Span<bNodeTreeInterfaceItem *> bNodeTree::interface_items() cons
return this->runtime->interface_cache.items;
}
inline bool bNodeTree::is_viewer() const
{
return this->flag & NTREE_IS_VIEWER;
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -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<bNodeTree *>(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()) {

View File

@ -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<bNode *> viewers = ntree.nodes_by_type("GeometryNodeViewer");
const Span<bNode *> 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();

View File

@ -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);

View File

@ -712,6 +712,8 @@ typedef struct bNodeTree {
[[nodiscard]] bool node_id_path_from_nested_node_ref(const int32_t nested_node_id,
blender::Vector<int32_t> &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 */

View File

@ -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);