WIP: Remove "Lazy Connect" feature #2

Closed
Nika Kutsniashvili wants to merge 1 commits from remove-lazy into main

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

View File

@ -28,10 +28,6 @@ def register():
name="Lazy Target!", name="Lazy Target!",
default="x", default="x",
description="An internal property used to store the last node in a Lazy Connect operation") description="An internal property used to store the last node in a Lazy Connect operation")
bpy.types.Scene.NWSourceSocket = IntProperty(
name="Source Socket!",
default=0,
description="An internal property used to store the source socket in a Lazy Connect operation")
operators.register() operators.register()
interface.register() interface.register()
@ -47,4 +43,3 @@ def unregister():
del bpy.types.Scene.NWBusyDrawing del bpy.types.Scene.NWBusyDrawing
del bpy.types.Scene.NWLazySource del bpy.types.Scene.NWLazySource
del bpy.types.Scene.NWLazyTarget del bpy.types.Scene.NWLazyTarget
del bpy.types.Scene.NWSourceSocket

View File

@ -162,45 +162,6 @@ class NWMergeMixMenu(Menu, NWBaseMenu):
props.merge_type = 'MIX' props.merge_type = 'MIX'
class NWConnectionListOutputs(Menu, NWBaseMenu):
bl_idname = "NODE_MT_nw_connection_list_out"
bl_label = "From:"
def draw(self, context):
layout = self.layout
nodes, links = get_nodes_links(context)
n1 = nodes[context.scene.NWLazySource]
for index, output in enumerate(n1.outputs):
# Only show sockets that are exposed.
if output.enabled:
layout.operator(
operators.NWCallInputsMenu.bl_idname,
text=output.name,
icon="RADIOBUT_OFF").from_socket = index
class NWConnectionListInputs(Menu, NWBaseMenu):
bl_idname = "NODE_MT_nw_connection_list_in"
bl_label = "To:"
def draw(self, context):
layout = self.layout
nodes, links = get_nodes_links(context)
n2 = nodes[context.scene.NWLazyTarget]
for index, input in enumerate(n2.inputs):
# Only show sockets that are exposed.
# This prevents, for example, the scale value socket
# of the vector math node being added to the list when
# the mode is not 'SCALE'.
if input.enabled:
op = layout.operator(operators.NWMakeLink.bl_idname, text=input.name, icon="FORWARD")
op.from_socket = context.scene.NWSourceSocket
op.to_socket = index
class NWMergeMathMenu(Menu, NWBaseMenu): class NWMergeMathMenu(Menu, NWBaseMenu):
bl_idname = "NODE_MT_nw_merge_math_menu" bl_idname = "NODE_MT_nw_merge_math_menu"
bl_label = "Merge Selected Nodes using Math" bl_label = "Merge Selected Nodes using Math"
@ -453,8 +414,6 @@ classes = (
NWMergeGeometryMenu, NWMergeGeometryMenu,
NWMergeShadersMenu, NWMergeShadersMenu,
NWMergeMixMenu, NWMergeMixMenu,
NWConnectionListOutputs,
NWConnectionListInputs,
NWMergeMathMenu, NWMergeMathMenu,
NWBatchChangeNodesMenu, NWBatchChangeNodesMenu,
NWBatchChangeBlendTypeMenu, NWBatchChangeBlendTypeMenu,

View File

@ -22,12 +22,10 @@ from glob import glob
from copy import copy from copy import copy
from itertools import chain from itertools import chain
from .interface import NWConnectionListInputs, NWConnectionListOutputs
from .utils.constants import blend_types, geo_combine_operations, operations, navs, get_texture_node_types, rl_outputs from .utils.constants import blend_types, geo_combine_operations, operations, navs, get_texture_node_types, rl_outputs
from .utils.draw import draw_callback_nodeoutline from .utils.draw import draw_callback_nodeoutline
from .utils.paths import match_files_to_socket_names, split_into_components from .utils.paths import match_files_to_socket_names, split_into_components
from .utils.nodes import (node_mid_pt, autolink, node_at_pos, get_nodes_links, from .utils.nodes import (node_mid_pt, node_at_pos, get_nodes_links,
get_group_output_node, get_output_location, force_update, get_internal_socket, nw_check, get_group_output_node, get_output_location, force_update, get_internal_socket, nw_check,
nw_check_not_empty, nw_check_selected, nw_check_active, nw_check_space_type, nw_check_not_empty, nw_check_selected, nw_check_active, nw_check_space_type,
nw_check_node_type, nw_check_visible_outputs, nw_check_viewer_node, NWBase, nw_check_node_type, nw_check_visible_outputs, nw_check_viewer_node, NWBase,
@ -114,116 +112,6 @@ class NWLazyMix(Operator, NWBase):
return {'CANCELLED'} return {'CANCELLED'}
class NWLazyConnect(Operator, NWBase):
"""Connect two nodes without clicking a specific socket (automatically determined"""
bl_idname = "node.nw_lazy_connect"
bl_label = "Lazy Connect"
bl_options = {'REGISTER', 'UNDO'}
with_menu: BoolProperty()
@classmethod
def poll(cls, context):
return nw_check(cls, context) and nw_check_not_empty(cls, context)
def modal(self, context, event):
context.area.tag_redraw()
nodes, links = get_nodes_links(context)
cont = True
start_pos = [event.mouse_region_x, event.mouse_region_y]
node1 = None
if not context.scene.NWBusyDrawing:
node1 = node_at_pos(nodes, context, event)
if node1:
context.scene.NWBusyDrawing = node1.name
else:
if context.scene.NWBusyDrawing != 'STOP':
node1 = nodes[context.scene.NWBusyDrawing]
context.scene.NWLazySource = node1.name
context.scene.NWLazyTarget = node_at_pos(nodes, context, event).name
if event.type == 'MOUSEMOVE':
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE':
end_pos = [event.mouse_region_x, event.mouse_region_y]
bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW')
node2 = None
node2 = node_at_pos(nodes, context, event)
if node2:
context.scene.NWBusyDrawing = node2.name
if node1 == node2:
cont = False
link_success = False
if cont:
if node1 and node2:
original_sel = []
original_unsel = []
for node in nodes:
if node.select:
node.select = False
original_sel.append(node)
else:
original_unsel.append(node)
node1.select = True
node2.select = True
# link_success = autolink(node1, node2, links)
if self.with_menu:
if len(node1.outputs) > 1 and node2.inputs:
bpy.ops.wm.call_menu("INVOKE_DEFAULT", name=NWConnectionListOutputs.bl_idname)
elif len(node1.outputs) == 1:
bpy.ops.node.nw_call_inputs_menu(from_socket=0)
else:
link_success = autolink(node1, node2, links)
for node in original_sel:
node.select = True
for node in original_unsel:
node.select = False
if link_success:
force_update(context)
context.scene.NWBusyDrawing = ""
return {'FINISHED'}
elif event.type == 'ESC':
bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW')
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.area.type == 'NODE_EDITOR':
nodes, links = get_nodes_links(context)
node = node_at_pos(nodes, context, event)
if node:
context.scene.NWBusyDrawing = node.name
# the arguments we pass the the callback
mode = "LINK"
if self.with_menu:
mode = "LINKMENU"
args = (self, context, mode)
# Add the region OpenGL drawing callback
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
self._handle = bpy.types.SpaceNodeEditor.draw_handler_add(
draw_callback_nodeoutline, args, 'WINDOW', 'POST_PIXEL')
self.mouse_path = []
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "View3D not found, cannot run operator")
return {'CANCELLED'}
class NWDeleteUnused(Operator, NWBase): class NWDeleteUnused(Operator, NWBase):
"""Delete all nodes whose output is not used""" """Delete all nodes whose output is not used"""
bl_idname = 'node.nw_del_unused' bl_idname = 'node.nw_del_unused'
@ -2050,48 +1938,6 @@ class NWLinkToOutputNode(Operator):
return {'FINISHED'} return {'FINISHED'}
class NWMakeLink(Operator, NWBase):
"""Make a link from one socket to another"""
bl_idname = 'node.nw_make_link'
bl_label = 'Make Link'
bl_options = {'REGISTER', 'UNDO'}
from_socket: IntProperty()
to_socket: IntProperty()
def execute(self, context):
nodes, links = get_nodes_links(context)
n1 = nodes[context.scene.NWLazySource]
n2 = nodes[context.scene.NWLazyTarget]
connect_sockets(n1.outputs[self.from_socket], n2.inputs[self.to_socket])
force_update(context)
return {'FINISHED'}
class NWCallInputsMenu(Operator, NWBase):
"""Link from this output"""
bl_idname = 'node.nw_call_inputs_menu'
bl_label = 'Make Link'
bl_options = {'REGISTER', 'UNDO'}
from_socket: IntProperty()
def execute(self, context):
nodes, links = get_nodes_links(context)
context.scene.NWSourceSocket = self.from_socket
n1 = nodes[context.scene.NWLazySource]
n2 = nodes[context.scene.NWLazyTarget]
if len(n2.inputs) > 1:
bpy.ops.wm.call_menu("INVOKE_DEFAULT", name=NWConnectionListInputs.bl_idname)
elif len(n2.inputs) == 1:
connect_sockets(n1.outputs[self.from_socket], n2.inputs[0])
return {'FINISHED'}
class NWAddSequence(Operator, NWBase, ImportHelper): class NWAddSequence(Operator, NWBase, ImportHelper):
"""Add an Image Sequence""" """Add an Image Sequence"""
bl_idname = 'node.nw_add_sequence' bl_idname = 'node.nw_add_sequence'
@ -2437,7 +2283,6 @@ class NWResetNodes(bpy.types.Operator):
classes = ( classes = (
NWLazyMix, NWLazyMix,
NWLazyConnect,
NWDeleteUnused, NWDeleteUnused,
NWSwapLinks, NWSwapLinks,
NWResetBG, NWResetBG,
@ -2459,8 +2304,6 @@ classes = (
NWSelectParentChildren, NWSelectParentChildren,
NWDetachOutputs, NWDetachOutputs,
NWLinkToOutputNode, NWLinkToOutputNode,
NWMakeLink,
NWCallInputsMenu,
NWAddSequence, NWAddSequence,
NWAddMultipleImages, NWAddMultipleImages,
NWSaveViewer, NWSaveViewer,

View File

@ -337,11 +337,6 @@ kmi_defs = (
(operators.NWReloadImages.bl_idname, 'R', 'PRESS', False, False, True, None, "Reload images"), (operators.NWReloadImages.bl_idname, 'R', 'PRESS', False, False, True, None, "Reload images"),
# Lazy Mix # Lazy Mix
(operators.NWLazyMix.bl_idname, 'RIGHTMOUSE', 'PRESS', True, True, False, None, "Lazy Mix"), (operators.NWLazyMix.bl_idname, 'RIGHTMOUSE', 'PRESS', True, True, False, None, "Lazy Mix"),
# Lazy Connect
(operators.NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False, False, True, (('with_menu', False),), "Lazy Connect"),
# Lazy Connect with Menu
(operators.NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False,
True, True, (('with_menu', True),), "Lazy Connect with Socket Menu"),
# Align Nodes # Align Nodes
(operators.NWAlignNodes.bl_idname, 'EQUAL', 'PRESS', False, True, (operators.NWAlignNodes.bl_idname, 'EQUAL', 'PRESS', False, True,
False, None, "Align selected nodes neatly in a row/column"), False, None, "Align selected nodes neatly in a row/column"),

View File

@ -31,45 +31,6 @@ def node_mid_pt(node, axis):
return d return d
def autolink(node1, node2, links):
available_inputs = [inp for inp in node2.inputs if inp.enabled]
available_outputs = [outp for outp in node1.outputs if outp.enabled]
for outp in available_outputs:
for inp in available_inputs:
if not inp.is_linked and inp.name == outp.name:
connect_sockets(outp, inp)
return True
for outp in available_outputs:
for inp in available_inputs:
if not inp.is_linked and inp.type == outp.type:
connect_sockets(outp, inp)
return True
# force some connection even if the type doesn't match
if available_outputs:
for inp in available_inputs:
if not inp.is_linked:
connect_sockets(available_outputs[0], inp)
return True
# even if no sockets are open, force one of matching type
for outp in available_outputs:
for inp in available_inputs:
if inp.type == outp.type:
connect_sockets(outp, inp)
return True
# do something!
for outp in available_outputs:
for inp in available_inputs:
connect_sockets(outp, inp)
return True
print("Could not make a link from " + node1.name + " to " + node2.name)
return False
def abs_node_location(node): def abs_node_location(node):
abs_location = node.location abs_location = node.location
if node.parent is None: if node.parent is None: