WIP: Remove "Lazy Connect" feature #2
@ -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
|
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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"),
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user