Skip to content

Commit f15ec7d

Browse files
committed
Add CallableCustom that devs can use in their GDExtensions
1 parent aa64e11 commit f15ec7d

File tree

12 files changed

+335
-53
lines changed

12 files changed

+335
-53
lines changed

binding_generator.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False):
110110

111111
for native_struct in api["native_structures"]:
112112
struct_name = native_struct["name"]
113+
if struct_name == "ObjectID":
114+
continue
113115
snake_struct_name = camel_to_snake(struct_name)
114116

115117
header_filename = include_gen_folder / "classes" / (snake_struct_name + ".hpp")
@@ -416,6 +418,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
416418
if class_name == "Array":
417419
result.append("#include <godot_cpp/variant/array_helpers.hpp>")
418420

421+
if class_name == "Callable":
422+
result.append("#include <godot_cpp/variant/callable_custom.hpp>")
423+
419424
for include in fully_used_classes:
420425
if include == "TypedArray":
421426
result.append("#include <godot_cpp/variant/typed_array.hpp>")
@@ -525,6 +530,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl
525530
result.append(f"\t{class_name}(const wchar_t *from);")
526531
result.append(f"\t{class_name}(const char16_t *from);")
527532
result.append(f"\t{class_name}(const char32_t *from);")
533+
if class_name == "Callable":
534+
result.append("\tCallable(CallableCustom *p_custom);")
535+
result.append("\tCallableCustom *get_custom() const;")
528536

529537
if "constants" in builtin_api:
530538
axis_constants_count = 0
@@ -1083,6 +1091,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
10831091
class_api["alias_for"] = "ClassDB"
10841092
engine_classes[class_api["name"]] = class_api["is_refcounted"]
10851093
for native_struct in api["native_structures"]:
1094+
if native_struct["name"] == "ObjectID":
1095+
continue
10861096
engine_classes[native_struct["name"]] = False
10871097
native_structures.append(native_struct["name"])
10881098

@@ -1210,6 +1220,8 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node):
12101220

12111221
for native_struct in api["native_structures"]:
12121222
struct_name = native_struct["name"]
1223+
if struct_name == "ObjectID":
1224+
continue
12131225
snake_struct_name = camel_to_snake(struct_name)
12141226

12151227
header_filename = include_gen_folder / (snake_struct_name + ".hpp")

include/godot_cpp/core/object.hpp

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333

3434
#include <godot_cpp/core/defs.hpp>
3535

36+
#include <godot_cpp/core/object_id.hpp>
37+
3638
#include <godot_cpp/core/property_info.hpp>
3739

3840
#include <godot_cpp/variant/variant.hpp>
@@ -106,28 +108,6 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name, const Args
106108
arguments = { args... };
107109
}
108110

109-
class ObjectID {
110-
uint64_t id = 0;
111-
112-
public:
113-
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
114-
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
115-
_FORCE_INLINE_ bool is_null() const { return id == 0; }
116-
_FORCE_INLINE_ operator uint64_t() const { return id; }
117-
_FORCE_INLINE_ operator int64_t() const { return id; }
118-
119-
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
120-
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
121-
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
122-
123-
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
124-
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
125-
126-
_FORCE_INLINE_ ObjectID() {}
127-
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
128-
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
129-
};
130-
131111
class ObjectDB {
132112
public:
133113
static Object *get_instance(uint64_t p_object_id) {

include/godot_cpp/core/object_id.hpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**************************************************************************/
2+
/* object_id.hpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#ifndef GODOT_OBJECT_ID_HPP
32+
#define GODOT_OBJECT_ID_HPP
33+
34+
#include <godot_cpp/core/defs.hpp>
35+
36+
namespace godot {
37+
38+
class ObjectID {
39+
uint64_t id = 0;
40+
41+
public:
42+
_FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; }
43+
_FORCE_INLINE_ bool is_valid() const { return id != 0; }
44+
_FORCE_INLINE_ bool is_null() const { return id == 0; }
45+
_FORCE_INLINE_ operator uint64_t() const { return id; }
46+
_FORCE_INLINE_ operator int64_t() const { return id; }
47+
48+
_FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; }
49+
_FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; }
50+
_FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; }
51+
52+
_FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; }
53+
_FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
54+
55+
_FORCE_INLINE_ ObjectID() {}
56+
_FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
57+
_FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }
58+
};
59+
60+
} // namespace godot
61+
62+
#endif // GODOT_OBJECT_ID_HPP

include/godot_cpp/godot.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ extern "C" GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to
166166
extern "C" GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id;
167167
extern "C" GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id;
168168
extern "C" GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create;
169+
extern "C" GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata;
169170
extern "C" GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object;
170171
extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object;
171172
extern "C" GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**************************************************************************/
2+
/* callable_custom.hpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#ifndef GODOT_CALLABLE_CUSTOM_HPP
32+
#define GODOT_CALLABLE_CUSTOM_HPP
33+
34+
#include <godot_cpp/core/object_id.hpp>
35+
#include <godot_cpp/variant/string_name.hpp>
36+
37+
namespace godot {
38+
39+
class Object;
40+
41+
class CallableCustomBase {
42+
public:
43+
virtual ObjectID get_object() const = 0;
44+
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
45+
virtual ~CallableCustomBase() {}
46+
};
47+
48+
class CallableCustom : public CallableCustomBase {
49+
public:
50+
typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
51+
typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
52+
53+
virtual uint32_t hash() const = 0;
54+
virtual String get_as_text() const = 0;
55+
virtual CompareEqualFunc get_compare_equal_func() const = 0;
56+
virtual CompareLessFunc get_compare_less_func() const = 0;
57+
virtual bool is_valid() const;
58+
virtual ObjectID get_object() const = 0;
59+
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
60+
};
61+
62+
} // namespace godot
63+
64+
#endif // GODOT_CALLABLE_CUSTOM_HPP

include/godot_cpp/variant/callable_method_pointer.hpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,12 @@
3636

3737
namespace godot {
3838

39-
class CallableCustomMethodPointerBase {
40-
public:
41-
virtual Object *get_object() const = 0;
42-
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0;
43-
virtual ~CallableCustomMethodPointerBase() {}
39+
class CallableCustomMethodPointerBase : public CallableCustomBase {
4440
};
4541

4642
namespace internal {
4743

48-
Callable create_custom_callable(CallableCustomMethodPointerBase *p_callable_method_pointer);
44+
Callable create_callable_from_ccmp(CallableCustomMethodPointerBase *p_callable_method_pointer);
4945

5046
} // namespace internal
5147

@@ -59,8 +55,8 @@ class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
5955
void (T::*method)(P...);
6056

6157
public:
62-
virtual Object *get_object() const override {
63-
return instance;
58+
virtual ObjectID get_object() const override {
59+
return ObjectID(instance->get_instance_id());
6460
}
6561

6662
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
@@ -77,7 +73,7 @@ template <class T, class... P>
7773
Callable create_custom_callable_function_pointer(T *p_instance, void (T::*p_method)(P...)) {
7874
typedef CallableCustomMethodPointer<T, P...> CCMP;
7975
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
80-
return ::godot::internal::create_custom_callable(ccmp);
76+
return ::godot::internal::create_callable_from_ccmp(ccmp);
8177
}
8278

8379
//
@@ -91,8 +87,8 @@ class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
9187
(P...);
9288

9389
public:
94-
virtual Object *get_object() const override {
95-
return instance;
90+
virtual ObjectID get_object() const override {
91+
return ObjectID(instance->get_instance_id());
9692
}
9793

9894
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
@@ -109,7 +105,7 @@ template <class T, class R, class... P>
109105
Callable create_custom_callable_function_pointer(T *p_instance, R (T::*p_method)(P...)) {
110106
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
111107
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
112-
return ::godot::internal::create_custom_callable(ccmp);
108+
return ::godot::internal::create_callable_from_ccmp(ccmp);
113109
}
114110

115111
//
@@ -123,8 +119,8 @@ class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
123119
(P...) const;
124120

125121
public:
126-
virtual Object *get_object() const override {
127-
return instance;
122+
virtual ObjectID get_object() const override {
123+
return ObjectID(instance->get_instance_id());
128124
}
129125

130126
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
@@ -141,7 +137,7 @@ template <class T, class R, class... P>
141137
Callable create_custom_callable_function_pointer(const T *p_instance, R (T::*p_method)(P...) const) {
142138
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
143139
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
144-
return ::godot::internal::create_custom_callable(ccmp);
140+
return ::godot::internal::create_callable_from_ccmp(ccmp);
145141
}
146142

147143
//
@@ -153,8 +149,8 @@ class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase
153149
void (*method)(P...);
154150

155151
public:
156-
virtual Object *get_object() const override {
157-
return nullptr;
152+
virtual ObjectID get_object() const override {
153+
return ObjectID();
158154
}
159155

160156
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
@@ -171,7 +167,7 @@ template <class... P>
171167
Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) {
172168
typedef CallableCustomStaticMethodPointer<P...> CCMP;
173169
CCMP *ccmp = memnew(CCMP(p_method));
174-
return ::godot::internal::create_custom_callable(ccmp);
170+
return ::godot::internal::create_callable_from_ccmp(ccmp);
175171
}
176172

177173
//
@@ -184,8 +180,8 @@ class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerB
184180
(P...);
185181

186182
public:
187-
virtual Object *get_object() const override {
188-
return nullptr;
183+
virtual ObjectID get_object() const override {
184+
return ObjectID();
189185
}
190186

191187
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const override {
@@ -201,7 +197,7 @@ template <class R, class... P>
201197
Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
202198
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP;
203199
CCMP *ccmp = memnew(CCMP(p_method));
204-
return ::godot::internal::create_custom_callable(ccmp);
200+
return ::godot::internal::create_callable_from_ccmp(ccmp);
205201
}
206202

207203
//

src/godot.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ GDExtensionInterfaceObjectCastTo gdextension_interface_object_cast_to = nullptr;
172172
GDExtensionInterfaceObjectGetInstanceFromId gdextension_interface_object_get_instance_from_id = nullptr;
173173
GDExtensionInterfaceObjectGetInstanceId gdextension_interface_object_get_instance_id = nullptr;
174174
GDExtensionInterfaceCallableCustomCreate gdextension_interface_callable_custom_create = nullptr;
175+
GDExtensionInterfaceCallableCustomGetUserData gdextension_interface_callable_custom_get_userdata = nullptr;
175176
GDExtensionInterfaceRefGetObject gdextension_interface_ref_get_object = nullptr;
176177
GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr;
177178
GDExtensionInterfaceScriptInstanceCreate2 gdextension_interface_script_instance_create2 = nullptr;
@@ -390,6 +391,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge
390391
LOAD_PROC_ADDRESS(object_get_instance_from_id, GDExtensionInterfaceObjectGetInstanceFromId);
391392
LOAD_PROC_ADDRESS(object_get_instance_id, GDExtensionInterfaceObjectGetInstanceId);
392393
LOAD_PROC_ADDRESS(callable_custom_create, GDExtensionInterfaceCallableCustomCreate);
394+
LOAD_PROC_ADDRESS(callable_custom_get_userdata, GDExtensionInterfaceCallableCustomGetUserData);
393395
LOAD_PROC_ADDRESS(ref_get_object, GDExtensionInterfaceRefGetObject);
394396
LOAD_PROC_ADDRESS(ref_set_object, GDExtensionInterfaceRefSetObject);
395397
LOAD_PROC_ADDRESS(script_instance_create2, GDExtensionInterfaceScriptInstanceCreate2);

0 commit comments

Comments
 (0)