Geometry Nodes: shortcuts for viewer nodes
Implement shortcuts for viewer nodes. Viewer nodes are now activated using the operator `bpy.ops.node.activate_viewer()` instead of activating the viewer by setting the node to active. This also unifies the behavior with viewer shortcuts in the compositor (see attachment in the original PR). Pull Request: https://projects.blender.org/blender/blender/pulls/134555
This commit is contained in:
@@ -565,7 +565,7 @@ class NODE_OT_viewer_shortcut_set(Operator):
|
||||
(space is not None) and
|
||||
space.type == 'NODE_EDITOR' and
|
||||
space.node_tree is not None and
|
||||
space.tree_type == 'CompositorNodeTree'
|
||||
space.tree_type in {'CompositorNodeTree', 'GeometryNodeTree'}
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
@@ -580,7 +580,6 @@ class NODE_OT_viewer_shortcut_set(Operator):
|
||||
|
||||
# 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:
|
||||
@@ -600,10 +599,8 @@ class NODE_OT_viewer_shortcut_set(Operator):
|
||||
)
|
||||
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
|
||||
with bpy.context.temp_override(node=viewer_node):
|
||||
bpy.ops.node.activate_viewer()
|
||||
|
||||
viewer_node.ui_shortcut = self.viewer_index
|
||||
self.report({'INFO'}, "Assigned shortcut {:d} to {:s}".format(self.viewer_index, viewer_node.name))
|
||||
@@ -629,7 +626,7 @@ class NODE_OT_viewer_shortcut_get(Operator):
|
||||
(space is not None) and
|
||||
space.type == 'NODE_EDITOR' and
|
||||
space.node_tree is not None and
|
||||
space.tree_type == 'CompositorNodeTree'
|
||||
space.tree_type in {'CompositorNodeTree', 'GeometryNodeTree'}
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
@@ -645,11 +642,8 @@ class NODE_OT_viewer_shortcut_get(Operator):
|
||||
self.report({'INFO'}, "Shortcut {:d} is not assigned to a Viewer node yet".format(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
|
||||
with bpy.context.temp_override(node=viewer_node):
|
||||
bpy.ops.node.activate_viewer()
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@@ -3608,14 +3608,16 @@ void node_tree_free_local_tree(bNodeTree *ntree)
|
||||
void node_tree_set_output(bNodeTree &ntree)
|
||||
{
|
||||
const bool is_compositor = ntree.type == NTREE_COMPOSIT;
|
||||
const bool is_geometry = ntree.type == NTREE_GEOMETRY;
|
||||
/* find the active outputs, might become tree type dependent handler */
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree.nodes) {
|
||||
if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) {
|
||||
/* we need a check for which output node should be tagged like this, below an exception */
|
||||
if (ELEM(node->type_legacy, CMP_NODE_OUTPUT_FILE, GEO_NODE_VIEWER)) {
|
||||
if (node->is_type("CompositorNodeOutputFile")) {
|
||||
continue;
|
||||
}
|
||||
const bool node_is_output = node->type_legacy == CMP_NODE_VIEWER;
|
||||
const bool node_is_output = node->is_type("CompositorNodeViewer") ||
|
||||
node->is_type("GeometryNodeViewer");
|
||||
|
||||
int output = 0;
|
||||
/* there is more types having output class, each one is checked */
|
||||
@@ -3626,12 +3628,15 @@ void node_tree_set_output(bNodeTree &ntree)
|
||||
}
|
||||
|
||||
/* same type, exception for 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 has_same_shortcut = compositor_case && node != tnode &&
|
||||
const bool tnode_is_output = tnode->is_type("CompositorNodeViewer") ||
|
||||
tnode->is_type("GeometryNodeViewer");
|
||||
const bool viewer_case = (is_compositor || is_geometry) && tnode_is_output &&
|
||||
node_is_output;
|
||||
const bool has_same_shortcut = viewer_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 || viewer_case) {
|
||||
if (tnode->flag & NODE_DO_OUTPUT) {
|
||||
output++;
|
||||
if (output > 1) {
|
||||
|
||||
@@ -3317,7 +3317,7 @@ 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"));
|
||||
BLI_assert(node.is_type("CompositorNodeViewer") || node.is_type("GeometryNodeViewer"));
|
||||
switch (node.custom1) {
|
||||
case NODE_VIEWER_SHORTCUT_NONE:
|
||||
/* No change by default. */
|
||||
@@ -3532,9 +3532,24 @@ static void node_draw_basis(const bContext &C,
|
||||
0,
|
||||
"");
|
||||
/* Selection implicitly activates the node. */
|
||||
const char *operator_idname = is_active ? "NODE_OT_deactivate_viewer" : "NODE_OT_select";
|
||||
const char *operator_idname = is_active ? "NODE_OT_deactivate_viewer" :
|
||||
"NODE_OT_activate_viewer";
|
||||
UI_but_func_set(
|
||||
but, node_toggle_button_cb, POINTER_FROM_INT(node.identifier), (void *)operator_idname);
|
||||
|
||||
short shortcut_icon = get_viewer_shortcut_icon(node);
|
||||
uiDefIconBut(&block,
|
||||
UI_BTYPE_BUT,
|
||||
0,
|
||||
shortcut_icon,
|
||||
iconofs - 1.2 * iconbutw,
|
||||
rct.ymax - NODE_DY,
|
||||
iconbutw,
|
||||
UI_UNIT_Y,
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
UI_block_emboss_set(&block, UI_EMBOSS);
|
||||
}
|
||||
/* Viewer node shortcuts. */
|
||||
|
||||
@@ -1344,18 +1344,40 @@ static void rna_NodeTree_active_node_set(PointerRNA *ptr,
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_Node_shortcut_node_set(PointerRNA *ptr, int value)
|
||||
static void node_viewer_set_shortcut_fn(bNode *node, bNodeTree &ntree, int value)
|
||||
{
|
||||
/* Avoid having two nodes with the same shortcut. */
|
||||
for (bNode *other_node : ntree.all_nodes()) {
|
||||
if ((other_node->is_type("CompositorNodeViewer") ||
|
||||
other_node->is_type("GeometryNodeViewer")) &&
|
||||
other_node->custom1 == value)
|
||||
{
|
||||
other_node->custom1 = NODE_VIEWER_SHORTCUT_NONE;
|
||||
}
|
||||
}
|
||||
node->custom1 = value;
|
||||
}
|
||||
|
||||
void rna_Node_Viewer_shortcut_node_set(PointerRNA *ptr, PropertyRNA * /*prop*/, 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;
|
||||
node_viewer_set_shortcut_fn(curr_node, ntree, value);
|
||||
}
|
||||
|
||||
int rna_Node_Viewer_shortcut_node_get(PointerRNA *ptr, PropertyRNA * /*prop*/)
|
||||
{
|
||||
bNode *curr_node = static_cast<bNode *>(ptr->data);
|
||||
return curr_node->custom1;
|
||||
}
|
||||
|
||||
void rna_Node_Viewer_shortcut_node_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
bNode *curr_node = static_cast<bNode *>(ptr->data);
|
||||
bNodeTree &ntree = curr_node->owner_tree();
|
||||
|
||||
node_viewer_set_shortcut_fn(curr_node, ntree, value);
|
||||
}
|
||||
|
||||
static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree,
|
||||
@@ -9164,7 +9186,7 @@ static void def_cmp_viewer(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
|
||||
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_int_funcs(prop, nullptr, "rna_Node_Viewer_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);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
void rna_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr);
|
||||
void rna_Node_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr);
|
||||
void rna_Node_update_relations(Main *bmain, Scene *scne, PointerRNA *ptr);
|
||||
void rna_Node_Viewer_shortcut_node_set(PointerRNA *ptr, PropertyRNA *prop, int value);
|
||||
int rna_Node_Viewer_shortcut_node_get(PointerRNA *ptr, PropertyRNA *prop);
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
|
||||
@@ -138,6 +138,15 @@ static void node_rna(StructRNA *srna)
|
||||
rna_enum_attribute_domain_with_auto_items,
|
||||
NOD_storage_enum_accessors(domain),
|
||||
int(AttrDomain::Point));
|
||||
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_property(srna, "ui_shortcut", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_funcs_runtime(
|
||||
prop, rna_Node_Viewer_shortcut_node_get, rna_Node_Viewer_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_notifier(prop, NC_NODE | ND_DISPLAY);
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
|
||||
Reference in New Issue
Block a user