Nodes: Panel declarations for grouping sockets

Adds an optional list of panels to node trees. Each socket can be
assigned a panel. UI panels will be created in the future in the
modifier for these grouped sockets.

Panels are stored as a pointer array in node trees, next to socket
declarations. Each panel has a name, but it does not have to be unique.
In future a panel might also store whether it is visible by default and
similar information.

C API and RNA API are both added. Panels and their socket
assignments are accessible to users through another list in the "Group"
tab of the node editor sidebar.

Sockets in the same panel will remain together even when adding,
removing, or moving sockets or panels, renaming, etc.
A socket can be moved up or down within a panel but each panel
remains a contiguous block. Actual tree views may be created later.

Pull Request: https://projects.blender.org/blender/blender/pulls/108649
This commit is contained in:
Lukas Tönne
2023-06-14 18:02:40 +02:00
parent 8d457cb68f
commit 8c2ad8bbd3
13 changed files with 674 additions and 7 deletions
+83
View File
@@ -9,6 +9,7 @@ from bpy.types import (
from bpy.props import (
BoolProperty,
CollectionProperty,
EnumProperty,
FloatVectorProperty,
StringProperty,
)
@@ -243,11 +244,93 @@ class NODE_OT_tree_path_parent(Operator):
return {'FINISHED'}
class NodePanelOperator():
@classmethod
def poll(cls, context):
snode = context.space_data
if snode is None:
return False
tree = snode.edit_tree
if tree is None:
return False
if tree.is_embedded_data:
return False
return True
class NODE_OT_panel_add(NodePanelOperator, Operator):
'''Add a new panel to the tree'''
bl_idname = "node.panel_add"
bl_label = "Add Panel"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
snode = context.space_data
tree = snode.edit_tree
panels = tree.panels
# Remember index to move the item.
dst_index = min(panels.active_index + 1, len(panels))
panels.new("Panel")
panels.move(len(panels) - 1, dst_index)
panels.active_index = dst_index
return {'FINISHED'}
class NODE_OT_panel_remove(NodePanelOperator, Operator):
'''Remove a panel from the tree'''
bl_idname = "node.panel_remove"
bl_label = "Remove Panel"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
snode = context.space_data
tree = snode.edit_tree
panels = tree.panels
if panels.active:
panels.remove(panels.active)
panels.active_index = min(panels.active_index, len(panels) - 1)
return {'FINISHED'}
class NODE_OT_panel_move(NodePanelOperator, Operator):
'''Move a panel to another position'''
bl_idname = "node.panel_move"
bl_label = "Move Panel"
bl_options = {'REGISTER', 'UNDO'}
direction: EnumProperty(
name="Direction",
items=[('UP', "Up", ""), ('DOWN', "Down", "")],
default='UP',
)
def execute(self, context):
snode = context.space_data
tree = snode.edit_tree
panels = tree.panels
if self.direction == 'UP' and panels.active_index > 0:
panels.move(panels.active_index, panels.active_index - 1)
panels.active_index -= 1
elif self.direction == 'DOWN' and panels.active_index < len(panels) - 1:
panels.move(panels.active_index, panels.active_index + 1)
panels.active_index += 1
return {'FINISHED'}
classes = (
NodeSetting,
NODE_OT_add_node,
NODE_OT_add_simulation_zone,
NODE_OT_collapse_hide_unused_toggle,
NODE_OT_panel_add,
NODE_OT_panel_remove,
NODE_OT_panel_move,
NODE_OT_tree_path_parent,
)