Fix: Node Wrangler: new reroutes offset when output hidden
[blender-addons.git] / amaranth / node_editor / display_image.py
blobc548a146f93d5dca8ffe884a98a372e3f2bd4fb0
1 # SPDX-License-Identifier: GPL-2.0-or-later
2 """
3 Display Active Image Node on Image Editor
5 When selecting an Image node, it will show it on the Image editor (if
6 there is any available). If you don't like this behavior, you can
7 disable it from the Amaranth Toolset panel on the Scene properties.
8 Coded by the awesome Sergey Sharybin. This feature only works on Blender
9 2.68 and newer. Select an Image Node in the Compositor or Cycles nodes
10 editor, there must be at least one image editor available.
11 """
13 import bpy
16 KEYMAPS = list()
18 image_nodes = ("CompositorNodeRLayers",
19 "CompositorNodeImage",
20 "CompositorNodeViewer",
21 "CompositorNodeComposite",
22 "ShaderNodeTexImage",
23 "ShaderNodeTexEnvironment",
24 "GeometryNodeImageTexture")
27 class AMTH_NODE_OT_show_active_node_image(bpy.types.Operator):
28 """Display source image in the Image Editor (if available)"""
29 bl_idname = "node.show_active_node_image"
30 bl_label = "Open Node Source Image"
31 bl_options = {"UNDO"}
33 @classmethod
34 def poll(cls, context):
35 return context.space_data.type == 'NODE_EDITOR' \
36 and context.active_node is not None \
37 and context.active_node.bl_idname in image_nodes
39 def execute(self, context):
40 return {'FINISHED'}
42 def invoke(self, context, event):
43 mlocx = event.mouse_region_x
44 mlocy = event.mouse_region_y
45 select_node = bpy.ops.node.select(location=(mlocx, mlocy), extend=False)
47 if 'FINISHED' in select_node: # Only run if we're clicking on a node
48 get_addon = "amaranth" in context.preferences.addons.keys()
49 if not get_addon:
50 return {"CANCELLED"}
52 preferences = context.preferences.addons["amaranth"].preferences
53 if preferences.use_image_node_display:
54 if context.active_node:
55 active_node = context.active_node
57 if active_node.bl_idname in image_nodes:
58 # Use largest image editor
59 area = None
60 area_size = 0
61 for a in context.screen.areas:
62 if a.type == "IMAGE_EDITOR":
63 size = a.width * a.height
64 if size > area_size:
65 area_size = size
66 area = a
67 if area:
68 for space in area.spaces:
69 if space.type == "IMAGE_EDITOR":
70 if active_node.bl_idname == "CompositorNodeViewer":
71 space.image = bpy.data.images[
72 "Viewer Node"]
73 elif active_node.bl_idname in ["CompositorNodeComposite", "CompositorNodeRLayers"]:
74 space.image = bpy.data.images[
75 "Render Result"]
76 elif active_node.bl_idname == "GeometryNodeImageTexture":
77 if active_node.inputs['Image'].is_linked:
78 self.report({'INFO'}, "Previewing linked sockets is not supported yet")
79 break
80 if active_node.inputs['Image'].default_value:
81 space.image = active_node.inputs['Image'].default_value
82 elif active_node.image:
83 space.image = active_node.image
84 else:
85 self.report({'INFO'}, "No image detected")
86 break
87 break
88 else:
89 return {'CANCELLED'}
91 return {"FINISHED"}
92 else:
93 return {"PASS_THROUGH"}
96 def ui(self, context):
97 node = context.active_node
99 if node is not None and node.bl_idname in image_nodes:
100 self.layout.separator()
101 self.layout.operator_context = 'INVOKE_DEFAULT'
102 self.layout.operator(
103 AMTH_NODE_OT_show_active_node_image.bl_idname,
104 icon="IMAGE", text="Display in Image Editor")
107 def register():
108 bpy.utils.register_class(AMTH_NODE_OT_show_active_node_image)
109 kc = bpy.context.window_manager.keyconfigs.addon
110 km = kc.keymaps.new(name="Node Editor", space_type="NODE_EDITOR")
111 kmi = km.keymap_items.new("node.show_active_node_image",
112 "LEFTMOUSE", "DOUBLE_CLICK")
113 KEYMAPS.append((km, kmi))
115 bpy.types.NODE_MT_node.append(ui)
116 bpy.types.NODE_MT_context_menu.append(ui)
119 def unregister():
120 bpy.utils.unregister_class(AMTH_NODE_OT_show_active_node_image)
121 for km, kmi in KEYMAPS:
122 km.keymap_items.remove(kmi)
123 KEYMAPS.clear()
125 bpy.types.NODE_MT_node.remove(ui)
126 bpy.types.NODE_MT_context_menu.remove(ui)