Let SceneTreeDock duplicate nodes via Node::duplicate()
Helps with #11182.
This commit is contained in:
parent
7286966971
commit
5a0be858f4
4 changed files with 45 additions and 84 deletions
|
@ -443,8 +443,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
||||||
List<Node *> owned;
|
List<Node *> owned;
|
||||||
node->get_owned_by(node->get_owner(), &owned);
|
node->get_owned_by(node->get_owner(), &owned);
|
||||||
|
|
||||||
Map<Node *, Node *> duplimap;
|
Map<const Node *, Node *> duplimap;
|
||||||
Node *dup = _duplicate(node, duplimap);
|
Node *dup = node->duplicate_from_editor(duplimap);
|
||||||
|
|
||||||
ERR_CONTINUE(!dup);
|
ERR_CONTINUE(!dup);
|
||||||
|
|
||||||
|
@ -821,82 +821,6 @@ void SceneTreeDock::_node_renamed() {
|
||||||
_node_selected();
|
_node_selected();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node *, Node *> &duplimap) {
|
|
||||||
|
|
||||||
Node *node = NULL;
|
|
||||||
|
|
||||||
if (p_node->get_filename() != "") { //an instance
|
|
||||||
|
|
||||||
Ref<PackedScene> 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<Node>(obj);
|
|
||||||
if (!node)
|
|
||||||
memdelete(obj);
|
|
||||||
ERR_FAIL_COND_V(!node, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<PropertyInfo> plist;
|
|
||||||
|
|
||||||
p_node->get_property_list(&plist);
|
|
||||||
|
|
||||||
for (List<PropertyInfo>::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<Connection> conns;
|
|
||||||
p_node->get_all_signal_connections(&conns);
|
|
||||||
for (List<Connection>::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<Node::GroupInfo> group_info;
|
|
||||||
p_node->get_groups(&group_info);
|
|
||||||
for (List<Node::GroupInfo>::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) {
|
void SceneTreeDock::_set_owners(Node *p_owner, const Array &p_nodes) {
|
||||||
|
|
||||||
for (int i = 0; i < p_nodes.size(); i++) {
|
for (int i = 0; i < p_nodes.size(); i++) {
|
||||||
|
|
|
@ -130,7 +130,6 @@ class SceneTreeDock : public VBoxContainer {
|
||||||
|
|
||||||
void _add_children_to_popup(Object *p_obj, int p_depth);
|
void _add_children_to_popup(Object *p_obj, int p_depth);
|
||||||
|
|
||||||
Node *_duplicate(Node *p_node, Map<Node *, Node *> &duplimap);
|
|
||||||
void _node_reparent(NodePath p_path, bool p_keep_global_xform);
|
void _node_reparent(NodePath p_path, bool p_keep_global_xform);
|
||||||
void _do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform);
|
void _do_reparent(Node *p_new_parent, int p_position_in_parent, Vector<Node *> p_nodes, bool p_keep_global_xform);
|
||||||
|
|
||||||
|
|
|
@ -2067,7 +2067,7 @@ int Node::get_position_in_parent() const {
|
||||||
return data.pos;
|
return data.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *Node::_duplicate(int p_flags) const {
|
Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const {
|
||||||
|
|
||||||
Node *node = NULL;
|
Node *node = NULL;
|
||||||
|
|
||||||
|
@ -2084,7 +2084,12 @@ Node *Node::_duplicate(int p_flags) const {
|
||||||
|
|
||||||
Ref<PackedScene> res = ResourceLoader::load(get_filename());
|
Ref<PackedScene> res = ResourceLoader::load(get_filename());
|
||||||
ERR_FAIL_COND_V(res.is_null(), NULL);
|
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);
|
ERR_FAIL_COND_V(!node, NULL);
|
||||||
|
|
||||||
instanced = true;
|
instanced = true;
|
||||||
|
@ -2134,11 +2139,21 @@ Node *Node::_duplicate(int p_flags) const {
|
||||||
|
|
||||||
node->set_name(get_name());
|
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) {
|
if (p_flags & DUPLICATE_GROUPS) {
|
||||||
List<GroupInfo> gi;
|
List<GroupInfo> gi;
|
||||||
get_groups(&gi);
|
get_groups(&gi);
|
||||||
for (List<GroupInfo>::Element *E = gi.front(); E; E = E->next()) {
|
for (List<GroupInfo>::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);
|
node->add_to_group(E->get().name, E->get().persistent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2150,7 +2165,7 @@ Node *Node::_duplicate(int p_flags) const {
|
||||||
if (instanced && get_child(i)->data.owner == this)
|
if (instanced && get_child(i)->data.owner == this)
|
||||||
continue; //part of instance
|
continue; //part of instance
|
||||||
|
|
||||||
Node *dup = get_child(i)->duplicate(p_flags);
|
Node *dup = get_child(i)->_duplicate(p_flags, r_duplimap);
|
||||||
if (!dup) {
|
if (!dup) {
|
||||||
|
|
||||||
memdelete(node);
|
memdelete(node);
|
||||||
|
@ -2174,6 +2189,20 @@ Node *Node::duplicate(int p_flags) const {
|
||||||
return dupe;
|
return dupe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Node *Node::duplicate_from_editor(Map<const Node *, Node *> &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<Node *, Node *> &p_reown_map) const {
|
void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const {
|
||||||
|
|
||||||
if (get_owner() != get_parent()->get_owner())
|
if (get_owner() != get_parent()->get_owner())
|
||||||
|
@ -2321,6 +2350,9 @@ Node *Node::duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const {
|
||||||
get_child(i)->_duplicate_and_reown(node, p_reown_map);
|
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);
|
_duplicate_signals(this, node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,10 @@ public:
|
||||||
DUPLICATE_SIGNALS = 1,
|
DUPLICATE_SIGNALS = 1,
|
||||||
DUPLICATE_GROUPS = 2,
|
DUPLICATE_GROUPS = 2,
|
||||||
DUPLICATE_SCRIPTS = 4,
|
DUPLICATE_SCRIPTS = 4,
|
||||||
DUPLICATE_USE_INSTANCING = 8
|
DUPLICATE_USE_INSTANCING = 8,
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
DUPLICATE_FROM_EDITOR = 16,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RPCMode {
|
enum RPCMode {
|
||||||
|
@ -169,7 +172,7 @@ private:
|
||||||
|
|
||||||
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
|
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
|
||||||
void _duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const;
|
void _duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p_reown_map) const;
|
||||||
Node *_duplicate(int p_flags) const;
|
Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = NULL) const;
|
||||||
|
|
||||||
Array _get_children() const;
|
Array _get_children() const;
|
||||||
Array _get_groups() const;
|
Array _get_groups() const;
|
||||||
|
@ -326,6 +329,9 @@ public:
|
||||||
|
|
||||||
Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const;
|
Node *duplicate(int p_flags = DUPLICATE_GROUPS | DUPLICATE_SIGNALS | DUPLICATE_SCRIPTS) const;
|
||||||
Node *duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const;
|
Node *duplicate_and_reown(const Map<Node *, Node *> &p_reown_map) const;
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
Node *duplicate_from_editor(Map<const Node *, Node *> &r_duplimap) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
//Node *clone_tree() const;
|
//Node *clone_tree() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue