Duplicate Arrays and Dictionaries when instancing scene in editor

Also, add deep (=false) parameter to Array.duplicate and Dictionary.duplicate

Fixes #13971
This commit is contained in:
Bojidar Marinov 2018-03-09 21:16:08 +02:00
parent b842369442
commit 9f6c0c6eae
No known key found for this signature in database
GPG Key ID: 4D546A8F1E091856
11 changed files with 32 additions and 28 deletions

View File

@ -35,8 +35,8 @@
#include "variant.h"
#include "vector.h"
struct ArrayPrivate {
class ArrayPrivate {
public:
SafeRefCount refcount;
Vector<Variant> array;
};
@ -211,13 +211,13 @@ const Variant &Array::get(int p_idx) const {
return operator[](p_idx);
}
Array Array::duplicate() const {
Array Array::duplicate(bool p_deep) const {
Array new_arr;
int element_count = size();
new_arr.resize(element_count);
for (int i = 0; i < element_count; i++) {
new_arr[i] = get(i);
new_arr[i] = p_deep ? get(i).duplicate(p_deep) : get(i);
}
return new_arr;

View File

@ -88,7 +88,7 @@ public:
Variant pop_back();
Variant pop_front();
Array duplicate() const;
Array duplicate(bool p_deep = false) const;
Array(const Array &p_from);
Array();

View File

@ -211,7 +211,7 @@ const Variant *Dictionary::next(const Variant *p_key) const {
return NULL;
}
Dictionary Dictionary::duplicate() const {
Dictionary Dictionary::duplicate(bool p_deep) const {
Dictionary n;
@ -219,7 +219,7 @@ Dictionary Dictionary::duplicate() const {
get_key_list(&keys);
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
n[E->get()] = operator[](E->get());
n[E->get()] = p_deep ? operator[](E->get()).duplicate(p_deep) : operator[](E->get());
}
return n;

View File

@ -75,7 +75,7 @@ public:
Array keys() const;
Array values() const;
Dictionary duplicate() const;
Dictionary duplicate(bool p_deep = false) const;
Dictionary(const Dictionary &p_from);
Dictionary();

View File

@ -226,7 +226,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
continue;
Variant p = get(E->get().name);
Variant p = get(E->get().name).duplicate(true);
if (p.get_type() == Variant::OBJECT && p_subresources) {
RES sr = p;

View File

@ -338,6 +338,7 @@ public:
}
void zero();
Variant duplicate(bool deep = false) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);

View File

@ -465,7 +465,7 @@ struct _VariantCall {
VCALL_LOCALMEM0R(Dictionary, hash);
VCALL_LOCALMEM0R(Dictionary, keys);
VCALL_LOCALMEM0R(Dictionary, values);
VCALL_LOCALMEM0R(Dictionary, duplicate);
VCALL_LOCALMEM1R(Dictionary, duplicate);
VCALL_LOCALMEM2(Array, set);
VCALL_LOCALMEM1R(Array, get);
@ -494,7 +494,7 @@ struct _VariantCall {
VCALL_LOCALMEM0(Array, shuffle);
VCALL_LOCALMEM2R(Array, bsearch);
VCALL_LOCALMEM4R(Array, bsearch_custom);
VCALL_LOCALMEM0R(Array, duplicate);
VCALL_LOCALMEM1R(Array, duplicate);
VCALL_LOCALMEM0(Array, invert);
static void _call_PoolByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) {
@ -1613,7 +1613,7 @@ void register_variant_methods() {
ADDFUNC0R(DICTIONARY, INT, Dictionary, hash, varray());
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray());
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray());
ADDFUNC0R(DICTIONARY, DICTIONARY, Dictionary, duplicate, varray());
ADDFUNC1R(DICTIONARY, DICTIONARY, Dictionary, duplicate, BOOL, "deep", varray(false));
ADDFUNC0R(ARRAY, INT, Array, size, varray());
ADDFUNC0R(ARRAY, BOOL, Array, empty, varray());
@ -1641,7 +1641,7 @@ void register_variant_methods() {
ADDFUNC2R(ARRAY, INT, Array, bsearch, NIL, "value", BOOL, "before", varray(true));
ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true));
ADDFUNC0NC(ARRAY, NIL, Array, invert, varray());
ADDFUNC0RNC(ARRAY, ARRAY, Array, duplicate, varray());
ADDFUNC1R(ARRAY, ARRAY, Array, duplicate, BOOL, "deep", varray(false));
ADDFUNC0R(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray());

View File

@ -3415,6 +3415,19 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
return Variant();
}
Variant Variant::duplicate(bool deep) const {
switch (type) {
// case OBJECT:
// return operator Object *()->duplicate();
case DICTIONARY:
return operator Dictionary().duplicate(deep);
case ARRAY:
return operator Array().duplicate(deep);
default:
return *this;
}
}
void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
if (a.type != b.type) {
if (a.is_num() && b.is_num()) {

View File

@ -3939,7 +3939,7 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
if (_might_be_in_instance() && _get_instanced_node_original_property(prop, vorig)) {
_edit_set(prop, vorig);
_edit_set(prop, vorig.duplicate(true)); // Set, making sure to duplicate arrays properly
return;
}

View File

@ -2163,13 +2163,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
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).duplicate();
} else if (value.get_type() == Variant::ARRAY) {
value = Array(value).duplicate();
}
Variant value = N->get()->get(name).duplicate(true);
if (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) {
@ -2313,13 +2307,7 @@ void Node::_duplicate_and_reown(Node *p_new_parent, const Map<Node *, Node *> &p
continue;
String name = E->get().name;
Variant value = get(name);
// Duplicate dictionaries and arrays, mainly needed for __meta__
if (value.get_type() == Variant::DICTIONARY) {
value = Dictionary(value).duplicate();
} else if (value.get_type() == Variant::ARRAY) {
value = Array(value).duplicate();
}
Variant value = get(name).duplicate(true);
node->set(name, value);
}

View File

@ -249,6 +249,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
//must make a copy, because this res is local to scene
}
}
} else if (p_edit_state == GEN_EDIT_STATE_INSTANCE) {
value = value.duplicate(true); // Duplicate arrays and dictionaries for the editor
}
node->set(snames[nprops[j].name], value, &valid);
}