Nodes: Duplicate Linked operator + User Preference option for Node Tree

This operator (Alt + D) allows users to explicitly create a linked copy
of a group node (same current behaviour for the Duplicate operator).

The duplicate operator (Shift + D) now takes the new User Preference
duplicate data option for Node Tree into account. It is by default
disabled, leading to no functional change for users.

Although we could make in the future make this option "on" by default,
to make it consistent with the rest of Blender we do not at the time.

Differential Revision: https://developer.blender.org/D16210
This commit is contained in:
Dalai Felinto 2022-10-13 20:06:20 +02:00
parent a5d3b648e3
commit 6beeba1ef5
Notes: blender-bot 2023-02-14 08:42:53 +01:00
Referenced by issue #102864, Regression: delete with reconnect not working properly in the node editor
Referenced by issue #102864, Regression: delete with reconnect not working properly in the node editor
Referenced by issue #102276, Hotkey conflict Alt D in Node Editor with Duplicate Linked and Detach
7 changed files with 48 additions and 3 deletions

View File

@ -2073,6 +2073,8 @@ def km_node_editor(params):
op_menu("NODE_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
("node.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True},
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
("node.duplicate_move_linked", {"type": 'D', "value": 'PRESS', "alt": True},
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
("node.duplicate_move_keep_inputs", {"type": 'D', "value": 'PRESS', "shift": True, "ctrl": True},
{"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}),
("node.parent_set", {"type": 'P', "value": 'PRESS', "ctrl": True}, None),

View File

@ -318,6 +318,7 @@ class NODE_MT_node(Menu):
layout.operator("node.clipboard_copy", text="Copy")
layout.operator("node.clipboard_paste", text="Paste")
layout.operator("node.duplicate_move")
layout.operator("node.duplicate_move_linked")
layout.operator("node.delete")
layout.operator("node.delete_reconnect")

View File

@ -397,17 +397,18 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
# col.prop(edit, "use_duplicate_fcurve", text="F-Curve") # Not implemented.
col.prop(edit, "use_duplicate_curves", text="Curves")
col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
col.prop(edit, "use_duplicate_lattice", text="Lattice")
col = flow.column()
col.prop(edit, "use_duplicate_lattice", text="Lattice")
col.prop(edit, "use_duplicate_light", text="Light")
col.prop(edit, "use_duplicate_lightprobe", text="Light Probe")
col.prop(edit, "use_duplicate_material", text="Material")
col.prop(edit, "use_duplicate_mesh", text="Mesh")
col.prop(edit, "use_duplicate_metaball", text="Metaball")
col.prop(edit, "use_duplicate_node_tree", text="Node Tree")
col.prop(edit, "use_duplicate_particle", text="Particle")
col = flow.column()
col.prop(edit, "use_duplicate_particle", text="Particle")
if hasattr(edit, "use_duplicate_pointcloud"):
col.prop(edit, "use_duplicate_pointcloud", text="Point Cloud")
col.prop(edit, "use_duplicate_speaker", text="Speaker")

View File

@ -1361,12 +1361,15 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
const bool keep_inputs = RNA_boolean_get(op->ptr, "keep_inputs");
bool linked = RNA_boolean_get(op->ptr, "linked") || ((U.dupflag & USER_DUP_NTREE) == 0);
const bool dupli_node_tree = !linked;
bool changed = false;
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
Map<const bNode *, bNode *> node_map;
Map<const bNodeSocket *, bNodeSocket *> socket_map;
Map<const ID *, ID *> duplicated_node_groups;
bNode *lastnode = (bNode *)ntree->nodes.last;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@ -1374,6 +1377,18 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
bNode *new_node = bke::node_copy_with_mapping(
ntree, *node, LIB_ID_COPY_DEFAULT, true, socket_map);
node_map.add_new(node, new_node);
if (node->id && dupli_node_tree) {
ID *new_group = duplicated_node_groups.lookup_or_add_cb(node->id, [&]() {
ID *new_group = BKE_id_copy(bmain, node->id);
/* Remove user added by copying. */
id_us_min(new_group);
return new_group;
});
id_us_plus(new_group);
id_us_min(new_node->id);
new_node->id = new_group;
}
changed = true;
}
@ -1462,6 +1477,8 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
void NODE_OT_duplicate(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Duplicate Nodes";
ot->description = "Duplicate selected nodes";
@ -1476,6 +1493,13 @@ void NODE_OT_duplicate(wmOperatorType *ot)
RNA_def_boolean(
ot->srna, "keep_inputs", false, "Keep Inputs", "Keep the input links to duplicated nodes");
prop = RNA_def_boolean(ot->srna,
"linked",
true,
"Linked",
"Duplicate node but not node trees, linking to the original data");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* XXX: some code needing updating to operators. */

View File

@ -174,7 +174,17 @@ void ED_operatormacros_node()
"Duplicate",
"Duplicate selected nodes and move them",
OPTYPE_UNDO | OPTYPE_REGISTER);
WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
RNA_boolean_set(mot->ptr, "linked", false);
WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
ot = WM_operatortype_append_macro(
"NODE_OT_duplicate_move_linked",
"Duplicate Linked",
"Duplicate selected nodes, but not their node trees, and move them",
OPTYPE_UNDO | OPTYPE_REGISTER);
mot = WM_operatortype_macro_define(ot, "NODE_OT_duplicate");
RNA_boolean_set(mot->ptr, "linked", true);
WM_operatortype_macro_define(ot, "NODE_OT_translate_attach");
/* modified operator call for duplicating with input links */

View File

@ -39,6 +39,7 @@ typedef enum eDupli_ID_Flags {
USER_DUP_LATTICE = (1 << 17),
USER_DUP_CAMERA = (1 << 18),
USER_DUP_SPEAKER = (1 << 19),
USER_DUP_NTREE = (1 << 20),
USER_DUP_OBDATA = (~0) & ((1 << 24) - 1),

View File

@ -5232,6 +5232,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Duplicate Volume", "Causes volume data to be duplicated with the object");
prop = RNA_def_property(srna, "use_duplicate_node_tree", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_NTREE);
RNA_def_property_ui_text(prop,
"Duplicate Node Tree",
"Make copies of node groups when duplicating nodes in the node editor");
/* Currently only used for insert offset (aka auto-offset),
* maybe also be useful for later stuff though. */
prop = RNA_def_property(srna, "node_margin", PROP_INT, PROP_PIXEL);