WIP: Geometry Nodes: Viewer Node Group #112152
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user