Compositor: Implement shortcuts for Viewer nodes
Artists often want to quickly switch back and forth between two or more nodes while compositing. This patch implements two operators `NODE_OT_viewer_shortcut_set` and `NODE_OT_viewer_shortcut_get` that allow users to map a viewer node to a shortcut. For example, pressing `cltr+1` while a node is selected, assigns that node to the shortcut `1`, creates a viewer node if it has none attached and sets that viewer node to active. Pressing `1` will set the active node with shortcut `1` to active. Shortcuts are saved in DNA to preserve them after saving/loading blend files. Limitations: - Only compositor node tree is supported, because shading editor has no viewer node and geometry nodes viewer works differently. Pull Request: https://projects.blender.org/blender/blender/pulls/123641
This commit is contained in:
parent
5eb8101efa
commit
b51c560f6e
@ -2277,6 +2277,34 @@ def km_node_editor(params):
|
|||||||
("wm.context_toggle", {"type": 'Z', "value": 'PRESS', "alt": True, "shift": True},
|
("wm.context_toggle", {"type": 'Z', "value": 'PRESS', "alt": True, "shift": True},
|
||||||
{"properties": [("data_path", "space_data.overlay.show_overlays")]}),
|
{"properties": [("data_path", "space_data.overlay.show_overlays")]}),
|
||||||
*_template_items_context_menu("NODE_MT_context_menu", params.context_menu_event),
|
*_template_items_context_menu("NODE_MT_context_menu", params.context_menu_event),
|
||||||
|
# Viewer shortcuts.
|
||||||
|
("node.viewer_shortcut_get", {"type": 'ONE', "value": 'PRESS'}, {"properties": [("viewer_index", 1)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'ONE', "value": 'PRESS',
|
||||||
|
'ctrl': True}, {"properties": [("viewer_index", 1)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'TWO', "value": 'PRESS'}, {"properties": [("viewer_index", 2)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'TWO', "value": 'PRESS',
|
||||||
|
'ctrl': True}, {"properties": [("viewer_index", 2)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'THREE', "value": 'PRESS'}, {"properties": [("viewer_index", 3)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'THREE', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 3)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'FOUR', "value": 'PRESS'}, {"properties": [("viewer_index", 4)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'FOUR', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 4)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'FIVE', "value": 'PRESS'}, {"properties": [("viewer_index", 5)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'FIVE', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 5)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'SIX', "value": 'PRESS'}, {"properties": [("viewer_index", 6)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'SIX', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 6)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'SEVEN', "value": 'PRESS'}, {"properties": [("viewer_index", 7)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'SEVEN', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 7)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'EIGHT', "value": 'PRESS'}, {"properties": [("viewer_index", 8)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'EIGHT', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 8)]}),
|
||||||
|
("node.viewer_shortcut_get", {"type": 'NINE', "value": 'PRESS'}, {"properties": [("viewer_index", 9)]}),
|
||||||
|
("node.viewer_shortcut_set", {"type": 'NINE', "value": 'PRESS', 'ctrl': True},
|
||||||
|
{"properties": [("viewer_index", 9)]}),
|
||||||
])
|
])
|
||||||
|
|
||||||
return keymap
|
return keymap
|
||||||
|
@ -16,6 +16,7 @@ from bpy.props import (
|
|||||||
EnumProperty,
|
EnumProperty,
|
||||||
FloatVectorProperty,
|
FloatVectorProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
|
IntProperty,
|
||||||
)
|
)
|
||||||
from mathutils import (
|
from mathutils import (
|
||||||
Vector,
|
Vector,
|
||||||
@ -408,6 +409,104 @@ class NODE_OT_interface_item_remove(NodeInterfaceOperator, Operator):
|
|||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_OT_viewer_shortcut_set(Operator):
|
||||||
|
"""Create a compositor viewer shortcut for the selected node by pressing ctrl+1,2,..9"""
|
||||||
|
bl_idname = "node.viewer_shortcut_set"
|
||||||
|
bl_label = "Fast Preview"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
viewer_index: IntProperty(
|
||||||
|
name="Viewer Index",
|
||||||
|
description="Index corresponding to the shortcut, e.g. number key 1 corresponds to index 1 etc..")
|
||||||
|
|
||||||
|
def get_connected_viewer(self, node):
|
||||||
|
for out in node.outputs:
|
||||||
|
for link in out.links:
|
||||||
|
nv = link.to_node
|
||||||
|
if nv.type == 'VIEWER':
|
||||||
|
return nv
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(self, context):
|
||||||
|
return context.space_data.tree_type == 'CompositorNodeTree'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
nodes = context.space_data.edit_tree.nodes
|
||||||
|
links = context.space_data.edit_tree.links
|
||||||
|
selected_nodes = context.selected_nodes
|
||||||
|
|
||||||
|
if len(selected_nodes) == 0:
|
||||||
|
self.report({'ERROR'}, "Select a node to assign a shortcut")
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
fav_node = selected_nodes[0]
|
||||||
|
|
||||||
|
# Only viewer nodes can be set to favorites. However, the user can
|
||||||
|
# create a new favorite viewer by selecting any node and pressing ctrl+1.
|
||||||
|
old_active = nodes.active
|
||||||
|
if fav_node.type == 'VIEWER':
|
||||||
|
viewer_node = fav_node
|
||||||
|
else:
|
||||||
|
viewer_node = self.get_connected_viewer(fav_node)
|
||||||
|
if not viewer_node:
|
||||||
|
# Calling link_viewer() if a viewer node is connected will connect the next available socket to the viewer node.
|
||||||
|
# This behavior is not desired as we want to create a shortcut to the exisiting connected viewer node.
|
||||||
|
# Therefore link_viewer() is called only when no viewer node is connected.
|
||||||
|
bpy.ops.node.link_viewer()
|
||||||
|
viewer_node = self.get_connected_viewer(fav_node)
|
||||||
|
|
||||||
|
if not viewer_node:
|
||||||
|
self.report({'ERROR'}, "Unable to set shortcut, selected node is not a viewer node or does not support viewing")
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
# Use the node active status to enable this viewer node and disable others.
|
||||||
|
nodes.active = viewer_node
|
||||||
|
if old_active.type != 'VIEWER':
|
||||||
|
nodes.active = old_active
|
||||||
|
|
||||||
|
viewer_node.ui_shortcut = self.viewer_index
|
||||||
|
self.report({'INFO'}, "Assigned shortcut %i to %s" % (self.viewer_index, viewer_node.name))
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
|
class NODE_OT_viewer_shortcut_get(Operator):
|
||||||
|
"""Activate a specific compositor viewer node using 1,2,..,9 keys"""
|
||||||
|
bl_idname = "node.viewer_shortcut_get"
|
||||||
|
bl_label = "Fast Preview"
|
||||||
|
bl_options = {'REGISTER', 'UNDO'}
|
||||||
|
|
||||||
|
viewer_index: IntProperty(
|
||||||
|
name="Viewer Index",
|
||||||
|
description="Index corresponding to the shortcut, e.g. number key 1 corresponds to index 1 etc..")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(self, context):
|
||||||
|
return context.space_data.tree_type == 'CompositorNodeTree'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
nodes = context.space_data.edit_tree.nodes
|
||||||
|
|
||||||
|
# Get viewer node with exisiting shortcut.
|
||||||
|
viewer_node = None
|
||||||
|
for n in nodes:
|
||||||
|
if n.type == 'VIEWER' and n.ui_shortcut == self.viewer_index:
|
||||||
|
viewer_node = n
|
||||||
|
|
||||||
|
if not viewer_node:
|
||||||
|
self.report({'INFO'}, "Shortcut %i is not assigned to a Viewer node yet" % self.viewer_index)
|
||||||
|
return {'CANCELLED'}
|
||||||
|
|
||||||
|
# Use the node active status to enable this viewer node and disable others.
|
||||||
|
old_active = nodes.active
|
||||||
|
nodes.active = viewer_node
|
||||||
|
if old_active.type != "VIEWER":
|
||||||
|
nodes.active = old_active
|
||||||
|
|
||||||
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
class NODE_FH_image_node(FileHandler):
|
class NODE_FH_image_node(FileHandler):
|
||||||
bl_idname = "NODE_FH_image_node"
|
bl_idname = "NODE_FH_image_node"
|
||||||
bl_label = "Image node"
|
bl_label = "Image node"
|
||||||
@ -438,4 +537,6 @@ classes = (
|
|||||||
NODE_OT_interface_item_duplicate,
|
NODE_OT_interface_item_duplicate,
|
||||||
NODE_OT_interface_item_remove,
|
NODE_OT_interface_item_remove,
|
||||||
NODE_OT_tree_path_parent,
|
NODE_OT_tree_path_parent,
|
||||||
|
NODE_OT_viewer_shortcut_get,
|
||||||
|
NODE_OT_viewer_shortcut_set,
|
||||||
)
|
)
|
||||||
|
@ -3674,6 +3674,9 @@ void node_tree_set_output(bNodeTree *ntree)
|
|||||||
/* same type, exception for viewer */
|
/* same type, exception for viewer */
|
||||||
const bool tnode_is_output = tnode->type_legacy == CMP_NODE_VIEWER;
|
const bool tnode_is_output = tnode->type_legacy == CMP_NODE_VIEWER;
|
||||||
const bool compositor_case = is_compositor && tnode_is_output && node_is_output;
|
const bool compositor_case = is_compositor && tnode_is_output && node_is_output;
|
||||||
|
const bool has_same_shortcut = compositor_case && node != tnode &&
|
||||||
|
tnode->custom1 == node->custom1 &&
|
||||||
|
tnode->custom1 != NODE_VIEWER_SHORTCUT_NONE;
|
||||||
if (tnode->type_legacy == node->type_legacy || compositor_case) {
|
if (tnode->type_legacy == node->type_legacy || compositor_case) {
|
||||||
if (tnode->flag & NODE_DO_OUTPUT) {
|
if (tnode->flag & NODE_DO_OUTPUT) {
|
||||||
output++;
|
output++;
|
||||||
@ -3682,6 +3685,9 @@ void node_tree_set_output(bNodeTree *ntree)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (has_same_shortcut) {
|
||||||
|
tnode->custom1 = NODE_VIEWER_SHORTCUT_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output == 0) {
|
if (output == 0) {
|
||||||
|
@ -1283,6 +1283,17 @@ static void do_version_color_to_float_conversion(bNodeTree *node_tree)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_version_viewer_shortcut(bNodeTree *node_tree)
|
||||||
|
{
|
||||||
|
LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_tree->nodes) {
|
||||||
|
if (node->type_legacy != CMP_NODE_VIEWER) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* custom1 was previously used for Tile Order for the Tiled Compositor. */
|
||||||
|
node->custom1 = NODE_VIEWER_SHORTCUT_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool all_scenes_use(Main *bmain, const blender::Span<const char *> engines)
|
static bool all_scenes_use(Main *bmain, const blender::Span<const char *> engines)
|
||||||
{
|
{
|
||||||
if (!bmain->scenes.first) {
|
if (!bmain->scenes.first) {
|
||||||
@ -5807,6 +5818,15 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 404, 27)) {
|
||||||
|
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||||
|
if (ntree->type == NTREE_COMPOSIT) {
|
||||||
|
do_version_viewer_shortcut(ntree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOREACH_NODETREE_END;
|
||||||
|
}
|
||||||
|
|
||||||
/* Always run this versioning; meshes are written with the legacy format which always needs to
|
/* Always run this versioning; meshes are written with the legacy format which always needs to
|
||||||
* be converted to the new format on file load. Can be moved to a subversion check in a larger
|
* be converted to the new format on file load. Can be moved to a subversion check in a larger
|
||||||
* breaking release. */
|
* breaking release. */
|
||||||
|
@ -3268,6 +3268,36 @@ static void node_draw_extra_info_panel(const bContext &C,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static short get_viewer_shortcut_icon(const bNode &node)
|
||||||
|
{
|
||||||
|
BLI_assert(node.is_type("CompositorNodeViewer"));
|
||||||
|
switch (node.custom1) {
|
||||||
|
case NODE_VIEWER_SHORTCUT_NONE:
|
||||||
|
/* No change by default. */
|
||||||
|
return node.typeinfo->ui_icon;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_1:
|
||||||
|
return ICON_EVENT_ONEKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_2:
|
||||||
|
return ICON_EVENT_TWOKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_3:
|
||||||
|
return ICON_EVENT_THREEKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_4:
|
||||||
|
return ICON_EVENT_FOURKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_5:
|
||||||
|
return ICON_EVENT_FIVEKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_6:
|
||||||
|
return ICON_EVENT_SIXKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_7:
|
||||||
|
return ICON_EVENT_SEVENKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_8:
|
||||||
|
return ICON_EVENT_EIGHTKEY;
|
||||||
|
case NODE_VIEWER_SHORCTUT_SLOT_9:
|
||||||
|
return ICON_EVENT_NINEKEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.typeinfo->ui_icon;
|
||||||
|
}
|
||||||
|
|
||||||
static void node_draw_basis(const bContext &C,
|
static void node_draw_basis(const bContext &C,
|
||||||
TreeDrawContext &tree_draw_ctx,
|
TreeDrawContext &tree_draw_ctx,
|
||||||
const View2D &v2d,
|
const View2D &v2d,
|
||||||
@ -3461,6 +3491,25 @@ static void node_draw_basis(const bContext &C,
|
|||||||
but, node_toggle_button_cb, POINTER_FROM_INT(node.identifier), (void *)operator_idname);
|
but, node_toggle_button_cb, POINTER_FROM_INT(node.identifier), (void *)operator_idname);
|
||||||
UI_block_emboss_set(&block, UI_EMBOSS);
|
UI_block_emboss_set(&block, UI_EMBOSS);
|
||||||
}
|
}
|
||||||
|
/* Viewer node shortcuts. */
|
||||||
|
if (node.is_type("CompositorNodeViewer")) {
|
||||||
|
short shortcut_icon = get_viewer_shortcut_icon(node);
|
||||||
|
iconofs -= iconbutw;
|
||||||
|
UI_block_emboss_set(&block, UI_EMBOSS_NONE);
|
||||||
|
uiDefIconBut(&block,
|
||||||
|
UI_BTYPE_BUT,
|
||||||
|
0,
|
||||||
|
shortcut_icon,
|
||||||
|
iconofs,
|
||||||
|
rct.ymax - NODE_DY,
|
||||||
|
iconbutw,
|
||||||
|
UI_UNIT_Y,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
"");
|
||||||
|
UI_block_emboss_set(&block, UI_EMBOSS);
|
||||||
|
}
|
||||||
|
|
||||||
node_add_error_message_button(tree_draw_ctx, node, block, rct, iconofs);
|
node_add_error_message_button(tree_draw_ctx, node, block, rct, iconofs);
|
||||||
|
|
||||||
|
@ -739,7 +739,7 @@ static int view_socket(const bContext &C,
|
|||||||
/* Try to find a viewer that is already active. */
|
/* Try to find a viewer that is already active. */
|
||||||
for (bNode *node : btree.all_nodes()) {
|
for (bNode *node : btree.all_nodes()) {
|
||||||
if (is_viewer_node(*node)) {
|
if (is_viewer_node(*node)) {
|
||||||
if (node->flag & NODE_DO_OUTPUT) {
|
if (node->flag & NODE_DO_OUTPUT && node->custom1 == NODE_VIEWER_SHORTCUT_NONE) {
|
||||||
viewer_node = node;
|
viewer_node = node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -759,7 +759,7 @@ static int view_socket(const bContext &C,
|
|||||||
|
|
||||||
if (viewer_node == nullptr) {
|
if (viewer_node == nullptr) {
|
||||||
for (bNode *node : btree.all_nodes()) {
|
for (bNode *node : btree.all_nodes()) {
|
||||||
if (is_viewer_node(*node)) {
|
if (is_viewer_node(*node) && node->custom1 == NODE_VIEWER_SHORTCUT_NONE) {
|
||||||
viewer_node = node;
|
viewer_node = node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -353,6 +353,21 @@ typedef struct bNodePanelState {
|
|||||||
#endif
|
#endif
|
||||||
} bNodePanelState;
|
} bNodePanelState;
|
||||||
|
|
||||||
|
typedef enum eViewerNodeShortcut {
|
||||||
|
NODE_VIEWER_SHORTCUT_NONE = 0,
|
||||||
|
/* Users can set custom keys to shortcuts,
|
||||||
|
* but shortcuts should always be referred to as enums. */
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_1 = 1,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_2 = 2,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_3 = 3,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_4 = 4,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_5 = 5,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_6 = 6,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_7 = 7,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_8 = 8,
|
||||||
|
NODE_VIEWER_SHORCTUT_SLOT_9 = 9
|
||||||
|
} eViewerNodeShortcut;
|
||||||
|
|
||||||
typedef enum NodeWarningPropagation {
|
typedef enum NodeWarningPropagation {
|
||||||
NODE_WARNING_PROPAGATION_ALL = 0,
|
NODE_WARNING_PROPAGATION_ALL = 0,
|
||||||
NODE_WARNING_PROPAGATION_NONE = 1,
|
NODE_WARNING_PROPAGATION_NONE = 1,
|
||||||
|
@ -1356,6 +1356,20 @@ static void rna_NodeTree_active_node_set(PointerRNA *ptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rna_Node_shortcut_node_set(PointerRNA *ptr, int value)
|
||||||
|
{
|
||||||
|
bNode *curr_node = static_cast<bNode *>(ptr->data);
|
||||||
|
bNodeTree &ntree = curr_node->owner_tree();
|
||||||
|
|
||||||
|
/* Avoid having two nodes with the same shortcut. */
|
||||||
|
for (bNode *node : ntree.all_nodes()) {
|
||||||
|
if (node->is_type("CompositorNodeViewer") && node->custom1 == value) {
|
||||||
|
node->custom1 = NODE_VIEWER_SHORTCUT_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr_node->custom1 = value;
|
||||||
|
}
|
||||||
|
|
||||||
static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree,
|
static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree,
|
||||||
Main *bmain,
|
Main *bmain,
|
||||||
ReportList *reports,
|
ReportList *reports,
|
||||||
@ -9125,6 +9139,14 @@ static void def_cmp_viewer(BlenderRNA * /*brna*/, StructRNA *srna)
|
|||||||
"Use Alpha",
|
"Use Alpha",
|
||||||
"Colors are treated alpha premultiplied, or colors output straight (alpha gets set to 1)");
|
"Colors are treated alpha premultiplied, or colors output straight (alpha gets set to 1)");
|
||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "ui_shortcut", PROP_INT, PROP_NONE);
|
||||||
|
RNA_def_property_int_sdna(prop, nullptr, "custom1");
|
||||||
|
RNA_def_property_int_funcs(prop, nullptr, "rna_Node_shortcut_node_set", nullptr);
|
||||||
|
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||||
|
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
|
||||||
|
RNA_def_property_int_default(prop, NODE_VIEWER_SHORTCUT_NONE);
|
||||||
|
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void def_cmp_composite(BlenderRNA * /*brna*/, StructRNA *srna)
|
static void def_cmp_composite(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||||
|
@ -40,6 +40,7 @@ static void node_composit_init_viewer(bNodeTree * /*ntree*/, bNode *node)
|
|||||||
ImageUser *iuser = MEM_cnew<ImageUser>(__func__);
|
ImageUser *iuser = MEM_cnew<ImageUser>(__func__);
|
||||||
node->storage = iuser;
|
node->storage = iuser;
|
||||||
iuser->sfra = 1;
|
iuser->sfra = 1;
|
||||||
|
node->custom1 = NODE_VIEWER_SHORTCUT_NONE;
|
||||||
|
|
||||||
node->id = (ID *)BKE_image_ensure_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node");
|
node->id = (ID *)BKE_image_ensure_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user