summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJuan Linietsky <juan@godotengine.org>2020-02-12 14:24:06 -0300
committerJuan Linietsky <juan@godotengine.org>2020-02-12 14:24:54 -0300
commitcf8c679a23b21d6c6f29cba6a54eaa2eed88bf92 (patch)
tree52aca947b395362b2addec4843915b15947c32ca /core
parent4aa31a2851e3dd5b67193194f899850239b2669d (diff)
ObjectID converted to a structure, fixes many bugs where used incorrectly as 32 bits.
Diffstat (limited to 'core')
-rw-r--r--core/func_ref.cpp9
-rw-r--r--core/hashfuncs.h3
-rw-r--r--core/io/marshalls.cpp9
-rw-r--r--core/io/multiplayer_api.cpp1
-rw-r--r--core/method_ptrcall.h16
-rw-r--r--core/object.cpp9
-rw-r--r--core/object.h7
-rw-r--r--core/object_id.h32
-rw-r--r--core/reference.cpp9
-rw-r--r--core/type_info.h10
-rw-r--r--core/variant.cpp13
-rw-r--r--core/variant.h4
12 files changed, 97 insertions, 25 deletions
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 2dffb30bab..e20188c813 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -32,7 +32,7 @@
Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
- if (id == 0) {
+ if (id.is_null()) {
r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
return Variant();
}
@@ -48,7 +48,7 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Variant::Call
Variant FuncRef::call_funcv(const Array &p_args) {
- ERR_FAIL_COND_V(id == 0, Variant());
+ ERR_FAIL_COND_V(id.is_null(), Variant());
Object *obj = ObjectDB::get_instance(id);
@@ -69,7 +69,7 @@ void FuncRef::set_function(const StringName &p_func) {
}
bool FuncRef::is_valid() const {
- if (id == 0)
+ if (id.is_null())
return false;
Object *obj = ObjectDB::get_instance(id);
@@ -95,6 +95,5 @@ void FuncRef::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid);
}
-FuncRef::FuncRef() :
- id(0) {
+FuncRef::FuncRef() {
}
diff --git a/core/hashfuncs.h b/core/hashfuncs.h
index 647e8a40b2..d6cf04e560 100644
--- a/core/hashfuncs.h
+++ b/core/hashfuncs.h
@@ -34,10 +34,10 @@
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
#include "core/node_path.h"
+#include "core/object_id.h"
#include "core/string_name.h"
#include "core/typedefs.h"
#include "core/ustring.h"
-
/**
* Hashing functions
*/
@@ -137,6 +137,7 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
+ static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index e847a9cf0c..fdce9db2a0 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -53,8 +53,7 @@ ObjectID EncodedObjectAsID::get_object_id() const {
return id;
}
-EncodedObjectAsID::EncodedObjectAsID() :
- id(0) {
+EncodedObjectAsID::EncodedObjectAsID() {
}
#define _S(a) ((int32_t)a)
@@ -386,11 +385,11 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
if (type & ENCODE_FLAG_OBJECT_AS_ID) {
//this _is_ allowed
ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA);
- ObjectID val = decode_uint64(buf);
+ ObjectID val = ObjectID(decode_uint64(buf));
if (r_len)
(*r_len) += 8;
- if (val == 0) {
+ if (val.is_null()) {
r_variant = (Object *)NULL;
} else {
Ref<EncodedObjectAsID> obj_as_id;
@@ -1129,7 +1128,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (buf) {
Object *obj = p_variant;
- ObjectID id = 0;
+ ObjectID id;
if (obj && ObjectDB::instance_validate(obj)) {
id = obj->get_instance_id();
}
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 27c122fac7..ce641dd0f5 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -446,7 +446,6 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet,
PathGetCache::NodeInfo ni;
ni.path = path;
- ni.instance = 0;
path_get_cache[p_from].nodes[id] = ni;
diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h
index 0f2458d982..118970de80 100644
--- a/core/method_ptrcall.h
+++ b/core/method_ptrcall.h
@@ -32,6 +32,7 @@
#define METHOD_PTRCALL_H
#include "core/math/transform_2d.h"
+#include "core/object_id.h"
#include "core/typedefs.h"
#include "core/variant.h"
@@ -167,6 +168,21 @@ struct PtrToArg<const T *> {
}
};
+//this is for ObjectID
+
+template <>
+struct PtrToArg<ObjectID> {
+ _FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) {
+
+ return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr));
+ }
+
+ _FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) {
+
+ *((uint64_t *)p_ptr) = p_val;
+ }
+};
+
//this is for the special cases used by Variant
#define MAKE_VECARG(m_type) \
diff --git a/core/object.cpp b/core/object.cpp
index 937b1ae8d4..dc1dc2c41f 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1916,7 +1916,6 @@ Object::Object() {
_class_ptr = NULL;
_block_signals = false;
_predelete_ok = 0;
- _instance_id = 0;
_instance_id = ObjectDB::add_instance(this);
_can_translate = true;
_is_queued_for_deletion = false;
@@ -1972,7 +1971,7 @@ Object::~Object() {
}
ObjectDB::remove_instance(this);
- _instance_id = 0;
+ _instance_id = ObjectID();
_predelete_ok = 2;
if (!ScriptServer::are_languages_finished()) {
@@ -1995,14 +1994,14 @@ void postinitialize_handler(Object *p_object) {
}
HashMap<ObjectID, Object *> ObjectDB::instances;
-ObjectID ObjectDB::instance_counter = 1;
+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() != 0, 0);
+ ERR_FAIL_COND_V(p_object->get_instance_id().is_valid(), ObjectID());
rw_lock->write_lock();
- ObjectID instance_id = ++instance_counter;
+ ObjectID instance_id = ObjectID(++instance_counter);
instances[instance_id] = p_object;
instance_checks[p_object] = instance_id;
diff --git a/core/object.h b/core/object.h
index 865c155764..312fe07a17 100644
--- a/core/object.h
+++ b/core/object.h
@@ -34,6 +34,7 @@
#include "core/hash_map.h"
#include "core/list.h"
#include "core/map.h"
+#include "core/object_id.h"
#include "core/os/rw_lock.h"
#include "core/set.h"
#include "core/variant.h"
@@ -89,6 +90,7 @@ enum PropertyHint {
PROPERTY_HINT_OBJECT_TOO_BIG, ///< object is too big to send
PROPERTY_HINT_NODE_PATH_VALID_TYPES,
PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
+ PROPERTY_HINT_INT_IS_OBJECTID,
PROPERTY_HINT_MAX,
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};
@@ -397,7 +399,6 @@ public: \
private:
class ScriptInstance;
-typedef uint64_t ObjectID;
class Object {
public:
@@ -452,7 +453,7 @@ private:
_id(p_id),
method(p_method) {
}
- Target() { _id = 0; }
+ Target() { _id = ObjectID(); }
};
struct Slot {
@@ -775,7 +776,7 @@ class ObjectDB {
static HashMap<ObjectID, Object *> instances;
static HashMap<Object *, ObjectID, ObjectPtrHash> instance_checks;
- static ObjectID instance_counter;
+ static uint64_t instance_counter;
friend class Object;
friend void unregister_core_types();
diff --git a/core/object_id.h b/core/object_id.h
new file mode 100644
index 0000000000..f0ff2a24f5
--- /dev/null
+++ b/core/object_id.h
@@ -0,0 +1,32 @@
+#ifndef OBJECT_ID_H
+#define OBJECT_ID_H
+
+#include "core/typedefs.h"
+
+// Class to store an object ID (int64)
+// needs to be compatile with int64 because this is what Variant uses
+// Also, need to be explicitly only castable to 64 bits integer types
+// to avoid bugs due to loss of precision
+
+class ObjectID {
+ uint64_t id = 0;
+
+public:
+ _ALWAYS_INLINE_ bool is_valid() const { return id != 0; }
+ _ALWAYS_INLINE_ bool is_null() const { return id == 0; }
+ _ALWAYS_INLINE_ operator uint64_t() const { return id; }
+ _ALWAYS_INLINE_ operator int64_t() const { return id; }
+
+ _ALWAYS_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
+ _ALWAYS_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
+ _ALWAYS_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
+
+ _ALWAYS_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
+ _ALWAYS_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
+
+ _ALWAYS_INLINE_ ObjectID() {}
+ _ALWAYS_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
+ _ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
+};
+
+#endif // OBJECT_ID_H
diff --git a/core/reference.cpp b/core/reference.cpp
index b24b2a3ec0..5c211fe301 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -113,7 +113,7 @@ Reference::~Reference() {
Variant WeakRef::get_ref() const {
- if (ref == 0)
+ if (ref.is_null())
return Variant();
Object *obj = ObjectDB::get_instance(ref);
@@ -129,16 +129,15 @@ Variant WeakRef::get_ref() const {
}
void WeakRef::set_obj(Object *p_object) {
- ref = p_object ? p_object->get_instance_id() : 0;
+ ref = p_object ? p_object->get_instance_id() : ObjectID();
}
void WeakRef::set_ref(const REF &p_ref) {
- ref = p_ref.is_valid() ? p_ref->get_instance_id() : 0;
+ ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID();
}
-WeakRef::WeakRef() :
- ref(0) {
+WeakRef::WeakRef() {
}
void WeakRef::_bind_methods() {
diff --git a/core/type_info.h b/core/type_info.h
index 68bc1cc554..b9e5b61a6a 100644
--- a/core/type_info.h
+++ b/core/type_info.h
@@ -187,6 +187,16 @@ struct GetTypeInfo<const RefPtr &> {
}
};
+//objectID
+template <>
+struct GetTypeInfo<ObjectID> {
+ static const Variant::Type VARIANT_TYPE = Variant::INT;
+ static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
+ static inline PropertyInfo get_class_info() {
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_OBJECTID);
+ }
+};
+
//for variant
template <>
struct GetTypeInfo<Variant> {
diff --git a/core/variant.cpp b/core/variant.cpp
index f4e4cd5341..0f04710d13 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1248,6 +1248,14 @@ Variant::operator uint64_t() const {
}
}
+Variant::operator ObjectID() const {
+ if (type == INT) {
+ return ObjectID(_data._int);
+ } else {
+ return ObjectID();
+ }
+}
+
#ifdef NEED_LONG_INT
Variant::operator signed long() const {
@@ -2193,6 +2201,11 @@ Variant::Variant(double p_double) {
_data._real = p_double;
}
+Variant::Variant(const ObjectID &p_id) {
+ type = INT;
+ _data._int = p_id;
+}
+
Variant::Variant(const StringName &p_string) {
type = STRING;
diff --git a/core/variant.h b/core/variant.h
index 06be914408..d8007f9e12 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -44,6 +44,7 @@
#include "core/math/transform_2d.h"
#include "core/math/vector3.h"
#include "core/node_path.h"
+#include "core/object_id.h"
#include "core/pool_vector.h"
#include "core/ref_ptr.h"
#include "core/rid.h"
@@ -177,6 +178,8 @@ public:
operator unsigned long() const;
#endif
+ operator ObjectID() const;
+
operator CharType() const;
operator float() const;
operator double() const;
@@ -248,6 +251,7 @@ public:
Variant(uint64_t p_int);
Variant(float p_float);
Variant(double p_double);
+ Variant(const ObjectID &p_id);
Variant(const String &p_string);
Variant(const StringName &p_string);
Variant(const char *const p_cstring);