Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/variant/variant_caster.h
45997 views
1
/**************************************************************************/
2
/* variant_caster.h */
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
#pragma once
32
33
#include "core/object/object.h"
34
#include "core/variant/type_info.h"
35
36
enum class HatDir;
37
enum class HatMask;
38
enum class JoyAxis;
39
enum class JoyButton;
40
41
enum class MIDIMessage;
42
enum class MouseButton;
43
enum class MouseButtonMask;
44
45
enum class Key;
46
enum class KeyModifierMask;
47
enum class KeyLocation;
48
49
// Variant cannot define an implicit cast operator for every Object subclass, so the
50
// casting is done here, to allow binding methods with parameters more specific than Object *
51
52
template <typename T>
53
struct VariantCaster {
54
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
55
using TStripped = std::remove_pointer_t<T>;
56
if constexpr (std::is_base_of_v<Object, TStripped>) {
57
return Object::cast_to<TStripped>(p_variant);
58
} else {
59
return p_variant;
60
}
61
}
62
};
63
64
template <typename T>
65
struct VariantCaster<T &> {
66
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
67
using TStripped = std::remove_pointer_t<T>;
68
if constexpr (std::is_base_of_v<Object, TStripped>) {
69
return Object::cast_to<TStripped>(p_variant);
70
} else {
71
return p_variant;
72
}
73
}
74
};
75
76
template <typename T>
77
struct VariantCaster<const T &> {
78
static _FORCE_INLINE_ T cast(const Variant &p_variant) {
79
using TStripped = std::remove_pointer_t<T>;
80
if constexpr (std::is_base_of_v<Object, TStripped>) {
81
return Object::cast_to<TStripped>(p_variant);
82
} else {
83
return p_variant;
84
}
85
}
86
};
87
88
// Object enum casts must go here
89
VARIANT_BITFIELD_CAST(Object::ConnectFlags);
90
91
VARIANT_ENUM_CAST(Vector2::Axis);
92
VARIANT_ENUM_CAST(Vector2i::Axis);
93
VARIANT_ENUM_CAST(Vector3::Axis);
94
VARIANT_ENUM_CAST(Vector3i::Axis);
95
VARIANT_ENUM_CAST(Vector4::Axis);
96
VARIANT_ENUM_CAST(Vector4i::Axis);
97
VARIANT_ENUM_CAST(EulerOrder);
98
VARIANT_ENUM_CAST(Projection::Planes);
99
100
VARIANT_ENUM_CAST(Error);
101
VARIANT_ENUM_CAST(Side);
102
VARIANT_ENUM_CAST(ClockDirection);
103
VARIANT_ENUM_CAST(Corner);
104
VARIANT_ENUM_CAST(HatDir);
105
VARIANT_BITFIELD_CAST(HatMask);
106
VARIANT_ENUM_CAST(JoyAxis);
107
VARIANT_ENUM_CAST(JoyButton);
108
109
VARIANT_ENUM_CAST(MIDIMessage);
110
VARIANT_ENUM_CAST(MouseButton);
111
VARIANT_BITFIELD_CAST(MouseButtonMask);
112
VARIANT_ENUM_CAST(Orientation);
113
VARIANT_ENUM_CAST(HorizontalAlignment);
114
VARIANT_ENUM_CAST(VerticalAlignment);
115
VARIANT_ENUM_CAST(InlineAlignment);
116
VARIANT_ENUM_CAST(PropertyHint);
117
VARIANT_BITFIELD_CAST(PropertyUsageFlags);
118
VARIANT_ENUM_CAST(Variant::Type);
119
VARIANT_ENUM_CAST(Variant::Operator);
120
121
// Key
122
123
VARIANT_ENUM_CAST(Key);
124
VARIANT_BITFIELD_CAST(KeyModifierMask);
125
VARIANT_ENUM_CAST(KeyLocation);
126
127
template <>
128
struct VariantCaster<char32_t> {
129
static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) {
130
return (char32_t)p_variant.operator int();
131
}
132
};
133
134
template <typename T>
135
struct VariantObjectClassChecker {
136
static _FORCE_INLINE_ bool check(const Variant &p_variant) {
137
using TStripped = std::remove_pointer_t<T>;
138
if constexpr (std::is_base_of_v<Object, TStripped>) {
139
Object *obj = p_variant;
140
return Object::cast_to<TStripped>(p_variant) || !obj;
141
} else {
142
return true;
143
}
144
}
145
};
146
147
template <typename T>
148
class Ref;
149
150
template <typename T>
151
struct VariantObjectClassChecker<const Ref<T> &> {
152
static _FORCE_INLINE_ bool check(const Variant &p_variant) {
153
Object *obj = p_variant;
154
const Ref<T> node = p_variant;
155
return node.ptr() || !obj;
156
}
157
};
158
159
#ifdef DEBUG_ENABLED
160
161
template <typename T>
162
struct VariantCasterAndValidate {
163
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
164
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
165
if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
166
!VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
167
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
168
r_error.argument = p_arg_idx;
169
r_error.expected = argtype;
170
}
171
172
return VariantCaster<T>::cast(*p_args[p_arg_idx]);
173
}
174
};
175
176
template <typename T>
177
struct VariantCasterAndValidate<T &> {
178
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
179
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
180
if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
181
!VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
182
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
183
r_error.argument = p_arg_idx;
184
r_error.expected = argtype;
185
}
186
187
return VariantCaster<T>::cast(*p_args[p_arg_idx]);
188
}
189
};
190
191
template <typename T>
192
struct VariantCasterAndValidate<const T &> {
193
static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) {
194
Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE;
195
if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) ||
196
!VariantObjectClassChecker<T>::check(*p_args[p_arg_idx])) {
197
r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
198
r_error.argument = p_arg_idx;
199
r_error.expected = argtype;
200
}
201
202
return VariantCaster<T>::cast(*p_args[p_arg_idx]);
203
}
204
};
205
206
#endif // DEBUG_ENABLED
207
208