Compositor: "Copy" button duplicates node tree

Currently, the compositor template ID creates a new node tree. This is
inconsistent with other node editors where the button copies the node
tree.
Also use "New" in geometry nodes operator description instead of "Copy"

Pull Request: https://projects.blender.org/blender/blender/pulls/146222
This commit is contained in:
Habib Gahbiche
2025-09-30 11:46:32 +02:00
parent d75b8e5b6e
commit 4f722eaae3
5 changed files with 81 additions and 30 deletions

View File

@@ -152,7 +152,10 @@ class NODE_HT_header(Header):
if snode.node_tree_sub_type == 'SCENE':
row = layout.row()
row.enabled = not snode.pin
row.template_ID(scene, "compositing_node_group", new="node.new_compositing_node_group")
if scene.compositing_node_group:
row.template_ID(scene, "compositing_node_group", new="node.duplicate_compositing_node_group")
else:
row.template_ID(scene, "compositing_node_group", new="node.new_compositing_node_group")
elif snode.node_tree_sub_type == 'SEQUENCER':
row = layout.row()
sequencer_scene = context.workspace.sequencer_scene

View File

@@ -3594,8 +3594,9 @@ static wmOperatorStatus geometry_node_tree_copy_assign_exec(bContext *C, wmOpera
void OBJECT_OT_geometry_node_tree_copy_assign(wmOperatorType *ot)
{
ot->name = "Copy Geometry Node Group";
ot->description = "Copy the active geometry node group and assign it to the active modifier";
ot->name = "New Geometry Node Group";
ot->description =
"Duplicate the active geometry node group and assign it to the active modifier";
ot->idname = "OBJECT_OT_geometry_node_tree_copy_assign";
ot->exec = geometry_node_tree_copy_assign_exec;

View File

@@ -114,6 +114,39 @@ bNode *add_static_node(const bContext &C, int type, const float2 &location)
return node;
}
/**
* Hook an existing node tree to a templateID UI button.
*/
static void node_templateID_assign(bContext *C, bNodeTree *node_tree)
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
PointerRNA ptr;
PropertyRNA *prop;
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* #RNA_property_pointer_set increases the user count, fixed here as the editor is the initial
* user. */
id_us_min(&node_tree->id);
if (ptr.owner_id) {
BKE_id_move_to_same_lib(*bmain, node_tree->id, *ptr.owner_id);
}
PointerRNA idptr = RNA_id_pointer_create(&node_tree->id);
RNA_property_pointer_set(&ptr, prop, idptr, nullptr);
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
snode->nodetree = node_tree;
tree_update(C);
}
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -1595,34 +1628,9 @@ void NODE_OT_add_color(wmOperatorType *ot)
static bNodeTree *new_node_tree_impl(bContext *C, StringRef treename, StringRef idname)
{
Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
PointerRNA ptr;
PropertyRNA *prop;
bNodeTree *node_tree;
node_tree = bke::node_tree_add_tree(bmain, treename, idname);
/* Hook into UI. */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
if (prop) {
/* #RNA_property_pointer_set increases the user count, fixed here as the editor is the initial
* user. */
id_us_min(&node_tree->id);
if (ptr.owner_id) {
BKE_id_move_to_same_lib(*bmain, node_tree->id, *ptr.owner_id);
}
PointerRNA idptr = RNA_id_pointer_create(&node_tree->id);
RNA_property_pointer_set(&ptr, prop, idptr, nullptr);
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
snode->nodetree = node_tree;
tree_update(C);
}
bNodeTree *node_tree = bke::node_tree_add_tree(bmain, treename, idname);
node_templateID_assign(C, node_tree);
return node_tree;
}
@@ -1749,6 +1757,43 @@ void NODE_OT_new_compositing_node_group(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "");
}
/* -------------------------------------------------------------------- */
/** \name Duplicate Compositing Node Tree Operator
* \{ */
static wmOperatorStatus duplicate_compositing_node_group_exec(bContext *C, wmOperator * /*op*/)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
PointerRNA ptr;
if (scene->compositing_node_group == nullptr) {
return OPERATOR_CANCELLED;
}
bNodeTree *node_tree = bke::node_tree_copy_tree(bmain, *scene->compositing_node_group);
node_templateID_assign(C, node_tree);
WM_event_add_notifier(C, NC_NODE | NA_ADDED, nullptr);
BKE_ntree_update_after_single_tree_change(*bmain, *node_tree);
return OPERATOR_FINISHED;
}
void NODE_OT_duplicate_compositing_node_group(wmOperatorType *ot)
{
ot->name = "New Compositing Node Group";
ot->idname = "NODE_OT_duplicate_compositing_node_group";
ot->description = "Duplicate the currently assigned compositing node group.";
ot->exec = duplicate_compositing_node_group_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name New Compositor Sequencer Node Group Operator
* \{ */

View File

@@ -310,6 +310,7 @@ void NODE_OT_add_import_node(wmOperatorType *ot);
void NODE_OT_swap_group_asset(wmOperatorType *ot);
void NODE_OT_new_node_tree(wmOperatorType *ot);
void NODE_OT_new_compositing_node_group(wmOperatorType *ot);
void NODE_OT_duplicate_compositing_node_group(wmOperatorType *ot);
void NODE_OT_new_compositor_sequencer_node_group(wmOperatorType *operator_type);
void NODE_OT_add_group_input_node(wmOperatorType *ot);

View File

@@ -95,6 +95,7 @@ void node_operatortypes()
WM_operatortype_append(NODE_OT_new_node_tree);
WM_operatortype_append(NODE_OT_new_compositing_node_group);
WM_operatortype_append(NODE_OT_duplicate_compositing_node_group);
WM_operatortype_append(NODE_OT_new_compositor_sequencer_node_group);
WM_operatortype_append(NODE_OT_parent_set);