Compare commits
15 Commits
temp-T9904
...
temp-node-
Author | SHA1 | Date | |
---|---|---|---|
8300ba81f2 | |||
2db2afeeb6 | |||
fb7d203d21 | |||
bcc6b87881 | |||
1faf31f62d | |||
0f69327140 | |||
497167d3a0 | |||
6a82b2f4c6 | |||
9d20624760 | |||
b9aa7f3ce8 | |||
9a7f0b7fec | |||
47006dbdce | |||
d98e05f4b5 | |||
64d2881650 | |||
acef1af28d |
@@ -1831,6 +1831,7 @@ def km_node_editor(params):
|
||||
])
|
||||
|
||||
items.extend([
|
||||
("node.follow_portal", {"type": 'TAB', "value": 'PRESS'}, None),
|
||||
("node.select_box", {"type": params.select_tweak, "value": 'ANY'},
|
||||
{"properties": [("tweak", True)]}),
|
||||
("node.select_lasso", {"type": 'EVT_TWEAK_L', "value": 'ANY', "ctrl": True, "alt": True},
|
||||
|
@@ -21,6 +21,7 @@ from __future__ import annotations
|
||||
|
||||
import bpy
|
||||
import nodeitems_utils
|
||||
from mathutils import Vector
|
||||
from bpy.types import (
|
||||
Operator,
|
||||
PropertyGroup,
|
||||
@@ -303,6 +304,187 @@ class NODE_OT_tree_path_parent(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class NODE_OT_follow_portal(Operator):
|
||||
'''Follow portal'''
|
||||
bl_idname = "node.follow_portal"
|
||||
bl_label = "Follow Portal"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
space = context.space_data
|
||||
return (space.type == 'NODE_EDITOR'
|
||||
and space.node_tree
|
||||
and space.node_tree.nodes.active.bl_idname in ('NodePortalIn', 'NodePortalOut'))
|
||||
|
||||
def execute(self, context):
|
||||
space = context.space_data
|
||||
ntree = space.node_tree
|
||||
old_active_node = ntree.nodes.active
|
||||
|
||||
portal_id = old_active_node.portal_id
|
||||
if old_active_node.bl_idname == 'NodePortalIn':
|
||||
out_nodes = [n for n in ntree.nodes if n.bl_idname == 'NodePortalOut' and n.portal_id == portal_id]
|
||||
if len(out_nodes) != 1:
|
||||
return {'CANCELLED'}
|
||||
out_node = out_nodes[0]
|
||||
for node in ntree.nodes:
|
||||
node.select = False
|
||||
out_node.select = True
|
||||
ntree.nodes.active = out_node
|
||||
if old_active_node.bl_idname == 'NodePortalOut':
|
||||
in_nodes = [n for n in ntree.nodes if n.bl_idname == 'NodePortalIn' and n.portal_id == portal_id]
|
||||
if len(in_nodes) != 1:
|
||||
return {'CANCELLED'}
|
||||
in_node = in_nodes[0]
|
||||
for node in ntree.nodes:
|
||||
node.select = False
|
||||
in_node.select = True
|
||||
ntree.nodes.active = in_node
|
||||
|
||||
bpy.ops.node.view_selected()
|
||||
return {'FINISHED'}
|
||||
|
||||
PAGE_SIZE = 20000
|
||||
|
||||
def get_page_center(page):
|
||||
return Vector(((page - 1) * PAGE_SIZE, 0))
|
||||
|
||||
def position_is_on_page(pos, page):
|
||||
page_center = get_page_center(page)
|
||||
return (abs(page_center.x - pos[0]) < PAGE_SIZE / 2
|
||||
and abs(page_center.y - pos[1]) < PAGE_SIZE / 2)
|
||||
|
||||
def node_is_on_page(node, page):
|
||||
return position_is_on_page(node.location, page)
|
||||
|
||||
def get_nodes_on_page(ntree, page):
|
||||
return [n for n in ntree.nodes if node_is_on_page(n, page)]
|
||||
|
||||
def get_current_page(context):
|
||||
for region in context.area.regions:
|
||||
if region.type != 'WINDOW':
|
||||
continue
|
||||
pos = region.view2d.region_to_view(0, 0)
|
||||
for page in range(10):
|
||||
if position_is_on_page(pos, page):
|
||||
return page
|
||||
return None
|
||||
|
||||
class NODE_OT_view_page(Operator):
|
||||
'''View page'''
|
||||
bl_idname = "node.view_page"
|
||||
bl_label = "View Page"
|
||||
|
||||
page: bpy.props.IntProperty(default=0)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
space = context.space_data
|
||||
return space.type == 'NODE_EDITOR'
|
||||
|
||||
def invoke(self, context, event):
|
||||
if event.ctrl:
|
||||
bpy.ops.node.move_to_page('INVOKE_DEFAULT', page=self.page)
|
||||
return {'FINISHED'}
|
||||
return self.execute(context)
|
||||
|
||||
def execute(self, context):
|
||||
space = context.space_data
|
||||
ntree = space.node_tree
|
||||
for node in ntree.nodes:
|
||||
node.select = False
|
||||
|
||||
nodes_on_page = get_nodes_on_page(ntree, self.page)
|
||||
if len(nodes_on_page) > 0:
|
||||
for node in nodes_on_page:
|
||||
node.select = True
|
||||
bpy.ops.node.view_selected()
|
||||
for node in nodes_on_page:
|
||||
node.select = False
|
||||
ntree.nodes.active = None
|
||||
else:
|
||||
page_center = get_page_center(self.page)
|
||||
new_node = ntree.nodes.new('NodeReroute')
|
||||
new_node.select = True
|
||||
new_node.location = page_center
|
||||
|
||||
context_copy = context.copy()
|
||||
def update_after_draw():
|
||||
bpy.ops.node.view_selected(context_copy)
|
||||
ntree.nodes.remove(new_node)
|
||||
bpy.app.timers.register(update_after_draw, first_interval=0.01)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class NODE_OT_move_to_page(Operator):
|
||||
'''Move to page'''
|
||||
bl_idname = "node.move_to_page"
|
||||
bl_label = "Move to Page"
|
||||
|
||||
page: IntProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
space = context.space_data
|
||||
return space.type == 'NODE_EDITOR'
|
||||
|
||||
def execute(self, context):
|
||||
ntree = context.space_data.node_tree
|
||||
nodes_to_move = [n for n in ntree.nodes if n.select]
|
||||
if len(nodes_to_move) == 0:
|
||||
return {'CANCELLED'}
|
||||
|
||||
old_center = sum((n.location for n in nodes_to_move), Vector((0, 0))) / len(nodes_to_move)
|
||||
new_center = get_page_center(self.page)
|
||||
offset = new_center - old_center
|
||||
|
||||
view2d = context.region.view2d
|
||||
old_center_region = Vector(view2d.view_to_region(old_center.x, old_center.y, clip=False))
|
||||
new_center_region = Vector(view2d.view_to_region(new_center.x, new_center.y, clip=False))
|
||||
offset_region = new_center_region - old_center_region
|
||||
|
||||
for node in nodes_to_move:
|
||||
node.location += offset
|
||||
|
||||
bpy.ops.view2d.pan(deltax=offset_region.x, deltay=offset_region.y)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class NODE_OT_add_portal(Operator):
|
||||
'''Add portal'''
|
||||
bl_idname = "node.add_portal"
|
||||
bl_label = "Add Portal"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.space_data.type != 'NODE_EDITOR':
|
||||
return False
|
||||
ntree = context.space_data.node_tree
|
||||
if ntree is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
def invoke(self, context, event):
|
||||
ntree = context.space_data.node_tree
|
||||
bpy.ops.node.add_and_link_node(type="NodePortalIn")
|
||||
portal_in = ntree.nodes[-1]
|
||||
bpy.ops.node.add_and_link_node(type="NodePortalOut")
|
||||
portal_out = ntree.nodes[-1]
|
||||
|
||||
portal_in.location.x -= 200
|
||||
portal_out.location.x += 60
|
||||
|
||||
for node in ntree.nodes:
|
||||
node.select = False
|
||||
|
||||
portal_in.select = True
|
||||
portal_out.select = True
|
||||
|
||||
portal_out.portal_id = portal_in.portal_id
|
||||
|
||||
bpy.ops.node.translate_attach("INVOKE_DEFAULT")
|
||||
return {'FINISHED'}
|
||||
|
||||
classes = (
|
||||
NodeSetting,
|
||||
|
||||
@@ -311,4 +493,8 @@ classes = (
|
||||
NODE_OT_add_search,
|
||||
NODE_OT_collapse_hide_unused_toggle,
|
||||
NODE_OT_tree_path_parent,
|
||||
NODE_OT_follow_portal,
|
||||
NODE_OT_view_page,
|
||||
NODE_OT_add_portal,
|
||||
NODE_OT_move_to_page,
|
||||
)
|
||||
|
@@ -171,6 +171,16 @@ class NODE_HT_header(Header):
|
||||
else:
|
||||
row.template_ID(snode, "node_tree", new="node.new_geometry_nodes_modifier")
|
||||
|
||||
import bl_operators.node as node_module
|
||||
current_page = node_module.get_current_page(context)
|
||||
|
||||
row = layout.row(align=True)
|
||||
for page in range(1, 6):
|
||||
subrow = row.row(align=True)
|
||||
subrow.enabled = page != current_page
|
||||
props = subrow.operator("node.view_page", text=str(page))
|
||||
props.page = page
|
||||
|
||||
else:
|
||||
# Custom node tree is edited as independent ID block
|
||||
NODE_MT_editor_menus.draw_collapsible(context, layout)
|
||||
@@ -238,6 +248,8 @@ class NODE_MT_add(bpy.types.Menu):
|
||||
# actual node submenus are defined by draw functions from node categories
|
||||
nodeitems_utils.draw_node_categories_menu(self, context)
|
||||
|
||||
layout.operator("node.add_portal")
|
||||
|
||||
|
||||
class NODE_MT_view(Menu):
|
||||
bl_label = "View"
|
||||
|
@@ -564,6 +564,8 @@ geometry_node_categories = [
|
||||
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[
|
||||
NodeItem("NodeFrame"),
|
||||
NodeItem("NodeReroute"),
|
||||
NodeItem("NodePortalIn"),
|
||||
NodeItem("NodePortalOut"),
|
||||
]),
|
||||
]
|
||||
|
||||
|
@@ -860,6 +860,8 @@ bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node
|
||||
#define NODE_GROUP_INPUT 7
|
||||
#define NODE_GROUP_OUTPUT 8
|
||||
#define NODE_CUSTOM_GROUP 9
|
||||
#define NODE_PORTAL_IN 10
|
||||
#define NODE_PORTAL_OUT 11
|
||||
|
||||
void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree);
|
||||
|
||||
|
@@ -4963,6 +4963,8 @@ static void registerGeometryNodes()
|
||||
register_node_type_geo_transform();
|
||||
register_node_type_geo_triangulate();
|
||||
register_node_type_geo_volume_to_mesh();
|
||||
register_node_type_portal_in();
|
||||
register_node_type_portal_out();
|
||||
}
|
||||
|
||||
static void registerFunctionNodes()
|
||||
|
@@ -137,6 +137,7 @@ bool node_connected_to_output(Main *bmain, bNodeTree *ntree, bNode *node)
|
||||
if (ntree_has_drivers(ntree)) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
LISTBASE_FOREACH (bNode *, current_node, &ntree->nodes) {
|
||||
/* Special case for group nodes -- if modified node connected to a group
|
||||
* with active output inside we consider refresh is needed.
|
||||
|
@@ -1298,6 +1298,14 @@ typedef struct NodeGeometryMeshCone {
|
||||
uint8_t fill_type;
|
||||
} NodeGeometryMeshCone;
|
||||
|
||||
typedef struct NodePortalIn {
|
||||
int portal_id;
|
||||
} NodePortalIn;
|
||||
|
||||
typedef struct NodePortalOut {
|
||||
int portal_id;
|
||||
} NodePortalOut;
|
||||
|
||||
typedef struct NodeGeometryMeshLine {
|
||||
/* GeometryNodeMeshLineMode. */
|
||||
uint8_t mode;
|
||||
|
@@ -9574,6 +9574,28 @@ static void def_geo_mesh_line(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
|
||||
}
|
||||
|
||||
static void def_portal_in(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodePortalIn", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "portal_id", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Portal ID", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_portal_out(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodePortalOut", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "portal_id", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Portal ID", "");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void rna_def_shader_node(BlenderRNA *brna)
|
||||
|
@@ -38,6 +38,7 @@ set(INC
|
||||
../makesdna
|
||||
../makesrna
|
||||
../render
|
||||
../windowmanager
|
||||
../../../intern/glew-mx
|
||||
../../../intern/guardedalloc
|
||||
../../../intern/sky/include
|
||||
@@ -177,6 +178,7 @@ set(SRC
|
||||
geometry/nodes/node_geo_point_separate.cc
|
||||
geometry/nodes/node_geo_point_translate.cc
|
||||
geometry/nodes/node_geo_points_to_volume.cc
|
||||
geometry/nodes/node_geo_portals.cc
|
||||
geometry/nodes/node_geo_subdivide.cc
|
||||
geometry/nodes/node_geo_subdivision_surface.cc
|
||||
geometry/nodes/node_geo_transform.cc
|
||||
|
@@ -68,6 +68,8 @@ void register_node_type_geo_subdivision_surface(void);
|
||||
void register_node_type_geo_transform(void);
|
||||
void register_node_type_geo_triangulate(void);
|
||||
void register_node_type_geo_volume_to_mesh(void);
|
||||
void register_node_type_portal_in(void);
|
||||
void register_node_type_portal_out(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -178,6 +178,8 @@ class NodeRef : NonCopyable, NonMovable {
|
||||
bool is_group_output_node() const;
|
||||
bool is_muted() const;
|
||||
bool is_frame() const;
|
||||
bool is_portal_in() const;
|
||||
bool is_portal_out() const;
|
||||
|
||||
void *storage() const;
|
||||
template<typename T> T *storage() const;
|
||||
@@ -225,6 +227,8 @@ class NodeTreeRef : NonCopyable, NonMovable {
|
||||
Vector<OutputSocketRef *> output_sockets_;
|
||||
Vector<LinkRef *> links_;
|
||||
MultiValueMap<const bNodeType *, NodeRef *> nodes_by_type_;
|
||||
MultiValueMap<int, NodeRef *> portal_in_nodes_by_id_;
|
||||
MultiValueMap<int, NodeRef *> portal_out_nodes_by_id_;
|
||||
|
||||
public:
|
||||
NodeTreeRef(bNodeTree *btree);
|
||||
@@ -240,6 +244,9 @@ class NodeTreeRef : NonCopyable, NonMovable {
|
||||
|
||||
Span<const LinkRef *> links() const;
|
||||
|
||||
Span<const NodeRef *> portal_in_nodes_by_id(int portal_id) const;
|
||||
Span<const NodeRef *> portal_out_nodes_by_id(int portal_id) const;
|
||||
|
||||
bool has_link_cycles() const;
|
||||
|
||||
bNodeTree *btree() const;
|
||||
@@ -541,6 +548,16 @@ inline bool NodeRef::is_muted() const
|
||||
return (bnode_->flag & NODE_MUTED) != 0;
|
||||
}
|
||||
|
||||
inline bool NodeRef::is_portal_in() const
|
||||
{
|
||||
return bnode_->type == NODE_PORTAL_IN;
|
||||
}
|
||||
|
||||
inline bool NodeRef::is_portal_out() const
|
||||
{
|
||||
return bnode_->type == NODE_PORTAL_OUT;
|
||||
}
|
||||
|
||||
inline void *NodeRef::storage() const
|
||||
{
|
||||
return bnode_->storage;
|
||||
@@ -634,6 +651,16 @@ inline Span<const LinkRef *> NodeTreeRef::links() const
|
||||
return links_;
|
||||
}
|
||||
|
||||
inline Span<const NodeRef *> NodeTreeRef::portal_in_nodes_by_id(int portal_id) const
|
||||
{
|
||||
return portal_in_nodes_by_id_.lookup(portal_id);
|
||||
}
|
||||
|
||||
inline Span<const NodeRef *> NodeTreeRef::portal_out_nodes_by_id(int portal_id) const
|
||||
{
|
||||
return portal_out_nodes_by_id_.lookup(portal_id);
|
||||
}
|
||||
|
||||
inline bNodeTree *NodeTreeRef::btree() const
|
||||
{
|
||||
return btree_;
|
||||
|
@@ -36,6 +36,9 @@ DefNode(Node, NODE_GROUP, def_group, "GROUP"
|
||||
DefNode(Node, NODE_GROUP_INPUT, def_group_input, "GROUP_INPUT", GroupInput, "Group Input", "" )
|
||||
DefNode(Node, NODE_GROUP_OUTPUT, def_group_output, "GROUP_OUTPUT", GroupOutput, "Group Output", "" )
|
||||
DefNode(Node, NODE_REROUTE, 0, "REROUTE", Reroute, "Reroute", "" )
|
||||
DefNode(Node, NODE_PORTAL_IN, def_portal_in, "PORTAL_IN", PortalIn, "Portal In", "" )
|
||||
DefNode(Node, NODE_PORTAL_OUT, def_portal_out, "PORTAL_OUT", PortalOut, "Portal Out", "" )
|
||||
|
||||
|
||||
DefNode(ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
|
||||
DefNode(ShaderNode, SH_NODE_VALUE, 0, "VALUE", Value, "Value", "" )
|
||||
|
128
source/blender/nodes/geometry/nodes/node_geo_portals.cc
Normal file
128
source/blender/nodes/geometry/nodes/node_geo_portals.cc
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
static bNodeSocketTemplate node_portal_sockets[] = {
|
||||
{SOCK_GEOMETRY, N_("Geometry")},
|
||||
{SOCK_FLOAT, N_("Float"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
|
||||
{SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX},
|
||||
{SOCK_RGBA, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
|
||||
{SOCK_INT, N_("Integer"), 0, 0, 0, 0, -10000, 10000},
|
||||
{SOCK_BOOLEAN, N_("Boolean")},
|
||||
{SOCK_STRING, N_("String")},
|
||||
{SOCK_OBJECT, N_("Object")},
|
||||
{SOCK_COLLECTION, N_("Collection")},
|
||||
{-1, ""},
|
||||
};
|
||||
|
||||
static void node_portal_in_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
uiItemR(layout, ptr, "name", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_portal_out_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||
{
|
||||
const int portal_id = RNA_int_get(ptr, "portal_id");
|
||||
bNodeTree &ntree = *(bNodeTree *)ptr->owner_id;
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
|
||||
if (node->type == NODE_PORTAL_IN) {
|
||||
NodePortalIn *storage = (NodePortalIn *)node->storage;
|
||||
if (storage->portal_id == portal_id) {
|
||||
PointerRNA other_ptr;
|
||||
RNA_pointer_create(ptr->owner_id, &RNA_Node, node, &other_ptr);
|
||||
uiItemR(layout, &other_ptr, "name", 0, "", ICON_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void node_portal_in_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||
{
|
||||
NodePortalIn *data = (NodePortalIn *)MEM_callocN(sizeof(NodePortalIn), __func__);
|
||||
data->portal_id = rand();
|
||||
node->storage = data;
|
||||
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
|
||||
if (!STREQ(socket->name, "Geometry")) {
|
||||
socket->flag |= SOCK_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void node_portal_out_init(bNodeTree *UNUSED(tree), bNode *node)
|
||||
{
|
||||
NodePortalOut *data = (NodePortalOut *)MEM_callocN(sizeof(NodePortalOut), __func__);
|
||||
node->storage = data;
|
||||
|
||||
LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
|
||||
if (!STREQ(socket->name, "Geometry")) {
|
||||
socket->flag |= SOCK_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void node_portal_in_update(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodePortalIn &node_storage = *(NodePortalIn *)node->storage;
|
||||
UNUSED_VARS(node_storage);
|
||||
}
|
||||
|
||||
static void node_portal_out_update(bNodeTree *UNUSED(ntree), bNode *node)
|
||||
{
|
||||
NodePortalOut &node_storage = *(NodePortalOut *)node->storage;
|
||||
UNUSED_VARS(node_storage);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
void register_node_type_portal_in()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, NODE_PORTAL_IN, "Portal In", NODE_CLASS_LAYOUT, 0);
|
||||
node_type_socket_templates(&ntype, node_portal_sockets, nullptr);
|
||||
node_type_init(&ntype, blender::nodes::node_portal_in_init);
|
||||
node_type_update(&ntype, blender::nodes::node_portal_in_update);
|
||||
node_type_storage(
|
||||
&ntype, "NodePortalIn", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.draw_buttons = node_portal_in_layout;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
void register_node_type_portal_out()
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, NODE_PORTAL_OUT, "Portal Out", NODE_CLASS_LAYOUT, 0);
|
||||
node_type_socket_templates(&ntype, nullptr, node_portal_sockets);
|
||||
node_type_init(&ntype, blender::nodes::node_portal_out_init);
|
||||
node_type_update(&ntype, blender::nodes::node_portal_out_update);
|
||||
node_type_storage(
|
||||
&ntype, "NodePortalOut", node_free_standard_storage, node_copy_standard_storage);
|
||||
ntype.draw_buttons = node_portal_out_layout;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
@@ -105,12 +105,21 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
|
||||
}
|
||||
}
|
||||
|
||||
this->create_linked_socket_caches();
|
||||
|
||||
for (NodeRef *node : nodes_by_id_) {
|
||||
const bNodeType *nodetype = node->bnode_->typeinfo;
|
||||
nodes_by_type_.add(nodetype, node);
|
||||
|
||||
if (node->is_portal_in()) {
|
||||
NodePortalIn *storage = (NodePortalIn *)node->bnode_->storage;
|
||||
portal_in_nodes_by_id_.add(storage->portal_id, node);
|
||||
}
|
||||
else if (node->is_portal_out()) {
|
||||
NodePortalOut *storage = (NodePortalOut *)node->bnode_->storage;
|
||||
portal_out_nodes_by_id_.add(storage->portal_id, node);
|
||||
}
|
||||
}
|
||||
|
||||
this->create_linked_socket_caches();
|
||||
}
|
||||
|
||||
NodeTreeRef::~NodeTreeRef()
|
||||
@@ -223,6 +232,12 @@ void NodeTreeRef::foreach_logical_origin(InputSocketRef &socket,
|
||||
if (origin_node->is_reroute_node()) {
|
||||
this->foreach_logical_origin(*origin_node->inputs_[0], callback, false);
|
||||
}
|
||||
else if (origin_node->is_portal_out()) {
|
||||
NodePortalOut *storage = origin_node->storage<NodePortalOut>();
|
||||
for (NodeRef *input_node : portal_in_nodes_by_id_.lookup(storage->portal_id)) {
|
||||
this->foreach_logical_origin(*input_node->inputs_[0], callback);
|
||||
}
|
||||
}
|
||||
else if (origin_node->is_muted()) {
|
||||
for (InternalLinkRef *internal_link : origin_node->internal_links_) {
|
||||
if (internal_link->to_ == origin) {
|
||||
@@ -249,6 +264,12 @@ void NodeTreeRef::foreach_logical_target(OutputSocketRef &socket,
|
||||
if (target_node->is_reroute_node()) {
|
||||
this->foreach_logical_target(*target_node->outputs_[0], callback);
|
||||
}
|
||||
else if (target_node->is_portal_in()) {
|
||||
NodePortalIn *storage = target_node->storage<NodePortalIn>();
|
||||
for (NodeRef *output_node : portal_out_nodes_by_id_.lookup(storage->portal_id)) {
|
||||
this->foreach_logical_target(*output_node->outputs_[0], callback);
|
||||
}
|
||||
}
|
||||
else if (target_node->is_muted()) {
|
||||
for (InternalLinkRef *internal_link : target_node->internal_links_) {
|
||||
if (internal_link->from_ == target) {
|
||||
|
Reference in New Issue
Block a user