-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathgodot_cpp.cpp
More file actions
104 lines (86 loc) · 4.23 KB
/
Copy pathgodot_cpp.cpp
File metadata and controls
104 lines (86 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Behavioral test for compat.godot-cpp.
//
// Two things are under test, and both can fail:
//
// 1. The PRE-GENERATED bindings are really in the package. gen/include is
// what upstream's binding_generator.py would have produced at build time;
// if it were missing, <godot_cpp/classes/node.hpp> and the global
// constants below would not compile at all.
// 2. The library links. Vector2::length(), Basis::orthonormalized(),
// Color::to_rgba32() and AABB::get_volume() are declared in the headers
// but DEFINED in src/variant/*.cpp, so these calls only resolve if the
// ~1000 translation units of the package were compiled and linked in.
//
// Everything asserted here is pure math -- no gdextension_interface function
// pointers, so no running Godot process is needed. Engine classes are checked
// by compiling against them (types, enums, sizes), which is all that can be
// done outside a loaded extension.
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/classes/node.hpp>
#include <godot_cpp/variant/aabb.hpp>
#include <godot_cpp/variant/basis.hpp>
#include <godot_cpp/variant/color.hpp>
#include <godot_cpp/variant/vector2.hpp>
#include <godot_cpp/variant/vector3.hpp>
#include <cmath>
#include <type_traits>
#include <cstdio>
namespace {
bool close(double a, double b) {
return std::fabs(a - b) < 1e-5;
}
} // namespace
using namespace godot;
// A GDCLASS subclass with bound methods -- the shape every GDExtension is
// written in, and the one that breaks first on a new platform: without
// TYPED_METHOD_BIND, ClassDB::bind_method casts member pointers through a
// forward-declared class, which the MSVC ABI rejects outright. Compiling and
// linking this is the assertion; it is never CALLED, because ClassDB and
// StringName go through the gdextension_interface_* pointers, which are null
// outside a Godot process that has loaded the extension.
class TestSprite : public Node {
GDCLASS(TestSprite, Node)
protected:
static void _bind_methods() {
ClassDB::bind_method(D_METHOD("get_speed"), &TestSprite::get_speed);
ClassDB::bind_method(D_METHOD("set_speed", "speed"), &TestSprite::set_speed);
}
public:
double get_speed() const { return speed; }
void set_speed(double p_speed) { speed = p_speed; }
private:
double speed = 1.0;
};
int main() {
// --- out-of-line variant math: proves the library linked ---
const bool vec2_ok = close(Vector2(3, 4).length(), 5.0) &&
close(Vector2(3, 4).normalized().length(), 1.0);
const Vector3 cross = Vector3(1, 0, 0).cross(Vector3(0, 1, 0));
const bool vec3_ok = cross == Vector3(0, 0, 1) &&
close(Vector3(2, 3, 6).length(), 7.0);
const Basis basis = Basis().orthonormalized();
const bool basis_ok = close(basis.determinant(), 1.0);
const bool color_ok = Color(1.0f, 0.0f, 0.0f, 1.0f).to_rgba32() == 0xff0000ffu;
const AABB box(Vector3(0, 0, 0), Vector3(2, 3, 4));
const AABB other(Vector3(1, 1, 1), Vector3(4, 4, 4));
const bool aabb_ok = close(box.get_volume(), 24.0) &&
box.intersects(other) &&
close(box.intersection(other).get_volume(), 1.0 * 2.0 * 3.0);
// --- generated bindings: engine class + global enums are visible ---
const bool gen_ok = sizeof(Node) > 0 &&
Node::PROCESS_MODE_INHERIT == 0 &&
Node::PROCESS_MODE_DISABLED == 4 &&
godot::OK == 0 &&
godot::ERR_FILE_NOT_FOUND == 7 &&
godot::SIDE_LEFT == 0 &&
Variant::OBJECT != Variant::NIL;
// ODR-use what GDCLASS generated without calling into the engine
const StringName &(*class_name_fn)() = &TestSprite::get_class_static;
void (*init_fn)() = &TestSprite::initialize_class;
const bool bind_ok = class_name_fn != nullptr && init_fn != nullptr &&
std::is_base_of<Node, TestSprite>::value;
const bool ok = bind_ok && vec2_ok && vec3_ok && basis_ok && color_ok && aabb_ok && gen_ok;
std::printf("bind=%d vec2=%d vec3=%d basis=%d color=%d aabb=%d gen=%d\n",
bind_ok, vec2_ok, vec3_ok, basis_ok, color_ok, aabb_ok, gen_ok);
return ok ? 0 : 1;
}