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:
@@ -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,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user