mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
Merge pull request #100673 from RandomShaper/res_duplicate
Overhaul resource duplication
This commit is contained in:
commit
63dff62948
19 changed files with 951 additions and 140 deletions
|
|
@ -37,7 +37,6 @@
|
|||
#include "core/templates/vector.h"
|
||||
#include "core/variant/callable.h"
|
||||
#include "core/variant/dictionary.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
struct ArrayPrivate {
|
||||
SafeRefCount refcount;
|
||||
|
|
@ -518,10 +517,14 @@ const Variant &Array::get(int p_idx) const {
|
|||
}
|
||||
|
||||
Array Array::duplicate(bool p_deep) const {
|
||||
return recursive_duplicate(p_deep, 0);
|
||||
return recursive_duplicate(p_deep, RESOURCE_DEEP_DUPLICATE_NONE, 0);
|
||||
}
|
||||
|
||||
Array Array::recursive_duplicate(bool p_deep, int recursion_count) const {
|
||||
Array Array::duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode) const {
|
||||
return recursive_duplicate(true, p_deep_subresources_mode, 0);
|
||||
}
|
||||
|
||||
Array Array::recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const {
|
||||
Array new_arr;
|
||||
new_arr._p->typed = _p->typed;
|
||||
|
||||
|
|
@ -531,12 +534,19 @@ Array Array::recursive_duplicate(bool p_deep, int recursion_count) const {
|
|||
}
|
||||
|
||||
if (p_deep) {
|
||||
bool is_call_chain_end = recursion_count == 0;
|
||||
|
||||
recursion_count++;
|
||||
int element_count = size();
|
||||
new_arr.resize(element_count);
|
||||
Variant *write = new_arr._p->array.ptrw();
|
||||
for (int i = 0; i < element_count; i++) {
|
||||
write[i] = get(i).recursive_duplicate(true, recursion_count);
|
||||
write[i] = get(i).recursive_duplicate(true, p_deep_subresources_mode, recursion_count);
|
||||
}
|
||||
|
||||
// Variant::recursive_duplicate() may have created a remap cache by now.
|
||||
if (is_call_chain_end) {
|
||||
Resource::_teardown_duplicate_from_variant();
|
||||
}
|
||||
} else {
|
||||
new_arr._p->array = _p->array;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/typedefs.h"
|
||||
#include "core/variant/variant_deep_duplicate.h"
|
||||
|
||||
#include <climits>
|
||||
#include <initializer_list>
|
||||
|
|
@ -164,7 +165,8 @@ public:
|
|||
Variant pop_at(int p_pos);
|
||||
|
||||
Array duplicate(bool p_deep = false) const;
|
||||
Array recursive_duplicate(bool p_deep, int recursion_count) const;
|
||||
Array duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode = RESOURCE_DEEP_DUPLICATE_INTERNAL) const;
|
||||
Array recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const;
|
||||
|
||||
Array slice(int p_begin, int p_end = INT_MAX, int p_step = 1, bool p_deep = false) const;
|
||||
Array filter(const Callable &p_callable) const;
|
||||
|
|
|
|||
|
|
@ -569,7 +569,11 @@ const Variant *Dictionary::next(const Variant *p_key) const {
|
|||
}
|
||||
|
||||
Dictionary Dictionary::duplicate(bool p_deep) const {
|
||||
return recursive_duplicate(p_deep, 0);
|
||||
return recursive_duplicate(p_deep, RESOURCE_DEEP_DUPLICATE_NONE, 0);
|
||||
}
|
||||
|
||||
Dictionary Dictionary::duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode) const {
|
||||
return recursive_duplicate(true, p_deep_subresources_mode, 0);
|
||||
}
|
||||
|
||||
void Dictionary::make_read_only() {
|
||||
|
|
@ -581,7 +585,7 @@ bool Dictionary::is_read_only() const {
|
|||
return _p->read_only != nullptr;
|
||||
}
|
||||
|
||||
Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) const {
|
||||
Dictionary Dictionary::recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const {
|
||||
Dictionary n;
|
||||
n._p->typed_key = _p->typed_key;
|
||||
n._p->typed_value = _p->typed_value;
|
||||
|
|
@ -592,9 +596,16 @@ Dictionary Dictionary::recursive_duplicate(bool p_deep, int recursion_count) con
|
|||
}
|
||||
|
||||
if (p_deep) {
|
||||
bool is_call_chain_end = recursion_count == 0;
|
||||
|
||||
recursion_count++;
|
||||
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
|
||||
n[E.key.recursive_duplicate(true, recursion_count)] = E.value.recursive_duplicate(true, recursion_count);
|
||||
n[E.key.recursive_duplicate(true, p_deep_subresources_mode, recursion_count)] = E.value.recursive_duplicate(true, p_deep_subresources_mode, recursion_count);
|
||||
}
|
||||
|
||||
// Variant::recursive_duplicate() may have created a remap cache by now.
|
||||
if (is_call_chain_end) {
|
||||
Resource::_teardown_duplicate_from_variant();
|
||||
}
|
||||
} else {
|
||||
for (const KeyValue<Variant, Variant> &E : _p->variant_map) {
|
||||
|
|
@ -643,6 +654,10 @@ bool Dictionary::is_typed_value() const {
|
|||
return _p->typed_value.type != Variant::NIL;
|
||||
}
|
||||
|
||||
bool Dictionary::is_same_instance(const Dictionary &p_other) const {
|
||||
return _p == p_other._p;
|
||||
}
|
||||
|
||||
bool Dictionary::is_same_typed(const Dictionary &p_other) const {
|
||||
return is_same_typed_key(p_other) && is_same_typed_value(p_other);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/pair.h"
|
||||
#include "core/variant/array.h"
|
||||
#include "core/variant/variant_deep_duplicate.h"
|
||||
|
||||
class Variant;
|
||||
|
||||
|
|
@ -98,7 +99,8 @@ public:
|
|||
Array values() const;
|
||||
|
||||
Dictionary duplicate(bool p_deep = false) const;
|
||||
Dictionary recursive_duplicate(bool p_deep, int recursion_count) const;
|
||||
Dictionary duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode = RESOURCE_DEEP_DUPLICATE_INTERNAL) const;
|
||||
Dictionary recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const;
|
||||
|
||||
void set_typed(const ContainerType &p_key_type, const ContainerType &p_value_type);
|
||||
void set_typed(uint32_t p_key_type, const StringName &p_key_class_name, const Variant &p_key_script, uint32_t p_value_type, const StringName &p_value_class_name, const Variant &p_value_script);
|
||||
|
|
@ -106,6 +108,7 @@ public:
|
|||
bool is_typed() const;
|
||||
bool is_typed_key() const;
|
||||
bool is_typed_value() const;
|
||||
bool is_same_instance(const Dictionary &p_other) const;
|
||||
bool is_same_typed(const Dictionary &p_other) const;
|
||||
bool is_same_typed_key(const Dictionary &p_other) const;
|
||||
bool is_same_typed_value(const Dictionary &p_other) const;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "core/variant/array.h"
|
||||
#include "core/variant/callable.h"
|
||||
#include "core/variant/dictionary.h"
|
||||
#include "core/variant/variant_deep_duplicate.h"
|
||||
|
||||
class Object;
|
||||
class RefCounted;
|
||||
|
|
@ -612,7 +613,8 @@ public:
|
|||
|
||||
void zero();
|
||||
Variant duplicate(bool p_deep = false) const;
|
||||
Variant recursive_duplicate(bool p_deep, int recursion_count) const;
|
||||
Variant duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode = RESOURCE_DEEP_DUPLICATE_INTERNAL) const;
|
||||
Variant recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const;
|
||||
|
||||
/* Built-In Methods */
|
||||
|
||||
|
|
|
|||
|
|
@ -2408,6 +2408,7 @@ static void _register_variant_builtin_methods_misc() {
|
|||
bind_method(Dictionary, keys, sarray(), varray());
|
||||
bind_method(Dictionary, values, sarray(), varray());
|
||||
bind_method(Dictionary, duplicate, sarray("deep"), varray(false));
|
||||
bind_method(Dictionary, duplicate_deep, sarray("deep_subresources_mode"), varray(RESOURCE_DEEP_DUPLICATE_INTERNAL));
|
||||
bind_method(Dictionary, get, sarray("key", "default"), varray(Variant()));
|
||||
bind_method(Dictionary, get_or_add, sarray("key", "default"), varray(Variant()));
|
||||
bind_method(Dictionary, set, sarray("key", "value"), varray());
|
||||
|
|
@ -2466,6 +2467,7 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_method(Array, bsearch_custom, sarray("value", "func", "before"), varray(true));
|
||||
bind_method(Array, reverse, sarray(), varray());
|
||||
bind_method(Array, duplicate, sarray("deep"), varray(false));
|
||||
bind_method(Array, duplicate_deep, sarray("deep_subresources_mode"), varray(RESOURCE_DEEP_DUPLICATE_INTERNAL));
|
||||
bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(INT_MAX, 1, false));
|
||||
bind_method(Array, filter, sarray("method"), varray());
|
||||
bind_method(Array, map, sarray("method"), varray());
|
||||
|
|
|
|||
41
core/variant/variant_deep_duplicate.h
Normal file
41
core/variant/variant_deep_duplicate.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/**************************************************************************/
|
||||
/* variant_deep_duplicate.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
// This would be ideally declared nested in Variant, but that would cause circular
|
||||
// includes with Array and Dictionary, for instance.
|
||||
// Also, this enum is be exposed via Resource.
|
||||
enum ResourceDeepDuplicateMode {
|
||||
RESOURCE_DEEP_DUPLICATE_NONE,
|
||||
RESOURCE_DEEP_DUPLICATE_INTERNAL,
|
||||
RESOURCE_DEEP_DUPLICATE_ALL,
|
||||
RESOURCE_DEEP_DUPLICATE_MAX
|
||||
};
|
||||
|
|
@ -29,9 +29,10 @@
|
|||
/**************************************************************************/
|
||||
|
||||
#include "variant_setget.h"
|
||||
|
||||
#include "variant_callable.h"
|
||||
|
||||
#include "core/io/resource.h"
|
||||
|
||||
struct VariantSetterGetterInfo {
|
||||
void (*setter)(Variant *base, const Variant *value, bool &valid);
|
||||
void (*getter)(const Variant *base, Variant *value);
|
||||
|
|
@ -1969,26 +1970,33 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
|
|||
}
|
||||
|
||||
Variant Variant::duplicate(bool p_deep) const {
|
||||
return recursive_duplicate(p_deep, 0);
|
||||
return recursive_duplicate(p_deep, RESOURCE_DEEP_DUPLICATE_NONE, 0);
|
||||
}
|
||||
|
||||
Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
|
||||
Variant Variant::duplicate_deep(ResourceDeepDuplicateMode p_deep_subresources_mode) const {
|
||||
ERR_FAIL_INDEX_V(p_deep_subresources_mode, RESOURCE_DEEP_DUPLICATE_MAX, Variant());
|
||||
return recursive_duplicate(true, p_deep_subresources_mode, 0);
|
||||
}
|
||||
|
||||
Variant Variant::recursive_duplicate(bool p_deep, ResourceDeepDuplicateMode p_deep_subresources_mode, int recursion_count) const {
|
||||
switch (type) {
|
||||
case OBJECT: {
|
||||
/* breaks stuff :(
|
||||
if (p_deep && !_get_obj().ref.is_null()) {
|
||||
Ref<Resource> resource = _get_obj().ref;
|
||||
if (resource.is_valid()) {
|
||||
return resource->duplicate(true);
|
||||
}
|
||||
// If the root target of duplicate() is a Resource, we can't early-reject because that
|
||||
// resource itself must be duplicated, much as if Resource::duplicate() had been called.
|
||||
if (p_deep_subresources_mode == RESOURCE_DEEP_DUPLICATE_NONE && recursion_count > 0) {
|
||||
return *this;
|
||||
}
|
||||
Resource *res = Object::cast_to<Resource>(_get_obj().obj);
|
||||
if (res) {
|
||||
return res->_duplicate_from_variant(p_deep, p_deep_subresources_mode, recursion_count);
|
||||
} else {
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
return *this;
|
||||
} break;
|
||||
case DICTIONARY:
|
||||
return operator Dictionary().recursive_duplicate(p_deep, recursion_count);
|
||||
return operator Dictionary().recursive_duplicate(p_deep, p_deep_subresources_mode, recursion_count);
|
||||
case ARRAY:
|
||||
return operator Array().recursive_duplicate(p_deep, recursion_count);
|
||||
return operator Array().recursive_duplicate(p_deep, p_deep_subresources_mode, recursion_count);
|
||||
case PACKED_BYTE_ARRAY:
|
||||
return operator Vector<uint8_t>().duplicate();
|
||||
case PACKED_INT32_ARRAY:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue