[Bf-blender-cvs] [e26d7a7] object_nodes: 'Make Group' operator (ctrl+g) to easily create a node group from selected nodes.
Lukas Tönne
noreply at git.blender.org
Sun Dec 27 18:40:17 CET 2015
Commit: e26d7a72fd3a5fbd4668751f274703393954ae4e
Author: Lukas Tönne
Date: Sun Dec 27 18:39:48 2015 +0100
Branches: object_nodes
https://developer.blender.org/rBe26d7a72fd3a5fbd4668751f274703393954ae4e
'Make Group' operator (ctrl+g) to easily create a node group from selected nodes.
===================================================================
M release/scripts/nodes/geometry_nodes.py
M release/scripts/nodes/group_nodes.py
M release/scripts/nodes/instancing_nodes.py
M release/scripts/nodes/socket_types.py
===================================================================
diff --git a/release/scripts/nodes/geometry_nodes.py b/release/scripts/nodes/geometry_nodes.py
index 359b54f..98725cf 100644
--- a/release/scripts/nodes/geometry_nodes.py
+++ b/release/scripts/nodes/geometry_nodes.py
@@ -421,7 +421,7 @@ def register():
GeometryNodeCategory("GEO_CURVE", "Curve", items=[
NodeItem("CurvePathNode"),
]),
- group_nodes.GroupNodeCategory("GEO", gnode),
+ group_nodes.GroupNodeCategory("GEO", gnode, ginput, goutput),
]
nodeitems_utils.register_node_categories("GEOMETRY_NODES", node_categories)
diff --git a/release/scripts/nodes/group_nodes.py b/release/scripts/nodes/group_nodes.py
index df06e35..4c3ae3c 100644
--- a/release/scripts/nodes/group_nodes.py
+++ b/release/scripts/nodes/group_nodes.py
@@ -22,7 +22,7 @@ import bpy
import nodeitems_utils
from bpy.types import Operator, Panel, UIList, NodeTree, Node, NodeSocket, ObjectNode, PropertyGroup, BVMTypeDesc
from bpy.props import *
-from socket_types import socket_type_items, socket_type_to_rna, socket_type_to_bvm_type
+from socket_types import socket_type_items, socket_type_to_rna, socket_type_to_bvm_type, rna_to_socket_type
from nodeitems_utils import NodeCategory as NodeCategoryBase, NodeItem, NodeItemCustom
###############################################################################
@@ -419,7 +419,171 @@ def make_node_group_types(prefix, treetype, node_base):
###############################################################################
-def GroupNodeCategory(prefix, gnode):
+def GroupNodeCategory(prefix, gnode, ginput, goutput):
+ ntree_idname = gnode.bl_ntree_idname
+
+ def copy_node(dst, src):
+ copy_attrs = ['color', 'height', 'hide', 'label',
+ 'location', 'id', 'mute', 'name',
+ 'show_options', 'show_preview', 'show_texture', 'use_custom_color',
+ 'width', 'width_hidden']
+ for attr in copy_attrs:
+ if not hasattr(dst, attr):
+ continue
+ if dst.is_property_readonly(attr):
+ continue
+ setattr(dst, attr, getattr(src, attr))
+
+ for key, value in src.items():
+ dst[key] = value
+
+ class NodeGroupMake(Operator):
+ """Make a node group from selected nodes"""
+ bl_idname = "object_nodes.%s_nodegroup_make" % prefix.lower()
+ bl_label = "Make Group"
+ bl_options = {'REGISTER', 'UNDO'}
+ bl_ntree_idname = ntree_idname
+
+ name = StringProperty(
+ name="Name",
+ default="Node Group",
+ )
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+ if not space or space.type != 'NODE_EDITOR':
+ return False
+ ntree = space.edit_tree
+ if not ntree or not gnode.poll(ntree):
+ return False
+ return True
+
+ def execute(self, context):
+ ntree = context.space_data.edit_tree
+
+ # Warning! this has to happen right at the start
+ # because creating a node will make it selected by default!
+ selected_nodes = [node for node in ntree.nodes if node.select]
+ internal_links = []
+ input_links = []
+ output_links = []
+ for link in ntree.links:
+ if link.is_hidden or not link.is_valid:
+ continue
+ sel_from = link.from_node.select
+ sel_to = link.to_node.select
+ if not sel_from and not sel_to:
+ continue
+ elif sel_from and sel_to:
+ internal_links.append(link)
+ elif sel_from:
+ output_links.append(link)
+ elif sel_to:
+ input_links.append(link)
+
+ groupnode = ntree.nodes.new(gnode.bl_idname)
+ if groupnode is None:
+ return {'CANCELLED'}
+ grouptree = bpy.data.node_groups.new(self.name, self.bl_ntree_idname)
+ if grouptree is None:
+ return {'CANCELLED'}
+ groupinput = grouptree.nodes.new(ginput.bl_idname)
+ groupoutput = grouptree.nodes.new(goutput.bl_idname)
+ groupnode.id = grouptree
+
+ new_nodes = dict()
+ new_sockets = dict()
+ # copy nodes and local attributes
+ for node in selected_nodes:
+ inode = grouptree.nodes.new(node.bl_idname)
+ copy_node(inode, node)
+
+ # map old to new
+ new_nodes[node] = inode
+ for old, new in zip(node.inputs, inode.inputs):
+ new_sockets[old] = new
+ for old, new in zip(node.outputs, inode.outputs):
+ new_sockets[old] = new
+ # parent node must be mapped to new nodes
+ for node, inode in new_nodes.items():
+ if node.parent:
+ iparent = new_nodes.get(node.parent, None)
+ if iparent:
+ inode.parent = iparent
+
+ # move nodes to sensible locations
+ if selected_nodes:
+ bbx = (min(node.location[0] for node in selected_nodes),
+ max(node.location[0] + node.width for node in selected_nodes))
+ bby = (min(node.location[1] - node.height for node in selected_nodes),
+ max(node.location[1] for node in selected_nodes))
+ else:
+ bbx = (0.0, 0.0)
+ bby = (0.0, 0.0)
+ center = (0.5*(bbx[0] + bbx[1]), 0.5*(bby[0] + bby[1]))
+ for node in new_nodes.values():
+ node.location[0] -= center[0]
+ node.location[1] -= center[1]
+ offsetx = 0.5*(bbx[1] - bbx[0])
+ groupinput.location[0] = -offsetx - groupinput.bl_width_default - 50
+ groupinput.location[1] = 0.5*groupinput.bl_height_default
+ groupoutput.location[0] = offsetx + 50
+ groupoutput.location[1] = 0.5*groupoutput.bl_height_default
+
+ groupnode.location[0] = center[0] - 0.5*groupnode.bl_width_default
+ groupnode.location[1] = center[1] + 0.5*groupnode.bl_height_default
+
+ # define the group interface
+ io_inputs = dict()
+ io_outputs = dict()
+ for link in input_links:
+ if link.from_socket not in io_inputs:
+ io_inputs[link.from_socket] = {link.to_socket,}
+ else:
+ io_inputs[link.from_socket].add(link.to_socket)
+ for link in output_links:
+ if link.from_socket not in io_outputs:
+ io_outputs[link.from_socket] = {link.to_socket,}
+ else:
+ io_outputs[link.from_socket].add(link.to_socket)
+
+ # reconstruct links
+ for link in internal_links:
+ ifrom_socket = new_sockets[link.from_socket]
+ ito_socket = new_sockets[link.to_socket]
+ grouptree.links.new(ifrom_socket, ito_socket)
+ for io, targets in io_inputs.items():
+ grouptree.add_input(io.name, rna_to_socket_type(type(io)))
+ io_extern = groupnode.inputs[-1]
+ io_intern = groupinput.outputs[-1]
+
+ ntree.links.new(io, io_extern)
+ for s in targets:
+ grouptree.links.new(io_intern, new_sockets[s])
+ for io, targets in io_outputs.items():
+ grouptree.add_output(io.name, rna_to_socket_type(type(io)))
+ io_extern = groupnode.outputs[-1]
+ io_intern = groupoutput.inputs[-1]
+
+ grouptree.links.new(new_sockets[io], io_intern)
+ for s in targets:
+ ntree.links.new(io_extern, s)
+
+ # delete replaced nodes
+ for node in selected_nodes:
+ ntree.nodes.remove(node)
+
+ # clean up selection
+ for node in grouptree.nodes:
+ node.select = False
+ grouptree.nodes.active = None
+ for node in ntree.nodes:
+ node.select = (node == groupnode)
+ ntree.nodes.active = groupnode
+
+ return {'FINISHED'}
+
# menu entry for node group tools
def group_tools_draw(self, layout, context):
# TODO C node operators won't work for our nodes
@@ -459,12 +623,26 @@ def GroupNodeCategory(prefix, gnode):
return False
return gnode.poll(ntree)
+ bpy.utils.register_class(NodeGroupMake)
+
+ # create keymap
+ wm = bpy.context.window_manager
+ km = wm.keyconfigs.default.keymaps.new(name="Node Generic", space_type='NODE_EDITOR')
+ kmi = km.keymap_items.new(NodeGroupMake.bl_idname, 'G', 'PRESS', ctrl=True)
+ keymaps.append(km)
+
return NodeCategory()
###############################################################################
+keymaps = []
+
def register():
pass
def unregister():
- pass
+ # remove keymap
+ wm = bpy.context.window_manager
+ for km in keymaps:
+ wm.keyconfigs.default.keymaps.remove(km)
+ keymaps.clear()
diff --git a/release/scripts/nodes/instancing_nodes.py b/release/scripts/nodes/instancing_nodes.py
index db765d3..8ee25b9 100644
--- a/release/scripts/nodes/instancing_nodes.py
+++ b/release/scripts/nodes/instancing_nodes.py
@@ -226,7 +226,7 @@ def register():
NodeItem("ObjectTextureCloudsNode"),
NodeItem("ObjectTextureVoronoiNode"),
]),
- group_nodes.GroupNodeCategory("INS", gnode),
+ group_nodes.GroupNodeCategory("INS", gnode, ginput, goutput),
]
nodeitems_utils.register_node_categories("INSTANCING_NODES", node_categories)
diff --git a/release/scripts/nodes/socket_types.py b/release/scripts/nodes/socket_types.py
index 9ff53b4..0b2af20 100644
--- a/release/scripts/nodes/socket_types.py
+++ b/release/scripts/nodes/socket
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list