WIP: Compositor Viewer shortcuts prototype #105268
@ -20,6 +20,7 @@ from mathutils import Vector
|
|||||||
from os import path
|
from os import path
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
import json
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from .interface import NWConnectionListInputs, NWConnectionListOutputs
|
from .interface import NWConnectionListInputs, NWConnectionListOutputs
|
||||||
@ -486,6 +487,54 @@ class NWAddAttrNode(Operator, NWBase):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class NWFastPreview(Operator):
|
||||||
|
bl_idname = "node.nw_fast_preview"
|
||||||
|
bl_label = "Fast Preview"
|
||||||
|
bl_description = "Preview favorite nodes by pressing 1, 2, 3, 4 and 5"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
# Workaround: simulating a dict with json.loads() and json.dumps()
|
||||||
|
|||||||
|
node_preview_map : StringProperty(name="")
|
||||||
|
update_map : BoolProperty(default=False)
|
||||||
|
|
||||||
|
viewer_index : IntProperty()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(self, context):
|
||||||
|
return bpy.ops.node.link_viewer.poll()
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
nodes, _ = get_nodes_links(context)
|
||||||
|
|
||||||
|
if self.node_preview_map != '':
|
||||||
|
temp_dict = json.loads(self.node_preview_map)
|
||||||
|
else:
|
||||||
|
temp_dict = {}
|
||||||
|
|
||||||
|
selected_nodes = context.selected_nodes
|
||||||
|
if self.update_map:
|
||||||
|
if len(selected_nodes) > 0:
|
||||||
|
n1 = selected_nodes[0]
|
||||||
|
|
||||||
|
temp_dict[self.viewer_index] = n1.name
|
||||||
|
self.node_preview_map = json.dumps(temp_dict)
|
||||||
|
bpy.ops.node.link_viewer()
|
||||||
Damien Picard
commented
With a slight modification of
With a slight modification of `NWPreviewNode`, you could use this to make it work in shader trees as well:
```python
if context.space_data.tree_type in {'CompositorNodeTree', 'GeometryNodeTree'}:
bpy.ops.node.link_viewer()
elif context.space_data.tree_type == 'ShaderNodeTree':
bpy.ops.node.nw_preview_node()
```
---
```diff
@@ -764,6 +764,8 @@ class NWPreviewNode(Operator, NWBase):
if 'FINISHED' not in select_node: # only run if mouse click is on a node
return {'CANCELLED'}
+ def execute(self, context):
+ space = context.space_data
base_node_tree = space.node_tree
active_tree = context.space_data.edit_tree
path = context.space_data.path
```
|
|||||||
|
self.report({'INFO'}, "Set node %s to shortcut %i" % (n1.name, self.viewer_index))
|
||||||
|
else:
|
||||||
|
self.report({'ERROR'}, "No previews to set. Reason: No nodes selected.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
if str(self.viewer_index) in temp_dict:
|
||||||
|
if temp_dict[str(self.viewer_index)] in nodes:
|
||||||
|
n = nodes[temp_dict[str(self.viewer_index)]]
|
||||||
|
n.select = True
|
||||||
|
nodes.active = n
|
||||||
|
bpy.ops.node.link_viewer()
|
||||||
|
n.select = False
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class NWPreviewNode(Operator, NWBase):
|
class NWPreviewNode(Operator, NWBase):
|
||||||
bl_idname = "node.nw_preview_node"
|
bl_idname = "node.nw_preview_node"
|
||||||
bl_label = "Preview Node"
|
bl_label = "Preview Node"
|
||||||
@ -2592,6 +2641,63 @@ class NWAddMultipleImages(Operator, NWBase, ImportHelper):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class NWViewerFocus(bpy.types.Operator):
|
||||||
Damien Picard
commented
I think this was added back by mistake? I think this was added back by mistake?
|
|||||||
|
"""Set the viewer tile center to the mouse position"""
|
||||||
|
bl_idname = "node.nw_viewer_focus"
|
||||||
|
bl_label = "Viewer Focus"
|
||||||
|
|
||||||
|
x: bpy.props.IntProperty()
|
||||||
|
y: bpy.props.IntProperty()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
return (nw_check(cls, context)
|
||||||
|
and nw_check_space_type(cls, context, {'CompositorNodeTree'}))
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
def invoke(self, context, event):
|
||||||
|
render = context.scene.render
|
||||||
|
space = context.space_data
|
||||||
|
percent = render.resolution_percentage * 0.01
|
||||||
|
|
||||||
|
nodes, links = get_nodes_links(context)
|
||||||
|
viewers = [n for n in nodes if n.type == 'VIEWER']
|
||||||
|
|
||||||
|
if viewers:
|
||||||
|
mlocx = event.mouse_region_x
|
||||||
|
mlocy = event.mouse_region_y
|
||||||
|
select_node = bpy.ops.node.select(location=(mlocx, mlocy), extend=False)
|
||||||
|
|
||||||
|
if 'FINISHED' not in select_node: # only run if we're not clicking on a node
|
||||||
|
region_x = context.region.width
|
||||||
|
region_y = context.region.height
|
||||||
|
|
||||||
|
region_center_x = context.region.width / 2
|
||||||
|
region_center_y = context.region.height / 2
|
||||||
|
|
||||||
|
bd_x = render.resolution_x * percent * space.backdrop_zoom
|
||||||
|
bd_y = render.resolution_y * percent * space.backdrop_zoom
|
||||||
|
|
||||||
|
backdrop_center_x = (bd_x / 2) - space.backdrop_offset[0]
|
||||||
|
backdrop_center_y = (bd_y / 2) - space.backdrop_offset[1]
|
||||||
|
|
||||||
|
margin_x = region_center_x - backdrop_center_x
|
||||||
|
margin_y = region_center_y - backdrop_center_y
|
||||||
|
|
||||||
|
abs_mouse_x = (mlocx - margin_x) / bd_x
|
||||||
|
abs_mouse_y = (mlocy - margin_y) / bd_y
|
||||||
|
|
||||||
|
for node in viewers:
|
||||||
|
node.center_x = abs_mouse_x
|
||||||
|
node.center_y = abs_mouse_y
|
||||||
|
else:
|
||||||
|
return {'PASS_THROUGH'}
|
||||||
|
|
||||||
|
return self.execute(context)
|
||||||
|
|
||||||
|
|
||||||
class NWSaveViewer(bpy.types.Operator, ExportHelper):
|
class NWSaveViewer(bpy.types.Operator, ExportHelper):
|
||||||
"""Save the current viewer node to an image file"""
|
"""Save the current viewer node to an image file"""
|
||||||
bl_idname = "node.nw_save_viewer"
|
bl_idname = "node.nw_save_viewer"
|
||||||
@ -2759,6 +2865,7 @@ classes = (
|
|||||||
NWSwapLinks,
|
NWSwapLinks,
|
||||||
NWResetBG,
|
NWResetBG,
|
||||||
NWAddAttrNode,
|
NWAddAttrNode,
|
||||||
|
NWFastPreview,
|
||||||
NWPreviewNode,
|
NWPreviewNode,
|
||||||
NWFrameSelected,
|
NWFrameSelected,
|
||||||
NWReloadImages,
|
NWReloadImages,
|
||||||
@ -2781,6 +2888,7 @@ classes = (
|
|||||||
NWCallInputsMenu,
|
NWCallInputsMenu,
|
||||||
NWAddSequence,
|
NWAddSequence,
|
||||||
NWAddMultipleImages,
|
NWAddMultipleImages,
|
||||||
|
NWViewerFocus,
|
||||||
NWSaveViewer,
|
NWSaveViewer,
|
||||||
NWResetNodes,
|
NWResetNodes,
|
||||||
)
|
)
|
||||||
|
@ -338,6 +338,35 @@ kmi_defs = (
|
|||||||
False, (('run_in_geometry_nodes', False),), "Preview node output"),
|
False, (('run_in_geometry_nodes', False),), "Preview node output"),
|
||||||
(operators.NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', False, True,
|
(operators.NWPreviewNode.bl_idname, 'LEFTMOUSE', 'PRESS', False, True,
|
||||||
True, (('run_in_geometry_nodes', True),), "Preview node output"),
|
True, (('run_in_geometry_nodes', True),), "Preview node output"),
|
||||||
|
|
||||||
|
|
||||||
|
# Fast Preview
|
||||||
|
(operators.NWFastPreview.bl_idname, 'ONE', 'PRESS', False, False, False,
|
||||||
|
(('viewer_index', 1), ('update_map', False)), "Fast Preview"),
|
||||||
|
(operators.NWFastPreview.bl_idname, 'ONE', 'PRESS', True, False, False,
|
||||||
|
(('viewer_index', 1), ('update_map', True)), "Fast Preview"),
|
||||||
|
|
||||||
|
(operators.NWFastPreview.bl_idname, 'TWO', 'PRESS', False, False, False,
|
||||||
|
(('viewer_index', 2), ('update_map', False)), "Fast Preview"),
|
||||||
|
(operators.NWFastPreview.bl_idname, 'TWO', 'PRESS', True, False, False,
|
||||||
|
(('viewer_index', 2), ('update_map', True)), "Fast Preview"),
|
||||||
|
|
||||||
|
(operators.NWFastPreview.bl_idname, 'THREE', 'PRESS', False, False, False,
|
||||||
|
(('viewer_index', 3), ('update_map', False)), "Fast Preview"),
|
||||||
|
(operators.NWFastPreview.bl_idname, 'THREE', 'PRESS', True, False, False,
|
||||||
|
(('viewer_index', 3), ('update_map', True)), "Fast Preview"),
|
||||||
|
|
||||||
|
(operators.NWFastPreview.bl_idname, 'FOUR', 'PRESS', False, False, False,
|
||||||
|
(('viewer_index', 4), ('update_map', False)), "Fast Preview"),
|
||||||
|
(operators.NWFastPreview.bl_idname, 'FOUR', 'PRESS', True, False, False,
|
||||||
|
(('viewer_index', 4), ('update_map', True)), "Fast Preview"),
|
||||||
|
|
||||||
|
(operators.NWFastPreview.bl_idname, 'FIVE', 'PRESS', False, False, False,
|
||||||
|
(('viewer_index', 5), ('update_map', False)), "Fast Preview"),
|
||||||
|
(operators.NWFastPreview.bl_idname, 'FIVE', 'PRESS', True, False, False,
|
||||||
|
(('viewer_index', 5), ('update_map', True)), "Fast Preview"),
|
||||||
|
|
||||||
|
|
||||||
# Reload Images
|
# Reload Images
|
||||||
(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
|
||||||
@ -347,6 +376,8 @@ kmi_defs = (
|
|||||||
# Lazy Connect with Menu
|
# Lazy Connect with Menu
|
||||||
(operators.NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False,
|
(operators.NWLazyConnect.bl_idname, 'RIGHTMOUSE', 'PRESS', False,
|
||||||
True, True, (('with_menu', True),), "Lazy Connect with Socket Menu"),
|
True, True, (('with_menu', True),), "Lazy Connect with Socket Menu"),
|
||||||
|
# Viewer Tile Center
|
||||||
|
(operators.NWViewerFocus.bl_idname, 'LEFTMOUSE', 'DOUBLE_CLICK', False, False, False, None, "Set Viewers Tile Center"),
|
||||||
# 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"),
|
||||||
|
Loading…
Reference in New Issue
Block a user
You can store the dict directly here, I don’t think you need to bother serializing to a property.
That didn't seem to work. I think it has to be a property for it to be persistent throughout the lifetime of the operator.