Nodes: Added "Move Item" operator for re-ordering nodegroup sockets and panels #117130

Open
quackarooni wants to merge 1 commits from quackarooni/blender:nodegroup_move_item_operator into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
2 changed files with 98 additions and 1 deletions

View File

@ -386,6 +386,98 @@ class NODE_OT_interface_item_remove(NodeInterfaceOperator, Operator):
return {'FINISHED'}
class NODE_OT_interface_item_move(NodeInterfaceOperator, Operator):
'''Move the active item to the specified direction'''
bl_idname = "node.interface_item_move"
bl_label = "Move Item"
bl_options = {'REGISTER', 'UNDO'}
direction: EnumProperty(
name="Direction",
description="Specifies which direction the active item is moved towards",
items=(
('UP', "Move Up", ""),
('DOWN', "Move Down", "")
),
)
@classmethod
def poll(cls, context):
if not super().poll(context):
return False
snode = context.space_data
tree = snode.edit_tree
interface = tree.interface
return interface.active is not None
@staticmethod
def fetch_all_parents(interface):
# The root panel that sockets are parented to by default is not directly accessible
# Hence we retrieve it by creating a new socket and getting its parent
new_socket = interface.new_socket(name="DUMMY_SOCKET")
yield new_socket.parent
interface.remove(new_socket)
# Retrieve all other panels
for item in interface.items_tree:
if item.item_type == 'PANEL':
yield item
@staticmethod
def get_prev_parent(parents, current_parent):
prev_parent = parents[0]
for parent in parents:
if parent == current_parent:
break
prev_parent = parent
return prev_parent
@staticmethod
def get_next_parent(parents, current_parent):
iter_parents = iter(parents)
for parent in iter_parents:
if parent == current_parent:
break
try:
next_parent = next(iter_parents)
except StopIteration:
next_parent = parent
return next_parent
def execute(self, context):
interface = context.space_data.edit_tree.interface
active_item = interface.active
offset = -1 if self.direction == 'UP' else 2
old_position = active_item.position
interface.move(active_item, active_item.position + offset)
if active_item.position == old_position and active_item.item_type == 'SOCKET':
parents = tuple(self.fetch_all_parents(interface))
if self.direction == 'UP':
new_parent = self.get_prev_parent(parents, active_item.parent)
new_position = len(new_parent.interface_items)
else:
new_parent = self.get_next_parent(parents, active_item.parent)
new_position = 0
if new_parent != active_item.parent:
interface.move_to_parent(active_item, new_parent, new_position)
else:
return {'CANCELLED'}
interface.active_index = active_item.index
return {'FINISHED'}
classes = (
NodeSetting,
@ -396,5 +488,7 @@ classes = (
NODE_OT_interface_item_new,
NODE_OT_interface_item_duplicate,
NODE_OT_interface_item_remove,
NODE_OT_interface_item_move,
NODE_OT_tree_path_parent,
)

View File

@ -928,7 +928,10 @@ class NODE_PT_node_tree_interface(Panel):
ops_col.operator("node.interface_item_remove", icon='REMOVE', text="")
ops_col.separator()
ops_col.menu("NODE_MT_node_tree_interface_context_menu", icon='DOWNARROW_HLT', text="")
ops_col.separator()
ops_col.operator("node.interface_item_move", icon='TRIA_UP', text="").direction = "UP"
ops_col.operator("node.interface_item_move", icon='TRIA_DOWN', text="").direction = "DOWN"
ops_col.separator()
active_item = tree.interface.active