1/**************************************************************************/
2/* callable.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 CALLABLE_H
32#define CALLABLE_H
33
34#include "core/object/object_id.h"
35#include "core/string/string_name.h"
36#include "core/templates/list.h"
37
38class Object;
39class Variant;
40class CallableCustom;
41
42// This is an abstraction of things that can be called.
43// It is used for signals and other cases where efficient calling of functions
44// is required. It is designed for the standard case (object and method)
45// but can be optimized or customized.
46
47// Enforce 16 bytes with `alignas` to avoid arch-specific alignment issues on x86 vs armv7.
48
49class Callable {
50 alignas(8) StringName method;
51 union {
52 uint64_t object = 0;
53 CallableCustom *custom;
54 };
55
56public:
57 struct CallError {
58 enum Error {
59 CALL_OK,
60 CALL_ERROR_INVALID_METHOD,
61 CALL_ERROR_INVALID_ARGUMENT, // expected is variant type
62 CALL_ERROR_TOO_MANY_ARGUMENTS, // expected is number of arguments
63 CALL_ERROR_TOO_FEW_ARGUMENTS, // expected is number of arguments
64 CALL_ERROR_INSTANCE_IS_NULL,
65 CALL_ERROR_METHOD_NOT_CONST,
66 };
67 Error error = Error::CALL_OK;
68 int argument = 0;
69 int expected = 0;
70 };
71
72 void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const;
73 void call_deferredp(const Variant **p_arguments, int p_argcount) const;
74 Variant callv(const Array &p_arguments) const;
75
76 template <typename... VarArgs>
77 void call_deferred(VarArgs... p_args) const {
78 Variant args[sizeof...(p_args) + 1] = { p_args..., 0 }; // +1 makes sure zero sized arrays are also supported.
79 const Variant *argptrs[sizeof...(p_args) + 1];
80 for (uint32_t i = 0; i < sizeof...(p_args); i++) {
81 argptrs[i] = &args[i];
82 }
83 return call_deferredp(sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
84 }
85
86 Error rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const;
87
88 _FORCE_INLINE_ bool is_null() const {
89 return method == StringName() && object == 0;
90 }
91 _FORCE_INLINE_ bool is_custom() const {
92 return method == StringName() && custom != nullptr;
93 }
94 _FORCE_INLINE_ bool is_standard() const {
95 return method != StringName();
96 }
97 bool is_valid() const;
98
99 template <typename... VarArgs>
100 Callable bind(VarArgs... p_args);
101 Callable bindv(const Array &p_arguments);
102
103 Callable bindp(const Variant **p_arguments, int p_argcount) const;
104 Callable unbind(int p_argcount) const;
105
106 Object *get_object() const;
107 ObjectID get_object_id() const;
108 StringName get_method() const;
109 CallableCustom *get_custom() const;
110 int get_bound_arguments_count() const;
111 void get_bound_arguments_ref(Vector<Variant> &r_arguments, int &r_argcount) const; // Internal engine use, the exposed one is below.
112 Array get_bound_arguments() const;
113
114 uint32_t hash() const;
115
116 const Callable *get_base_comparator() const; //used for bind/unbind to do less precise comparisons (ignoring binds) in signal connect/disconnect
117
118 bool operator==(const Callable &p_callable) const;
119 bool operator!=(const Callable &p_callable) const;
120 bool operator<(const Callable &p_callable) const;
121
122 void operator=(const Callable &p_callable);
123
124 operator String() const;
125
126 Callable(const Object *p_object, const StringName &p_method);
127 Callable(ObjectID p_object, const StringName &p_method);
128 Callable(CallableCustom *p_custom);
129 Callable(const Callable &p_callable);
130 Callable() {}
131 ~Callable();
132};
133
134class CallableCustom {
135 friend class Callable;
136 SafeRefCount ref_count;
137 bool referenced = false;
138
139public:
140 typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
141 typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b);
142
143 //for every type that inherits, these must always be the same for this type
144 virtual uint32_t hash() const = 0;
145 virtual String get_as_text() const = 0;
146 virtual CompareEqualFunc get_compare_equal_func() const = 0;
147 virtual CompareLessFunc get_compare_less_func() const = 0;
148 virtual bool is_valid() const;
149 virtual StringName get_method() const;
150 virtual ObjectID get_object() const = 0;
151 virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const = 0;
152 virtual Error rpc(int p_peer_id, const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) const;
153 virtual const Callable *get_base_comparator() const;
154 virtual int get_bound_arguments_count() const;
155 virtual void get_bound_arguments(Vector<Variant> &r_arguments, int &r_argcount) const;
156
157 CallableCustom();
158 virtual ~CallableCustom() {}
159};
160
161// This is just a proxy object to object signals, its only
162// allocated on demand by/for scripting languages so it can
163// be put inside a Variant, but it is not
164// used by the engine itself.
165
166// Enforce 16 bytes with `alignas` to avoid arch-specific alignment issues on x86 vs armv7.
167class Signal {
168 alignas(8) StringName name;
169 ObjectID object;
170
171public:
172 _FORCE_INLINE_ bool is_null() const {
173 return object.is_null() && name == StringName();
174 }
175 Object *get_object() const;
176 ObjectID get_object_id() const;
177 StringName get_name() const;
178
179 bool operator==(const Signal &p_signal) const;
180 bool operator!=(const Signal &p_signal) const;
181 bool operator<(const Signal &p_signal) const;
182
183 operator String() const;
184
185 Error emit(const Variant **p_arguments, int p_argcount) const;
186 Error connect(const Callable &p_callable, uint32_t p_flags = 0);
187 void disconnect(const Callable &p_callable);
188 bool is_connected(const Callable &p_callable) const;
189
190 Array get_connections() const;
191 Signal(const Object *p_object, const StringName &p_name);
192 Signal(ObjectID p_object, const StringName &p_name);
193 Signal() {}
194};
195
196struct CallableComparator {
197 const Callable &func;
198
199 bool operator()(const Variant &p_l, const Variant &p_r) const;
200};
201
202#endif // CALLABLE_H
203