1 # SPDX-License-Identifier: GPL-2.0-or-later
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.
18 image_nodes
= ("CompositorNodeRLayers",
19 "CompositorNodeImage",
20 "CompositorNodeViewer",
21 "CompositorNodeComposite",
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"
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
):
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()
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
61 for a
in context
.screen
.areas
:
62 if a
.type == "IMAGE_EDITOR":
63 size
= a
.width
* a
.height
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
[
73 elif active_node
.bl_idname
in ["CompositorNodeComposite", "CompositorNodeRLayers"]:
74 space
.image
= bpy
.data
.images
[
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")
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
85 self
.report({'INFO'}, "No image detected")
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")
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
)
120 bpy
.utils
.unregister_class(AMTH_NODE_OT_show_active_node_image
)
121 for km
, kmi
in KEYMAPS
:
122 km
.keymap_items
.remove(kmi
)
125 bpy
.types
.NODE_MT_node
.remove(ui
)
126 bpy
.types
.NODE_MT_context_menu
.remove(ui
)