mirror of https://github.com/godotengine/godot
Changed logic and optimized ObjectID in ObjectDB and Variant, removed RefPtr.
This commit is contained in:
parent
53cf289f30
commit
867d073b98
|
|
@ -802,10 +802,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Variant::OBJECT: {
|
case Variant::OBJECT: {
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
// Test for potential wrong values sent by the debugger when it breaks.
|
// Test for potential wrong values sent by the debugger when it breaks.
|
||||||
Object *obj = p_variant;
|
Object *obj = p_variant.get_validated_object();
|
||||||
if (!obj || !ObjectDB::instance_validate(obj)) {
|
if (!obj) {
|
||||||
// Object is invalid, send a NULL instead.
|
// Object is invalid, send a NULL instead.
|
||||||
if (buf) {
|
if (buf) {
|
||||||
encode_uint32(Variant::NIL, buf);
|
encode_uint32(Variant::NIL, buf);
|
||||||
|
|
@ -813,7 +813,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
||||||
r_len += 4;
|
r_len += 4;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
#endif // DEBUG_ENABLED
|
|
||||||
if (!p_full_objects) {
|
if (!p_full_objects) {
|
||||||
flags |= ENCODE_FLAG_OBJECT_AS_ID;
|
flags |= ENCODE_FLAG_OBJECT_AS_ID;
|
||||||
}
|
}
|
||||||
|
|
@ -1127,9 +1127,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
|
||||||
} else {
|
} else {
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
|
||||||
Object *obj = p_variant;
|
Object *obj = p_variant.get_validated_object();
|
||||||
ObjectID id;
|
ObjectID id;
|
||||||
if (obj && ObjectDB::instance_validate(obj)) {
|
if (obj) {
|
||||||
id = obj->get_instance_id();
|
id = obj->get_instance_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1573,7 +1573,7 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
|
||||||
switch (p_variant.get_type()) {
|
switch (p_variant.get_type()) {
|
||||||
case Variant::OBJECT: {
|
case Variant::OBJECT: {
|
||||||
|
|
||||||
RES res = p_variant.operator RefPtr();
|
RES res = p_variant;
|
||||||
|
|
||||||
if (res.is_null() || external_resources.has(res))
|
if (res.is_null() || external_resources.has(res))
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -955,7 +955,7 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
|
||||||
ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + ".");
|
ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + ".");
|
||||||
|
|
||||||
ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj);
|
ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj);
|
||||||
crl->set_script(s.get_ref_ptr());
|
crl->set_script(s);
|
||||||
ResourceLoader::add_resource_format_loader(crl);
|
ResourceLoader::add_resource_format_loader(crl);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
|
||||||
ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + ".");
|
ERR_FAIL_COND_V_MSG(obj == NULL, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + ".");
|
||||||
|
|
||||||
ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj);
|
ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj);
|
||||||
crl->set_script(s.get_ref_ptr());
|
crl->set_script(s);
|
||||||
ResourceSaver::add_resource_format_saver(crl);
|
ResourceSaver::add_resource_format_saver(crl);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
197
core/object.cpp
197
core/object.cpp
|
|
@ -968,7 +968,7 @@ void Object::cancel_delete() {
|
||||||
_predelete_ok = true;
|
_predelete_ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance) {
|
void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) {
|
||||||
|
|
||||||
//this function is not meant to be used in any of these ways
|
//this function is not meant to be used in any of these ways
|
||||||
ERR_FAIL_COND(p_script.is_null());
|
ERR_FAIL_COND(p_script.is_null());
|
||||||
|
|
@ -979,7 +979,7 @@ void Object::set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_i
|
||||||
script_instance = p_instance;
|
script_instance = p_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::set_script(const RefPtr &p_script) {
|
void Object::set_script(const Variant &p_script) {
|
||||||
|
|
||||||
if (script == p_script)
|
if (script == p_script)
|
||||||
return;
|
return;
|
||||||
|
|
@ -990,7 +990,7 @@ void Object::set_script(const RefPtr &p_script) {
|
||||||
}
|
}
|
||||||
|
|
||||||
script = p_script;
|
script = p_script;
|
||||||
Ref<Script> s(script);
|
Ref<Script> s = script;
|
||||||
|
|
||||||
if (!s.is_null()) {
|
if (!s.is_null()) {
|
||||||
if (s->can_instance()) {
|
if (s->can_instance()) {
|
||||||
|
|
@ -1017,12 +1017,12 @@ void Object::set_script_instance(ScriptInstance *p_instance) {
|
||||||
script_instance = p_instance;
|
script_instance = p_instance;
|
||||||
|
|
||||||
if (p_instance)
|
if (p_instance)
|
||||||
script = p_instance->get_script().get_ref_ptr();
|
script = p_instance->get_script();
|
||||||
else
|
else
|
||||||
script = RefPtr();
|
script = Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr Object::get_script() const {
|
Variant Object::get_script() const {
|
||||||
|
|
||||||
return script;
|
return script;
|
||||||
}
|
}
|
||||||
|
|
@ -1911,8 +1911,8 @@ void Object::set_script_instance_binding(int p_script_language_index, void *p_da
|
||||||
_script_instance_bindings[p_script_language_index] = p_data;
|
_script_instance_bindings[p_script_language_index] = p_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::Object() {
|
void Object::_construct_object(bool p_reference) {
|
||||||
|
type_is_reference = p_reference;
|
||||||
_class_ptr = NULL;
|
_class_ptr = NULL;
|
||||||
_block_signals = false;
|
_block_signals = false;
|
||||||
_predelete_ok = 0;
|
_predelete_ok = 0;
|
||||||
|
|
@ -1933,6 +1933,14 @@ Object::Object() {
|
||||||
_lock_index.init(1);
|
_lock_index.init(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Object::Object(bool p_reference) {
|
||||||
|
_construct_object(p_reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object::Object() {
|
||||||
|
|
||||||
|
_construct_object(false);
|
||||||
|
}
|
||||||
|
|
||||||
Object::~Object() {
|
Object::~Object() {
|
||||||
|
|
||||||
|
|
@ -1993,96 +2001,139 @@ void postinitialize_handler(Object *p_object) {
|
||||||
p_object->_postinitialize();
|
p_object->_postinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
HashMap<ObjectID, Object *> ObjectDB::instances;
|
|
||||||
uint64_t ObjectDB::instance_counter = 1;
|
|
||||||
HashMap<Object *, ObjectID, ObjectDB::ObjectPtrHash> ObjectDB::instance_checks;
|
|
||||||
ObjectID ObjectDB::add_instance(Object *p_object) {
|
|
||||||
|
|
||||||
ERR_FAIL_COND_V(p_object->get_instance_id().is_valid(), ObjectID());
|
|
||||||
|
|
||||||
rw_lock->write_lock();
|
|
||||||
ObjectID instance_id = ObjectID(++instance_counter);
|
|
||||||
instances[instance_id] = p_object;
|
|
||||||
instance_checks[p_object] = instance_id;
|
|
||||||
|
|
||||||
rw_lock->write_unlock();
|
|
||||||
|
|
||||||
return instance_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectDB::remove_instance(Object *p_object) {
|
|
||||||
|
|
||||||
rw_lock->write_lock();
|
|
||||||
|
|
||||||
instances.erase(p_object->get_instance_id());
|
|
||||||
instance_checks.erase(p_object);
|
|
||||||
|
|
||||||
rw_lock->write_unlock();
|
|
||||||
}
|
|
||||||
Object *ObjectDB::get_instance(ObjectID p_instance_id) {
|
|
||||||
|
|
||||||
rw_lock->read_lock();
|
|
||||||
Object **obj = instances.getptr(p_instance_id);
|
|
||||||
rw_lock->read_unlock();
|
|
||||||
|
|
||||||
if (!obj)
|
|
||||||
return NULL;
|
|
||||||
return *obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectDB::debug_objects(DebugFunc p_func) {
|
void ObjectDB::debug_objects(DebugFunc p_func) {
|
||||||
|
|
||||||
rw_lock->read_lock();
|
spin_lock.lock();
|
||||||
|
for (uint32_t i = 0; i < slot_count; i++) {
|
||||||
const ObjectID *K = NULL;
|
uint32_t slot = object_slots[i].next_free;
|
||||||
while ((K = instances.next(K))) {
|
p_func(object_slots[slot].object);
|
||||||
|
|
||||||
p_func(instances[*K]);
|
|
||||||
}
|
}
|
||||||
|
spin_lock.unlock();
|
||||||
rw_lock->read_unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
|
void Object::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpinLock ObjectDB::spin_lock;
|
||||||
|
uint32_t ObjectDB::slot_count = 0;
|
||||||
|
uint32_t ObjectDB::slot_max = 0;
|
||||||
|
ObjectDB::ObjectSlot *ObjectDB::object_slots = nullptr;
|
||||||
|
uint64_t ObjectDB::validator_counter = 0;
|
||||||
|
|
||||||
int ObjectDB::get_object_count() {
|
int ObjectDB::get_object_count() {
|
||||||
|
|
||||||
rw_lock->read_lock();
|
return slot_count;
|
||||||
int count = instances.size();
|
|
||||||
rw_lock->read_unlock();
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RWLock *ObjectDB::rw_lock = NULL;
|
ObjectID ObjectDB::add_instance(Object *p_object) {
|
||||||
|
|
||||||
|
spin_lock.lock();
|
||||||
|
if (unlikely(slot_count == slot_max)) {
|
||||||
|
|
||||||
|
CRASH_COND(slot_count == (1 << OBJECTDB_SLOT_MAX_COUNT_BITS));
|
||||||
|
|
||||||
|
uint32_t new_slot_max = slot_max > 0 ? slot_max * 2 : 1;
|
||||||
|
object_slots = (ObjectSlot *)memrealloc(object_slots, sizeof(ObjectSlot) * new_slot_max);
|
||||||
|
for (uint32_t i = slot_max; i < new_slot_max; i++) {
|
||||||
|
object_slots[i].object = nullptr;
|
||||||
|
object_slots[i].is_reference = false;
|
||||||
|
object_slots[i].next_free = i;
|
||||||
|
object_slots[i].validator = 0;
|
||||||
|
}
|
||||||
|
slot_max = new_slot_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t slot = object_slots[slot_count].next_free;
|
||||||
|
if (object_slots[slot].object != nullptr) {
|
||||||
|
spin_lock.unlock();
|
||||||
|
ERR_FAIL_COND_V(object_slots[slot].object != nullptr, ObjectID());
|
||||||
|
}
|
||||||
|
object_slots[slot].object = p_object;
|
||||||
|
object_slots[slot].is_reference = p_object->is_reference();
|
||||||
|
validator_counter = (validator_counter + 1) & OBJECTDB_VALIDATOR_MASK;
|
||||||
|
if (unlikely(validator_counter == 0)) {
|
||||||
|
validator_counter = 1;
|
||||||
|
}
|
||||||
|
object_slots[slot].validator = validator_counter;
|
||||||
|
|
||||||
|
uint64_t id = validator_counter;
|
||||||
|
id <<= OBJECTDB_SLOT_MAX_COUNT_BITS;
|
||||||
|
id |= uint64_t(slot);
|
||||||
|
|
||||||
|
if (p_object->is_reference()) {
|
||||||
|
id |= OBJECTDB_REFERENCE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_count++;
|
||||||
|
|
||||||
|
spin_lock.unlock();
|
||||||
|
|
||||||
|
return ObjectID(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectDB::remove_instance(Object *p_object) {
|
||||||
|
uint64_t t = p_object->get_instance_id();
|
||||||
|
uint32_t slot = t & OBJECTDB_SLOT_MAX_COUNT_MASK; //slot is always valid on valid object
|
||||||
|
|
||||||
|
spin_lock.lock();
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
|
if (object_slots[slot].object != p_object) {
|
||||||
|
spin_lock.unlock();
|
||||||
|
ERR_FAIL_COND(object_slots[slot].object != p_object);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uint64_t validator = (t >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
|
||||||
|
if (object_slots[slot].validator != validator) {
|
||||||
|
spin_lock.unlock();
|
||||||
|
ERR_FAIL_COND(object_slots[slot].validator != validator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//decrease slot count
|
||||||
|
slot_count--;
|
||||||
|
//set the free slot properly
|
||||||
|
object_slots[slot_count].next_free = slot;
|
||||||
|
//invalidate, so checks against it fail
|
||||||
|
object_slots[slot].validator = 0;
|
||||||
|
object_slots[slot].is_reference = false;
|
||||||
|
object_slots[slot].object = nullptr;
|
||||||
|
|
||||||
|
spin_lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectDB::setup() {
|
void ObjectDB::setup() {
|
||||||
|
|
||||||
rw_lock = RWLock::create();
|
//nothing to do now
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectDB::cleanup() {
|
void ObjectDB::cleanup() {
|
||||||
|
|
||||||
rw_lock->write_lock();
|
if (slot_count > 0) {
|
||||||
if (instances.size()) {
|
spin_lock.lock();
|
||||||
|
|
||||||
WARN_PRINT("ObjectDB Instances still exist!");
|
WARN_PRINT("ObjectDB Instances still exist!");
|
||||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||||
const ObjectID *K = NULL;
|
for (uint32_t i = 0; i < slot_count; i++) {
|
||||||
while ((K = instances.next(K))) {
|
uint32_t slot = object_slots[i].next_free;
|
||||||
|
Object *obj = object_slots[slot].object;
|
||||||
|
|
||||||
String node_name;
|
String node_name;
|
||||||
if (instances[*K]->is_class("Node"))
|
if (obj->is_class("Node"))
|
||||||
node_name = " - Node name: " + String(instances[*K]->call("get_name"));
|
node_name = " - Node name: " + String(obj->call("get_name"));
|
||||||
if (instances[*K]->is_class("Resource"))
|
if (obj->is_class("Resource"))
|
||||||
node_name = " - Resource name: " + String(instances[*K]->call("get_name")) + " Path: " + String(instances[*K]->call("get_path"));
|
node_name = " - Resource name: " + String(obj->call("get_name")) + " Path: " + String(obj->call("get_path"));
|
||||||
print_line("Leaked instance: " + String(instances[*K]->get_class()) + ":" + itos(*K) + node_name);
|
|
||||||
|
uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0);
|
||||||
|
print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + node_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spin_lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object_slots) {
|
||||||
|
memfree(object_slots);
|
||||||
}
|
}
|
||||||
instances.clear();
|
|
||||||
instance_checks.clear();
|
|
||||||
rw_lock->write_unlock();
|
|
||||||
memdelete(rw_lock);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include "core/object_id.h"
|
#include "core/object_id.h"
|
||||||
#include "core/os/rw_lock.h"
|
#include "core/os/rw_lock.h"
|
||||||
#include "core/set.h"
|
#include "core/set.h"
|
||||||
|
#include "core/spin_lock.h"
|
||||||
#include "core/variant.h"
|
#include "core/variant.h"
|
||||||
#include "core/vmap.h"
|
#include "core/vmap.h"
|
||||||
|
|
||||||
|
|
@ -488,7 +489,7 @@ private:
|
||||||
Set<String> editor_section_folding;
|
Set<String> editor_section_folding;
|
||||||
#endif
|
#endif
|
||||||
ScriptInstance *script_instance;
|
ScriptInstance *script_instance;
|
||||||
RefPtr script;
|
Variant script; //reference does not yet exist, store it in a
|
||||||
Dictionary metadata;
|
Dictionary metadata;
|
||||||
mutable StringName _class_name;
|
mutable StringName _class_name;
|
||||||
mutable const StringName *_class_ptr;
|
mutable const StringName *_class_ptr;
|
||||||
|
|
@ -506,9 +507,13 @@ private:
|
||||||
|
|
||||||
void property_list_changed_notify();
|
void property_list_changed_notify();
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void _construct_object(bool p_reference);
|
||||||
|
|
||||||
friend class Reference;
|
friend class Reference;
|
||||||
|
bool type_is_reference = false;
|
||||||
uint32_t instance_binding_count;
|
uint32_t instance_binding_count;
|
||||||
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
|
void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
|
||||||
|
Object(bool p_reference);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _initialize_classv() { initialize_class(); }
|
virtual void _initialize_classv() { initialize_class(); }
|
||||||
|
|
@ -680,8 +685,8 @@ public:
|
||||||
|
|
||||||
/* SCRIPT */
|
/* SCRIPT */
|
||||||
|
|
||||||
void set_script(const RefPtr &p_script);
|
void set_script(const Variant &p_script);
|
||||||
RefPtr get_script() const;
|
Variant get_script() const;
|
||||||
|
|
||||||
/* SCRIPT */
|
/* SCRIPT */
|
||||||
|
|
||||||
|
|
@ -700,7 +705,7 @@ public:
|
||||||
void set_script_instance(ScriptInstance *p_instance);
|
void set_script_instance(ScriptInstance *p_instance);
|
||||||
_FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; }
|
_FORCE_INLINE_ ScriptInstance *get_script_instance() const { return script_instance; }
|
||||||
|
|
||||||
void set_script_and_instance(const RefPtr &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
|
void set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance); //some script languages can't control instance creation, so this function eases the process
|
||||||
|
|
||||||
void add_user_signal(const MethodInfo &p_signal);
|
void add_user_signal(const MethodInfo &p_signal);
|
||||||
Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
|
Error emit_signal(const StringName &p_name, VARIANT_ARG_LIST);
|
||||||
|
|
@ -751,6 +756,7 @@ public:
|
||||||
|
|
||||||
void clear_internal_resource_paths();
|
void clear_internal_resource_paths();
|
||||||
|
|
||||||
|
_ALWAYS_INLINE_ bool is_reference() const { return type_is_reference; }
|
||||||
Object();
|
Object();
|
||||||
virtual ~Object();
|
virtual ~Object();
|
||||||
};
|
};
|
||||||
|
|
@ -760,49 +766,63 @@ void postinitialize_handler(Object *p_object);
|
||||||
|
|
||||||
class ObjectDB {
|
class ObjectDB {
|
||||||
|
|
||||||
struct ObjectPtrHash {
|
//this needs to add up to 63, 1 bit is for reference
|
||||||
|
#define OBJECTDB_VALIDATOR_BITS 39
|
||||||
|
#define OBJECTDB_VALIDATOR_MASK ((uint64_t(1) << OBJECTDB_VALIDATOR_BITS) - 1)
|
||||||
|
#define OBJECTDB_SLOT_MAX_COUNT_BITS 24
|
||||||
|
#define OBJECTDB_SLOT_MAX_COUNT_MASK ((uint64_t(1) << OBJECTDB_SLOT_MAX_COUNT_BITS) - 1)
|
||||||
|
#define OBJECTDB_REFERENCE_BIT (uint64_t(1) << (OBJECTDB_SLOT_MAX_COUNT_BITS + OBJECTDB_VALIDATOR_BITS))
|
||||||
|
|
||||||
static _FORCE_INLINE_ uint32_t hash(const Object *p_obj) {
|
struct ObjectSlot { //128 bits per slot
|
||||||
|
uint64_t validator : OBJECTDB_VALIDATOR_BITS;
|
||||||
union {
|
uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS;
|
||||||
const Object *p;
|
uint64_t is_reference : 1;
|
||||||
unsigned long i;
|
Object *object;
|
||||||
} u;
|
|
||||||
u.p = p_obj;
|
|
||||||
return HashMapHasherDefault::hash((uint64_t)u.i);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static HashMap<ObjectID, Object *> instances;
|
static SpinLock spin_lock;
|
||||||
static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
|
static uint32_t slot_count;
|
||||||
|
static uint32_t slot_max;
|
||||||
|
static ObjectSlot *object_slots;
|
||||||
|
static uint64_t validator_counter;
|
||||||
|
|
||||||
static uint64_t instance_counter;
|
|
||||||
friend class Object;
|
friend class Object;
|
||||||
friend void unregister_core_types();
|
friend void unregister_core_types();
|
||||||
|
|
||||||
static RWLock *rw_lock;
|
|
||||||
static void cleanup();
|
static void cleanup();
|
||||||
|
|
||||||
static ObjectID add_instance(Object *p_object);
|
static ObjectID add_instance(Object *p_object);
|
||||||
static void remove_instance(Object *p_object);
|
static void remove_instance(Object *p_object);
|
||||||
|
|
||||||
friend void register_core_types();
|
friend void register_core_types();
|
||||||
static void setup();
|
static void setup();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef void (*DebugFunc)(Object *p_obj);
|
typedef void (*DebugFunc)(Object *p_obj);
|
||||||
|
|
||||||
static Object *get_instance(ObjectID p_instance_id);
|
_ALWAYS_INLINE_ static Object *get_instance(ObjectID p_instance_id) {
|
||||||
|
|
||||||
|
uint64_t id = p_instance_id;
|
||||||
|
uint32_t slot = id & OBJECTDB_SLOT_MAX_COUNT_MASK;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(slot >= slot_max, nullptr); //this should never happen unless RID is corrupted
|
||||||
|
|
||||||
|
spin_lock.lock();
|
||||||
|
|
||||||
|
uint64_t validator = (id >> OBJECTDB_SLOT_MAX_COUNT_BITS) & OBJECTDB_VALIDATOR_MASK;
|
||||||
|
|
||||||
|
if (unlikely(object_slots[slot].validator != validator)) {
|
||||||
|
spin_lock.unlock();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *object = object_slots[slot].object;
|
||||||
|
|
||||||
|
spin_lock.unlock();
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
static void debug_objects(DebugFunc p_func);
|
static void debug_objects(DebugFunc p_func);
|
||||||
static int get_object_count();
|
static int get_object_count();
|
||||||
|
|
||||||
_FORCE_INLINE_ static bool instance_validate(Object *p_ptr) {
|
|
||||||
rw_lock->read_lock();
|
|
||||||
|
|
||||||
bool exists = instance_checks.has(p_ptr);
|
|
||||||
|
|
||||||
rw_lock->read_unlock();
|
|
||||||
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//needed by macros
|
//needed by macros
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ class ObjectID {
|
||||||
uint64_t id = 0;
|
uint64_t id = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
_ALWAYS_INLINE_ bool is_reference() const { return (id & (uint64_t(1) << 63)) != 0; }
|
||||||
_ALWAYS_INLINE_ bool is_valid() const { return id != 0; }
|
_ALWAYS_INLINE_ bool is_valid() const { return id != 0; }
|
||||||
_ALWAYS_INLINE_ bool is_null() const { return id == 0; }
|
_ALWAYS_INLINE_ bool is_null() const { return id == 0; }
|
||||||
_ALWAYS_INLINE_ operator uint64_t() const { return id; }
|
_ALWAYS_INLINE_ operator uint64_t() const { return id; }
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ void MainLoop::input_event(const Ref<InputEvent> &p_event) {
|
||||||
void MainLoop::init() {
|
void MainLoop::init() {
|
||||||
|
|
||||||
if (init_script.is_valid())
|
if (init_script.is_valid())
|
||||||
set_script(init_script.get_ref_ptr());
|
set_script(init_script);
|
||||||
|
|
||||||
if (get_script_instance())
|
if (get_script_instance())
|
||||||
get_script_instance()->call("_initialize");
|
get_script_instance()->call("_initialize");
|
||||||
|
|
@ -131,6 +131,6 @@ void MainLoop::finish() {
|
||||||
|
|
||||||
if (get_script_instance()) {
|
if (get_script_instance()) {
|
||||||
get_script_instance()->call("_finalize");
|
get_script_instance()->call("_finalize");
|
||||||
set_script(RefPtr()); //clear script
|
set_script(Variant()); //clear script
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
core/ref_ptr.cpp
103
core/ref_ptr.cpp
|
|
@ -1,103 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* ref_ptr.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* 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. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#include "ref_ptr.h"
|
|
||||||
|
|
||||||
#include "core/reference.h"
|
|
||||||
#include "core/resource.h"
|
|
||||||
|
|
||||||
void RefPtr::operator=(const RefPtr &p_other) {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
|
|
||||||
|
|
||||||
*ref = *ref_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RefPtr::operator==(const RefPtr &p_other) const {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
|
|
||||||
|
|
||||||
return *ref == *ref_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RefPtr::operator!=(const RefPtr &p_other) const {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
|
|
||||||
|
|
||||||
return *ref != *ref_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr::RefPtr(const RefPtr &p_other) {
|
|
||||||
|
|
||||||
memnew_placement(&data[0], Ref<Reference>);
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
Ref<Reference> *ref_other = reinterpret_cast<Ref<Reference> *>(const_cast<char *>(&p_other.data[0]));
|
|
||||||
|
|
||||||
*ref = *ref_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RefPtr::is_null() const {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
return ref->is_null();
|
|
||||||
}
|
|
||||||
|
|
||||||
RID RefPtr::get_rid() const {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
if (ref->is_null())
|
|
||||||
return RID();
|
|
||||||
Resource *res = Object::cast_to<Resource>(ref->ptr());
|
|
||||||
if (res)
|
|
||||||
return res->get_rid();
|
|
||||||
return RID();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefPtr::unref() {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
ref->unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr::RefPtr() {
|
|
||||||
|
|
||||||
ERR_FAIL_COND(sizeof(Ref<Reference>) > DATASIZE);
|
|
||||||
memnew_placement(&data[0], Ref<Reference>);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr::~RefPtr() {
|
|
||||||
|
|
||||||
Ref<Reference> *ref = reinterpret_cast<Ref<Reference> *>(&data[0]);
|
|
||||||
ref->~Ref<Reference>();
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* ref_ptr.h */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* 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. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#ifndef REF_PTR_H
|
|
||||||
#define REF_PTR_H
|
|
||||||
/**
|
|
||||||
@author Juan Linietsky <reduzio@gmail.com>
|
|
||||||
* This class exists to workaround a limitation in C++ but keep the design OK.
|
|
||||||
* It's basically an opaque container of a Reference reference, so Variant can use it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "core/rid.h"
|
|
||||||
|
|
||||||
class RefPtr {
|
|
||||||
|
|
||||||
enum {
|
|
||||||
|
|
||||||
DATASIZE = sizeof(void *) //*4 -ref was shrunk
|
|
||||||
};
|
|
||||||
|
|
||||||
mutable char data[DATASIZE]; // too much probably, virtual class + pointer
|
|
||||||
public:
|
|
||||||
bool is_null() const;
|
|
||||||
void operator=(const RefPtr &p_other);
|
|
||||||
bool operator==(const RefPtr &p_other) const;
|
|
||||||
bool operator!=(const RefPtr &p_other) const;
|
|
||||||
RID get_rid() const;
|
|
||||||
void unref();
|
|
||||||
_FORCE_INLINE_ void *get_data() const { return data; }
|
|
||||||
RefPtr(const RefPtr &p_other);
|
|
||||||
RefPtr();
|
|
||||||
~RefPtr();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // REF_PTR_H
|
|
||||||
|
|
@ -102,7 +102,8 @@ bool Reference::unreference() {
|
||||||
return die;
|
return die;
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference::Reference() {
|
Reference::Reference() :
|
||||||
|
Object(true) {
|
||||||
|
|
||||||
refcount.init();
|
refcount.init();
|
||||||
refcount_init.init();
|
refcount_init.init();
|
||||||
|
|
|
||||||
106
core/reference.h
106
core/reference.h
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
#include "core/class_db.h"
|
#include "core/class_db.h"
|
||||||
#include "core/object.h"
|
#include "core/object.h"
|
||||||
#include "core/ref_ptr.h"
|
|
||||||
#include "core/safe_refcount.h"
|
#include "core/safe_refcount.h"
|
||||||
|
|
||||||
class Reference : public Object {
|
class Reference : public Object {
|
||||||
|
|
@ -133,17 +132,9 @@ public:
|
||||||
return reference;
|
return reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr get_ref_ptr() const {
|
|
||||||
|
|
||||||
RefPtr refptr;
|
|
||||||
Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data());
|
|
||||||
*irr = *this;
|
|
||||||
return refptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
operator Variant() const {
|
operator Variant() const {
|
||||||
|
|
||||||
return Variant(get_ref_ptr());
|
return Variant(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(const Ref &p_from) {
|
void operator=(const Ref &p_from) {
|
||||||
|
|
@ -165,33 +156,24 @@ public:
|
||||||
r.reference = NULL;
|
r.reference = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(const RefPtr &p_refptr) {
|
|
||||||
|
|
||||||
Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data());
|
|
||||||
Reference *refb = irr->ptr();
|
|
||||||
if (!refb) {
|
|
||||||
unref();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Ref r;
|
|
||||||
r.reference = Object::cast_to<T>(refb);
|
|
||||||
ref(r);
|
|
||||||
r.reference = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(const Variant &p_variant) {
|
void operator=(const Variant &p_variant) {
|
||||||
|
|
||||||
RefPtr refptr = p_variant;
|
Object *object = p_variant.get_validated_object();
|
||||||
Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data());
|
|
||||||
Reference *refb = irr->ptr();
|
if (object == reference) {
|
||||||
if (!refb) {
|
|
||||||
unref();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ref r;
|
|
||||||
r.reference = Object::cast_to<T>(refb);
|
unref();
|
||||||
ref(r);
|
|
||||||
r.reference = NULL;
|
if (!object) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference *r = Object::cast_to<Reference>(object);
|
||||||
|
if (r && r->reference()) {
|
||||||
|
reference = static_cast<T *>(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T_Other>
|
template <class T_Other>
|
||||||
|
|
@ -237,33 +219,19 @@ public:
|
||||||
|
|
||||||
Ref(const Variant &p_variant) {
|
Ref(const Variant &p_variant) {
|
||||||
|
|
||||||
RefPtr refptr = p_variant;
|
Object *object = p_variant.get_validated_object();
|
||||||
Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(refptr.get_data());
|
|
||||||
reference = NULL;
|
if (!object) {
|
||||||
Reference *refb = irr->ptr();
|
reference = nullptr;
|
||||||
if (!refb) {
|
|
||||||
unref();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Ref r;
|
|
||||||
r.reference = Object::cast_to<T>(refb);
|
|
||||||
ref(r);
|
|
||||||
r.reference = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref(const RefPtr &p_refptr) {
|
Reference *r = Object::cast_to<Reference>(object);
|
||||||
|
if (r && r->reference()) {
|
||||||
Ref<Reference> *irr = reinterpret_cast<Ref<Reference> *>(p_refptr.get_data());
|
reference = static_cast<T *>(r);
|
||||||
reference = NULL;
|
} else {
|
||||||
Reference *refb = irr->ptr();
|
reference = nullptr;
|
||||||
if (!refb) {
|
|
||||||
unref();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
Ref r;
|
|
||||||
r.reference = Object::cast_to<T>(refb);
|
|
||||||
ref(r);
|
|
||||||
r.reference = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_valid() const { return reference != NULL; }
|
inline bool is_valid() const { return reference != NULL; }
|
||||||
|
|
@ -340,32 +308,6 @@ struct PtrToArg<const Ref<T> &> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//this is for RefPtr
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct PtrToArg<RefPtr> {
|
|
||||||
|
|
||||||
_FORCE_INLINE_ static RefPtr convert(const void *p_ptr) {
|
|
||||||
|
|
||||||
return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
_FORCE_INLINE_ static void encode(RefPtr p_val, const void *p_ptr) {
|
|
||||||
|
|
||||||
Ref<Reference> r = p_val;
|
|
||||||
*(Ref<Reference> *)p_ptr = r;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct PtrToArg<const RefPtr &> {
|
|
||||||
|
|
||||||
_FORCE_INLINE_ static RefPtr convert(const void *p_ptr) {
|
|
||||||
|
|
||||||
return Ref<Reference>(const_cast<Reference *>(reinterpret_cast<const Reference *>(p_ptr))).get_ref_ptr();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PTRCALL_ENABLED
|
#endif // PTRCALL_ENABLED
|
||||||
|
|
||||||
#ifdef DEBUG_METHODS_ENABLED
|
#ifdef DEBUG_METHODS_ENABLED
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
|
|
||||||
#include "core/class_db.h"
|
#include "core/class_db.h"
|
||||||
#include "core/object.h"
|
#include "core/object.h"
|
||||||
#include "core/ref_ptr.h"
|
|
||||||
#include "core/reference.h"
|
#include "core/reference.h"
|
||||||
#include "core/safe_refcount.h"
|
#include "core/safe_refcount.h"
|
||||||
#include "core/self_list.h"
|
#include "core/self_list.h"
|
||||||
|
|
|
||||||
|
|
@ -169,24 +169,6 @@ MAKE_TYPE_INFO(IP_Address, Variant::STRING)
|
||||||
class BSP_Tree;
|
class BSP_Tree;
|
||||||
MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY)
|
MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY)
|
||||||
|
|
||||||
//for RefPtr
|
|
||||||
template <>
|
|
||||||
struct GetTypeInfo<RefPtr> {
|
|
||||||
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
|
|
||||||
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
|
|
||||||
static inline PropertyInfo get_class_info() {
|
|
||||||
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
struct GetTypeInfo<const RefPtr &> {
|
|
||||||
static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
|
|
||||||
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
|
|
||||||
static inline PropertyInfo get_class_info() {
|
|
||||||
return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//objectID
|
//objectID
|
||||||
template <>
|
template <>
|
||||||
struct GetTypeInfo<ObjectID> {
|
struct GetTypeInfo<ObjectID> {
|
||||||
|
|
|
||||||
127
core/variant.cpp
127
core/variant.cpp
|
|
@ -908,6 +908,14 @@ bool Variant::is_one() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Variant::is_null() const {
|
||||||
|
if (type == OBJECT && _get_obj().obj) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Variant::reference(const Variant &p_variant) {
|
void Variant::reference(const Variant &p_variant) {
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
@ -999,7 +1007,20 @@ void Variant::reference(const Variant &p_variant) {
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
memnew_placement(_data._mem, ObjData(p_variant._get_obj()));
|
memnew_placement(_data._mem, ObjData);
|
||||||
|
|
||||||
|
if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) {
|
||||||
|
Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj);
|
||||||
|
if (!reference->reference()) {
|
||||||
|
_get_obj().obj = nullptr;
|
||||||
|
_get_obj().id = ObjectID();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj);
|
||||||
|
_get_obj().id = p_variant._get_obj().id;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NODE_PATH: {
|
case NODE_PATH: {
|
||||||
|
|
||||||
|
|
@ -1114,8 +1135,15 @@ void Variant::clear() {
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
|
if (_get_obj().id.is_reference()) {
|
||||||
|
//we are safe that there is a reference here
|
||||||
|
Reference *reference = static_cast<Reference *>(_get_obj().obj);
|
||||||
|
if (reference->unreference()) {
|
||||||
|
memdelete(reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
_get_obj().obj = NULL;
|
_get_obj().obj = NULL;
|
||||||
_get_obj().ref.unref();
|
_get_obj().id = ObjectID();
|
||||||
} break;
|
} break;
|
||||||
case _RID: {
|
case _RID: {
|
||||||
// not much need probably
|
// not much need probably
|
||||||
|
|
@ -1589,14 +1617,11 @@ String Variant::stringify(List<const void *> &stack) const {
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
if (_get_obj().obj) {
|
if (_get_obj().obj) {
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
|
if (!_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
//only if debugging!
|
return "[Freed Object]";
|
||||||
if (!ObjectDB::instance_validate(_get_obj().obj)) {
|
|
||||||
return "[Deleted Object]";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
return _get_obj().obj->to_string();
|
return _get_obj().obj->to_string();
|
||||||
} else
|
} else
|
||||||
return "[Object:null]";
|
return "[Object:null]";
|
||||||
|
|
@ -1739,24 +1764,16 @@ Variant::operator NodePath() const {
|
||||||
return NodePath();
|
return NodePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::operator RefPtr() const {
|
|
||||||
|
|
||||||
if (type == OBJECT)
|
|
||||||
return _get_obj().ref;
|
|
||||||
else
|
|
||||||
return RefPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
Variant::operator RID() const {
|
Variant::operator RID() const {
|
||||||
|
|
||||||
if (type == _RID)
|
if (type == _RID)
|
||||||
return *reinterpret_cast<const RID *>(_data._mem);
|
return *reinterpret_cast<const RID *>(_data._mem);
|
||||||
else if (type == OBJECT && !_get_obj().ref.is_null()) {
|
else if (type == OBJECT && _get_obj().obj == nullptr) {
|
||||||
return _get_obj().ref.get_rid();
|
return RID();
|
||||||
} else if (type == OBJECT && _get_obj().obj) {
|
} else if (type == OBJECT && _get_obj().obj) {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton()) {
|
if (ScriptDebugger::get_singleton()) {
|
||||||
ERR_FAIL_COND_V_MSG(!ObjectDB::instance_validate(_get_obj().obj), RID(), "Invalid pointer (object was deleted).");
|
ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed).");
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
Variant::CallError ce;
|
Variant::CallError ce;
|
||||||
|
|
@ -1777,6 +1794,25 @@ Variant::operator Object *() const {
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object *Variant::get_validated_object_with_check(bool &r_previously_freed) const {
|
||||||
|
if (type == OBJECT) {
|
||||||
|
Object *instance = ObjectDB::get_instance(_get_obj().id);
|
||||||
|
r_previously_freed = !instance && _get_obj().id != ObjectID();
|
||||||
|
return instance;
|
||||||
|
} else {
|
||||||
|
r_previously_freed = false;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *Variant::get_validated_object() const {
|
||||||
|
if (type == OBJECT)
|
||||||
|
return ObjectDB::get_instance(_get_obj().id);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Variant::operator Node *() const {
|
Variant::operator Node *() const {
|
||||||
|
|
||||||
if (type == OBJECT)
|
if (type == OBJECT)
|
||||||
|
|
@ -2289,15 +2325,6 @@ Variant::Variant(const NodePath &p_node_path) {
|
||||||
memnew_placement(_data._mem, NodePath(p_node_path));
|
memnew_placement(_data._mem, NodePath(p_node_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::Variant(const RefPtr &p_resource) {
|
|
||||||
|
|
||||||
type = OBJECT;
|
|
||||||
memnew_placement(_data._mem, ObjData);
|
|
||||||
REF *ref = reinterpret_cast<REF *>(p_resource.get_data());
|
|
||||||
_get_obj().obj = ref->ptr();
|
|
||||||
_get_obj().ref = p_resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
Variant::Variant(const RID &p_rid) {
|
Variant::Variant(const RID &p_rid) {
|
||||||
|
|
||||||
type = _RID;
|
type = _RID;
|
||||||
|
|
@ -2309,7 +2336,24 @@ Variant::Variant(const Object *p_object) {
|
||||||
type = OBJECT;
|
type = OBJECT;
|
||||||
|
|
||||||
memnew_placement(_data._mem, ObjData);
|
memnew_placement(_data._mem, ObjData);
|
||||||
_get_obj().obj = const_cast<Object *>(p_object);
|
|
||||||
|
if (p_object) {
|
||||||
|
|
||||||
|
if (p_object->is_reference()) {
|
||||||
|
Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(p_object));
|
||||||
|
if (!reference->init_ref()) {
|
||||||
|
_get_obj().obj = nullptr;
|
||||||
|
_get_obj().id = ObjectID();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_obj().obj = const_cast<Object *>(p_object);
|
||||||
|
_get_obj().id = p_object->get_instance_id();
|
||||||
|
} else {
|
||||||
|
_get_obj().obj = nullptr;
|
||||||
|
_get_obj().id = ObjectID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant::Variant(const Dictionary &p_dictionary) {
|
Variant::Variant(const Dictionary &p_dictionary) {
|
||||||
|
|
@ -2620,7 +2664,26 @@ void Variant::operator=(const Variant &p_variant) {
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
*reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj();
|
if (_get_obj().id.is_reference()) {
|
||||||
|
//we are safe that there is a reference here
|
||||||
|
Reference *reference = static_cast<Reference *>(_get_obj().obj);
|
||||||
|
if (reference->unreference()) {
|
||||||
|
memdelete(reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) {
|
||||||
|
Reference *reference = static_cast<Reference *>(p_variant._get_obj().obj);
|
||||||
|
if (!reference->reference()) {
|
||||||
|
_get_obj().obj = nullptr;
|
||||||
|
_get_obj().id = ObjectID();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_obj().obj = const_cast<Object *>(p_variant._get_obj().obj);
|
||||||
|
_get_obj().id = p_variant._get_obj().id;
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case NODE_PATH: {
|
case NODE_PATH: {
|
||||||
|
|
||||||
|
|
@ -3131,7 +3194,7 @@ bool Variant::hash_compare(const Variant &p_variant) const {
|
||||||
|
|
||||||
bool Variant::is_ref() const {
|
bool Variant::is_ref() const {
|
||||||
|
|
||||||
return type == OBJECT && !_get_obj().ref.is_null();
|
return type == OBJECT && _get_obj().id.is_reference();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Variant> varray() {
|
Vector<Variant> varray() {
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,9 @@
|
||||||
#include "core/node_path.h"
|
#include "core/node_path.h"
|
||||||
#include "core/object_id.h"
|
#include "core/object_id.h"
|
||||||
#include "core/pool_vector.h"
|
#include "core/pool_vector.h"
|
||||||
#include "core/ref_ptr.h"
|
|
||||||
#include "core/rid.h"
|
#include "core/rid.h"
|
||||||
#include "core/ustring.h"
|
#include "core/ustring.h"
|
||||||
|
|
||||||
class RefPtr;
|
|
||||||
class Object;
|
class Object;
|
||||||
class Node; // helper
|
class Node; // helper
|
||||||
class Control; // helper
|
class Control; // helper
|
||||||
|
|
@ -128,12 +126,12 @@ private:
|
||||||
|
|
||||||
struct ObjData {
|
struct ObjData {
|
||||||
|
|
||||||
|
ObjectID id;
|
||||||
Object *obj;
|
Object *obj;
|
||||||
RefPtr ref;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_FORCE_INLINE_ ObjData &_get_obj();
|
_ALWAYS_INLINE_ ObjData &_get_obj();
|
||||||
_FORCE_INLINE_ const ObjData &_get_obj() const;
|
_ALWAYS_INLINE_ const ObjData &_get_obj() const;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
bool _bool;
|
bool _bool;
|
||||||
|
|
@ -162,6 +160,7 @@ public:
|
||||||
bool is_shared() const;
|
bool is_shared() const;
|
||||||
bool is_zero() const;
|
bool is_zero() const;
|
||||||
bool is_one() const;
|
bool is_one() const;
|
||||||
|
bool is_null() const;
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator signed int() const;
|
operator signed int() const;
|
||||||
|
|
@ -197,7 +196,6 @@ public:
|
||||||
|
|
||||||
operator Color() const;
|
operator Color() const;
|
||||||
operator NodePath() const;
|
operator NodePath() const;
|
||||||
operator RefPtr() const;
|
|
||||||
operator RID() const;
|
operator RID() const;
|
||||||
|
|
||||||
operator Object *() const;
|
operator Object *() const;
|
||||||
|
|
@ -235,6 +233,9 @@ public:
|
||||||
|
|
||||||
operator IP_Address() const;
|
operator IP_Address() const;
|
||||||
|
|
||||||
|
Object *get_validated_object() const;
|
||||||
|
Object *get_validated_object_with_check(bool &r_previously_freed) const;
|
||||||
|
|
||||||
Variant(bool p_bool);
|
Variant(bool p_bool);
|
||||||
Variant(signed int p_int); // real one
|
Variant(signed int p_int); // real one
|
||||||
Variant(unsigned int p_int);
|
Variant(unsigned int p_int);
|
||||||
|
|
@ -267,7 +268,6 @@ public:
|
||||||
Variant(const Transform &p_transform);
|
Variant(const Transform &p_transform);
|
||||||
Variant(const Color &p_color);
|
Variant(const Color &p_color);
|
||||||
Variant(const NodePath &p_node_path);
|
Variant(const NodePath &p_node_path);
|
||||||
Variant(const RefPtr &p_resource);
|
|
||||||
Variant(const RID &p_rid);
|
Variant(const RID &p_rid);
|
||||||
Variant(const Object *p_object);
|
Variant(const Object *p_object);
|
||||||
Variant(const Dictionary &p_dictionary);
|
Variant(const Dictionary &p_dictionary);
|
||||||
|
|
|
||||||
|
|
@ -1099,12 +1099,9 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
//only if debugging!
|
r_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
|
||||||
if (!ObjectDB::instance_validate(obj)) {
|
return;
|
||||||
r_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1274,18 +1271,11 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
|
||||||
bool Variant::has_method(const StringName &p_method) const {
|
bool Variant::has_method(const StringName &p_method) const {
|
||||||
|
|
||||||
if (type == OBJECT) {
|
if (type == OBJECT) {
|
||||||
Object *obj = operator Object *();
|
Object *obj = get_validated_object();
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (ScriptDebugger::get_singleton()) {
|
return obj->has_method(p_method);
|
||||||
if (ObjectDB::instance_validate(obj)) {
|
|
||||||
#endif
|
|
||||||
return obj->has_method(p_method);
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type];
|
const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type];
|
||||||
|
|
|
||||||
|
|
@ -1515,7 +1515,7 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (!_get_obj().obj) {
|
if (!_get_obj().obj) {
|
||||||
break;
|
break;
|
||||||
} else if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
|
} else if (ScriptDebugger::get_singleton() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1684,7 +1684,7 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
|
||||||
return "Instance base is null.";
|
return "Instance base is null.";
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
if (r_valid)
|
if (r_valid)
|
||||||
*r_valid = false;
|
*r_valid = false;
|
||||||
return "Attempted use of stray pointer object.";
|
return "Attempted use of stray pointer object.";
|
||||||
|
|
@ -2172,13 +2172,11 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
|
||||||
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
|
|
||||||
if (!ObjectDB::instance_validate(obj)) {
|
WARN_PRINT("Attempted use of previously freed pointer object.");
|
||||||
WARN_PRINT("Attempted use of stray pointer object.");
|
valid = false;
|
||||||
valid = false;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -2546,12 +2544,10 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
|
||||||
if (obj) {
|
if (obj) {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
|
|
||||||
//only if debugging!
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
if (!ObjectDB::instance_validate(obj)) {
|
valid = false;
|
||||||
valid = false;
|
return "Attempted get on previously freed instance.";
|
||||||
return "Attempted get on stray pointer.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -2611,15 +2607,14 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const {
|
||||||
|
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
|
|
||||||
//only if debugging!
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
if (!ObjectDB::instance_validate(obj)) {
|
if (r_valid) {
|
||||||
if (r_valid) {
|
*r_valid = false;
|
||||||
*r_valid = false;
|
|
||||||
}
|
|
||||||
return true; // Attempted get on stray pointer.
|
|
||||||
}
|
}
|
||||||
|
return true; // Attempted get on stray pointer.
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (p_index.get_type() != Variant::STRING) {
|
if (p_index.get_type() != Variant::STRING) {
|
||||||
|
|
@ -2883,13 +2878,12 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
|
||||||
Object *obj = _get_obj().obj;
|
Object *obj = _get_obj().obj;
|
||||||
if (obj) {
|
if (obj) {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null()) {
|
|
||||||
//only if debugging!
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
if (!ObjectDB::instance_validate(obj)) {
|
WARN_PRINT("Attempted get_property list on previously freed instance.");
|
||||||
WARN_PRINT("Attempted get_property list on stray pointer.");
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
obj->get_property_list(p_list);
|
obj->get_property_list(p_list);
|
||||||
|
|
@ -2961,16 +2955,18 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (!_get_obj().obj) {
|
if (!_get_obj().obj) {
|
||||||
valid = false;
|
valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
valid = false;
|
valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Variant::CallError ce;
|
Variant::CallError ce;
|
||||||
ce.error = Variant::CallError::CALL_OK;
|
ce.error = Variant::CallError::CALL_OK;
|
||||||
|
|
@ -3129,16 +3125,18 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (!_get_obj().obj) {
|
if (!_get_obj().obj) {
|
||||||
valid = false;
|
valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
valid = false;
|
valid = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Variant::CallError ce;
|
Variant::CallError ce;
|
||||||
ce.error = Variant::CallError::CALL_OK;
|
ce.error = Variant::CallError::CALL_OK;
|
||||||
|
|
@ -3288,16 +3286,16 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const {
|
||||||
} break;
|
} break;
|
||||||
case OBJECT: {
|
case OBJECT: {
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (!_get_obj().obj) {
|
if (!_get_obj().obj) {
|
||||||
r_valid = false;
|
r_valid = false;
|
||||||
return Variant();
|
return Variant();
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
|
if (ScriptDebugger::get_singleton() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) {
|
||||||
r_valid = false;
|
r_valid = false;
|
||||||
return Variant();
|
return Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Variant::CallError ce;
|
Variant::CallError ce;
|
||||||
ce.error = Variant::CallError::CALL_OK;
|
ce.error = Variant::CallError::CALL_OK;
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,7 @@ Node *EditorAutoloadSettings::_create_autoload(const String &p_path) {
|
||||||
ERR_FAIL_COND_V_MSG(obj == NULL, NULL, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt) + ".");
|
ERR_FAIL_COND_V_MSG(obj == NULL, NULL, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt) + ".");
|
||||||
|
|
||||||
n = Object::cast_to<Node>(obj);
|
n = Object::cast_to<Node>(obj);
|
||||||
n->set_script(s.get_ref_ptr());
|
n->set_script(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_FAIL_COND_V_MSG(!n, NULL, "Path in autoload not a node or script: " + p_path + ".");
|
ERR_FAIL_COND_V_MSG(!n, NULL, "Path in autoload not a node or script: " + p_path + ".");
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ Object *EditorData::instance_custom_type(const String &p_type, const String &p_i
|
||||||
if (ob->is_class("Node")) {
|
if (ob->is_class("Node")) {
|
||||||
ob->call("set_name", p_type);
|
ob->call("set_name", p_type);
|
||||||
}
|
}
|
||||||
ob->set_script(script.get_ref_ptr());
|
ob->set_script(script);
|
||||||
return ob;
|
return ob;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -907,7 +907,7 @@ Object *EditorData::script_class_instance(const String &p_class) {
|
||||||
if (obj) {
|
if (obj) {
|
||||||
Ref<Script> script = script_class_load_script(p_class);
|
Ref<Script> script = script_class_load_script(p_class);
|
||||||
if (script.is_valid())
|
if (script.is_valid())
|
||||||
obj->set_script(script.get_ref_ptr());
|
obj->set_script(script);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3107,7 +3107,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorPlugin *ep = memnew(EditorPlugin);
|
EditorPlugin *ep = memnew(EditorPlugin);
|
||||||
ep->set_script(script.get_ref_ptr());
|
ep->set_script(script);
|
||||||
plugin_addons[p_addon] = ep;
|
plugin_addons[p_addon] = ep;
|
||||||
add_editor_plugin(ep, p_config_changed);
|
add_editor_plugin(ep, p_config_changed);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1473,7 +1473,7 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
post_import_script = Ref<EditorScenePostImport>(memnew(EditorScenePostImport));
|
post_import_script = Ref<EditorScenePostImport>(memnew(EditorScenePostImport));
|
||||||
post_import_script->set_script(scr.get_ref_ptr());
|
post_import_script->set_script(scr);
|
||||||
if (!post_import_script->get_script_instance()) {
|
if (!post_import_script->get_script_instance()) {
|
||||||
EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):") + " " + post_import_script_path);
|
EditorNode::add_io_error(TTR("Invalid/broken script for post-import (check console):") + " " + post_import_script_path);
|
||||||
post_import_script.unref();
|
post_import_script.unref();
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
|
||||||
AnimationNode *an = Object::cast_to<AnimationNode>(ClassDB::instance(base_type));
|
AnimationNode *an = Object::cast_to<AnimationNode>(ClassDB::instance(base_type));
|
||||||
ERR_FAIL_COND(!an);
|
ERR_FAIL_COND(!an);
|
||||||
anode = Ref<AnimationNode>(an);
|
anode = Ref<AnimationNode>(an);
|
||||||
anode->set_script(add_options[p_idx].script.get_ref_ptr());
|
anode->set_script(add_options[p_idx].script);
|
||||||
base_name = add_options[p_idx].name;
|
base_name = add_options[p_idx].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1257,7 +1257,7 @@ void ScriptEditor::_menu_option(int p_option) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<EditorScript> es = memnew(EditorScript);
|
Ref<EditorScript> es = memnew(EditorScript);
|
||||||
es->set_script(scr.get_ref_ptr());
|
es->set_script(scr);
|
||||||
es->set_editor(EditorNode::get_singleton());
|
es->set_editor(EditorNode::get_singleton());
|
||||||
|
|
||||||
es->_run();
|
es->_run();
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ void VersionControlEditorPlugin::_initialize_vcs() {
|
||||||
ERR_FAIL_COND_MSG(!addon_script_instance, "Failed to create addon script instance.");
|
ERR_FAIL_COND_MSG(!addon_script_instance, "Failed to create addon script instance.");
|
||||||
|
|
||||||
// The addon is attached as a script to the VCS interface as a proxy end-point
|
// The addon is attached as a script to the VCS interface as a proxy end-point
|
||||||
vcs_interface->set_script_and_instance(script.get_ref_ptr(), addon_script_instance);
|
vcs_interface->set_script_and_instance(script, addon_script_instance);
|
||||||
|
|
||||||
EditorVCSInterface::set_singleton(vcs_interface);
|
EditorVCSInterface::set_singleton(vcs_interface);
|
||||||
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_refresh_stage_area");
|
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_refresh_stage_area");
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ void VisualShaderEditor::update_custom_nodes() {
|
||||||
|
|
||||||
Ref<VisualShaderNodeCustom> ref;
|
Ref<VisualShaderNodeCustom> ref;
|
||||||
ref.instance();
|
ref.instance();
|
||||||
ref->set_script(script.get_ref_ptr());
|
ref->set_script(script);
|
||||||
|
|
||||||
String name;
|
String name;
|
||||||
if (ref->has_method("_get_name")) {
|
if (ref->has_method("_get_name")) {
|
||||||
|
|
@ -1415,7 +1415,7 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) {
|
||||||
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(base_type));
|
VisualShaderNode *vsn = Object::cast_to<VisualShaderNode>(ClassDB::instance(base_type));
|
||||||
ERR_FAIL_COND_V(!vsn, NULL);
|
ERR_FAIL_COND_V(!vsn, NULL);
|
||||||
vsnode = Ref<VisualShaderNode>(vsn);
|
vsnode = Ref<VisualShaderNode>(vsn);
|
||||||
vsnode->set_script(add_options[p_idx].script.get_ref_ptr());
|
vsnode->set_script(add_options[p_idx].script);
|
||||||
}
|
}
|
||||||
|
|
||||||
Point2 position = graph->get_scroll_ofs();
|
Point2 position = graph->get_scroll_ofs();
|
||||||
|
|
|
||||||
|
|
@ -176,9 +176,9 @@ void CustomPropertyEditor::_menu_option(int p_which) {
|
||||||
|
|
||||||
case OBJ_MENU_EDIT: {
|
case OBJ_MENU_EDIT: {
|
||||||
|
|
||||||
RefPtr RefPtr = v;
|
REF r = v;
|
||||||
|
|
||||||
if (!RefPtr.is_null()) {
|
if (!r.is_null()) {
|
||||||
|
|
||||||
emit_signal("resource_edit_request");
|
emit_signal("resource_edit_request");
|
||||||
hide();
|
hide();
|
||||||
|
|
@ -193,8 +193,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
|
||||||
|
|
||||||
case OBJ_MENU_MAKE_UNIQUE: {
|
case OBJ_MENU_MAKE_UNIQUE: {
|
||||||
|
|
||||||
RefPtr RefPtr = v;
|
Ref<Resource> res_orig = v;
|
||||||
Ref<Resource> res_orig = RefPtr;
|
|
||||||
if (res_orig.is_null())
|
if (res_orig.is_null())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -229,7 +228,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
|
||||||
res->set(p.first, p.second);
|
res->set(p.first, p.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
v = res.get_ref_ptr();
|
v = res;
|
||||||
emit_signal("variant_changed");
|
emit_signal("variant_changed");
|
||||||
hide();
|
hide();
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -311,7 +310,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
|
||||||
res->call("set_instance_base_type", owner->get_class());
|
res->call("set_instance_base_type", owner->get_class());
|
||||||
}
|
}
|
||||||
|
|
||||||
v = Ref<Resource>(res).get_ref_ptr();
|
v = res;
|
||||||
emit_signal("variant_changed");
|
emit_signal("variant_changed");
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -1103,7 +1102,7 @@ void CustomPropertyEditor::_file_selected(String p_file) {
|
||||||
error->popup_centered_minsize();
|
error->popup_centered_minsize();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
v = res.get_ref_ptr();
|
v = res;
|
||||||
emit_signal("variant_changed");
|
emit_signal("variant_changed");
|
||||||
hide();
|
hide();
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -1168,7 +1167,7 @@ void CustomPropertyEditor::_type_create_selected(int p_idx) {
|
||||||
Resource *res = Object::cast_to<Resource>(obj);
|
Resource *res = Object::cast_to<Resource>(obj);
|
||||||
ERR_FAIL_COND(!res);
|
ERR_FAIL_COND(!res);
|
||||||
|
|
||||||
v = Ref<Resource>(res).get_ref_ptr();
|
v = res;
|
||||||
emit_signal("variant_changed");
|
emit_signal("variant_changed");
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
@ -1373,7 +1372,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
|
||||||
Resource *res = Object::cast_to<Resource>(obj);
|
Resource *res = Object::cast_to<Resource>(obj);
|
||||||
ERR_BREAK(!res);
|
ERR_BREAK(!res);
|
||||||
|
|
||||||
v = Ref<Resource>(res).get_ref_ptr();
|
v = res;
|
||||||
emit_signal("variant_changed");
|
emit_signal("variant_changed");
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
@ -1395,9 +1394,9 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
|
||||||
|
|
||||||
} else if (p_which == 2) {
|
} else if (p_which == 2) {
|
||||||
|
|
||||||
RefPtr RefPtr = v;
|
RES r = v;
|
||||||
|
|
||||||
if (!RefPtr.is_null()) {
|
if (!r.is_null()) {
|
||||||
|
|
||||||
emit_signal("resource_edit_request");
|
emit_signal("resource_edit_request");
|
||||||
hide();
|
hide();
|
||||||
|
|
@ -1410,8 +1409,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
|
||||||
hide();
|
hide();
|
||||||
} else if (p_which == 4) {
|
} else if (p_which == 4) {
|
||||||
|
|
||||||
RefPtr RefPtr = v;
|
Ref<Resource> res_orig = v;
|
||||||
Ref<Resource> res_orig = RefPtr;
|
|
||||||
if (res_orig.is_null())
|
if (res_orig.is_null())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -1442,7 +1440,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
|
||||||
res->set(p.first, p.second);
|
res->set(p.first, p.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
v = res.get_ref_ptr();
|
v = res;
|
||||||
emit_signal("variant_changed");
|
emit_signal("variant_changed");
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -972,7 +972,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
||||||
new_node = Object::cast_to<Node>(ClassDB::instance(ScriptServer::get_global_class_native_base(name)));
|
new_node = Object::cast_to<Node>(ClassDB::instance(ScriptServer::get_global_class_native_base(name)));
|
||||||
Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(name), "Script");
|
Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(name), "Script");
|
||||||
if (new_node && script.is_valid()) {
|
if (new_node && script.is_valid()) {
|
||||||
new_node->set_script(script.get_ref_ptr());
|
new_node->set_script(script);
|
||||||
new_node->set_name(name);
|
new_node->set_name(name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1725,7 +1725,7 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
|
||||||
for (List<Node *>::Element *E = selected.front(); E; E = E->next()) {
|
for (List<Node *>::Element *E = selected.front(); E; E = E->next()) {
|
||||||
|
|
||||||
Ref<Script> existing = E->get()->get_script();
|
Ref<Script> existing = E->get()->get_script();
|
||||||
editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script.get_ref_ptr());
|
editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script);
|
||||||
editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing);
|
editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing);
|
||||||
editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
|
editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
|
||||||
editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
|
editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,9 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
|
||||||
emit_signal("open", n->get_filename());
|
emit_signal("open", n->get_filename());
|
||||||
}
|
}
|
||||||
} else if (p_id == BUTTON_SCRIPT) {
|
} else if (p_id == BUTTON_SCRIPT) {
|
||||||
RefPtr script = n->get_script();
|
Ref<Script> script_typed = n->get_script();
|
||||||
Ref<Script> script_typed = script;
|
|
||||||
if (!script_typed.is_null())
|
if (!script_typed.is_null())
|
||||||
emit_signal("open_script", script);
|
emit_signal("open_script", script_typed);
|
||||||
|
|
||||||
} else if (p_id == BUTTON_VISIBILITY) {
|
} else if (p_id == BUTTON_VISIBILITY) {
|
||||||
undo_redo->create_action(TTR("Toggle Visible"));
|
undo_redo->create_action(TTR("Toggle Visible"));
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ void ScriptCreateDialog::_load_exist() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_signal("script_created", p_script.get_ref_ptr());
|
emit_signal("script_created", p_script);
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -619,7 +619,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
|
||||||
|
|
||||||
if (pinfo.hint_string == "Script") {
|
if (pinfo.hint_string == "Script") {
|
||||||
if (debugObj->get_script() != var) {
|
if (debugObj->get_script() != var) {
|
||||||
debugObj->set_script(RefPtr());
|
debugObj->set_script(REF());
|
||||||
Ref<Script> script(var);
|
Ref<Script> script(var);
|
||||||
if (!script.is_null()) {
|
if (!script.is_null()) {
|
||||||
ScriptInstance *script_instance = script->placeholder_instance_create(debugObj);
|
ScriptInstance *script_instance = script->placeholder_instance_create(debugObj);
|
||||||
|
|
|
||||||
|
|
@ -1719,7 +1719,7 @@ bool Main::start() {
|
||||||
ERR_CONTINUE_MSG(obj == NULL, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt));
|
ERR_CONTINUE_MSG(obj == NULL, "Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt));
|
||||||
|
|
||||||
n = Object::cast_to<Node>(obj);
|
n = Object::cast_to<Node>(obj);
|
||||||
n->set_script(script_res.get_ref_ptr());
|
n->set_script(script_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + path);
|
ERR_CONTINUE_MSG(!n, "Path in autoload not a node or script: " + path);
|
||||||
|
|
|
||||||
|
|
@ -166,10 +166,6 @@ void _gdnative_report_loading_error(const godot_object *p_library, const char *p
|
||||||
_err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr());
|
_err_print_error("gdnative_init", library->get_current_library_path().utf8().ptr(), 0, message.utf8().ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDAPI godot_is_instance_valid(const godot_object *p_object) {
|
|
||||||
return ObjectDB::instance_validate((Object *)p_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id) {
|
godot_object GDAPI *godot_instance_from_id(godot_int p_instance_id) {
|
||||||
return (godot_object *)ObjectDB::get_instance(ObjectID(p_instance_id));
|
return (godot_object *)ObjectDB::get_instance(ObjectID(p_instance_id));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p
|
||||||
ref = REF(reference);
|
ref = REF(reference);
|
||||||
}
|
}
|
||||||
if (!ref.is_null()) {
|
if (!ref.is_null()) {
|
||||||
memnew_placement_custom(dest, Variant, Variant(ref.get_ref_ptr()));
|
memnew_placement_custom(dest, Variant, Variant(ref));
|
||||||
} else {
|
} else {
|
||||||
#if defined(DEBUG_METHODS_ENABLED)
|
#if defined(DEBUG_METHODS_ENABLED)
|
||||||
if (reference) {
|
if (reference) {
|
||||||
|
|
|
||||||
|
|
@ -403,13 +403,6 @@
|
||||||
["const godot_vector3 *", "p_scale"]
|
["const godot_vector3 *", "p_scale"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "godot_is_instance_valid",
|
|
||||||
"return_type": "bool",
|
|
||||||
"arguments": [
|
|
||||||
["const godot_object *", "p_object"]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "godot_quat_new_with_basis",
|
"name": "godot_quat_new_with_basis",
|
||||||
"return_type": "void",
|
"return_type": "void",
|
||||||
|
|
|
||||||
|
|
@ -282,9 +282,7 @@ void GDAPI godot_print_error(const char *p_description, const char *p_function,
|
||||||
void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line);
|
void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line);
|
||||||
void GDAPI godot_print(const godot_string *p_message);
|
void GDAPI godot_print(const godot_string *p_message);
|
||||||
|
|
||||||
// GDNATIVE CORE 1.0.1
|
// GDNATIVE CORE 1.0.2?
|
||||||
|
|
||||||
bool GDAPI godot_is_instance_valid(const godot_object *p_object);
|
|
||||||
|
|
||||||
//tags used for safe dynamic casting
|
//tags used for safe dynamic casting
|
||||||
void GDAPI *godot_get_class_tag(const godot_string_name *p_class);
|
void GDAPI *godot_get_class_tag(const godot_string_name *p_class);
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
|
||||||
instance->members.resize(member_indices.size());
|
instance->members.resize(member_indices.size());
|
||||||
instance->script = Ref<GDScript>(this);
|
instance->script = Ref<GDScript>(this);
|
||||||
instance->owner = p_owner;
|
instance->owner = p_owner;
|
||||||
|
instance->owner_id = p_owner->get_instance_id();
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
//needed for hot reloading
|
//needed for hot reloading
|
||||||
for (Map<StringName, MemberInfo>::Element *E = member_indices.front(); E; E = E->next()) {
|
for (Map<StringName, MemberInfo>::Element *E = member_indices.front(); E; E = E->next()) {
|
||||||
|
|
@ -1792,7 +1793,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
|
||||||
|
|
||||||
obj->get_script_instance()->get_property_state(state);
|
obj->get_script_instance()->get_property_state(state);
|
||||||
map[obj->get_instance_id()] = state;
|
map[obj->get_instance_id()] = state;
|
||||||
obj->set_script(RefPtr());
|
obj->set_script(Variant());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1808,7 +1809,7 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
|
||||||
map.insert(obj->get_instance_id(), List<Pair<StringName, Variant> >());
|
map.insert(obj->get_instance_id(), List<Pair<StringName, Variant> >());
|
||||||
List<Pair<StringName, Variant> > &state = map[obj->get_instance_id()];
|
List<Pair<StringName, Variant> > &state = map[obj->get_instance_id()];
|
||||||
obj->get_script_instance()->get_property_state(state);
|
obj->get_script_instance()->get_property_state(state);
|
||||||
obj->set_script(RefPtr());
|
obj->set_script(Variant());
|
||||||
} else {
|
} else {
|
||||||
// no instance found. Let's remove it so we don't loop forever
|
// no instance found. Let's remove it so we don't loop forever
|
||||||
E->get()->placeholders.erase(E->get()->placeholders.front()->get());
|
E->get()->placeholders.erase(E->get()->placeholders.front()->get());
|
||||||
|
|
@ -1839,9 +1840,9 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
|
||||||
|
|
||||||
if (!p_soft_reload) {
|
if (!p_soft_reload) {
|
||||||
//clear it just in case (may be a pending reload state)
|
//clear it just in case (may be a pending reload state)
|
||||||
obj->set_script(RefPtr());
|
obj->set_script(Variant());
|
||||||
}
|
}
|
||||||
obj->set_script(scr.get_ref_ptr());
|
obj->set_script(scr);
|
||||||
|
|
||||||
ScriptInstance *script_instance = obj->get_script_instance();
|
ScriptInstance *script_instance = obj->get_script_instance();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,7 @@ class GDScriptInstance : public ScriptInstance {
|
||||||
friend class GDScriptFunctions;
|
friend class GDScriptFunctions;
|
||||||
friend class GDScriptCompiler;
|
friend class GDScriptCompiler;
|
||||||
|
|
||||||
|
ObjectID owner_id;
|
||||||
Object *owner;
|
Object *owner;
|
||||||
Ref<GDScript> script;
|
Ref<GDScript> script;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
|
||||||
|
|
@ -137,18 +137,19 @@ static String _get_var_type(const Variant *p_var) {
|
||||||
String basestr;
|
String basestr;
|
||||||
|
|
||||||
if (p_var->get_type() == Variant::OBJECT) {
|
if (p_var->get_type() == Variant::OBJECT) {
|
||||||
Object *bobj = *p_var;
|
bool was_freed;
|
||||||
|
Object *bobj = p_var->get_validated_object_with_check(was_freed);
|
||||||
if (!bobj) {
|
if (!bobj) {
|
||||||
basestr = "null instance";
|
if (was_freed) {
|
||||||
} else {
|
basestr = "null instance";
|
||||||
if (ObjectDB::instance_validate(bobj)) {
|
|
||||||
if (bobj->get_script_instance())
|
|
||||||
basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")";
|
|
||||||
else
|
|
||||||
basestr = bobj->get_class();
|
|
||||||
} else {
|
} else {
|
||||||
basestr = "previously freed instance";
|
basestr = "previously freed";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (bobj->get_script_instance())
|
||||||
|
basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")";
|
||||||
|
else
|
||||||
|
basestr = bobj->get_class();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -497,14 +498,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
|
|
||||||
bool extends_ok = false;
|
bool extends_ok = false;
|
||||||
if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) {
|
if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) {
|
||||||
Object *obj_A = *a;
|
|
||||||
Object *obj_B = *b;
|
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (!ObjectDB::instance_validate(obj_A)) {
|
bool was_freed;
|
||||||
err_text = "Left operand of 'is' was already freed.";
|
Object *obj_A = a->get_validated_object_with_check(was_freed);
|
||||||
|
|
||||||
|
if (was_freed) {
|
||||||
|
err_text = "Left operand of 'is' is a previously freed instance.";
|
||||||
OPCODE_BREAK;
|
OPCODE_BREAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object *obj_B = b->get_validated_object_with_check(was_freed);
|
||||||
|
|
||||||
|
if (was_freed) {
|
||||||
|
err_text = "Right operand of 'is' is a previously freed instance.";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
Object *obj_A = *a;
|
||||||
|
Object *obj_B = *b;
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
|
||||||
GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
|
GDScript *scr_B = Object::cast_to<GDScript>(obj_B);
|
||||||
|
|
@ -1298,20 +1311,20 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Object *obj = argobj->operator Object *();
|
#ifdef DEBUG_ENABLED
|
||||||
|
bool was_freed;
|
||||||
|
Object *obj = argobj->get_validated_object_with_check(was_freed);
|
||||||
String signal = argname->operator String();
|
String signal = argname->operator String();
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
if (was_freed) {
|
||||||
|
err_text = "First argument of yield() is a previously freed instance.";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
err_text = "First argument of yield() is null.";
|
err_text = "First argument of yield() is null.";
|
||||||
OPCODE_BREAK;
|
OPCODE_BREAK;
|
||||||
}
|
}
|
||||||
if (ScriptDebugger::get_singleton()) {
|
|
||||||
if (!ObjectDB::instance_validate(obj)) {
|
|
||||||
err_text = "First argument of yield() is a previously freed instance.";
|
|
||||||
OPCODE_BREAK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (signal.length() == 0) {
|
if (signal.length() == 0) {
|
||||||
|
|
||||||
err_text = "Second argument of yield() is an empty string (for signal name).";
|
err_text = "Second argument of yield() is an empty string (for signal name).";
|
||||||
|
|
@ -1324,6 +1337,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
OPCODE_BREAK;
|
OPCODE_BREAK;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
Object *obj = argobj->operator Object *();
|
||||||
|
String signal = argname->operator String();
|
||||||
|
|
||||||
obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
|
obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -1565,14 +1581,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
//error
|
//error
|
||||||
// function, file, line, error, explanation
|
// function, file, line, error, explanation
|
||||||
String err_file;
|
String err_file;
|
||||||
if (p_instance && ObjectDB::instance_validate(p_instance->owner) && p_instance->script->is_valid() && p_instance->script->path != "")
|
if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->path != "")
|
||||||
err_file = p_instance->script->path;
|
err_file = p_instance->script->path;
|
||||||
else if (script)
|
else if (script)
|
||||||
err_file = script->path;
|
err_file = script->path;
|
||||||
if (err_file == "")
|
if (err_file == "")
|
||||||
err_file = "<built-in>";
|
err_file = "<built-in>";
|
||||||
String err_func = name;
|
String err_func = name;
|
||||||
if (p_instance && ObjectDB::instance_validate(p_instance->owner) && p_instance->script->is_valid() && p_instance->script->name != "")
|
if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->name != "")
|
||||||
err_func = p_instance->script->name + "." + err_func;
|
err_func = p_instance->script->name + "." + err_func;
|
||||||
int err_line = line;
|
int err_line = line;
|
||||||
if (err_text == "") {
|
if (err_text == "") {
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,8 @@ struct GDScriptDataType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *obj = p_variant.operator Object *();
|
Object *obj = p_variant.get_validated_object();
|
||||||
if (!obj || !ObjectDB::instance_validate(obj)) {
|
if (!obj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,8 +100,8 @@ struct GDScriptDataType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *obj = p_variant.operator Object *();
|
Object *obj = p_variant.get_validated_object();
|
||||||
if (!obj || !ObjectDB::instance_validate(obj)) {
|
if (!obj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1441,8 +1441,8 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
|
||||||
if (p_args[0]->get_type() != Variant::OBJECT) {
|
if (p_args[0]->get_type() != Variant::OBJECT) {
|
||||||
r_ret = false;
|
r_ret = false;
|
||||||
} else {
|
} else {
|
||||||
Object *obj = *p_args[0];
|
Object *obj = p_args[0]->get_validated_object();
|
||||||
r_ret = ObjectDB::instance_validate(obj);
|
r_ret = obj != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
|
||||||
|
|
@ -854,7 +854,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
||||||
|
|
||||||
while (script->instances.front()) {
|
while (script->instances.front()) {
|
||||||
Object *obj = script->instances.front()->get();
|
Object *obj = script->instances.front()->get();
|
||||||
obj->set_script(RefPtr()); // Remove script and existing script instances (placeholder are not removed before domain reload)
|
obj->set_script(REF()); // Remove script and existing script instances (placeholder are not removed before domain reload)
|
||||||
}
|
}
|
||||||
|
|
||||||
script->_clear();
|
script->_clear();
|
||||||
|
|
@ -877,7 +877,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
||||||
|
|
||||||
// Use a placeholder for now to avoid losing the state when saving a scene
|
// Use a placeholder for now to avoid losing the state when saving a scene
|
||||||
|
|
||||||
obj->set_script(scr.get_ref_ptr());
|
obj->set_script(scr);
|
||||||
|
|
||||||
PlaceHolderScriptInstance *placeholder = scr->placeholder_instance_create(obj);
|
PlaceHolderScriptInstance *placeholder = scr->placeholder_instance_create(obj);
|
||||||
obj->set_script_instance(placeholder);
|
obj->set_script_instance(placeholder);
|
||||||
|
|
@ -1003,7 +1003,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
||||||
CRASH_COND(si != NULL);
|
CRASH_COND(si != NULL);
|
||||||
#endif
|
#endif
|
||||||
// Re-create script instance
|
// Re-create script instance
|
||||||
obj->set_script(script.get_ref_ptr()); // will create the script instance as well
|
obj->set_script(script); // will create the script instance as well
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
|
||||||
|
|
||||||
ScriptInstance *si = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
|
ScriptInstance *si = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
|
||||||
|
|
||||||
unmanaged->set_script_and_instance(script.get_ref_ptr(), si);
|
unmanaged->set_script_and_instance(script, si);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unhandled_exception(MonoException *p_exc) {
|
void unhandled_exception(MonoException *p_exc) {
|
||||||
|
|
|
||||||
|
|
@ -4963,7 +4963,7 @@ Ref<VisualScriptNode> _VisualScriptEditor::create_node_custom(const String &p_na
|
||||||
}
|
}
|
||||||
|
|
||||||
_VisualScriptEditor *_VisualScriptEditor::singleton = NULL;
|
_VisualScriptEditor *_VisualScriptEditor::singleton = NULL;
|
||||||
Map<String, RefPtr> _VisualScriptEditor::custom_nodes;
|
Map<String, REF> _VisualScriptEditor::custom_nodes;
|
||||||
|
|
||||||
_VisualScriptEditor::_VisualScriptEditor() {
|
_VisualScriptEditor::_VisualScriptEditor() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
|
|
@ -4975,7 +4975,7 @@ _VisualScriptEditor::~_VisualScriptEditor() {
|
||||||
|
|
||||||
void _VisualScriptEditor::add_custom_node(const String &p_name, const String &p_category, const Ref<Script> &p_script) {
|
void _VisualScriptEditor::add_custom_node(const String &p_name, const String &p_category, const Ref<Script> &p_script) {
|
||||||
String node_name = "custom/" + p_category + "/" + p_name;
|
String node_name = "custom/" + p_category + "/" + p_name;
|
||||||
custom_nodes.insert(node_name, p_script.get_ref_ptr());
|
custom_nodes.insert(node_name, p_script);
|
||||||
VisualScriptLanguage::singleton->add_register_func(node_name, &_VisualScriptEditor::create_node_custom);
|
VisualScriptLanguage::singleton->add_register_func(node_name, &_VisualScriptEditor::create_node_custom);
|
||||||
emit_signal("custom_nodes_updated");
|
emit_signal("custom_nodes_updated");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -341,7 +341,7 @@ protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
static _VisualScriptEditor *singleton;
|
static _VisualScriptEditor *singleton;
|
||||||
|
|
||||||
static Map<String, RefPtr> custom_nodes;
|
static Map<String, REF> custom_nodes;
|
||||||
static Ref<VisualScriptNode> create_node_custom(const String &p_name);
|
static Ref<VisualScriptNode> create_node_custom(const String &p_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const {
|
||||||
} else if (name.begins_with("anims/")) {
|
} else if (name.begins_with("anims/")) {
|
||||||
|
|
||||||
String which = name.get_slicec('/', 1);
|
String which = name.get_slicec('/', 1);
|
||||||
r_ret = get_animation(which).get_ref_ptr();
|
r_ret = get_animation(which);
|
||||||
|
|
||||||
} else if (name.begins_with("next/")) {
|
} else if (name.begins_with("next/")) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1227,7 +1227,6 @@ bool Tween::_build_interpolation(InterpolateType p_interpolation_type, Object *p
|
||||||
|
|
||||||
// Give it the object
|
// Give it the object
|
||||||
ERR_FAIL_COND_V_MSG(p_object == NULL, false, "Invalid object provided to Tween.");
|
ERR_FAIL_COND_V_MSG(p_object == NULL, false, "Invalid object provided to Tween.");
|
||||||
ERR_FAIL_COND_V_MSG(!ObjectDB::instance_validate(p_object), false, "Invalid object provided to Tween.");
|
|
||||||
data.id = p_object->get_instance_id();
|
data.id = p_object->get_instance_id();
|
||||||
|
|
||||||
// Validate the initial and final values
|
// Validate the initial and final values
|
||||||
|
|
@ -1328,7 +1327,6 @@ bool Tween::interpolate_callback(Object *p_object, real_t p_duration, String p_c
|
||||||
|
|
||||||
// Check that the target object is valid
|
// Check that the target object is valid
|
||||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false);
|
|
||||||
|
|
||||||
// Duration cannot be negative
|
// Duration cannot be negative
|
||||||
ERR_FAIL_COND_V(p_duration < 0, false);
|
ERR_FAIL_COND_V(p_duration < 0, false);
|
||||||
|
|
@ -1387,7 +1385,6 @@ bool Tween::interpolate_deferred_callback(Object *p_object, real_t p_duration, S
|
||||||
|
|
||||||
// Check that the target object is valid
|
// Check that the target object is valid
|
||||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false);
|
|
||||||
|
|
||||||
// No negative durations allowed
|
// No negative durations allowed
|
||||||
ERR_FAIL_COND_V(p_duration < 0, false);
|
ERR_FAIL_COND_V(p_duration < 0, false);
|
||||||
|
|
@ -1457,9 +1454,7 @@ bool Tween::follow_property(Object *p_object, NodePath p_property, Variant p_ini
|
||||||
|
|
||||||
// Confirm the source and target objects are valid
|
// Confirm the source and target objects are valid
|
||||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false);
|
|
||||||
ERR_FAIL_COND_V(p_target == NULL, false);
|
ERR_FAIL_COND_V(p_target == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_target), false);
|
|
||||||
|
|
||||||
// No negative durations
|
// No negative durations
|
||||||
ERR_FAIL_COND_V(p_duration < 0, false);
|
ERR_FAIL_COND_V(p_duration < 0, false);
|
||||||
|
|
@ -1521,9 +1516,7 @@ bool Tween::follow_method(Object *p_object, StringName p_method, Variant p_initi
|
||||||
|
|
||||||
// Verify the source and target objects are valid
|
// Verify the source and target objects are valid
|
||||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false);
|
|
||||||
ERR_FAIL_COND_V(p_target == NULL, false);
|
ERR_FAIL_COND_V(p_target == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_target), false);
|
|
||||||
|
|
||||||
// No negative durations
|
// No negative durations
|
||||||
ERR_FAIL_COND_V(p_duration < 0, false);
|
ERR_FAIL_COND_V(p_duration < 0, false);
|
||||||
|
|
@ -1587,9 +1580,7 @@ bool Tween::targeting_property(Object *p_object, NodePath p_property, Object *p_
|
||||||
|
|
||||||
// Verify both objects are valid
|
// Verify both objects are valid
|
||||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false);
|
|
||||||
ERR_FAIL_COND_V(p_initial == NULL, false);
|
ERR_FAIL_COND_V(p_initial == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_initial), false);
|
|
||||||
|
|
||||||
// No negative durations
|
// No negative durations
|
||||||
ERR_FAIL_COND_V(p_duration < 0, false);
|
ERR_FAIL_COND_V(p_duration < 0, false);
|
||||||
|
|
@ -1655,9 +1646,7 @@ bool Tween::targeting_method(Object *p_object, StringName p_method, Object *p_in
|
||||||
|
|
||||||
// Make sure the given objects are valid
|
// Make sure the given objects are valid
|
||||||
ERR_FAIL_COND_V(p_object == NULL, false);
|
ERR_FAIL_COND_V(p_object == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_object), false);
|
|
||||||
ERR_FAIL_COND_V(p_initial == NULL, false);
|
ERR_FAIL_COND_V(p_initial == NULL, false);
|
||||||
ERR_FAIL_COND_V(!ObjectDB::instance_validate(p_initial), false);
|
|
||||||
|
|
||||||
// No negative durations
|
// No negative durations
|
||||||
ERR_FAIL_COND_V(p_duration < 0, false);
|
ERR_FAIL_COND_V(p_duration < 0, false);
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_
|
||||||
packet_peer_stream->put_var(p_name);
|
packet_peer_stream->put_var(p_name);
|
||||||
|
|
||||||
Variant var = p_variable;
|
Variant var = p_variable;
|
||||||
if (p_variable.get_type() == Variant::OBJECT && !ObjectDB::instance_validate(p_variable)) {
|
if (p_variable.get_type() == Variant::OBJECT && p_variable.get_validated_object() == nullptr) {
|
||||||
var = Variant();
|
var = Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2664,7 +2664,7 @@ void RichTextLabel::set_effects(const Vector<Variant> &effects) {
|
||||||
Vector<Variant> RichTextLabel::get_effects() {
|
Vector<Variant> RichTextLabel::get_effects() {
|
||||||
Vector<Variant> r;
|
Vector<Variant> r;
|
||||||
for (int i = 0; i < custom_effects.size(); i++) {
|
for (int i = 0; i < custom_effects.size(); i++) {
|
||||||
r.push_back(custom_effects[i].get_ref_ptr());
|
r.push_back(custom_effects[i]);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ Vector<Variant> BitmapFont::_get_textures() const {
|
||||||
|
|
||||||
Vector<Variant> rtextures;
|
Vector<Variant> rtextures;
|
||||||
for (int i = 0; i < textures.size(); i++)
|
for (int i = 0; i < textures.size(); i++)
|
||||||
rtextures.push_back(textures[i].get_ref_ptr());
|
rtextures.push_back(textures[i]);
|
||||||
return rtextures;
|
return rtextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1377,7 +1377,7 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
|
||||||
switch (p_variant.get_type()) {
|
switch (p_variant.get_type()) {
|
||||||
case Variant::OBJECT: {
|
case Variant::OBJECT: {
|
||||||
|
|
||||||
RES res = p_variant.operator RefPtr();
|
RES res = p_variant;
|
||||||
|
|
||||||
if (res.is_null() || external_resources.has(res))
|
if (res.is_null() || external_resources.has(res))
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue