1 | /**************************************************************************/ |
2 | /* method_bind.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 | #ifndef METHOD_BIND_H |
32 | #define METHOD_BIND_H |
33 | |
34 | #include "core/variant/binder_common.h" |
35 | |
36 | VARIANT_BITFIELD_CAST(MethodFlags) |
37 | |
38 | // some helpers |
39 | |
40 | class MethodBind { |
41 | int method_id; |
42 | uint32_t hint_flags = METHOD_FLAGS_DEFAULT; |
43 | StringName name; |
44 | StringName instance_class; |
45 | Vector<Variant> default_arguments; |
46 | int default_argument_count = 0; |
47 | int argument_count = 0; |
48 | |
49 | bool _static = false; |
50 | bool _const = false; |
51 | bool _returns = false; |
52 | bool _returns_raw_obj_ptr = false; |
53 | |
54 | protected: |
55 | Variant::Type *argument_types = nullptr; |
56 | #ifdef DEBUG_METHODS_ENABLED |
57 | Vector<StringName> arg_names; |
58 | #endif |
59 | void _set_const(bool p_const); |
60 | void _set_static(bool p_static); |
61 | void _set_returns(bool p_returns); |
62 | virtual Variant::Type _gen_argument_type(int p_arg) const = 0; |
63 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0; |
64 | void _generate_argument_types(int p_count); |
65 | |
66 | void set_argument_count(int p_count) { argument_count = p_count; } |
67 | |
68 | public: |
69 | _FORCE_INLINE_ const Vector<Variant> &get_default_arguments() const { return default_arguments; } |
70 | _FORCE_INLINE_ int get_default_argument_count() const { return default_argument_count; } |
71 | |
72 | _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { |
73 | int idx = p_arg - (argument_count - default_arguments.size()); |
74 | |
75 | if (idx < 0 || idx >= default_arguments.size()) { |
76 | return false; |
77 | } else { |
78 | return true; |
79 | } |
80 | } |
81 | |
82 | _FORCE_INLINE_ Variant get_default_argument(int p_arg) const { |
83 | int idx = p_arg - (argument_count - default_arguments.size()); |
84 | |
85 | if (idx < 0 || idx >= default_arguments.size()) { |
86 | return Variant(); |
87 | } else { |
88 | return default_arguments[idx]; |
89 | } |
90 | } |
91 | |
92 | _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { |
93 | ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); |
94 | return argument_types[p_argument + 1]; |
95 | } |
96 | |
97 | PropertyInfo get_argument_info(int p_argument) const; |
98 | PropertyInfo get_return_info() const; |
99 | |
100 | #ifdef DEBUG_METHODS_ENABLED |
101 | void set_argument_names(const Vector<StringName> &p_names); // Set by ClassDB, can't be inferred otherwise. |
102 | Vector<StringName> get_argument_names() const; |
103 | |
104 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const = 0; |
105 | #endif |
106 | |
107 | void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } |
108 | uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0) | (is_static() ? METHOD_FLAG_STATIC : 0); } |
109 | _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } |
110 | _FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; } |
111 | |
112 | _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; |
113 | |
114 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const = 0; |
115 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const = 0; |
116 | |
117 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const = 0; |
118 | |
119 | StringName get_name() const; |
120 | void set_name(const StringName &p_name); |
121 | _FORCE_INLINE_ int get_method_id() const { return method_id; } |
122 | _FORCE_INLINE_ bool is_const() const { return _const; } |
123 | _FORCE_INLINE_ bool is_static() const { return _static; } |
124 | _FORCE_INLINE_ bool has_return() const { return _returns; } |
125 | virtual bool is_vararg() const { return false; } |
126 | |
127 | _FORCE_INLINE_ bool is_return_type_raw_object_ptr() { return _returns_raw_obj_ptr; } |
128 | _FORCE_INLINE_ void set_return_type_is_raw_object_ptr(bool p_returns_raw_obj) { _returns_raw_obj_ptr = p_returns_raw_obj; } |
129 | |
130 | void set_default_arguments(const Vector<Variant> &p_defargs); |
131 | |
132 | uint32_t get_hash() const; |
133 | |
134 | MethodBind(); |
135 | virtual ~MethodBind(); |
136 | }; |
137 | |
138 | // MethodBindVarArg base CRTP |
139 | template <class Derived, class T, class R, bool should_returns> |
140 | class MethodBindVarArgBase : public MethodBind { |
141 | protected: |
142 | R(T::*method) |
143 | (const Variant **, int, Callable::CallError &); |
144 | MethodInfo method_info; |
145 | |
146 | public: |
147 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
148 | if (p_arg < 0) { |
149 | return _gen_return_type_info(); |
150 | } else if (p_arg < method_info.arguments.size()) { |
151 | return method_info.arguments[p_arg]; |
152 | } else { |
153 | return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); |
154 | } |
155 | } |
156 | |
157 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
158 | return _gen_argument_type_info(p_arg).type; |
159 | } |
160 | |
161 | #ifdef DEBUG_METHODS_ENABLED |
162 | virtual GodotTypeInfo::Metadata get_argument_meta(int) const override { |
163 | return GodotTypeInfo::METADATA_NONE; |
164 | } |
165 | #endif |
166 | |
167 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
168 | ERR_FAIL_MSG("Validated call can't be used with vararg methods. This is a bug." ); |
169 | } |
170 | |
171 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
172 | ERR_FAIL_MSG("ptrcall can't be used with vararg methods. This is a bug." ); |
173 | } |
174 | |
175 | virtual bool is_const() const { return false; } |
176 | |
177 | virtual bool is_vararg() const override { return true; } |
178 | |
179 | MethodBindVarArgBase( |
180 | R (T::*p_method)(const Variant **, int, Callable::CallError &), |
181 | const MethodInfo &p_method_info, |
182 | bool p_return_nil_is_variant) : |
183 | method(p_method), method_info(p_method_info) { |
184 | set_argument_count(method_info.arguments.size()); |
185 | Variant::Type *at = memnew_arr(Variant::Type, method_info.arguments.size() + 1); |
186 | at[0] = _gen_return_type_info().type; |
187 | if (method_info.arguments.size()) { |
188 | #ifdef DEBUG_METHODS_ENABLED |
189 | Vector<StringName> names; |
190 | names.resize(method_info.arguments.size()); |
191 | #endif |
192 | for (int i = 0; i < method_info.arguments.size(); i++) { |
193 | at[i + 1] = method_info.arguments[i].type; |
194 | #ifdef DEBUG_METHODS_ENABLED |
195 | names.write[i] = method_info.arguments[i].name; |
196 | #endif |
197 | } |
198 | |
199 | #ifdef DEBUG_METHODS_ENABLED |
200 | set_argument_names(names); |
201 | #endif |
202 | } |
203 | argument_types = at; |
204 | if (p_return_nil_is_variant) { |
205 | method_info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; |
206 | } |
207 | |
208 | _set_returns(should_returns); |
209 | } |
210 | |
211 | private: |
212 | PropertyInfo _gen_return_type_info() const { |
213 | return Derived::_gen_return_type_info_impl(); |
214 | } |
215 | }; |
216 | |
217 | // variadic, no return |
218 | template <class T> |
219 | class MethodBindVarArgT : public MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false> { |
220 | friend class MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>; |
221 | |
222 | public: |
223 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
224 | (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>::method)(p_args, p_arg_count, r_error); |
225 | return {}; |
226 | } |
227 | |
228 | MethodBindVarArgT( |
229 | void (T::*p_method)(const Variant **, int, Callable::CallError &), |
230 | const MethodInfo &p_method_info, |
231 | bool p_return_nil_is_variant) : |
232 | MethodBindVarArgBase<MethodBindVarArgT<T>, T, void, false>(p_method, p_method_info, p_return_nil_is_variant) { |
233 | } |
234 | |
235 | private: |
236 | static PropertyInfo _gen_return_type_info_impl() { |
237 | return {}; |
238 | } |
239 | }; |
240 | |
241 | template <class T> |
242 | MethodBind *create_vararg_method_bind(void (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { |
243 | MethodBind *a = memnew((MethodBindVarArgT<T>)(p_method, p_info, p_return_nil_is_variant)); |
244 | a->set_instance_class(T::get_class_static()); |
245 | return a; |
246 | } |
247 | |
248 | // variadic, return |
249 | template <class T, class R> |
250 | class MethodBindVarArgTR : public MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true> { |
251 | friend class MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>; |
252 | |
253 | public: |
254 | #if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__) |
255 | // Workaround GH-66343 raised only with UBSAN, seems to be a false positive. |
256 | #pragma GCC diagnostic push |
257 | #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" |
258 | #endif |
259 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
260 | return (static_cast<T *>(p_object)->*MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>::method)(p_args, p_arg_count, r_error); |
261 | } |
262 | |
263 | #if defined(SANITIZERS_ENABLED) && defined(__GNUC__) && !defined(__clang__) |
264 | #pragma GCC diagnostic pop |
265 | #endif |
266 | |
267 | MethodBindVarArgTR( |
268 | R (T::*p_method)(const Variant **, int, Callable::CallError &), |
269 | const MethodInfo &p_info, |
270 | bool p_return_nil_is_variant) : |
271 | MethodBindVarArgBase<MethodBindVarArgTR<T, R>, T, R, true>(p_method, p_info, p_return_nil_is_variant) { |
272 | } |
273 | |
274 | private: |
275 | static PropertyInfo _gen_return_type_info_impl() { |
276 | return GetTypeInfo<R>::get_class_info(); |
277 | } |
278 | }; |
279 | |
280 | template <class T, class R> |
281 | MethodBind *create_vararg_method_bind(R (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { |
282 | MethodBind *a = memnew((MethodBindVarArgTR<T, R>)(p_method, p_info, p_return_nil_is_variant)); |
283 | a->set_instance_class(T::get_class_static()); |
284 | return a; |
285 | } |
286 | |
287 | /**** VARIADIC TEMPLATES ****/ |
288 | |
289 | #ifndef TYPED_METHOD_BIND |
290 | class __UnexistingClass; |
291 | #define MB_T __UnexistingClass |
292 | #else |
293 | #define MB_T T |
294 | #endif |
295 | |
296 | // no return, not const |
297 | #ifdef TYPED_METHOD_BIND |
298 | template <class T, class... P> |
299 | #else |
300 | template <class... P> |
301 | #endif |
302 | class MethodBindT : public MethodBind { |
303 | void (MB_T::*method)(P...); |
304 | |
305 | protected: |
306 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
307 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
308 | return call_get_argument_type<P...>(p_arg); |
309 | } else { |
310 | return Variant::NIL; |
311 | } |
312 | } |
313 | |
314 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
315 | PropertyInfo pi; |
316 | call_get_argument_type_info<P...>(p_arg, pi); |
317 | return pi; |
318 | } |
319 | |
320 | public: |
321 | #ifdef DEBUG_METHODS_ENABLED |
322 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { |
323 | return call_get_argument_metadata<P...>(p_arg); |
324 | } |
325 | |
326 | #endif |
327 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
328 | #ifdef TYPED_METHOD_BIND |
329 | call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); |
330 | #else |
331 | call_with_variant_args_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); |
332 | #endif |
333 | return Variant(); |
334 | } |
335 | |
336 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
337 | #ifdef TYPED_METHOD_BIND |
338 | call_with_validated_object_instance_args(static_cast<T *>(p_object), method, p_args); |
339 | #else |
340 | call_with_validated_object_instance_args(reinterpret_cast<MB_T *>(p_object), method, p_args); |
341 | #endif |
342 | } |
343 | |
344 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
345 | #ifdef TYPED_METHOD_BIND |
346 | call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args); |
347 | #else |
348 | call_with_ptr_args<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args); |
349 | #endif |
350 | } |
351 | |
352 | MethodBindT(void (MB_T::*p_method)(P...)) { |
353 | method = p_method; |
354 | _generate_argument_types(sizeof...(P)); |
355 | set_argument_count(sizeof...(P)); |
356 | } |
357 | }; |
358 | |
359 | template <class T, class... P> |
360 | MethodBind *create_method_bind(void (T::*p_method)(P...)) { |
361 | #ifdef TYPED_METHOD_BIND |
362 | MethodBind *a = memnew((MethodBindT<T, P...>)(p_method)); |
363 | #else |
364 | MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method))); |
365 | #endif |
366 | a->set_instance_class(T::get_class_static()); |
367 | return a; |
368 | } |
369 | |
370 | // no return, const |
371 | |
372 | #ifdef TYPED_METHOD_BIND |
373 | template <class T, class... P> |
374 | #else |
375 | template <class... P> |
376 | #endif |
377 | class MethodBindTC : public MethodBind { |
378 | void (MB_T::*method)(P...) const; |
379 | |
380 | protected: |
381 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
382 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
383 | return call_get_argument_type<P...>(p_arg); |
384 | } else { |
385 | return Variant::NIL; |
386 | } |
387 | } |
388 | |
389 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
390 | PropertyInfo pi; |
391 | call_get_argument_type_info<P...>(p_arg, pi); |
392 | return pi; |
393 | } |
394 | |
395 | public: |
396 | #ifdef DEBUG_METHODS_ENABLED |
397 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { |
398 | return call_get_argument_metadata<P...>(p_arg); |
399 | } |
400 | |
401 | #endif |
402 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
403 | #ifdef TYPED_METHOD_BIND |
404 | call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); |
405 | #else |
406 | call_with_variant_argsc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); |
407 | #endif |
408 | return Variant(); |
409 | } |
410 | |
411 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
412 | #ifdef TYPED_METHOD_BIND |
413 | call_with_validated_object_instance_argsc(static_cast<T *>(p_object), method, p_args); |
414 | #else |
415 | call_with_validated_object_instance_argsc(reinterpret_cast<MB_T *>(p_object), method, p_args); |
416 | #endif |
417 | } |
418 | |
419 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
420 | #ifdef TYPED_METHOD_BIND |
421 | call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args); |
422 | #else |
423 | call_with_ptr_argsc<MB_T, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args); |
424 | #endif |
425 | } |
426 | |
427 | MethodBindTC(void (MB_T::*p_method)(P...) const) { |
428 | method = p_method; |
429 | _set_const(true); |
430 | _generate_argument_types(sizeof...(P)); |
431 | set_argument_count(sizeof...(P)); |
432 | } |
433 | }; |
434 | |
435 | template <class T, class... P> |
436 | MethodBind *create_method_bind(void (T::*p_method)(P...) const) { |
437 | #ifdef TYPED_METHOD_BIND |
438 | MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method)); |
439 | #else |
440 | MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method))); |
441 | #endif |
442 | a->set_instance_class(T::get_class_static()); |
443 | return a; |
444 | } |
445 | |
446 | // return, not const |
447 | |
448 | #ifdef TYPED_METHOD_BIND |
449 | template <class T, class R, class... P> |
450 | #else |
451 | template <class R, class... P> |
452 | #endif |
453 | class MethodBindTR : public MethodBind { |
454 | R(MB_T::*method) |
455 | (P...); |
456 | |
457 | protected: |
458 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
459 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
460 | return call_get_argument_type<P...>(p_arg); |
461 | } else { |
462 | return GetTypeInfo<R>::VARIANT_TYPE; |
463 | } |
464 | } |
465 | |
466 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
467 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
468 | PropertyInfo pi; |
469 | call_get_argument_type_info<P...>(p_arg, pi); |
470 | return pi; |
471 | } else { |
472 | return GetTypeInfo<R>::get_class_info(); |
473 | } |
474 | } |
475 | |
476 | public: |
477 | #ifdef DEBUG_METHODS_ENABLED |
478 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { |
479 | if (p_arg >= 0) { |
480 | return call_get_argument_metadata<P...>(p_arg); |
481 | } else { |
482 | return GetTypeInfo<R>::METADATA; |
483 | } |
484 | } |
485 | #endif |
486 | |
487 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
488 | Variant ret; |
489 | #ifdef TYPED_METHOD_BIND |
490 | call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); |
491 | #else |
492 | call_with_variant_args_ret_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); |
493 | #endif |
494 | return ret; |
495 | } |
496 | |
497 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
498 | #ifdef TYPED_METHOD_BIND |
499 | call_with_validated_object_instance_args_ret(static_cast<T *>(p_object), method, p_args, r_ret); |
500 | #else |
501 | call_with_validated_object_instance_args_ret(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret); |
502 | #endif |
503 | } |
504 | |
505 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
506 | #ifdef TYPED_METHOD_BIND |
507 | call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); |
508 | #else |
509 | call_with_ptr_args_ret<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret); |
510 | #endif |
511 | } |
512 | |
513 | MethodBindTR(R (MB_T::*p_method)(P...)) { |
514 | method = p_method; |
515 | _set_returns(true); |
516 | _generate_argument_types(sizeof...(P)); |
517 | set_argument_count(sizeof...(P)); |
518 | } |
519 | }; |
520 | |
521 | template <class T, class R, class... P> |
522 | MethodBind *create_method_bind(R (T::*p_method)(P...)) { |
523 | #ifdef TYPED_METHOD_BIND |
524 | MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method)); |
525 | #else |
526 | MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method))); |
527 | #endif |
528 | |
529 | a->set_instance_class(T::get_class_static()); |
530 | return a; |
531 | } |
532 | |
533 | // return, const |
534 | |
535 | #ifdef TYPED_METHOD_BIND |
536 | template <class T, class R, class... P> |
537 | #else |
538 | template <class R, class... P> |
539 | #endif |
540 | class MethodBindTRC : public MethodBind { |
541 | R(MB_T::*method) |
542 | (P...) const; |
543 | |
544 | protected: |
545 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
546 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
547 | return call_get_argument_type<P...>(p_arg); |
548 | } else { |
549 | return GetTypeInfo<R>::VARIANT_TYPE; |
550 | } |
551 | } |
552 | |
553 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
554 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
555 | PropertyInfo pi; |
556 | call_get_argument_type_info<P...>(p_arg, pi); |
557 | return pi; |
558 | } else { |
559 | return GetTypeInfo<R>::get_class_info(); |
560 | } |
561 | } |
562 | |
563 | public: |
564 | #ifdef DEBUG_METHODS_ENABLED |
565 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { |
566 | if (p_arg >= 0) { |
567 | return call_get_argument_metadata<P...>(p_arg); |
568 | } else { |
569 | return GetTypeInfo<R>::METADATA; |
570 | } |
571 | } |
572 | #endif |
573 | |
574 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
575 | Variant ret; |
576 | #ifdef TYPED_METHOD_BIND |
577 | call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); |
578 | #else |
579 | call_with_variant_args_retc_dv(reinterpret_cast<MB_T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); |
580 | #endif |
581 | return ret; |
582 | } |
583 | |
584 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
585 | #ifdef TYPED_METHOD_BIND |
586 | call_with_validated_object_instance_args_retc(static_cast<T *>(p_object), method, p_args, r_ret); |
587 | #else |
588 | call_with_validated_object_instance_args_retc(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret); |
589 | #endif |
590 | } |
591 | |
592 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
593 | #ifdef TYPED_METHOD_BIND |
594 | call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); |
595 | #else |
596 | call_with_ptr_args_retc<MB_T, R, P...>(reinterpret_cast<MB_T *>(p_object), method, p_args, r_ret); |
597 | #endif |
598 | } |
599 | |
600 | MethodBindTRC(R (MB_T::*p_method)(P...) const) { |
601 | method = p_method; |
602 | _set_returns(true); |
603 | _set_const(true); |
604 | _generate_argument_types(sizeof...(P)); |
605 | set_argument_count(sizeof...(P)); |
606 | } |
607 | }; |
608 | |
609 | template <class T, class R, class... P> |
610 | MethodBind *create_method_bind(R (T::*p_method)(P...) const) { |
611 | #ifdef TYPED_METHOD_BIND |
612 | MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method)); |
613 | #else |
614 | MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method))); |
615 | #endif |
616 | a->set_instance_class(T::get_class_static()); |
617 | return a; |
618 | } |
619 | |
620 | /* STATIC BINDS */ |
621 | |
622 | // no return |
623 | |
624 | template <class... P> |
625 | class MethodBindTS : public MethodBind { |
626 | void (*function)(P...); |
627 | |
628 | protected: |
629 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
630 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
631 | return call_get_argument_type<P...>(p_arg); |
632 | } else { |
633 | return Variant::NIL; |
634 | } |
635 | } |
636 | |
637 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
638 | PropertyInfo pi; |
639 | call_get_argument_type_info<P...>(p_arg, pi); |
640 | return pi; |
641 | } |
642 | |
643 | public: |
644 | #ifdef DEBUG_METHODS_ENABLED |
645 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { |
646 | return call_get_argument_metadata<P...>(p_arg); |
647 | } |
648 | |
649 | #endif |
650 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
651 | (void)p_object; // unused |
652 | call_with_variant_args_static_dv(function, p_args, p_arg_count, r_error, get_default_arguments()); |
653 | return Variant(); |
654 | } |
655 | |
656 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
657 | call_with_validated_variant_args_static_method(function, p_args); |
658 | } |
659 | |
660 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
661 | (void)p_object; |
662 | (void)r_ret; |
663 | call_with_ptr_args_static_method(function, p_args); |
664 | } |
665 | |
666 | MethodBindTS(void (*p_function)(P...)) { |
667 | function = p_function; |
668 | _generate_argument_types(sizeof...(P)); |
669 | set_argument_count(sizeof...(P)); |
670 | _set_static(true); |
671 | } |
672 | }; |
673 | |
674 | template <class... P> |
675 | MethodBind *create_static_method_bind(void (*p_method)(P...)) { |
676 | MethodBind *a = memnew((MethodBindTS<P...>)(p_method)); |
677 | return a; |
678 | } |
679 | |
680 | // return |
681 | |
682 | template <class R, class... P> |
683 | class MethodBindTRS : public MethodBind { |
684 | R(*function) |
685 | (P...); |
686 | |
687 | protected: |
688 | virtual Variant::Type _gen_argument_type(int p_arg) const override { |
689 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
690 | return call_get_argument_type<P...>(p_arg); |
691 | } else { |
692 | return GetTypeInfo<R>::VARIANT_TYPE; |
693 | } |
694 | } |
695 | |
696 | virtual PropertyInfo _gen_argument_type_info(int p_arg) const override { |
697 | if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { |
698 | PropertyInfo pi; |
699 | call_get_argument_type_info<P...>(p_arg, pi); |
700 | return pi; |
701 | } else { |
702 | return GetTypeInfo<R>::get_class_info(); |
703 | } |
704 | } |
705 | |
706 | public: |
707 | #ifdef DEBUG_METHODS_ENABLED |
708 | virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override { |
709 | if (p_arg >= 0) { |
710 | return call_get_argument_metadata<P...>(p_arg); |
711 | } else { |
712 | return GetTypeInfo<R>::METADATA; |
713 | } |
714 | } |
715 | |
716 | #endif |
717 | virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override { |
718 | Variant ret; |
719 | call_with_variant_args_static_ret_dv(function, p_args, p_arg_count, ret, r_error, get_default_arguments()); |
720 | return ret; |
721 | } |
722 | |
723 | virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override { |
724 | call_with_validated_variant_args_static_method_ret(function, p_args, r_ret); |
725 | } |
726 | |
727 | virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override { |
728 | (void)p_object; |
729 | call_with_ptr_args_static_method_ret(function, p_args, r_ret); |
730 | } |
731 | |
732 | MethodBindTRS(R (*p_function)(P...)) { |
733 | function = p_function; |
734 | _generate_argument_types(sizeof...(P)); |
735 | set_argument_count(sizeof...(P)); |
736 | _set_static(true); |
737 | _set_returns(true); |
738 | } |
739 | }; |
740 | |
741 | template <class R, class... P> |
742 | MethodBind *create_static_method_bind(R (*p_method)(P...)) { |
743 | MethodBind *a = memnew((MethodBindTRS<R, P...>)(p_method)); |
744 | return a; |
745 | } |
746 | |
747 | #endif // METHOD_BIND_H |
748 | |