diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 21ac27dc4ea..f866a158f30 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -443,8 +443,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { List owned; node->get_owned_by(node->get_owner(), &owned); - Map duplimap; - Node *dup = _duplicate(node, duplimap); + Map duplimap; + Node *dup = node->duplicate_from_editor(duplimap); ERR_CONTINUE(!dup); @@ -821,82 +821,6 @@ void SceneTreeDock::_node_renamed() { _node_selected(); } -Node *SceneTreeDock::_duplicate(Node *p_node, Map &duplimap) { - - Node *node = NULL; - - if (p_node->get_filename() != "") { //an instance - - Ref sd = ResourceLoader::load(p_node->get_filename()); - ERR_FAIL_COND_V(!sd.is_valid(), NULL); - node = sd->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); - ERR_FAIL_COND_V(!node, NULL); - node->set_scene_instance_load_placeholder(p_node->get_scene_instance_load_placeholder()); - } else { - Object *obj = ClassDB::instance(p_node->get_class()); - ERR_FAIL_COND_V(!obj, NULL); - node = Object::cast_to(obj); - if (!node) - memdelete(obj); - ERR_FAIL_COND_V(!node, NULL); - } - - List plist; - - p_node->get_property_list(&plist); - - for (List::Element *E = plist.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) - continue; - String name = E->get().name; - Variant value = p_node->get(name); - // Duplicate dictionaries and arrays, mainly needed for __meta__ - if (value.get_type() == Variant::DICTIONARY) { - value = Dictionary(value).copy(); - } else if (value.get_type() == Variant::ARRAY) { - value = Array(value).duplicate(); - } - node->set(name, value); - } - - List conns; - p_node->get_all_signal_connections(&conns); - for (List::Element *E = conns.front(); E; E = E->next()) { - if (E->get().flags & CONNECT_PERSIST) { - node->connect(E->get().signal, E->get().target, E->get().method, E->get().binds, E->get().flags); - } - } - - List group_info; - p_node->get_groups(&group_info); - for (List::Element *E = group_info.front(); E; E = E->next()) { - - if (E->get().persistent) - node->add_to_group(E->get().name, true); - } - - node->set_name(p_node->get_name()); - duplimap[p_node] = node; - - for (int i = 0; i < p_node->get_child_count(); i++) { - - Node *child = p_node->get_child(i); - if (p_node->get_owner() != child->get_owner()) - continue; //don't bother with not in-scene nodes. - - Node *dup = _duplicate(child, duplimap); - if (!dup) { - memdelete(node); - return NULL; - } - - node->add_child(dup); - } - - return node; -} - void SceneTreeDock::_set_owners(Node *p_owner, const Array &p_nodes) { for (int i = 0; i < p_nodes.size(); i++) { diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 97d3c4748a4..78480522413 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -130,7 +130,6 @@ class SceneTreeDock : public VBoxContainer { void _add_children_to_popup(Object *p_obj, int p_depth); - Node *_duplicate(Node *p_node, Map &duplimap); void _node_reparent(NodePath p_path, bool p_keep_global_xform); void _do_reparent(Node *p_new_parent, int p_position_in_parent, Vector p_nodes, bool p_keep_global_xform); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 2bf45f11893..253084dd991 100755 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2067,7 +2067,7 @@ int Node::get_position_in_parent() const { return data.pos; } -Node *Node::_duplicate(int p_flags) const { +Node *Node::_duplicate(int p_flags, Map *r_duplimap) const { Node *node = NULL; @@ -2084,7 +2084,12 @@ Node *Node::_duplicate(int p_flags) const { Ref res = ResourceLoader::load(get_filename()); ERR_FAIL_COND_V(res.is_null(), NULL); - node = res->instance(); + PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED; +#ifdef TOOLS_ENABLED + if (p_flags & DUPLICATE_FROM_EDITOR) + ges = PackedScene::GEN_EDIT_STATE_INSTANCE; +#endif + node = res->instance(ges); ERR_FAIL_COND_V(!node, NULL); instanced = true; @@ -2099,10 +2104,6 @@ Node *Node::_duplicate(int p_flags) const { ERR_FAIL_COND_V(!node, NULL); } - if (get_filename() != "") { //an instance - node->set_filename(get_filename()); - } - List plist; get_property_list(&plist); @@ -2138,11 +2139,21 @@ Node *Node::_duplicate(int p_flags) const { node->set_name(get_name()); +#ifdef TOOLS_ENABLED + if ((p_flags & DUPLICATE_FROM_EDITOR) && r_duplimap) + r_duplimap->insert(this, node); +#endif + if (p_flags & DUPLICATE_GROUPS) { List gi; get_groups(&gi); for (List::Element *E = gi.front(); E; E = E->next()) { +#ifdef TOOLS_ENABLED + if ((p_flags & DUPLICATE_FROM_EDITOR) && !E->get().persistent) + continue; +#endif + node->add_to_group(E->get().name, E->get().persistent); } } @@ -2154,7 +2165,7 @@ Node *Node::_duplicate(int p_flags) const { if (instanced && get_child(i)->data.owner == this) continue; //part of instance - Node *dup = get_child(i)->duplicate(p_flags); + Node *dup = get_child(i)->_duplicate(p_flags, r_duplimap); if (!dup) { memdelete(node); @@ -2178,6 +2189,20 @@ Node *Node::duplicate(int p_flags) const { return dupe; } +#ifdef TOOLS_ENABLED +Node *Node::duplicate_from_editor(Map &r_duplimap) const { + + Node *dupe = _duplicate(DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS | DUPLICATE_USE_INSTANCING | DUPLICATE_FROM_EDITOR, &r_duplimap); + + // Duplication of signals must happen after all the node descendants have been copied, + // because re-targeting of connections from some descendant to another is not possible + // if the emitter node comes later in tree order than the receiver + _duplicate_signals(this, dupe); + + return dupe; +} +#endif + void Node::_duplicate_and_reown(Node *p_new_parent, const Map &p_reown_map) const { if (get_owner() != get_parent()->get_owner()) @@ -2325,6 +2350,9 @@ Node *Node::duplicate_and_reown(const Map &p_reown_map) const { get_child(i)->_duplicate_and_reown(node, p_reown_map); } + // Duplication of signals must happen after all the node descendants have been copied, + // because re-targeting of connections from some descendant to another is not possible + // if the emitter node comes later in tree order than the receiver _duplicate_signals(this, node); return node; } diff --git a/scene/main/node.h b/scene/main/node.h index c43e96063f0..bd0b18c87a4 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -58,7 +58,10 @@ public: DUPLICATE_SIGNALS = 1, DUPLICATE_GROUPS = 2, DUPLICATE_SCRIPTS = 4, - DUPLICATE_USE_INSTANCING = 8 + DUPLICATE_USE_INSTANCING = 8, +#ifdef TOOLS_ENABLED + DUPLICATE_FROM_EDITOR = 16, +#endif }; enum RPCMode { @@ -169,7 +172,7 @@ private: void _duplicate_signals(const Node *p_original, Node *p_copy) const; void _duplicate_and_reown(Node *p_new_parent, const Map &p_reown_map) const; - Node *_duplicate(int p_flags) const; + Node *_duplicate(int p_flags, Map *r_duplimap = NULL) const; Array _get_children() const; Array _get_groups() const; @@ -326,6 +329,9 @@ public: Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const; Node *duplicate_and_reown(const Map &p_reown_map) const; +#ifdef TOOLS_ENABLED + Node *duplicate_from_editor(Map &r_duplimap) const; +#endif //Node *clone_tree() const;