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

View file

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

View file

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

View file

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

View file

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

View file

@ -338,6 +338,7 @@ public:
} }
void zero(); void zero();
Variant duplicate(bool deep = false) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst); 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); 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, hash);
VCALL_LOCALMEM0R(Dictionary, keys); VCALL_LOCALMEM0R(Dictionary, keys);
VCALL_LOCALMEM0R(Dictionary, values); VCALL_LOCALMEM0R(Dictionary, values);
VCALL_LOCALMEM0R(Dictionary, duplicate); VCALL_LOCALMEM1R(Dictionary, duplicate);
VCALL_LOCALMEM2(Array, set); VCALL_LOCALMEM2(Array, set);
VCALL_LOCALMEM1R(Array, get); VCALL_LOCALMEM1R(Array, get);
@ -494,7 +494,7 @@ struct _VariantCall {
VCALL_LOCALMEM0(Array, shuffle); VCALL_LOCALMEM0(Array, shuffle);
VCALL_LOCALMEM2R(Array, bsearch); VCALL_LOCALMEM2R(Array, bsearch);
VCALL_LOCALMEM4R(Array, bsearch_custom); VCALL_LOCALMEM4R(Array, bsearch_custom);
VCALL_LOCALMEM0R(Array, duplicate); VCALL_LOCALMEM1R(Array, duplicate);
VCALL_LOCALMEM0(Array, invert); VCALL_LOCALMEM0(Array, invert);
static void _call_PoolByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { 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, INT, Dictionary, hash, varray());
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray()); ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray());
ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, 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, INT, Array, size, varray());
ADDFUNC0R(ARRAY, BOOL, Array, empty, 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)); 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)); ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true));
ADDFUNC0NC(ARRAY, NIL, Array, invert, varray()); 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()); ADDFUNC0R(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", 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(); 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) { void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
if (a.type != b.type) { if (a.type != b.type) {
if (a.is_num() && b.is_num()) { 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)) { 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; 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) if (name == script_property_name)
continue; continue;
Variant value = N->get()->get(name); Variant value = N->get()->get(name).duplicate(true);
// 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();
}
if (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) { 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; continue;
String name = E->get().name; String name = E->get().name;
Variant value = get(name); Variant value = get(name).duplicate(true);
// 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();
}
node->set(name, value); 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 //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); node->set(snames[nprops[j].name], value, &valid);
} }