Merge pull request #12129 from willnationsdev/duplicate-fix

Node.duplicate(): instanced node's descendants' props = original's runtime values.
This commit is contained in:
Rémi Verschelde 2017-11-22 15:42:31 +01:00 committed by GitHub
commit 09153f1143
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

64
scene/main/node.cpp Executable file → Normal file
View file

@ -2104,37 +2104,59 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
ERR_FAIL_COND_V(!node, NULL);
}
List<PropertyInfo> plist;
get_property_list(&plist);
if (get_filename() != "") { //an instance
node->set_filename(get_filename());
}
StringName script_property_name = CoreStringNames::get_singleton()->_script;
if (p_flags & DUPLICATE_SCRIPTS) {
bool is_valid = false;
Variant script = get(script_property_name, &is_valid);
if (is_valid) {
node->set(script_property_name, script);
List<const Node *> node_tree;
node_tree.push_front(this);
if (instanced) {
for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
for (int i = 0; i < N->get()->get_child_count(); ++i) {
node_tree.push_back(N->get()->get_child(i));
}
}
}
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
continue;
String name = E->get().name;
if (name == script_property_name)
continue;
Node *current_node = node->get_node(get_path_to(N->get()));
Variant value = 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();
if (p_flags & DUPLICATE_SCRIPTS) {
bool is_valid = false;
Variant script = N->get()->get(script_property_name, &is_valid);
if (is_valid) {
current_node->set(script_property_name, script);
}
}
node->set(name, value);
List<PropertyInfo> plist;
N->get()->get_property_list(&plist);
if (!current_node)
continue;
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
continue;
String name = E->get().name;
if (name == script_property_name)
continue;
Variant value = N->get()->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();
}
current_node->set(name, value);
}
}
node->set_name(get_name());