Node Wrangler: Improved accuracy on Align Nodes operator #104551
@ -65,7 +65,15 @@ def drawlayout(context, layout, mode='non-panel'):
|
||||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.operator(operators.NWAlignNodes.bl_idname, icon='CENTER_ONLY')
|
||||
col.operator(operators.NWAlignNodes.bl_idname, text='Auto-Align Nodes', icon='CENTER_ONLY').mode = 'AUTOMATIC'
|
||||
if mode == 'panel':
|
||||
row = col.row(align=True)
|
||||
row.operator(operators.NWAlignNodes.bl_idname, text='Align X').mode = 'HORIZONTAL'
|
||||
row.operator(operators.NWAlignNodes.bl_idname, text='Align Y').mode = 'VERTICAL'
|
||||
else:
|
||||
col.operator(operators.NWAlignNodes.bl_idname, text='Align X').mode = 'HORIZONTAL'
|
||||
col.operator(operators.NWAlignNodes.bl_idname, text='Align Y').mode = 'VERTICAL'
|
||||
|
||||
col.separator()
|
||||
|
||||
col = layout.column(align=True)
|
||||
|
@ -10,6 +10,7 @@ from bpy.props import (
|
||||
IntProperty,
|
||||
StringProperty,
|
||||
FloatVectorProperty,
|
||||
IntVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||
@ -2337,7 +2338,25 @@ class NWAlignNodes(Operator, NWBase):
|
||||
bl_idname = "node.nw_align_nodes"
|
||||
bl_label = "Align Nodes"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
margin: IntProperty(name='Margin', default=50, description='The amount of space between nodes')
|
||||
|
||||
mode: EnumProperty(
|
||||
name='Align Mode',
|
||||
default='AUTOMATIC',
|
||||
items=(
|
||||
('AUTOMATIC', 'Auto-Align', ''),
|
||||
('HORIZONTAL', 'Align X', ''),
|
||||
('VERTICAL', 'Align Y', ''),
|
||||
)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
if props.mode == 'AUTOMATIC':
|
||||
return "Aligns nodes horizontally/vertically based on which direction takes more space"
|
||||
elif props.mode == 'HORIZONTAL':
|
||||
return "Aligns nodes in a row from left to right"
|
||||
elif props.mode == 'VERTICAL':
|
||||
return "Aligns nodes in a column from top to bottom"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@ -2350,7 +2369,8 @@ class NWAlignNodes(Operator, NWBase):
|
||||
def execute(self, context):
|
||||
selection = [node for node in context.selected_nodes if node.type != 'FRAME']
|
||||
active_node = context.active_node
|
||||
margin = self.margin
|
||||
prefs = context.preferences.addons[__package__].preferences
|
||||
margin_x, margin_y = prefs.align_nodes_margin
|
||||
|
||||
# Somehow hidden nodes would come out 10 units higher that non-hidden nodes when aligned, so this offset has to exist
|
||||
weird_offset = 10
|
||||
@ -2364,13 +2384,13 @@ class NWAlignNodes(Operator, NWBase):
|
||||
# use dimension to get center of node, not corner
|
||||
x_locs = [n.location.x + (0.5 * n.dimensions.x) for n in selection]
|
||||
y_locs = [n.location.y - weird_offset if n.hide
|
||||
else n.location.y - (0.5 * n.dimensions.y) for n in selection]
|
||||
else n.location.y - (0.5 * n.dimensions.y) for n in selection]
|
||||
|
||||
x_range = max(x_locs) - min(x_locs)
|
||||
y_range = max(y_locs) - min(y_locs)
|
||||
horizontal = x_range > y_range
|
||||
|
||||
#Undo corrective offsets for hidden nodes if alignment is horizontal
|
||||
# Undo corrective offsets for hidden nodes if alignment is horizontal
|
||||
if not horizontal:
|
||||
y_locs = [n.location.y - (0.5 * n.dimensions.y) for n in selection]
|
||||
|
||||
@ -2383,6 +2403,9 @@ class NWAlignNodes(Operator, NWBase):
|
||||
else:
|
||||
selection.sort(key=lambda n: n.location.y - (n.dimensions.y / 2), reverse=True)
|
||||
|
||||
if self.mode != 'AUTOMATIC':
|
||||
horizontal = self.mode == 'HORIZONTAL'
|
||||
|
||||
# Alignment
|
||||
current_pos = 0
|
||||
|
||||
@ -2391,13 +2414,13 @@ class NWAlignNodes(Operator, NWBase):
|
||||
node.location.x = current_pos
|
||||
node.location.y = (mid_y + weird_offset) if node.hide else mid_y + (0.5 * node.dimensions.y)
|
||||
|
||||
current_pos += margin + node.dimensions.x
|
||||
current_pos += margin_x + node.dimensions.x
|
||||
else:
|
||||
for node in selection:
|
||||
node.location.x = mid_x - (0.5 * node.dimensions.x)
|
||||
node.location.y = (current_pos - (0.5 * node.dimensions.y) + weird_offset) if node.hide else current_pos
|
||||
|
||||
current_pos -= 0.3 * margin + node.dimensions.y # use half-margin for vertical alignment
|
||||
current_pos -= margin_y + node.dimensions.y
|
||||
|
||||
# If active node is selected, center nodes around it
|
||||
if active_loc is not None:
|
||||
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import bpy
|
||||
from bpy.props import EnumProperty, BoolProperty, StringProperty
|
||||
from bpy.props import EnumProperty, BoolProperty, StringProperty, IntVectorProperty
|
||||
from nodeitems_utils import node_categories_iter
|
||||
|
||||
from . import operators
|
||||
@ -104,11 +104,25 @@ class NWNodeWrangler(bpy.types.AddonPreferences):
|
||||
default=False,
|
||||
description="Expand this box into a list of all naming tags for principled texture setup"
|
||||
)
|
||||
align_nodes_margin: IntVectorProperty(
|
||||
name="Margin",
|
||||
default=(50, 15),
|
||||
subtype="XYZ",
|
||||
size=2,
|
||||
min=0,
|
||||
soft_min=0,
|
||||
soft_max=200,
|
||||
description='The amount of space between nodes during when the Align Nodes operator is called'
|
||||
)
|
||||
principled_tags: bpy.props.PointerProperty(type=NWPrincipledPreferences)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
col = layout.column()
|
||||
split = layout.split(factor=0.40)
|
||||
col = split.column(heading="Margin (Align Nodes):")
|
||||
col.prop(self, "align_nodes_margin", text="")
|
||||
|
||||
col = split.column(heading="Merge Node Options:")
|
||||
col.prop(self, "merge_position")
|
||||
col.prop(self, "merge_hide")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user