summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/config/engine.cpp10
-rw-r--r--core/config/engine.h5
-rw-r--r--core/core_bind.h3
-rw-r--r--core/core_constants.cpp2
-rw-r--r--core/input/input.cpp59
-rw-r--r--core/input/input.h7
-rw-r--r--core/input/input_event.cpp57
-rw-r--r--core/input/input_event.h15
-rw-r--r--core/input/input_map.cpp26
-rw-r--r--core/input/input_map.h7
-rw-r--r--core/io/file_access_pack.cpp30
-rw-r--r--core/io/file_access_pack.h24
-rw-r--r--core/io/file_access_zip.cpp1
-rw-r--r--core/io/http_client.cpp59
-rw-r--r--core/io/http_client.h4
-rw-r--r--core/io/image.cpp1
-rw-r--r--core/io/image.h2
-rw-r--r--core/io/ip.h2
-rw-r--r--core/io/ip_address.cpp1
-rw-r--r--core/io/json.cpp32
-rw-r--r--core/io/json.h24
-rw-r--r--core/io/marshalls.cpp4
-rw-r--r--core/io/multiplayer_api.h1
-rw-r--r--core/io/packed_data_container.cpp2
-rw-r--r--core/io/resource.cpp14
-rw-r--r--core/io/resource_format_binary.cpp4
-rw-r--r--core/io/resource_loader.cpp2
-rw-r--r--core/io/resource_saver.cpp2
-rw-r--r--core/io/resource_saver.h1
-rw-r--r--core/io/stream_peer_tcp.h1
-rw-r--r--core/math/color.cpp51
-rw-r--r--core/math/color.h69
-rw-r--r--core/math/color_names.inc10
-rw-r--r--core/math/expression.cpp717
-rw-r--r--core/math/expression.h82
-rw-r--r--core/math/geometry_3d.cpp2
-rw-r--r--core/math/math_defs.h5
-rw-r--r--core/math/math_fieldwise.cpp10
-rw-r--r--core/math/octree.h1
-rw-r--r--core/math/transform.cpp7
-rw-r--r--core/math/transform.h5
-rw-r--r--core/math/transform_2d.cpp2
-rw-r--r--core/math/transform_2d.h6
-rw-r--r--core/object/callable_method_pointer.h3
-rw-r--r--core/object/method_bind.h1
-rw-r--r--core/object/object.cpp6
-rw-r--r--core/object/object.h2
-rw-r--r--core/object/script_language.h1
-rw-r--r--core/os/file_access.cpp10
-rw-r--r--core/os/file_access.h1
-rw-r--r--core/os/keyboard.cpp1
-rw-r--r--core/os/keyboard.h3
-rw-r--r--core/os/os.h1
-rw-r--r--core/os/pool_allocator.h1
-rw-r--r--core/os/thread.h1
-rw-r--r--core/register_core_types.cpp18
-rw-r--r--core/string/string_name.h1
-rw-r--r--core/string/ustring.cpp1
-rw-r--r--core/string/ustring.h23
-rw-r--r--core/templates/sort_array.h1
-rw-r--r--core/variant/array.cpp7
-rw-r--r--core/variant/array.h1
-rw-r--r--core/variant/binder_common.h33
-rw-r--r--core/variant/type_info.h2
-rw-r--r--core/variant/typed_array.h4
-rw-r--r--core/variant/variant.cpp106
-rw-r--r--core/variant/variant.h196
-rw-r--r--core/variant/variant_call.cpp1676
-rw-r--r--core/variant/variant_construct.cpp812
-rw-r--r--core/variant/variant_internal.h495
-rw-r--r--core/variant/variant_op.cpp90
-rw-r--r--core/variant/variant_parser.h1
-rw-r--r--core/variant/variant_setget.cpp6
-rw-r--r--core/variant/variant_utility.cpp1381
74 files changed, 4034 insertions, 2220 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index b0037ffb37..8e2ab094b0 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -219,3 +219,13 @@ Engine *Engine::get_singleton() {
Engine::Engine() {
singleton = this;
}
+
+Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) :
+ name(p_name),
+ ptr(p_ptr) {
+#ifdef DEBUG_ENABLED
+ if (Object::cast_to<Reference>(p_ptr)) {
+ ERR_PRINT("A class intended to be used as a singleton must *not* inherit from Reference.");
+ }
+#endif
+}
diff --git a/core/config/engine.h b/core/config/engine.h
index 1d3d963b39..0d9aa02f28 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -41,10 +41,7 @@ public:
struct Singleton {
StringName name;
Object *ptr;
- Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr) :
- name(p_name),
- ptr(p_ptr) {
- }
+ Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr);
};
private:
diff --git a/core/core_bind.h b/core/core_bind.h
index 7794750387..4a642c47ce 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -83,7 +83,6 @@ protected:
public:
enum SaverFlags {
-
FLAG_RELATIVE_PATHS = 1,
FLAG_BUNDLE_RESOURCES = 2,
FLAG_CHANGE_PATH = 4,
@@ -361,7 +360,6 @@ protected:
public:
enum ModeFlags {
-
READ = 1,
WRITE = 2,
READ_WRITE = 3,
@@ -561,7 +559,6 @@ protected:
public:
enum Priority {
-
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH,
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 41fa188c5b..4229436e84 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -606,7 +606,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH);
- BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RID", Variant::_RID);
+ BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RID", Variant::RID);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_OBJECT", Variant::OBJECT);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_CALLABLE", Variant::CALLABLE);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_SIGNAL", Variant::SIGNAL);
diff --git a/core/input/input.cpp b/core/input/input.cpp
index ee66bf94cb..aa64ac09a7 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -149,6 +149,9 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed);
ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released);
ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength);
+ ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action"), &Input::get_action_strength);
+ ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis);
+ ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f));
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping);
ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed);
@@ -215,7 +218,9 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\"";
String pf = p_function;
- if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) {
+ if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" ||
+ pf == "is_action_just_pressed" || pf == "is_action_just_released" ||
+ pf == "get_action_strength" || pf == "get_axis" || pf == "get_vector")) {
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
@@ -326,6 +331,46 @@ float Input::get_action_strength(const StringName &p_action) const {
return E->get().strength;
}
+float Input::get_action_raw_strength(const StringName &p_action) const {
+ const Map<StringName, Action>::Element *E = action_state.find(p_action);
+ if (!E) {
+ return 0.0f;
+ }
+
+ return E->get().raw_strength;
+}
+
+float Input::get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const {
+ return get_action_strength(p_positive_action) - get_action_strength(p_negative_action);
+}
+
+Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone) const {
+ Vector2 vector = Vector2(
+ get_action_raw_strength(p_positive_x) - get_action_raw_strength(p_negative_x),
+ get_action_raw_strength(p_positive_y) - get_action_raw_strength(p_negative_y));
+
+ if (p_deadzone < 0.0f) {
+ // If the deadzone isn't specified, get it from the average of the actions.
+ p_deadzone = (InputMap::get_singleton()->action_get_deadzone(p_positive_x) +
+ InputMap::get_singleton()->action_get_deadzone(p_negative_x) +
+ InputMap::get_singleton()->action_get_deadzone(p_positive_y) +
+ InputMap::get_singleton()->action_get_deadzone(p_negative_y)) /
+ 4;
+ }
+
+ // Circular length limiting and deadzone.
+ float length = vector.length();
+ if (length <= p_deadzone) {
+ return Vector2();
+ } else if (length > 1.0f) {
+ return vector / length;
+ } else {
+ // Inverse lerp length to map (p_deadzone, 1) to (0, 1).
+ return vector * (Math::inverse_lerp(p_deadzone, 1.0f, length) / length);
+ }
+ return vector;
+}
+
float Input::get_joy_axis(int p_device, int p_axis) const {
_THREAD_SAFE_METHOD_
int c = _combine_device(p_axis, p_device);
@@ -603,10 +648,12 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em
action.physics_frame = Engine::get_singleton()->get_physics_frames();
action.idle_frame = Engine::get_singleton()->get_idle_frames();
action.pressed = p_event->is_action_pressed(E->key());
- action.strength = 0.f;
+ action.strength = 0.0f;
+ action.raw_strength = 0.0f;
action_state[E->key()] = action;
}
action_state[E->key()].strength = p_event->get_action_strength(E->key());
+ action_state[E->key()].raw_strength = p_event->get_action_raw_strength(E->key());
}
}
@@ -890,14 +937,6 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) {
return;
}
- if (p_value.value > joy.last_axis[p_axis]) {
- if (p_value.value < joy.last_axis[p_axis] + joy.filter) {
- return;
- }
- } else if (p_value.value > joy.last_axis[p_axis] - joy.filter) {
- return;
- }
-
//when changing direction quickly, insert fake event to release pending inputmap actions
float last = joy.last_axis[p_axis];
if (p_value.min == 0 && (last < 0.25 || last > 0.75) && (last - 0.5) * (p_value.value - 0.5) < 0) {
diff --git a/core/input/input.h b/core/input/input.h
index 98bbff6441..46e9d24bf2 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -117,6 +117,7 @@ private:
uint64_t idle_frame;
bool pressed;
float strength;
+ float raw_strength;
};
Map<StringName, Action> action_state;
@@ -146,7 +147,6 @@ private:
bool connected = false;
bool last_buttons[JOY_BUTTON_MAX] = { false };
float last_axis[JOY_AXIS_MAX] = { 0.0f };
- float filter = 0.01f;
int last_hat = HAT_MASK_CENTER;
int mapping = -1;
int hat_current = 0;
@@ -223,7 +223,6 @@ private:
JoyAxisList _get_output_axis(String output);
void _button_event(int p_device, int p_index, bool p_pressed);
void _axis_event(int p_device, int p_axis, float p_value);
- float _handle_deadzone(int p_device, int p_axis, float p_value);
void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated);
@@ -266,6 +265,10 @@ public:
bool is_action_just_pressed(const StringName &p_action) const;
bool is_action_just_released(const StringName &p_action) const;
float get_action_strength(const StringName &p_action) const;
+ float get_action_raw_strength(const StringName &p_action) const;
+
+ float get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const;
+ Vector2 get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone = -1.0f) const;
float get_joy_axis(int p_device, int p_axis) const;
String get_joy_name(int p_idx);
diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp
index 240f8c57d8..41bc5e84b0 100644
--- a/core/input/input_event.cpp
+++ b/core/input/input_event.cpp
@@ -61,12 +61,17 @@ bool InputEvent::is_action_released(const StringName &p_action) const {
}
float InputEvent::get_action_strength(const StringName &p_action) const {
- bool pressed;
float strength;
- bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed, &strength);
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, &strength);
return valid ? strength : 0.0f;
}
+float InputEvent::get_action_raw_strength(const StringName &p_action) const {
+ float raw_strength;
+ bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, nullptr, &raw_strength);
+ return valid ? raw_strength : 0.0f;
+}
+
bool InputEvent::is_pressed() const {
return false;
}
@@ -83,7 +88,7 @@ String InputEvent::as_text() const {
return String();
}
-bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
+bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
return false;
}
@@ -341,7 +346,7 @@ String InputEventKey::as_text() const {
return kc;
}
-bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
+bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
Ref<InputEventKey> key = p_event;
if (key.is_null()) {
return false;
@@ -363,8 +368,12 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed
if (p_pressed != nullptr) {
*p_pressed = key->is_pressed();
}
+ float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
if (p_strength != nullptr) {
- *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
+ *p_strength = strength;
+ }
+ if (p_raw_strength != nullptr) {
+ *p_raw_strength = strength;
}
}
return match;
@@ -504,7 +513,7 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co
return mb;
}
-bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
+bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_null()) {
return false;
@@ -515,8 +524,12 @@ bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p
if (p_pressed != nullptr) {
*p_pressed = mb->is_pressed();
}
+ float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
if (p_strength != nullptr) {
- *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
+ *p_strength = strength;
+ }
+ if (p_raw_strength != nullptr) {
+ *p_raw_strength = strength;
}
}
@@ -747,7 +760,7 @@ bool InputEventJoypadMotion::is_pressed() const {
return Math::abs(axis_value) >= 0.5f;
}
-bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
+bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
Ref<InputEventJoypadMotion> jm = p_event;
if (jm.is_null()) {
return false;
@@ -755,8 +768,9 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *
bool match = (axis == jm->axis); // Matches even if not in the same direction, but returns a "not pressed" event.
if (match) {
+ float jm_abs_axis_value = Math::abs(jm->get_axis_value());
bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0);
- bool pressed = same_direction ? Math::abs(jm->get_axis_value()) >= p_deadzone : false;
+ bool pressed = same_direction && jm_abs_axis_value >= p_deadzone;
if (p_pressed != nullptr) {
*p_pressed = pressed;
}
@@ -765,12 +779,19 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *
if (p_deadzone == 1.0f) {
*p_strength = 1.0f;
} else {
- *p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())), 0.0f, 1.0f);
+ *p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f);
}
} else {
*p_strength = 0.0f;
}
}
+ if (p_raw_strength != nullptr) {
+ if (same_direction) { // NOT pressed, because we want to ignore the deadzone.
+ *p_raw_strength = jm_abs_axis_value;
+ } else {
+ *p_raw_strength = 0.0f;
+ }
+ }
}
return match;
}
@@ -816,7 +837,7 @@ float InputEventJoypadButton::get_pressure() const {
return pressure;
}
-bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
+bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
Ref<InputEventJoypadButton> jb = p_event;
if (jb.is_null()) {
return false;
@@ -827,8 +848,12 @@ bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *
if (p_pressed != nullptr) {
*p_pressed = jb->is_pressed();
}
+ float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
if (p_strength != nullptr) {
- *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
+ *p_strength = strength;
+ }
+ if (p_raw_strength != nullptr) {
+ *p_raw_strength = strength;
}
}
@@ -1031,7 +1056,7 @@ bool InputEventAction::is_action(const StringName &p_action) const {
return action == p_action;
}
-bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const {
+bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const {
Ref<InputEventAction> act = p_event;
if (act.is_null()) {
return false;
@@ -1042,8 +1067,12 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pres
if (p_pressed != nullptr) {
*p_pressed = act->pressed;
}
+ float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
if (p_strength != nullptr) {
- *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f;
+ *p_strength = strength;
+ }
+ if (p_raw_strength != nullptr) {
+ *p_raw_strength = strength;
}
}
return match;
diff --git a/core/input/input_event.h b/core/input/input_event.h
index 969dc149e5..52b785c9a1 100644
--- a/core/input/input_event.h
+++ b/core/input/input_event.h
@@ -60,7 +60,6 @@ enum ButtonList {
};
enum JoyButtonList {
-
JOY_INVALID_BUTTON = -1,
// SDL Buttons
@@ -112,7 +111,6 @@ enum JoyButtonList {
};
enum JoyAxisList {
-
JOY_INVALID_AXIS = -1,
// SDL Axes
@@ -173,6 +171,7 @@ public:
bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false) const;
bool is_action_released(const StringName &p_action) const;
float get_action_strength(const StringName &p_action) const;
+ float get_action_raw_strength(const StringName &p_action) const;
// To be removed someday, since they do not make sense for all events
virtual bool is_pressed() const;
@@ -182,7 +181,7 @@ public:
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const;
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const;
virtual bool is_action_type() const;
@@ -289,7 +288,7 @@ public:
uint32_t get_keycode_with_modifiers() const;
uint32_t get_physical_keycode_with_modifiers() const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const override;
virtual bool is_action_type() const override { return true; }
@@ -348,7 +347,7 @@ public:
bool is_doubleclick() const;
virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool is_action_type() const override { return true; }
virtual String as_text() const override;
@@ -405,7 +404,7 @@ public:
virtual bool is_pressed() const override;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool is_action_type() const override { return true; }
virtual String as_text() const override;
@@ -432,7 +431,7 @@ public:
void set_pressure(float p_pressure);
float get_pressure() const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const override;
virtual bool is_action_type() const override { return true; }
@@ -517,7 +516,7 @@ public:
virtual bool is_action(const StringName &p_action) const;
- virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override;
+ virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override;
virtual bool shortcut_match(const Ref<InputEvent> &p_event) const override;
virtual bool is_action_type() const override { return true; }
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index ba1de3c58d..979809c7af 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -31,6 +31,7 @@
#include "input_map.h"
#include "core/config/project_settings.h"
+#include "core/input/input.h"
#include "core/os/keyboard.h"
InputMap *InputMap::singleton = nullptr;
@@ -50,7 +51,7 @@ void InputMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("action_erase_events", "action"), &InputMap::action_erase_events);
ClassDB::bind_method(D_METHOD("action_get_events", "action"), &InputMap::_action_get_events);
ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action);
- ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals);
+ ClassDB::bind_method(D_METHOD("load_from_project_settings"), &InputMap::load_from_project_settings);
}
void InputMap::add_action(const StringName &p_action, float p_deadzone) {
@@ -94,7 +95,7 @@ List<StringName> InputMap::get_actions() const {
return actions;
}
-List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const {
+List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
@@ -105,7 +106,7 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re
int device = e->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
- if (e->action_match(p_event, p_pressed, p_strength, p_action.deadzone)) {
+ if (e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
return E;
}
}
@@ -118,6 +119,12 @@ bool InputMap::has_action(const StringName &p_action) const {
return input_map.has(p_action);
}
+float InputMap::action_get_deadzone(const StringName &p_action) {
+ ERR_FAIL_COND_V_MSG(!input_map.has(p_action), 0.0f, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
+
+ return input_map[p_action].deadzone;
+}
+
void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) {
ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@@ -145,6 +152,9 @@ void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEve
List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event);
if (E) {
input_map[p_action].inputs.erase(E);
+ if (Input::get_singleton()->is_action_pressed(p_action)) {
+ Input::get_singleton()->action_release(p_action);
+ }
}
}
@@ -179,7 +189,7 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName
return event_get_action_status(p_event, p_action);
}
-bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) const {
+bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength, float *p_raw_strength) const {
Map<StringName, Action>::Element *E = input_map.find(p_action);
ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action '" + String(p_action) + "'.");
@@ -196,7 +206,8 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
bool pressed;
float strength;
- List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength);
+ float raw_strength;
+ List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength, &raw_strength);
if (event != nullptr) {
if (p_pressed != nullptr) {
*p_pressed = pressed;
@@ -204,6 +215,9 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str
if (p_strength != nullptr) {
*p_strength = strength;
}
+ if (p_raw_strength != nullptr) {
+ *p_raw_strength = raw_strength;
+ }
return true;
} else {
return false;
@@ -214,7 +228,7 @@ const Map<StringName, InputMap::Action> &InputMap::get_action_map() const {
return input_map;
}
-void InputMap::load_from_globals() {
+void InputMap::load_from_project_settings() {
input_map.clear();
List<PropertyInfo> pinfo;
diff --git a/core/input/input_map.h b/core/input/input_map.h
index 35c65d0881..948d78ebdd 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -54,7 +54,7 @@ private:
mutable Map<StringName, Action> input_map;
- List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr) const;
+ List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
Array _action_get_events(const StringName &p_action);
Array _get_actions();
@@ -70,6 +70,7 @@ public:
void add_action(const StringName &p_action, float p_deadzone = 0.5);
void erase_action(const StringName &p_action);
+ float action_get_deadzone(const StringName &p_action);
void action_set_deadzone(const StringName &p_action, float p_deadzone);
void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event);
bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event);
@@ -78,10 +79,10 @@ public:
const List<Ref<InputEvent>> *action_get_events(const StringName &p_action);
bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const;
- bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr) const;
+ bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const;
const Map<StringName, Action> &get_action_map() const;
- void load_from_globals();
+ void load_from_project_settings();
void load_default();
InputMap();
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index b63e0adc45..a025ca5730 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -442,8 +442,14 @@ String DirAccessPack::get_drive(int p_drive) {
return "";
}
-Error DirAccessPack::change_dir(String p_dir) {
+PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) {
String nd = p_dir.replace("\\", "/");
+
+ // Special handling since simplify_path() will forbid it
+ if (p_dir == "..") {
+ return current->parent;
+ }
+
bool absolute = false;
if (nd.begins_with("res://")) {
nd = nd.replace_first("res://", "");
@@ -483,13 +489,21 @@ Error DirAccessPack::change_dir(String p_dir) {
pd = pd->subdirs[p];
} else {
- return ERR_INVALID_PARAMETER;
+ return nullptr;
}
}
- current = pd;
+ return pd;
+}
- return OK;
+Error DirAccessPack::change_dir(String p_dir) {
+ PackedData::PackedDir *pd = _find_dir(p_dir);
+ if (pd) {
+ current = pd;
+ return OK;
+ } else {
+ return ERR_INVALID_PARAMETER;
+ }
}
String DirAccessPack::get_current_dir(bool p_include_drive) {
@@ -507,13 +521,17 @@ String DirAccessPack::get_current_dir(bool p_include_drive) {
bool DirAccessPack::file_exists(String p_file) {
p_file = fix_path(p_file);
- return current->files.has(p_file);
+ PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir());
+ if (!pd) {
+ return false;
+ }
+ return pd->files.has(p_file.get_file());
}
bool DirAccessPack::dir_exists(String p_dir) {
p_dir = fix_path(p_dir);
- return current->subdirs.has(p_dir);
+ return _find_dir(p_dir) != nullptr;
}
Error DirAccessPack::make_dir(String p_dir) {
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 5c58dc01b4..c13626a5aa 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -122,6 +122,9 @@ public:
_FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
+ _FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path);
+ _FORCE_INLINE_ bool has_directory(const String &p_path);
+
PackedData();
~PackedData();
};
@@ -199,6 +202,16 @@ bool PackedData::has_path(const String &p_path) {
return files.has(PathMD5(p_path.md5_buffer()));
}
+bool PackedData::has_directory(const String &p_path) {
+ DirAccess *da = try_open_directory(p_path);
+ if (da) {
+ memdelete(da);
+ return true;
+ } else {
+ return false;
+ }
+}
+
class DirAccessPack : public DirAccess {
PackedData::PackedDir *current;
@@ -206,6 +219,8 @@ class DirAccessPack : public DirAccess {
List<String> list_files;
bool cdir = false;
+ PackedData::PackedDir *_find_dir(String p_dir);
+
public:
virtual Error list_dir_begin();
virtual String get_next();
@@ -235,4 +250,13 @@ public:
~DirAccessPack() {}
};
+DirAccess *PackedData::try_open_directory(const String &p_path) {
+ DirAccess *da = memnew(DirAccessPack());
+ if (da->change_dir(p_path) != OK) {
+ memdelete(da);
+ da = nullptr;
+ }
+ return da;
+}
+
#endif // FILE_ACCESS_PACK_H
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index ce402fe8ed..1163c409bc 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -102,7 +102,6 @@ static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
static void godot_free(voidpf opaque, voidpf address) {
memfree(address);
}
-
} // extern "C"
void ZipArchive::close_handle(unzFile p_file) const {
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index a25413b21b..768fcdbb14 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -109,24 +109,41 @@ Ref<StreamPeer> HTTPClient::get_connection() const {
return connection;
}
+static bool _check_request_url(HTTPClient::Method p_method, const String &p_url) {
+ switch (p_method) {
+ case HTTPClient::METHOD_CONNECT: {
+ // Authority in host:port format, as in RFC7231
+ int pos = p_url.find_char(':');
+ return 0 < pos && pos < p_url.length() - 1;
+ }
+ case HTTPClient::METHOD_OPTIONS: {
+ if (p_url == "*") {
+ return true;
+ }
+ [[fallthrough]];
+ }
+ default:
+ // Absolute path or absolute URL
+ return p_url.begins_with("/") || p_url.begins_with("http://") || p_url.begins_with("https://");
+ }
+}
+
Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!_check_request_url(p_method, p_url), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
- if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
- // Don't append the standard ports
- request += "Host: " + conn_host + "\r\n";
- } else {
- request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
- }
+ bool add_host = true;
bool add_clen = p_body.size() > 0;
bool add_uagent = true;
bool add_accept = true;
for (int i = 0; i < p_headers.size(); i++) {
request += p_headers[i] + "\r\n";
+ if (add_host && p_headers[i].findn("Host:") == 0) {
+ add_host = false;
+ }
if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
add_clen = false;
}
@@ -137,6 +154,14 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
add_accept = false;
}
}
+ if (add_host) {
+ if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
+ // Don't append the standard ports
+ request += "Host: " + conn_host + "\r\n";
+ } else {
+ request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
+ }
+ }
if (add_clen) {
request += "Content-Length: " + itos(p_body.size()) + "\r\n";
// Should it add utf8 encoding?
@@ -178,22 +203,20 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector
Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) {
ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER);
- ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(!_check_request_url(p_method, p_url), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA);
String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n";
- if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
- // Don't append the standard ports
- request += "Host: " + conn_host + "\r\n";
- } else {
- request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
- }
+ bool add_host = true;
bool add_uagent = true;
bool add_accept = true;
bool add_clen = p_body.length() > 0;
for (int i = 0; i < p_headers.size(); i++) {
request += p_headers[i] + "\r\n";
+ if (add_host && p_headers[i].findn("Host:") == 0) {
+ add_host = false;
+ }
if (add_clen && p_headers[i].findn("Content-Length:") == 0) {
add_clen = false;
}
@@ -204,6 +227,14 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
add_accept = false;
}
}
+ if (add_host) {
+ if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) {
+ // Don't append the standard ports
+ request += "Host: " + conn_host + "\r\n";
+ } else {
+ request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n";
+ }
+ }
if (add_clen) {
request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n";
// Should it add utf8 encoding?
diff --git a/core/io/http_client.h b/core/io/http_client.h
index ece7e1924b..3d9fe321ba 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -41,7 +41,6 @@ class HTTPClient : public Reference {
public:
enum ResponseCode {
-
// 1xx informational
RESPONSE_CONTINUE = 100,
RESPONSE_SWITCHING_PROTOCOLS = 101,
@@ -116,7 +115,6 @@ public:
};
enum Method {
-
METHOD_GET,
METHOD_HEAD,
METHOD_POST,
@@ -131,7 +129,6 @@ public:
};
enum Status {
-
STATUS_DISCONNECTED,
STATUS_RESOLVING, // Resolving hostname (if passed a hostname)
STATUS_CANT_RESOLVE,
@@ -150,7 +147,6 @@ private:
static const int HOST_MIN_LEN = 4;
enum Port {
-
PORT_HTTP = 80,
PORT_HTTPS = 443,
diff --git a/core/io/image.cpp b/core/io/image.cpp
index 005fd481e8..f3c87a0f2d 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -80,7 +80,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = {
"ETC2_RGB8A1",
"ETC2_RA_AS_RG",
"FORMAT_DXT5_RA_AS_RG",
-
};
SavePNGFunc Image::save_png_func = nullptr;
diff --git a/core/io/image.h b/core/io/image.h
index fecb90cab0..c5ec74f02f 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -66,7 +66,6 @@ public:
};
enum Format {
-
FORMAT_L8, //luminance
FORMAT_LA8, //luminance-alpha
FORMAT_R8,
@@ -111,7 +110,6 @@ public:
static const char *format_names[FORMAT_MAX];
enum Interpolation {
-
INTERPOLATE_NEAREST,
INTERPOLATE_BILINEAR,
INTERPOLATE_CUBIC,
diff --git a/core/io/ip.h b/core/io/ip.h
index d434d02f9b..32572b8eb2 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -42,7 +42,6 @@ class IP : public Object {
public:
enum ResolverStatus {
-
RESOLVER_STATUS_NONE,
RESOLVER_STATUS_WAITING,
RESOLVER_STATUS_DONE,
@@ -50,7 +49,6 @@ public:
};
enum Type {
-
TYPE_NONE = 0,
TYPE_IPV4 = 1,
TYPE_IPV6 = 2,
diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp
index d0fb63b958..7d730e5ae8 100644
--- a/core/io/ip_address.cpp
+++ b/core/io/ip_address.cpp
@@ -31,7 +31,6 @@
#include "ip_address.h"
/*
IP_Address::operator Variant() const {
-
return operator String();
}*/
diff --git a/core/io/json.cpp b/core/io/json.cpp
index 58bce1cf63..d61c2b8236 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -455,3 +455,35 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &
return err;
}
+
+Error JSONParser::parse_string(const String &p_json_string) {
+ return JSON::parse(p_json_string, data, err_text, err_line);
+}
+String JSONParser::get_error_text() const {
+ return err_text;
+}
+int JSONParser::get_error_line() const {
+ return err_line;
+}
+Variant JSONParser::get_data() const {
+ return data;
+}
+
+Error JSONParser::decode_data(const Variant &p_data, const String &p_indent, bool p_sort_keys) {
+ string = JSON::print(p_data, p_indent, p_sort_keys);
+ data = p_data;
+ return OK;
+}
+
+String JSONParser::get_string() const {
+ return string;
+}
+
+void JSONParser::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("parse_string", "json_string"), &JSONParser::parse_string);
+ ClassDB::bind_method(D_METHOD("get_error_text"), &JSONParser::get_error_text);
+ ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParser::get_error_line);
+ ClassDB::bind_method(D_METHOD("get_data"), &JSONParser::get_data);
+ ClassDB::bind_method(D_METHOD("decode_data", "data", "indent", "sort_keys"), &JSONParser::decode_data, DEFVAL(""), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_string"), &JSONParser::get_string);
+}
diff --git a/core/io/json.h b/core/io/json.h
index 9fc6655fb4..431b252e55 100644
--- a/core/io/json.h
+++ b/core/io/json.h
@@ -31,8 +31,8 @@
#ifndef JSON_H
#define JSON_H
+#include "core/object/reference.h"
#include "core/variant/variant.h"
-
class JSON {
enum TokenType {
TK_CURLY_BRACKET_OPEN,
@@ -49,7 +49,6 @@ class JSON {
};
enum Expecting {
-
EXPECT_OBJECT,
EXPECT_OBJECT_KEY,
EXPECT_COLON,
@@ -75,4 +74,25 @@ public:
static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
};
+class JSONParser : public Reference {
+ GDCLASS(JSONParser, Reference);
+
+ Variant data;
+ String string;
+ String err_text;
+ int err_line = 0;
+
+protected:
+ static void _bind_methods();
+
+public:
+ Error parse_string(const String &p_json_string);
+ String get_error_text() const;
+ int get_error_line() const;
+ Variant get_data() const;
+
+ Error decode_data(const Variant &p_data, const String &p_indent = "", bool p_sort_keys = true);
+ String get_string() const;
+};
+
#endif // JSON_H
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index c354c8ea63..3cf4acaf39 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -420,7 +420,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
}
} break;
- case Variant::_RID: {
+ case Variant::RID: {
r_variant = RID();
} break;
case Variant::OBJECT: {
@@ -1172,7 +1172,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4 * 4;
} break;
- case Variant::_RID: {
+ case Variant::RID: {
} break;
case Variant::CALLABLE: {
} break;
diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h
index e0ce1c8ca4..5b30c2e680 100644
--- a/core/io/multiplayer_api.h
+++ b/core/io/multiplayer_api.h
@@ -102,7 +102,6 @@ public:
};
enum RPCMode {
-
RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default)
RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers
RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote
diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp
index f70482288d..fbe8fa8a28 100644
--- a/core/io/packed_data_container.cpp
+++ b/core/io/packed_data_container.cpp
@@ -246,7 +246,7 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
} break;
// misc types
- case Variant::_RID:
+ case Variant::RID:
case Variant::OBJECT: {
return _pack(Variant(), tmpdata, string_cache);
} break;
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 5b249f7af3..58ab9a8cde 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -147,8 +147,8 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
List<PropertyInfo> plist;
get_property_list(&plist);
- Resource *r = Object::cast_to<Resource>(ClassDB::instance(get_class()));
- ERR_FAIL_COND_V(!r, Ref<Resource>());
+ Ref<Resource> r = Object::cast_to<Resource>(ClassDB::instance(get_class()));
+ ERR_FAIL_COND_V(r.is_null(), Ref<Resource>());
r->local_scene = p_for_scene;
@@ -175,9 +175,7 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
r->set(E->get().name, p);
}
- RES res = Ref<Resource>(r);
-
- return res;
+ return r;
}
void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) {
@@ -209,8 +207,8 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
List<PropertyInfo> plist;
get_property_list(&plist);
- Resource *r = (Resource *)ClassDB::instance(get_class());
- ERR_FAIL_COND_V(!r, Ref<Resource>());
+ Ref<Resource> r = (Resource *)ClassDB::instance(get_class());
+ ERR_FAIL_COND_V(r.is_null(), Ref<Resource>());
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
@@ -230,7 +228,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
}
}
- return Ref<Resource>(r);
+ return r;
}
void Resource::_set_path(const String &p_path) {
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index fe93d9b067..aeb859aabd 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -41,7 +41,6 @@
#define print_bl(m_what) (void)(m_what)
enum {
-
//numbering must be different from variant, in case new variant types are added (variant must be always contiguous for jumptable optimization)
VARIANT_NIL = 1,
VARIANT_BOOL = 2,
@@ -90,7 +89,6 @@ enum {
FORMAT_VERSION = 3,
FORMAT_VERSION_CAN_RENAME_DEPS = 1,
FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3,
-
};
void ResourceLoaderBinary::_advance_padding(uint32_t p_len) {
@@ -1467,7 +1465,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
}
} break;
- case Variant::_RID: {
+ case Variant::RID: {
f->store_32(VARIANT_RID);
WARN_PRINT("Can't save RIDs.");
RID val = p_property;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 9991ee405e..a8ca6a817e 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -1057,7 +1057,7 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) {
ERR_FAIL_COND_V_MSG(obj == nullptr, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + ".");
- ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj);
+ Ref<ResourceFormatLoader> crl = Object::cast_to<ResourceFormatLoader>(obj);
crl->set_script(s);
ResourceLoader::add_resource_format_loader(crl);
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 2eac2a6b4d..6ded27d82f 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -214,7 +214,7 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) {
ERR_FAIL_COND_V_MSG(obj == nullptr, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + ".");
- ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj);
+ Ref<ResourceFormatSaver> crl = Object::cast_to<ResourceFormatSaver>(obj);
crl->set_script(s);
ResourceSaver::add_resource_format_saver(crl);
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 2e2950af53..c724c4a6e5 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -63,7 +63,6 @@ class ResourceSaver {
public:
enum SaverFlags {
-
FLAG_RELATIVE_PATHS = 1,
FLAG_BUNDLE_RESOURCES = 2,
FLAG_CHANGE_PATH = 4,
diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h
index 45205866b4..173f92e2b6 100644
--- a/core/io/stream_peer_tcp.h
+++ b/core/io/stream_peer_tcp.h
@@ -42,7 +42,6 @@ class StreamPeerTCP : public StreamPeer {
public:
enum Status {
-
STATUS_NONE,
STATUS_CONNECTING,
STATUS_CONNECTED,
diff --git a/core/math/color.cpp b/core/math/color.cpp
index 6e0f68a2d6..2afe14bd63 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -159,7 +159,7 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) {
a = p_alpha;
if (p_s == 0) {
- // acp_hromatic (grey)
+ // Achromatic (grey)
r = g = b = p_v;
return;
}
@@ -489,6 +489,13 @@ Color Color::operator+(const Color &p_color) const {
a + p_color.a);
}
+void Color::operator+=(const Color &p_color) {
+ r = r + p_color.r;
+ g = g + p_color.g;
+ b = b + p_color.b;
+ a = a + p_color.a;
+}
+
Color Color::operator-(const Color &p_color) const {
return Color(
r - p_color.r,
@@ -512,12 +519,12 @@ Color Color::operator*(const Color &p_color) const {
a * p_color.a);
}
-Color Color::operator*(real_t rvalue) const {
+Color Color::operator*(real_t p_rvalue) const {
return Color(
- r * rvalue,
- g * rvalue,
- b * rvalue,
- a * rvalue);
+ r * p_rvalue,
+ g * p_rvalue,
+ b * p_rvalue,
+ a * p_rvalue);
}
void Color::operator*=(const Color &p_color) {
@@ -527,11 +534,11 @@ void Color::operator*=(const Color &p_color) {
a = a * p_color.a;
}
-void Color::operator*=(real_t rvalue) {
- r = r * rvalue;
- g = g * rvalue;
- b = b * rvalue;
- a = a * rvalue;
+void Color::operator*=(real_t p_rvalue) {
+ r = r * p_rvalue;
+ g = g * p_rvalue;
+ b = b * p_rvalue;
+ a = a * p_rvalue;
}
Color Color::operator/(const Color &p_color) const {
@@ -542,12 +549,12 @@ Color Color::operator/(const Color &p_color) const {
a / p_color.a);
}
-Color Color::operator/(real_t rvalue) const {
+Color Color::operator/(real_t p_rvalue) const {
return Color(
- r / rvalue,
- g / rvalue,
- b / rvalue,
- a / rvalue);
+ r / p_rvalue,
+ g / p_rvalue,
+ b / p_rvalue,
+ a / p_rvalue);
}
void Color::operator/=(const Color &p_color) {
@@ -557,17 +564,17 @@ void Color::operator/=(const Color &p_color) {
a = a / p_color.a;
}
-void Color::operator/=(real_t rvalue) {
- if (rvalue == 0) {
+void Color::operator/=(real_t p_rvalue) {
+ if (p_rvalue == 0) {
r = 1.0;
g = 1.0;
b = 1.0;
a = 1.0;
} else {
- r = r / rvalue;
- g = g / rvalue;
- b = b / rvalue;
- a = a / rvalue;
+ r = r / p_rvalue;
+ g = g / p_rvalue;
+ b = b / p_rvalue;
+ a = a / p_rvalue;
}
}
diff --git a/core/math/color.h b/core/math/color.h
index a03ddbf5af..a9be9e9035 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -45,9 +45,6 @@ struct Color {
float components[4] = { 0, 0, 0, 1.0 };
};
- bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); }
- bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); }
-
uint32_t to_rgba32() const;
uint32_t to_argb32() const;
uint32_t to_abgr32() const;
@@ -59,34 +56,36 @@ struct Color {
float get_v() const;
void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0);
- _FORCE_INLINE_ float &operator[](int idx) {
- return components[idx];
+ _FORCE_INLINE_ float &operator[](int p_idx) {
+ return components[p_idx];
}
- _FORCE_INLINE_ const float &operator[](int idx) const {
- return components[idx];
+ _FORCE_INLINE_ const float &operator[](int p_idx) const {
+ return components[p_idx];
}
- Color operator+(const Color &p_color) const;
- _FORCE_INLINE_ void operator+=(const Color &p_color) {
- r = r + p_color.r;
- g = g + p_color.g;
- b = b + p_color.b;
- a = a + p_color.a;
+ bool operator==(const Color &p_color) const {
+ return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a);
+ }
+ bool operator!=(const Color &p_color) const {
+ return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a);
}
+ Color operator+(const Color &p_color) const;
+ void operator+=(const Color &p_color);
+
Color operator-() const;
Color operator-(const Color &p_color) const;
void operator-=(const Color &p_color);
Color operator*(const Color &p_color) const;
- Color operator*(real_t rvalue) const;
+ Color operator*(real_t p_rvalue) const;
void operator*=(const Color &p_color);
- void operator*=(real_t rvalue);
+ void operator*=(real_t p_rvalue);
Color operator/(const Color &p_color) const;
- Color operator/(real_t rvalue) const;
+ Color operator/(real_t p_rvalue) const;
void operator/=(const Color &p_color);
- void operator/=(real_t rvalue);
+ void operator/=(real_t p_rvalue);
bool is_equal_approx(const Color &p_color) const;
@@ -123,10 +122,9 @@ struct Color {
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
const float pow2to9 = 512.0f;
const float B = 15.0f;
- //const float Emax = 31.0f;
const float N = 9.0f;
- float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f);
+ float sharedexp = 65408.000f; // Result of: ((pow2to9 - 1.0f) / pow2to9) * powf(2.0f, 31.0f - 15.0f)
float cRed = MAX(0.0f, MIN(sharedexp, r));
float cGreen = MAX(0.0f, MIN(sharedexp, g));
@@ -134,8 +132,6 @@ struct Color {
float cMax = MAX(cRed, MAX(cGreen, cBlue));
- // expp = MAX(-B - 1, log2(maxc)) + 1 + B
-
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
@@ -196,26 +192,27 @@ struct Color {
_FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys
operator String() const;
- //for binder
+ // For the binder.
_FORCE_INLINE_ void set_r8(int32_t r8) { r = (CLAMP(r8, 0, 255) / 255.0); }
- _FORCE_INLINE_ int32_t get_r8() const { return CLAMP(uint32_t(r * 255.0), 0, 255); }
+ _FORCE_INLINE_ int32_t get_r8() const { return int32_t(CLAMP(r * 255.0, 0.0, 255.0)); }
_FORCE_INLINE_ void set_g8(int32_t g8) { g = (CLAMP(g8, 0, 255) / 255.0); }
- _FORCE_INLINE_ int32_t get_g8() const { return CLAMP(uint32_t(g * 255.0), 0, 255); }
+ _FORCE_INLINE_ int32_t get_g8() const { return int32_t(CLAMP(g * 255.0, 0.0, 255.0)); }
_FORCE_INLINE_ void set_b8(int32_t b8) { b = (CLAMP(b8, 0, 255) / 255.0); }
- _FORCE_INLINE_ int32_t get_b8() const { return CLAMP(uint32_t(b * 255.0), 0, 255); }
+ _FORCE_INLINE_ int32_t get_b8() const { return int32_t(CLAMP(b * 255.0, 0.0, 255.0)); }
_FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0); }
- _FORCE_INLINE_ int32_t get_a8() const { return CLAMP(uint32_t(a * 255.0), 0, 255); }
+ _FORCE_INLINE_ int32_t get_a8() const { return int32_t(CLAMP(a * 255.0, 0.0, 255.0)); }
- _FORCE_INLINE_ void set_h(float h) { set_hsv(h, get_s(), get_v()); }
- _FORCE_INLINE_ void set_s(float s) { set_hsv(get_h(), s, get_v()); }
- _FORCE_INLINE_ void set_v(float v) { set_hsv(get_h(), get_s(), v); }
+ _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v()); }
+ _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v()); }
+ _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v); }
_FORCE_INLINE_ Color() {}
/**
- * RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0
+ * RGBA construct parameters.
+ * Alpha is not optional as otherwise we can't bind the RGB version for scripting.
*/
- _FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) {
+ _FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a) {
r = p_r;
g = p_g;
b = p_b;
@@ -223,6 +220,16 @@ struct Color {
}
/**
+ * RGB construct parameters.
+ */
+ _FORCE_INLINE_ Color(float p_r, float p_g, float p_b) {
+ r = p_r;
+ g = p_g;
+ b = p_b;
+ a = 1.0;
+ }
+
+ /**
* Construct a Color from another Color, but with the specified alpha value.
*/
_FORCE_INLINE_ Color(const Color &p_c, float p_a) {
diff --git a/core/math/color_names.inc b/core/math/color_names.inc
index cbc821026e..523c7e3c59 100644
--- a/core/math/color_names.inc
+++ b/core/math/color_names.inc
@@ -61,9 +61,7 @@ static NamedColor named_colors[] = {
{ "gold", Color(1.00, 0.84, 0.00) },
{ "goldenrod", Color(0.85, 0.65, 0.13) },
{ "gray", Color(0.75, 0.75, 0.75) },
- { "webgray", Color(0.50, 0.50, 0.50) },
{ "green", Color(0.00, 1.00, 0.00) },
- { "webgreen", Color(0.00, 0.50, 0.00) },
{ "greenyellow", Color(0.68, 1.00, 0.18) },
{ "honeydew", Color(0.94, 1.00, 0.94) },
{ "hotpink", Color(1.00, 0.41, 0.71) },
@@ -93,7 +91,6 @@ static NamedColor named_colors[] = {
{ "linen", Color(0.98, 0.94, 0.90) },
{ "magenta", Color(1.00, 0.00, 1.00) },
{ "maroon", Color(0.69, 0.19, 0.38) },
- { "webmaroon", Color(0.50, 0.00, 0.00) },
{ "mediumaquamarine", Color(0.40, 0.80, 0.67) },
{ "mediumblue", Color(0.00, 0.00, 0.80) },
{ "mediumorchid", Color(0.73, 0.33, 0.83) },
@@ -126,7 +123,6 @@ static NamedColor named_colors[] = {
{ "plum", Color(0.87, 0.63, 0.87) },
{ "powderblue", Color(0.69, 0.88, 0.90) },
{ "purple", Color(0.63, 0.13, 0.94) },
- { "webpurple", Color(0.50, 0.00, 0.50) },
{ "rebeccapurple", Color(0.40, 0.20, 0.60) },
{ "red", Color(1.00, 0.00, 0.00) },
{ "rosybrown", Color(0.74, 0.56, 0.56) },
@@ -148,9 +144,13 @@ static NamedColor named_colors[] = {
{ "teal", Color(0.00, 0.50, 0.50) },
{ "thistle", Color(0.85, 0.75, 0.85) },
{ "tomato", Color(1.00, 0.39, 0.28) },
- { "turquoise", Color(0.25, 0.88, 0.82) },
{ "transparent", Color(1.00, 1.00, 1.00, 0.00) },
+ { "turquoise", Color(0.25, 0.88, 0.82) },
{ "violet", Color(0.93, 0.51, 0.93) },
+ { "webgray", Color(0.50, 0.50, 0.50) },
+ { "webgreen", Color(0.00, 0.50, 0.00) },
+ { "webmaroon", Color(0.50, 0.00, 0.00) },
+ { "webpurple", Color(0.50, 0.00, 0.50) },
{ "wheat", Color(0.96, 0.87, 0.70) },
{ "white", Color(1.00, 1.00, 1.00) },
{ "whitesmoke", Color(0.96, 0.96, 0.96) },
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 426586fc9c..d1f15caa5e 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -37,688 +37,6 @@
#include "core/os/os.h"
#include "core/variant/variant_parser.h"
-const char *Expression::func_name[Expression::FUNC_MAX] = {
- "sin",
- "cos",
- "tan",
- "sinh",
- "cosh",
- "tanh",
- "asin",
- "acos",
- "atan",
- "atan2",
- "sqrt",
- "fmod",
- "fposmod",
- "posmod",
- "floor",
- "ceil",
- "round",
- "abs",
- "sign",
- "pow",
- "log",
- "exp",
- "is_nan",
- "is_inf",
- "ease",
- "step_decimals",
- "stepify",
- "lerp",
- "lerp_angle",
- "inverse_lerp",
- "range_lerp",
- "smoothstep",
- "move_toward",
- "dectime",
- "randomize",
- "randi",
- "randf",
- "randf_range",
- "randi_range",
- "seed",
- "rand_seed",
- "deg2rad",
- "rad2deg",
- "linear2db",
- "db2linear",
- "polar2cartesian",
- "cartesian2polar",
- "wrapi",
- "wrapf",
- "max",
- "min",
- "clamp",
- "nearest_po2",
- "weakref",
- "convert",
- "typeof",
- "type_exists",
- "char",
- "ord",
- "str",
- "print",
- "printerr",
- "printraw",
- "var2str",
- "str2var",
- "var2bytes",
- "bytes2var",
- "color_named",
-};
-
-Expression::BuiltinFunc Expression::find_function(const String &p_string) {
- for (int i = 0; i < FUNC_MAX; i++) {
- if (p_string == func_name[i]) {
- return BuiltinFunc(i);
- }
- }
-
- return FUNC_MAX;
-}
-
-String Expression::get_func_name(BuiltinFunc p_func) {
- ERR_FAIL_INDEX_V(p_func, FUNC_MAX, String());
- return func_name[p_func];
-}
-
-int Expression::get_func_argument_count(BuiltinFunc p_func) {
- switch (p_func) {
- case MATH_RANDOMIZE:
- case MATH_RANDI:
- case MATH_RANDF:
- return 0;
- case MATH_SIN:
- case MATH_COS:
- case MATH_TAN:
- case MATH_SINH:
- case MATH_COSH:
- case MATH_TANH:
- case MATH_ASIN:
- case MATH_ACOS:
- case MATH_ATAN:
- case MATH_SQRT:
- case MATH_FLOOR:
- case MATH_CEIL:
- case MATH_ROUND:
- case MATH_ABS:
- case MATH_SIGN:
- case MATH_LOG:
- case MATH_EXP:
- case MATH_ISNAN:
- case MATH_ISINF:
- case MATH_STEP_DECIMALS:
- case MATH_SEED:
- case MATH_RANDSEED:
- case MATH_DEG2RAD:
- case MATH_RAD2DEG:
- case MATH_LINEAR2DB:
- case MATH_DB2LINEAR:
- case LOGIC_NEAREST_PO2:
- case OBJ_WEAKREF:
- case TYPE_OF:
- case TEXT_CHAR:
- case TEXT_ORD:
- case TEXT_STR:
- case TEXT_PRINT:
- case TEXT_PRINTERR:
- case TEXT_PRINTRAW:
- case VAR_TO_STR:
- case STR_TO_VAR:
- case TYPE_EXISTS:
- return 1;
- case VAR_TO_BYTES:
- case BYTES_TO_VAR:
- case MATH_ATAN2:
- case MATH_FMOD:
- case MATH_FPOSMOD:
- case MATH_POSMOD:
- case MATH_POW:
- case MATH_EASE:
- case MATH_STEPIFY:
- case MATH_RANDF_RANGE:
- case MATH_RANDI_RANGE:
- case MATH_POLAR2CARTESIAN:
- case MATH_CARTESIAN2POLAR:
- case LOGIC_MAX:
- case LOGIC_MIN:
- case TYPE_CONVERT:
- case COLORN:
- return 2;
- case MATH_LERP:
- case MATH_LERP_ANGLE:
- case MATH_INVERSE_LERP:
- case MATH_SMOOTHSTEP:
- case MATH_MOVE_TOWARD:
- case MATH_DECTIME:
- case MATH_WRAP:
- case MATH_WRAPF:
- case LOGIC_CLAMP:
- return 3;
- case MATH_RANGE_LERP:
- return 5;
- case FUNC_MAX: {
- }
- }
- return 0;
-}
-
-#define VALIDATE_ARG_NUM(m_arg) \
- if (!p_inputs[m_arg]->is_num()) { \
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \
- r_error.argument = m_arg; \
- r_error.expected = Variant::FLOAT; \
- return; \
- }
-
-void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str) {
- r_error.error = Callable::CallError::CALL_OK;
- switch (p_func) {
- case MATH_SIN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::sin((double)*p_inputs[0]);
- } break;
- case MATH_COS: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::cos((double)*p_inputs[0]);
- } break;
- case MATH_TAN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::tan((double)*p_inputs[0]);
- } break;
- case MATH_SINH: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::sinh((double)*p_inputs[0]);
- } break;
- case MATH_COSH: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::cosh((double)*p_inputs[0]);
- } break;
- case MATH_TANH: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::tanh((double)*p_inputs[0]);
- } break;
- case MATH_ASIN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::asin((double)*p_inputs[0]);
- } break;
- case MATH_ACOS: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::acos((double)*p_inputs[0]);
- } break;
- case MATH_ATAN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::atan((double)*p_inputs[0]);
- } break;
- case MATH_ATAN2: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::atan2((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_SQRT: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::sqrt((double)*p_inputs[0]);
- } break;
- case MATH_FMOD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::fmod((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_FPOSMOD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_POSMOD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]);
- } break;
- case MATH_FLOOR: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::floor((double)*p_inputs[0]);
- } break;
- case MATH_CEIL: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::ceil((double)*p_inputs[0]);
- } break;
- case MATH_ROUND: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::round((double)*p_inputs[0]);
- } break;
- case MATH_ABS: {
- if (p_inputs[0]->get_type() == Variant::INT) {
- int64_t i = *p_inputs[0];
- *r_return = ABS(i);
- } else if (p_inputs[0]->get_type() == Variant::FLOAT) {
- real_t r = *p_inputs[0];
- *r_return = Math::abs(r);
- } else {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::FLOAT;
- }
- } break;
- case MATH_SIGN: {
- if (p_inputs[0]->get_type() == Variant::INT) {
- int64_t i = *p_inputs[0];
- *r_return = i < 0 ? -1 : (i > 0 ? +1 : 0);
- } else if (p_inputs[0]->get_type() == Variant::FLOAT) {
- real_t r = *p_inputs[0];
- *r_return = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0);
- } else {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::FLOAT;
- }
- } break;
- case MATH_POW: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::pow((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_LOG: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::log((double)*p_inputs[0]);
- } break;
- case MATH_EXP: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::exp((double)*p_inputs[0]);
- } break;
- case MATH_ISNAN: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::is_nan((double)*p_inputs[0]);
- } break;
- case MATH_ISINF: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::is_inf((double)*p_inputs[0]);
- } break;
- case MATH_EASE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_STEP_DECIMALS: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::step_decimals((double)*p_inputs[0]);
- } break;
- case MATH_STEPIFY: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_LERP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_LERP_ANGLE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_INVERSE_LERP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_RANGE_LERP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- VALIDATE_ARG_NUM(3);
- VALIDATE_ARG_NUM(4);
- *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]);
- } break;
- case MATH_SMOOTHSTEP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_MOVE_TOWARD: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_DECTIME: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::dectime((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case MATH_RANDOMIZE: {
- Math::randomize();
-
- } break;
- case MATH_RANDI: {
- *r_return = Math::rand();
- } break;
- case MATH_RANDF: {
- *r_return = Math::randf();
- } break;
- case MATH_RANDF_RANGE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]);
- } break;
- case MATH_RANDI_RANGE: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- *r_return = Math::random((int)*p_inputs[0], (int)*p_inputs[1]);
- } break;
- case MATH_SEED: {
- VALIDATE_ARG_NUM(0);
- uint64_t seed = *p_inputs[0];
- Math::seed(seed);
-
- } break;
- case MATH_RANDSEED: {
- VALIDATE_ARG_NUM(0);
- uint64_t seed = *p_inputs[0];
- int ret = Math::rand_from_seed(&seed);
- Array reta;
- reta.push_back(ret);
- reta.push_back(seed);
- *r_return = reta;
-
- } break;
- case MATH_DEG2RAD: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::deg2rad((double)*p_inputs[0]);
- } break;
- case MATH_RAD2DEG: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::rad2deg((double)*p_inputs[0]);
- } break;
- case MATH_LINEAR2DB: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::linear2db((double)*p_inputs[0]);
- } break;
- case MATH_DB2LINEAR: {
- VALIDATE_ARG_NUM(0);
- *r_return = Math::db2linear((double)*p_inputs[0]);
- } break;
- case MATH_POLAR2CARTESIAN: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- double r = *p_inputs[0];
- double th = *p_inputs[1];
- *r_return = Vector2(r * Math::cos(th), r * Math::sin(th));
- } break;
- case MATH_CARTESIAN2POLAR: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- double x = *p_inputs[0];
- double y = *p_inputs[1];
- *r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
- } break;
- case MATH_WRAP: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::wrapi((int64_t)*p_inputs[0], (int64_t)*p_inputs[1], (int64_t)*p_inputs[2]);
- } break;
- case MATH_WRAPF: {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
- *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
- } break;
- case LOGIC_MAX: {
- if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) {
- int64_t a = *p_inputs[0];
- int64_t b = *p_inputs[1];
- *r_return = MAX(a, b);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- real_t a = *p_inputs[0];
- real_t b = *p_inputs[1];
-
- *r_return = MAX(a, b);
- }
-
- } break;
- case LOGIC_MIN: {
- if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) {
- int64_t a = *p_inputs[0];
- int64_t b = *p_inputs[1];
- *r_return = MIN(a, b);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
-
- real_t a = *p_inputs[0];
- real_t b = *p_inputs[1];
-
- *r_return = MIN(a, b);
- }
- } break;
- case LOGIC_CLAMP: {
- if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT && p_inputs[2]->get_type() == Variant::INT) {
- int64_t a = *p_inputs[0];
- int64_t b = *p_inputs[1];
- int64_t c = *p_inputs[2];
- *r_return = CLAMP(a, b, c);
- } else {
- VALIDATE_ARG_NUM(0);
- VALIDATE_ARG_NUM(1);
- VALIDATE_ARG_NUM(2);
-
- real_t a = *p_inputs[0];
- real_t b = *p_inputs[1];
- real_t c = *p_inputs[2];
-
- *r_return = CLAMP(a, b, c);
- }
- } break;
- case LOGIC_NEAREST_PO2: {
- VALIDATE_ARG_NUM(0);
- int64_t num = *p_inputs[0];
- *r_return = next_power_of_2(num);
- } break;
- case OBJ_WEAKREF: {
- if (p_inputs[0]->get_type() != Variant::OBJECT) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::OBJECT;
-
- return;
- }
-
- if (p_inputs[0]->is_ref()) {
- REF r = *p_inputs[0];
- if (!r.is_valid()) {
- return;
- }
-
- Ref<WeakRef> wref = memnew(WeakRef);
- wref->set_ref(r);
- *r_return = wref;
- } else {
- Object *obj = *p_inputs[0];
- if (!obj) {
- return;
- }
- Ref<WeakRef> wref = memnew(WeakRef);
- wref->set_obj(obj);
- *r_return = wref;
- }
-
- } break;
- case TYPE_CONVERT: {
- VALIDATE_ARG_NUM(1);
- int type = *p_inputs[1];
- if (type < 0 || type >= Variant::VARIANT_MAX) {
- r_error_str = RTR("Invalid type argument to convert(), use TYPE_* constants.");
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::INT;
- return;
-
- } else {
- *r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error);
- }
- } break;
- case TYPE_OF: {
- *r_return = p_inputs[0]->get_type();
-
- } break;
- case TYPE_EXISTS: {
- *r_return = ClassDB::class_exists(*p_inputs[0]);
-
- } break;
- case TEXT_CHAR: {
- char32_t result[2] = { *p_inputs[0], 0 };
-
- *r_return = String(result);
-
- } break;
- case TEXT_ORD: {
- if (p_inputs[0]->get_type() != Variant::STRING) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
-
- return;
- }
-
- String str = *p_inputs[0];
-
- if (str.length() != 1) {
- r_error_str = RTR("Expected a string of length 1 (a character).");
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
-
- return;
- }
-
- *r_return = str.get(0);
-
- } break;
- case TEXT_STR: {
- String str = *p_inputs[0];
-
- *r_return = str;
-
- } break;
- case TEXT_PRINT: {
- String str = *p_inputs[0];
- print_line(str);
-
- } break;
-
- case TEXT_PRINTERR: {
- String str = *p_inputs[0];
- print_error(str);
-
- } break;
- case TEXT_PRINTRAW: {
- String str = *p_inputs[0];
- OS::get_singleton()->print("%s", str.utf8().get_data());
-
- } break;
- case VAR_TO_STR: {
- String vars;
- VariantWriter::write_to_string(*p_inputs[0], vars);
- *r_return = vars;
- } break;
- case STR_TO_VAR: {
- if (p_inputs[0]->get_type() != Variant::STRING) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
-
- return;
- }
-
- VariantParser::StreamString ss;
- ss.s = *p_inputs[0];
-
- String errs;
- int line;
- Error err = VariantParser::parse(&ss, *r_return, errs, line);
-
- if (err != OK) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::STRING;
- *r_return = "Parse error at line " + itos(line) + ": " + errs;
- return;
- }
-
- } break;
- case VAR_TO_BYTES: {
- PackedByteArray barr;
- bool full_objects = *p_inputs[1];
- int len;
- Error err = encode_variant(*p_inputs[0], nullptr, len, full_objects);
- if (err) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::NIL;
- r_error_str = "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).";
- return;
- }
-
- barr.resize(len);
- {
- uint8_t *w = barr.ptrw();
- encode_variant(*p_inputs[0], w, len, full_objects);
- }
- *r_return = barr;
- } break;
- case BYTES_TO_VAR: {
- if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::PACKED_BYTE_ARRAY;
-
- return;
- }
-
- PackedByteArray varr = *p_inputs[0];
- bool allow_objects = *p_inputs[1];
- Variant ret;
- {
- const uint8_t *r = varr.ptr();
- Error err = decode_variant(ret, r, varr.size(), nullptr, allow_objects);
- if (err != OK) {
- r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format.");
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
- r_error.expected = Variant::PACKED_BYTE_ARRAY;
- return;
- }
- }
-
- *r_return = ret;
-
- } break;
- case COLORN: {
- VALIDATE_ARG_NUM(1);
-
- Color color = Color::named(*p_inputs[0]);
- color.a = *p_inputs[1];
-
- *r_return = String(color);
-
- } break;
- default: {
- }
- }
-}
-
-////////
-
static bool _is_number(char32_t c) {
return (c >= '0' && c <= '9');
}
@@ -1092,18 +410,9 @@ Error Expression::_get_token(Token &r_token) {
} else if (id == "self") {
r_token.type = TK_SELF;
} else {
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- if (id == Variant::get_type_name(Variant::Type(i))) {
- r_token.type = TK_BASIC_TYPE;
- r_token.value = i;
- return OK;
- }
- }
-
- BuiltinFunc bifunc = find_function(id);
- if (bifunc != FUNC_MAX) {
+ if (Variant::has_utility_function(id)) {
r_token.type = TK_BUILTIN_FUNC;
- r_token.value = bifunc;
+ r_token.value = id;
return OK;
}
@@ -1401,6 +710,8 @@ Expression::ENode *Expression::_parse_expression() {
case TK_BUILTIN_FUNC: {
//builtin function
+ StringName func = tk.value;
+
_get_token(tk);
if (tk.type != TK_PARENTHESIS_OPEN) {
_set_error("Expected '('");
@@ -1408,7 +719,7 @@ Expression::ENode *Expression::_parse_expression() {
}
BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>();
- bifunc->func = BuiltinFunc(int(tk.value));
+ bifunc->func = func;
while (true) {
int cofs = str_ofs;
@@ -1436,9 +747,11 @@ Expression::ENode *Expression::_parse_expression() {
}
}
- int expected_args = get_func_argument_count(bifunc->func);
- if (bifunc->arguments.size() != expected_args) {
- _set_error("Builtin func '" + get_func_name(bifunc->func) + "' expects " + itos(expected_args) + " arguments.");
+ if (!Variant::is_utility_function_vararg(bifunc->func)) {
+ int expected_args = Variant::get_utility_function_argument_count(bifunc->func);
+ if (expected_args != bifunc->arguments.size()) {
+ _set_error("Builtin func '" + String(bifunc->func) + "' expects " + itos(expected_args) + " arguments.");
+ }
}
expr = bifunc;
@@ -2021,7 +1334,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
}
Callable::CallError ce;
- r_ret = Variant::construct(constructor->data_type, (const Variant **)argp.ptr(), argp.size(), ce);
+ Variant::construct(constructor->data_type, r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
r_error_str = vformat(RTR("Invalid arguments to construct '%s'"), Variant::get_type_name(constructor->data_type));
@@ -2047,11 +1360,11 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
argp.write[i] = &arr[i];
}
+ r_ret = Variant(); //may not return anything
Callable::CallError ce;
- exec_func(bifunc->func, (const Variant **)argp.ptr(), &r_ret, ce, r_error_str);
-
+ Variant::call_utility_function(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
- r_error_str = "Builtin Call Failed. " + r_error_str;
+ r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce);
return true;
}
@@ -2083,7 +1396,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression:
}
Callable::CallError ce;
- r_ret = base.call(call->method, (const Variant **)argp.ptr(), argp.size(), ce);
+ base.call(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce);
if (ce.error != Callable::CallError::CALL_OK) {
r_error_str = vformat(RTR("On call to '%s':"), String(call->method));
diff --git a/core/math/expression.h b/core/math/expression.h
index 991554f4fd..d9cedb8c2c 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -36,87 +36,7 @@
class Expression : public Reference {
GDCLASS(Expression, Reference);
-public:
- enum BuiltinFunc {
- MATH_SIN,
- MATH_COS,
- MATH_TAN,
- MATH_SINH,
- MATH_COSH,
- MATH_TANH,
- MATH_ASIN,
- MATH_ACOS,
- MATH_ATAN,
- MATH_ATAN2,
- MATH_SQRT,
- MATH_FMOD,
- MATH_FPOSMOD,
- MATH_POSMOD,
- MATH_FLOOR,
- MATH_CEIL,
- MATH_ROUND,
- MATH_ABS,
- MATH_SIGN,
- MATH_POW,
- MATH_LOG,
- MATH_EXP,
- MATH_ISNAN,
- MATH_ISINF,
- MATH_EASE,
- MATH_STEP_DECIMALS,
- MATH_STEPIFY,
- MATH_LERP,
- MATH_LERP_ANGLE,
- MATH_INVERSE_LERP,
- MATH_RANGE_LERP,
- MATH_SMOOTHSTEP,
- MATH_MOVE_TOWARD,
- MATH_DECTIME,
- MATH_RANDOMIZE,
- MATH_RANDI,
- MATH_RANDF,
- MATH_RANDF_RANGE,
- MATH_RANDI_RANGE,
- MATH_SEED,
- MATH_RANDSEED,
- MATH_DEG2RAD,
- MATH_RAD2DEG,
- MATH_LINEAR2DB,
- MATH_DB2LINEAR,
- MATH_POLAR2CARTESIAN,
- MATH_CARTESIAN2POLAR,
- MATH_WRAP,
- MATH_WRAPF,
- LOGIC_MAX,
- LOGIC_MIN,
- LOGIC_CLAMP,
- LOGIC_NEAREST_PO2,
- OBJ_WEAKREF,
- TYPE_CONVERT,
- TYPE_OF,
- TYPE_EXISTS,
- TEXT_CHAR,
- TEXT_ORD,
- TEXT_STR,
- TEXT_PRINT,
- TEXT_PRINTERR,
- TEXT_PRINTRAW,
- VAR_TO_STR,
- STR_TO_VAR,
- VAR_TO_BYTES,
- BYTES_TO_VAR,
- COLORN,
- FUNC_MAX
- };
-
- static int get_func_argument_count(BuiltinFunc p_func);
- static String get_func_name(BuiltinFunc p_func);
- static void exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str);
- static BuiltinFunc find_function(const String &p_string);
-
private:
- static const char *func_name[FUNC_MAX];
-
struct Input {
Variant::Type type = Variant::NIL;
String name;
@@ -315,7 +235,7 @@ private:
};
struct BuiltinFuncNode : public ENode {
- BuiltinFunc func;
+ StringName func;
Vector<ENode *> arguments;
BuiltinFuncNode() {
type = TYPE_BUILTIN_FUNC;
diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp
index 56353de783..ccb6648561 100644
--- a/core/math/geometry_3d.cpp
+++ b/core/math/geometry_3d.cpp
@@ -241,7 +241,6 @@ Vector<Vector<Face3>> Geometry3D::separate_objects(Vector<Face3> p_array) {
/*** GEOMETRY WRAPPER ***/
enum _CellFlags {
-
_CELL_SOLID = 1,
_CELL_EXTERIOR = 2,
_CELL_STEP_MASK = 0x1C,
@@ -262,7 +261,6 @@ enum _CellFlags {
_CELL_PREV_Z_POS = 5 << 5,
_CELL_PREV_Z_NEG = 6 << 5,
_CELL_PREV_FIRST = 7 << 5,
-
};
static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, const Vector3 &voxelsize, const Face3 &p_face) {
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index 4928c96abd..5192722839 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -66,27 +66,23 @@ enum ClockDirection {
};
enum Orientation {
-
HORIZONTAL,
VERTICAL
};
enum HAlign {
-
HALIGN_LEFT,
HALIGN_CENTER,
HALIGN_RIGHT
};
enum VAlign {
-
VALIGN_TOP,
VALIGN_CENTER,
VALIGN_BOTTOM
};
enum Margin {
-
MARGIN_LEFT,
MARGIN_TOP,
MARGIN_RIGHT,
@@ -94,7 +90,6 @@ enum Margin {
};
enum Corner {
-
CORNER_TOP_LEFT,
CORNER_TOP_RIGHT,
CORNER_BOTTOM_RIGHT,
diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp
index ef2a0c5339..221c6812c1 100644
--- a/core/math/math_fieldwise.cpp
+++ b/core/math/math_fieldwise.cpp
@@ -47,9 +47,7 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
/* clang-format off */
switch (p_source.get_type()) {
-
case Variant::VECTOR2: {
-
SETUP_TYPE(Vector2)
/**/ TRY_TRANSFER_FIELD("x", x)
@@ -59,7 +57,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::RECT2: {
-
SETUP_TYPE(Rect2)
/**/ TRY_TRANSFER_FIELD("x", position.x)
@@ -71,7 +68,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::VECTOR3: {
-
SETUP_TYPE(Vector3)
/**/ TRY_TRANSFER_FIELD("x", x)
@@ -82,7 +78,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::PLANE: {
-
SETUP_TYPE(Plane)
/**/ TRY_TRANSFER_FIELD("x", normal.x)
@@ -94,7 +89,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::QUAT: {
-
SETUP_TYPE(Quat)
/**/ TRY_TRANSFER_FIELD("x", x)
@@ -106,7 +100,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::AABB: {
-
SETUP_TYPE(AABB)
/**/ TRY_TRANSFER_FIELD("px", position.x)
@@ -120,7 +113,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::TRANSFORM2D: {
-
SETUP_TYPE(Transform2D)
/**/ TRY_TRANSFER_FIELD("xx", elements[0][0])
@@ -134,7 +126,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::BASIS: {
-
SETUP_TYPE(Basis)
/**/ TRY_TRANSFER_FIELD("xx", elements[0][0])
@@ -151,7 +142,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const
}
case Variant::TRANSFORM: {
-
SETUP_TYPE(Transform)
/**/ TRY_TRANSFER_FIELD("xx", basis.elements[0][0])
diff --git a/core/math/octree.h b/core/math/octree.h
index 40201f99b1..be1e7d6a61 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -379,7 +379,6 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct
if (p_octant->aabb.size.x / OCTREE_DIVISOR < element_size) {
//if (p_octant->aabb.size.x*0.5 < element_size) {
-
/* at smallest possible size for the element */
typename Element::OctantOwner owner;
owner.octant = p_octant;
diff --git a/core/math/transform.cpp b/core/math/transform.cpp
index d36fd6a63d..733bb4d55e 100644
--- a/core/math/transform.cpp
+++ b/core/math/transform.cpp
@@ -200,6 +200,13 @@ Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) :
origin(p_origin) {
}
+Transform::Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) :
+ origin(p_origin) {
+ basis.set_axis(0, p_x);
+ basis.set_axis(1, p_y);
+ basis.set_axis(2, p_z);
+}
+
Transform::Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) {
basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz);
origin = Vector3(ox, oy, oz);
diff --git a/core/math/transform.h b/core/math/transform.h
index 71847d36ac..c63dbcb989 100644
--- a/core/math/transform.h
+++ b/core/math/transform.h
@@ -106,9 +106,10 @@ public:
operator String() const;
- Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
- Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3());
Transform() {}
+ Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3());
+ Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
+ Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
};
_FORCE_INLINE_ Vector3 Transform::xform(const Vector3 &p_vector) const {
diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp
index 180aeaa0af..00e561f973 100644
--- a/core/math/transform_2d.cpp
+++ b/core/math/transform_2d.cpp
@@ -251,7 +251,7 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t
real_t dot = v1.dot(v2);
- dot = (dot < -1.0) ? -1.0 : ((dot > 1.0) ? 1.0 : dot); //clamp dot to [-1,1]
+ dot = CLAMP(dot, -1.0, 1.0);
Vector2 v;
diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h
index 46e97abaa7..342623939e 100644
--- a/core/math/transform_2d.h
+++ b/core/math/transform_2d.h
@@ -128,6 +128,12 @@ struct Transform2D {
elements[2][1] = oy;
}
+ Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) {
+ elements[0] = p_x;
+ elements[1] = p_y;
+ elements[2] = p_origin;
+ }
+
Transform2D(real_t p_rot, const Vector2 &p_pos);
Transform2D() {
elements[0][0] = 1.0;
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index ee6da6a8db..68990dcb72 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -114,7 +114,6 @@ Callable create_custom_callable_function_pointer(T *p_instance,
const char *p_func_text,
#endif
void (T::*p_method)(P...)) {
-
typedef CallableCustomMethodPointer<T, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
@@ -170,7 +169,6 @@ Callable create_custom_callable_function_pointer(T *p_instance,
const char *p_func_text,
#endif
R (T::*p_method)(P...)) {
-
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
@@ -226,7 +224,6 @@ Callable create_custom_callable_function_pointer(T *p_instance,
const char *p_func_text,
#endif
R (T::*p_method)(P...) const) {
-
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
#ifdef DEBUG_METHODS_ENABLED
diff --git a/core/object/method_bind.h b/core/object/method_bind.h
index ab4ba90b94..ddd6ab6baa 100644
--- a/core/object/method_bind.h
+++ b/core/object/method_bind.h
@@ -34,7 +34,6 @@
#include "core/variant/binder_common.h"
enum MethodFlags {
-
METHOD_FLAG_NORMAL = 1,
METHOD_FLAG_EDITOR = 2,
METHOD_FLAG_NOSCRIPT = 4,
diff --git a/core/object/object.cpp b/core/object/object.cpp
index ffec2ae867..96a41d6852 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -597,9 +597,6 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons
_get_property_listv(p_list, p_reversed);
if (!is_class("Script")) { // can still be set, but this is for userfriendlyness
-#ifdef TOOLS_ENABLED
- p_list->push_back(PropertyInfo(Variant::NIL, "Script", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
-#endif
p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT));
}
if (!metadata.empty()) {
@@ -1690,7 +1687,8 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName>
}
Callable::CallError ce;
- Variant check = Variant::construct(t, nullptr, 0, ce);
+ Variant check;
+ Variant::construct(t, check, nullptr, 0, ce);
for (int i = 1; i < p_path.size(); i++) {
if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) {
diff --git a/core/object/object.h b/core/object/object.h
index c79745cf74..0bcfa42e3d 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -98,7 +98,6 @@ enum PropertyHint {
};
enum PropertyUsageFlags {
-
PROPERTY_USAGE_STORAGE = 1,
PROPERTY_USAGE_EDITOR = 2,
PROPERTY_USAGE_NETWORK = 4,
@@ -406,7 +405,6 @@ class ScriptInstance;
class Object {
public:
enum ConnectFlags {
-
CONNECT_DEFERRED = 1,
CONNECT_PERSIST = 2, // hint for scene to save this connection
CONNECT_ONESHOT = 4,
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 447216f14f..3fd56c2f15 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -57,7 +57,6 @@ struct SortNetData {
class ScriptServer {
enum {
-
MAX_LANGUAGES = 16
};
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index ef3eb6800a..fd3c6f8806 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -51,7 +51,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
}
bool FileAccess::exists(const String &p_name) {
- if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) {
return true;
}
@@ -456,7 +456,7 @@ void FileAccess::store_double(double p_dest) {
}
uint64_t FileAccess::get_modified_time(const String &p_file) {
- if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0;
}
@@ -469,7 +469,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
}
uint32_t FileAccess::get_unix_permissions(const String &p_file) {
- if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
return 0;
}
@@ -482,6 +482,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
}
Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) {
+ return ERR_UNAVAILABLE;
+ }
+
FileAccess *fa = create_for_path(p_file);
ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 39b977a4d9..777c82bbd7 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -81,7 +81,6 @@ public:
virtual void _set_access_type(AccessType p_access);
enum ModeFlags {
-
READ = 1,
WRITE = 2,
READ_WRITE = 3,
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index d088151a6d..ef341987dc 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -38,7 +38,6 @@ struct _KeyCodeText {
};
static const _KeyCodeText _keycodes[] = {
-
/* clang-format off */
{KEY_ESCAPE ,"Escape"},
{KEY_TAB ,"Tab"},
diff --git a/core/os/keyboard.h b/core/os/keyboard.h
index 92664aff8f..67c60a2dbe 100644
--- a/core/os/keyboard.h
+++ b/core/os/keyboard.h
@@ -294,11 +294,9 @@ enum KeyList {
KEY_DIVISION = 0x00F7,
KEY_YDIAERESIS = 0x00FF,
-
};
enum KeyModifierMask {
-
KEY_CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers.
KEY_MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers.
KEY_MASK_SHIFT = (1 << 25),
@@ -314,7 +312,6 @@ enum KeyModifierMask {
KEY_MASK_KPAD = (1 << 29),
KEY_MASK_GROUP_SWITCH = (1 << 30)
// bit 31 can't be used because variant uses regular 32 bits int as datatype
-
};
String keycode_get_string(uint32_t p_code);
diff --git a/core/os/os.h b/core/os/os.h
index a1e75b5ee9..40104b479b 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -77,7 +77,6 @@ public:
typedef bool (*HasServerFeatureCallback)(const String &p_feature);
enum RenderThreadMode {
-
RENDER_THREAD_UNSAFE,
RENDER_THREAD_SAFE,
RENDER_SEPARATE_THREAD
diff --git a/core/os/pool_allocator.h b/core/os/pool_allocator.h
index 7d77af6266..c67b4d7fa2 100644
--- a/core/os/pool_allocator.h
+++ b/core/os/pool_allocator.h
@@ -43,7 +43,6 @@
*/
enum {
-
POOL_ALLOCATOR_INVALID_ID = -1 ///< default invalid value. use INVALID_ID( id ) to test
};
diff --git a/core/os/thread.h b/core/os/thread.h
index d68476e683..b87ec84313 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -39,7 +39,6 @@ typedef void (*ThreadCreateCallback)(void *p_userdata);
class Thread {
public:
enum Priority {
-
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index c56de8ef93..7e32f215e7 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -43,6 +43,7 @@
#include "core/io/dtls_server.h"
#include "core/io/http_client.h"
#include "core/io/image_loader.h"
+#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/io/multiplayer_api.h"
#include "core/io/networked_multiplayer_peer.h"
@@ -96,12 +97,6 @@ extern Mutex _global_mutex;
extern void register_global_constants();
extern void unregister_global_constants();
-extern void register_variant_methods();
-extern void unregister_variant_methods();
-extern void register_variant_operators();
-extern void unregister_variant_operators();
-extern void register_variant_setters_getters();
-extern void unregister_variant_setters_getters();
void register_core_types() {
//consistency check
@@ -114,9 +109,8 @@ void register_core_types() {
ResourceLoader::initialize();
register_global_constants();
- register_variant_methods();
- register_variant_operators();
- register_variant_setters_getters();
+
+ Variant::register_types();
CoreStringNames::create();
@@ -204,6 +198,7 @@ void register_core_types() {
ClassDB::register_class<_Semaphore>();
ClassDB::register_class<XMLParser>();
+ ClassDB::register_class<JSONParser>();
ClassDB::register_class<ConfigFile>();
@@ -323,9 +318,8 @@ void unregister_core_types() {
ClassDB::cleanup_defaults();
ObjectDB::cleanup();
- unregister_variant_setters_getters();
- unregister_variant_operators();
- unregister_variant_methods();
+ Variant::unregister_types();
+
unregister_global_constants();
ClassDB::cleanup();
diff --git a/core/string/string_name.h b/core/string/string_name.h
index e6b46506c3..320f63bf68 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -44,7 +44,6 @@ struct StaticCString {
class StringName {
enum {
-
STRING_TABLE_BITS = 12,
STRING_TABLE_LEN = 1 << STRING_TABLE_BITS,
STRING_TABLE_MASK = STRING_TABLE_LEN - 1
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index b5758bddf3..213578485e 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -3864,7 +3864,6 @@ String String::xml_escape(bool p_escape_quotes) const {
}
/*
for (int i=1;i<32;i++) {
-
char chr[2]={i,0};
str=str.replace(chr,"&#"+String::num(i)+";");
}*/
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 35475a2124..bfae16fe64 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -198,7 +198,6 @@ class String {
public:
enum {
-
npos = -1 ///<for "some" compatibility with std::string (npos is a huge value in std::string)
};
@@ -433,10 +432,10 @@ public:
/**
* The constructors must not depend on other overloads
*/
- /* String(char32_t p_char);*/
_FORCE_INLINE_ String() {}
_FORCE_INLINE_ String(const String &p_str) { _cowdata._ref(p_str._cowdata); }
+
String &operator=(const String &p_str) {
_cowdata._ref(p_str._cowdata);
return *this;
@@ -536,4 +535,24 @@ String RTRN(const String &p_text, const String &p_text_plural, int p_n, const St
bool is_symbol(char32_t c);
bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end);
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {
+}
+
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
+ arr.push_back(p_str);
+}
+
+template <class... P>
+_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
+ arr.push_back(p_str);
+ sarray_add_str(arr, p_args...);
+}
+
+template <class... P>
+_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
+ Vector<String> arr;
+ sarray_add_str(arr, p_args...);
+ return arr;
+}
+
#endif // USTRING_H
diff --git a/core/templates/sort_array.h b/core/templates/sort_array.h
index a4326ac565..ece5e72e51 100644
--- a/core/templates/sort_array.h
+++ b/core/templates/sort_array.h
@@ -54,7 +54,6 @@ struct _DefaultComparator {
template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED>
class SortArray {
enum {
-
INTROSORT_THRESHOLD = 16
};
diff --git a/core/variant/array.cpp b/core/variant/array.cpp
index 64e31189de..79bc01b89c 100644
--- a/core/variant/array.cpp
+++ b/core/variant/array.cpp
@@ -165,7 +165,7 @@ void Array::_assign(const Array &p_array) {
} else if (Variant::can_convert_strict(src_val.get_type(), _p->typed.type)) {
Variant *ptr = &src_val;
Callable::CallError ce;
- new_array.write[i] = Variant::construct(_p->typed.type, (const Variant **)&ptr, 1, ce, true);
+ Variant::construct(_p->typed.type, new_array.write[i], (const Variant **)&ptr, 1, ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'.");
}
@@ -192,6 +192,11 @@ void Array::push_back(const Variant &p_value) {
_p->array.push_back(p_value);
}
+void Array::append_array(const Array &p_array) {
+ ERR_FAIL_COND(!_p->typed.validate(p_array, "append_array"));
+ _p->array.append_array(p_array._p->array);
+}
+
Error Array::resize(int p_new_size) {
return _p->array.resize(p_new_size);
}
diff --git a/core/variant/array.h b/core/variant/array.h
index b37d600abd..e01ac13168 100644
--- a/core/variant/array.h
+++ b/core/variant/array.h
@@ -68,6 +68,7 @@ public:
void push_back(const Variant &p_value);
_FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility
+ void append_array(const Array &p_array);
Error resize(int p_new_size);
void insert(int p_pos, const Variant &p_value);
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index e72f76c5e1..2e38ce5b06 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -650,6 +650,39 @@ void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *,
(void)p_args;
}
+template <class T, class R, class... P>
+void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &default_values, Callable::CallError &r_error) {
+#ifdef DEBUG_ENABLED
+ if ((size_t)p_argcount > sizeof...(P)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount;
+
+ int32_t dvs = default_values.size();
+#ifdef DEBUG_ENABLED
+ if (missing > dvs) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = sizeof...(P);
+ return;
+ }
+#endif
+
+ const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array
+ for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) {
+ if (i < p_argcount) {
+ args[i] = p_args[i];
+ } else {
+ args[i] = &default_values[i - p_argcount + (dvs - missing)];
+ }
+ }
+
+ call_with_variant_args_retc_static_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
diff --git a/core/variant/type_info.h b/core/variant/type_info.h
index b9ae88d97c..ce7c2bfe14 100644
--- a/core/variant/type_info.h
+++ b/core/variant/type_info.h
@@ -153,7 +153,7 @@ MAKE_TYPE_INFO(Transform, Variant::TRANSFORM)
MAKE_TYPE_INFO(Color, Variant::COLOR)
MAKE_TYPE_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH)
-MAKE_TYPE_INFO(RID, Variant::_RID)
+MAKE_TYPE_INFO(RID, Variant::RID)
MAKE_TYPE_INFO(Callable, Variant::CALLABLE)
MAKE_TYPE_INFO(Signal, Variant::SIGNAL)
MAKE_TYPE_INFO(Dictionary, Variant::DICTIONARY)
diff --git a/core/variant/typed_array.h b/core/variant/typed_array.h
index 0f3985b2f1..ff42cb687e 100644
--- a/core/variant/typed_array.h
+++ b/core/variant/typed_array.h
@@ -105,7 +105,7 @@ MAKE_TYPED_ARRAY(Transform, Variant::TRANSFORM)
MAKE_TYPED_ARRAY(Color, Variant::COLOR)
MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH)
-MAKE_TYPED_ARRAY(RID, Variant::_RID)
+MAKE_TYPED_ARRAY(RID, Variant::RID)
MAKE_TYPED_ARRAY(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY(Dictionary, Variant::DICTIONARY)
@@ -207,7 +207,7 @@ MAKE_TYPED_ARRAY_INFO(Transform, Variant::TRANSFORM)
MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR)
MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH)
-MAKE_TYPED_ARRAY_INFO(RID, Variant::_RID)
+MAKE_TYPED_ARRAY_INFO(RID, Variant::RID)
MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE)
MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL)
MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY)
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index 126420bd02..741d05c139 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -109,7 +109,7 @@ String Variant::get_type_name(Variant::Type p_type) {
return "Color";
} break;
- case _RID: {
+ case RID: {
return "RID";
} break;
case OBJECT: {
@@ -342,7 +342,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) {
} break;
- case _RID: {
+ case RID: {
static const Type valid[] = {
OBJECT,
NIL
@@ -649,7 +649,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type
} break;
- case _RID: {
+ case RID: {
static const Type valid[] = {
OBJECT,
NIL
@@ -891,8 +891,8 @@ bool Variant::is_zero() const {
return *reinterpret_cast<const Color *>(_data._mem) == Color();
} break;
- case _RID: {
- return *reinterpret_cast<const RID *>(_data._mem) == RID();
+ case RID: {
+ return *reinterpret_cast<const ::RID *>(_data._mem) == ::RID();
} break;
case OBJECT: {
return _get_obj().obj == nullptr;
@@ -1109,8 +1109,8 @@ void Variant::reference(const Variant &p_variant) {
memnew_placement(_data._mem, Color(*reinterpret_cast<const Color *>(p_variant._data._mem)));
} break;
- case _RID: {
- memnew_placement(_data._mem, RID(*reinterpret_cast<const RID *>(p_variant._data._mem)));
+ case RID: {
+ memnew_placement(_data._mem, ::RID(*reinterpret_cast<const ::RID *>(p_variant._data._mem)));
} break;
case OBJECT: {
memnew_placement(_data._mem, ObjData);
@@ -1266,7 +1266,7 @@ void Variant::zero() {
}
}
-void Variant::clear() {
+void Variant::_clear_internal() {
switch (type) {
case STRING: {
reinterpret_cast<String *>(_data._mem)->~String();
@@ -1311,9 +1311,11 @@ void Variant::clear() {
_get_obj().obj = nullptr;
_get_obj().id = ObjectID();
} break;
- case _RID: {
+ case RID: {
// not much need probably
- reinterpret_cast<RID *>(_data._mem)->~RID();
+ // Can't seem to use destructor + scoping operator, so hack.
+ typedef ::RID RID_Class;
+ reinterpret_cast<RID_Class *>(_data._mem)->~RID_Class();
} break;
case CALLABLE: {
reinterpret_cast<Callable *>(_data._mem)->~Callable();
@@ -1358,8 +1360,6 @@ void Variant::clear() {
default: {
} /* not needed */
}
-
- type = NIL;
}
Variant::operator signed int() const {
@@ -1849,8 +1849,8 @@ String Variant::stringify(List<const void *> &stack) const {
const Signal &s = *reinterpret_cast<const Signal *>(_data._mem);
return s;
} break;
- case _RID: {
- const RID &s = *reinterpret_cast<const RID *>(_data._mem);
+ case RID: {
+ const ::RID &s = *reinterpret_cast<const ::RID *>(_data._mem);
return "RID(" + itos(s.get_id()) + ")";
} break;
default: {
@@ -2041,25 +2041,25 @@ Variant::operator NodePath() const {
}
}
-Variant::operator RID() const {
- if (type == _RID) {
- return *reinterpret_cast<const RID *>(_data._mem);
+Variant::operator ::RID() const {
+ if (type == RID) {
+ return *reinterpret_cast<const ::RID *>(_data._mem);
} else if (type == OBJECT && _get_obj().obj == nullptr) {
- return RID();
+ return ::RID();
} else if (type == OBJECT && _get_obj().obj) {
#ifdef DEBUG_ENABLED
if (EngineDebugger::is_active()) {
- ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed).");
+ ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, ::RID(), "Invalid pointer (object was freed).");
}
#endif
Callable::CallError ce;
Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce);
- if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::_RID) {
+ if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) {
return ret;
}
- return RID();
+ return ::RID();
} else {
- return RID();
+ return ::RID();
}
}
@@ -2263,9 +2263,9 @@ Variant::operator Vector<Color>() const {
/* helpers */
-Variant::operator Vector<RID>() const {
+Variant::operator Vector<::RID>() const {
Array va = operator Array();
- Vector<RID> rids;
+ Vector<::RID> rids;
rids.resize(va.size());
for (int i = 0; i < rids.size(); i++) {
rids.write[i] = va[i];
@@ -2520,9 +2520,9 @@ Variant::Variant(const NodePath &p_node_path) {
memnew_placement(_data._mem, NodePath(p_node_path));
}
-Variant::Variant(const RID &p_rid) {
- type = _RID;
- memnew_placement(_data._mem, RID(p_rid));
+Variant::Variant(const ::RID &p_rid) {
+ type = RID;
+ memnew_placement(_data._mem, ::RID(p_rid));
}
Variant::Variant(const Object *p_object) {
@@ -2580,7 +2580,7 @@ Variant::Variant(const Vector<Plane> &p_array) {
}
}
-Variant::Variant(const Vector<RID> &p_array) {
+Variant::Variant(const Vector<::RID> &p_array) {
type = ARRAY;
Array *rid_array = memnew_placement(_data._mem, Array);
@@ -2753,8 +2753,8 @@ void Variant::operator=(const Variant &p_variant) {
case COLOR: {
*reinterpret_cast<Color *>(_data._mem) = *reinterpret_cast<const Color *>(p_variant._data._mem);
} break;
- case _RID: {
- *reinterpret_cast<RID *>(_data._mem) = *reinterpret_cast<const RID *>(p_variant._data._mem);
+ case RID: {
+ *reinterpret_cast<::RID *>(_data._mem) = *reinterpret_cast<const ::RID *>(p_variant._data._mem);
} break;
case OBJECT: {
if (_get_obj().id.is_reference()) {
@@ -2955,8 +2955,8 @@ uint32_t Variant::hash() const {
return hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->a, hash);
} break;
- case _RID: {
- return hash_djb2_one_64(reinterpret_cast<const RID *>(_data._mem)->get_id());
+ case RID: {
+ return hash_djb2_one_64(reinterpret_cast<const ::RID *>(_data._mem)->get_id());
} break;
case OBJECT: {
return hash_djb2_one_64(make_uint64_t(_get_obj().obj));
@@ -3401,7 +3401,8 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) {
Callable::CallError error;
- Variant ret = call(p_method, argptr, argc, error);
+ Variant ret;
+ call(p_method, argptr, argc, ret, error);
switch (error.error) {
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
@@ -3435,6 +3436,30 @@ String Variant::get_construct_string() const {
return vars;
}
+String Variant::get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
+ String err_text;
+
+ if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
+ int errorarg = ce.argument;
+ if (p_argptrs) {
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ } else {
+ err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + ".";
+ }
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) {
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) {
+ err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + ".";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
+ err_text = "Method not found.";
+ } else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) {
+ err_text = "Instance is null";
+ } else if (ce.error == Callable::CallError::CALL_OK) {
+ return "Call OK";
+ }
+ return "'" + String(p_method) + "': " + err_text;
+}
+
String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) {
String err_text;
@@ -3519,3 +3544,18 @@ String vformat(const String &p_text, const Variant &p1, const Variant &p2, const
return fmt;
}
+
+void Variant::register_types() {
+ _register_variant_operators();
+ _register_variant_methods();
+ _register_variant_setters_getters();
+ _register_variant_constructors();
+ _register_variant_utility_functions();
+}
+void Variant::unregister_types() {
+ _unregister_variant_operators();
+ _unregister_variant_methods();
+ _unregister_variant_setters_getters();
+ _unregister_variant_constructors();
+ _unregister_variant_utility_functions();
+}
diff --git a/core/variant/variant.h b/core/variant/variant.h
index c264bbcd48..093daf0c6f 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -97,7 +97,7 @@ public:
COLOR,
STRING_NAME,
NODE_PATH,
- _RID,
+ RID,
OBJECT,
CALLABLE,
SIGNAL,
@@ -207,7 +207,68 @@ private:
} _data alignas(8);
void reference(const Variant &p_variant);
- void clear();
+
+ void _clear_internal();
+
+ _FORCE_INLINE_ void clear() {
+ static const bool needs_deinit[Variant::VARIANT_MAX] = {
+ false, //NIL,
+ false, //BOOL,
+ false, //INT,
+ false, //FLOAT,
+ true, //STRING,
+ false, //VECTOR2,
+ false, //VECTOR2I,
+ false, //RECT2,
+ false, //RECT2I,
+ false, //VECTOR3,
+ false, //VECTOR3I,
+ true, //TRANSFORM2D,
+ false, //PLANE,
+ false, //QUAT,
+ true, //AABB,
+ true, //BASIS,
+ true, //TRANSFORM,
+
+ // misc types
+ false, //COLOR,
+ true, //STRING_NAME,
+ true, //NODE_PATH,
+ false, //RID,
+ true, //OBJECT,
+ true, //CALLABLE,
+ true, //SIGNAL,
+ true, //DICTIONARY,
+ true, //ARRAY,
+
+ // typed arrays
+ true, //PACKED_BYTE_ARRAY,
+ true, //PACKED_INT32_ARRAY,
+ true, //PACKED_INT64_ARRAY,
+ true, //PACKED_FLOAT32_ARRAY,
+ true, //PACKED_FLOAT64_ARRAY,
+ true, //PACKED_STRING_ARRAY,
+ true, //PACKED_VECTOR2_ARRAY,
+ true, //PACKED_VECTOR3_ARRAY,
+ true, //PACKED_COLOR_ARRAY,
+ };
+
+ if (unlikely(needs_deinit[type])) { //make it fast for types that dont need deinit
+ _clear_internal();
+ }
+ type = NIL;
+ }
+
+ static void _register_variant_operators();
+ static void _unregister_variant_operators();
+ static void _register_variant_methods();
+ static void _unregister_variant_methods();
+ static void _register_variant_setters_getters();
+ static void _unregister_variant_setters_getters();
+ static void _register_variant_constructors();
+ static void _unregister_variant_constructors();
+ static void _register_variant_utility_functions();
+ static void _unregister_variant_utility_functions();
public:
_FORCE_INLINE_ Type get_type() const {
@@ -266,7 +327,7 @@ public:
operator Color() const;
operator NodePath() const;
- operator RID() const;
+ operator ::RID() const;
operator Object *() const;
operator Node *() const;
@@ -291,7 +352,7 @@ public:
operator Vector<Variant>() const;
operator Vector<StringName>() const;
- operator Vector<RID>() const;
+ operator Vector<::RID>() const;
operator Vector<Vector2>() const;
// some core type enums to convert to
@@ -338,7 +399,7 @@ public:
Variant(const Transform &p_transform);
Variant(const Color &p_color);
Variant(const NodePath &p_node_path);
- Variant(const RID &p_rid);
+ Variant(const ::RID &p_rid);
Variant(const Object *p_object);
Variant(const Callable &p_callable);
Variant(const Signal &p_signal);
@@ -358,14 +419,13 @@ public:
Variant(const Vector<Variant> &p_array);
Variant(const Vector<StringName> &p_array);
- Variant(const Vector<RID> &p_array); // helper
+ Variant(const Vector<::RID> &p_array); // helper
Variant(const Vector<Vector2> &p_array); // helper
Variant(const IP_Address &p_address);
// If this changes the table in variant_op must be updated
enum Operator {
-
//comparison
OP_EQUAL,
OP_NOT_EQUAL,
@@ -408,7 +468,7 @@ public:
return res;
}
- Variant::Type get_operator_return_type(Operator p_operator, Type p_type_a, Type p_type_b);
+ static Variant::Type get_operator_return_type(Operator p_operator, Type p_type_a, Type p_type_b);
typedef void (*ValidatedOperatorEvaluator)(const Variant *left, const Variant *right, Variant *r_ret);
static ValidatedOperatorEvaluator get_validated_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b);
#ifdef PTRCALL_ENABLED
@@ -421,61 +481,53 @@ public:
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
- class InternalMethod {
-#ifdef DEBUG_ENABLED
- protected:
- StringName method_name;
- Variant::Type base_type;
-#endif
- public:
- enum Flags {
- FLAG_IS_CONST = 1,
- FLAG_RETURNS_VARIANT = 2,
- FLAG_NO_PTRCALL = 4,
- FLAG_VARARGS = 8
- };
+ /* Built-In Methods */
- virtual int get_argument_count() const = 0;
- virtual Type get_argument_type(int p_arg) const = 0;
- virtual Type get_return_type() const = 0;
- virtual uint32_t get_flags() const = 0;
+ typedef void (*ValidatedBuiltInMethod)(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret);
+ typedef void (*PTRBuiltInMethod)(void *p_base, const void **p_args, void *r_ret, int p_argcount);
-#ifdef DEBUG_ENABLED
- virtual String get_argument_name(int p_arg) const = 0;
- StringName get_name() const {
- return method_name;
- }
- Variant::Type get_base_type() const {
- return base_type;
- }
-#endif
- virtual Vector<Variant> get_default_arguments() const = 0;
- virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) = 0;
- virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) = 0;
-#ifdef PTRCALL_ENABLED
- virtual void ptrcall(void *p_base, const void **p_args, void *r_ret) = 0;
-#endif
- virtual ~InternalMethod() {}
- };
+ static bool has_builtin_method(Variant::Type p_type, const StringName &p_method);
+
+ static ValidatedBuiltInMethod get_validated_builtin_method(Variant::Type p_type, const StringName &p_method);
+ static PTRBuiltInMethod get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method);
- static InternalMethod *get_internal_method(Type p_type, const StringName &p_method_name);
+ static int get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method);
+ static Variant::Type get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument);
+ static String get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument);
+ static Vector<Variant> get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method);
+ static bool has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method);
+ static Variant::Type get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method);
+ static bool is_builtin_method_const(Variant::Type p_type, const StringName &p_method);
+ static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method);
+ static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list);
- void call_ptr(const StringName &p_method, const Variant **p_args, int p_argcount, Variant *r_ret, Callable::CallError &r_error);
- Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error);
Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant());
+ static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce);
- static Variant construct(const Variant::Type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict = true);
-
+ //dynamic (includes Object)
void get_method_list(List<MethodInfo> *p_list) const;
bool has_method(const StringName &p_method) const;
- static Vector<Variant::Type> get_method_argument_types(Variant::Type p_type, const StringName &p_method);
- static Vector<Variant> get_method_default_arguments(Variant::Type p_type, const StringName &p_method);
- static Variant::Type get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return = nullptr);
- static Vector<StringName> get_method_argument_names(Variant::Type p_type, const StringName &p_method);
- static bool is_method_const(Variant::Type p_type, const StringName &p_method);
+
+ /* Constructors */
+
+ typedef void (*ValidatedConstructor)(Variant &r_base, const Variant **p_args);
+ typedef void (*PTRConstructor)(void *base, const void **p_args);
+
+ static int get_constructor_count(Variant::Type p_type);
+ static ValidatedConstructor get_validated_constructor(Variant::Type p_type, int p_constructor);
+ static PTRConstructor get_ptr_constructor(Variant::Type p_type, int p_constructor);
+ static int get_constructor_argument_count(Variant::Type p_type, int p_constructor);
+ static Variant::Type get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument);
+ static String get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument);
+ static void construct(Variant::Type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+
+ static void get_constructor_list(Type p_type, List<MethodInfo> *r_list); //convenience
+
+ /* Properties */
void set_named(const StringName &p_member, const Variant &p_value, bool &r_valid);
Variant get_named(const StringName &p_member, bool &r_valid) const;
@@ -496,6 +548,8 @@ public:
static PTRSetter get_member_ptr_setter(Variant::Type p_type, const StringName &p_member);
static PTRGetter get_member_ptr_getter(Variant::Type p_type, const StringName &p_member);
+ /* Indexing */
+
static bool has_indexing(Variant::Type p_type);
static Variant::Type get_indexed_element_type(Variant::Type p_type);
@@ -516,6 +570,8 @@ public:
uint64_t get_indexed_size() const;
+ /* Keying */
+
static bool is_keyed(Variant::Type p_type);
typedef void (*ValidatedKeyedSetter)(Variant *base, const Variant *key, const Variant *value, bool &valid);
@@ -538,6 +594,8 @@ public:
Variant get_keyed(const Variant &p_key, bool &r_valid) const;
bool has_key(const Variant &p_key, bool &r_valid) const;
+ /* Generic */
+
void set(const Variant &p_index, const Variant &p_value, bool *r_valid = nullptr);
Variant get(const Variant &p_index, bool *r_valid = nullptr) const;
bool in(const Variant &p_index, bool *r_valid = nullptr) const;
@@ -548,6 +606,32 @@ public:
void get_property_list(List<PropertyInfo> *p_list) const;
+ static void call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ static bool has_utility_function(const StringName &p_name);
+
+ typedef void (*ValidatedUtilityFunction)(Variant *r_ret, const Variant **p_args, int p_argcount);
+ typedef void (*PTRUtilityFunction)(void *r_ret, const void **p_args, int p_argcount);
+
+ static ValidatedUtilityFunction get_validated_utility_function(const StringName &p_name);
+ static PTRUtilityFunction get_ptr_utility_function(const StringName &p_name);
+
+ enum UtilityFunctionType {
+ UTILITY_FUNC_TYPE_MATH,
+ UTILITY_FUNC_TYPE_RANDOM,
+ UTILITY_FUNC_TYPE_GENERAL,
+ };
+
+ static UtilityFunctionType get_utility_function_type(const StringName &p_name);
+
+ static int get_utility_function_argument_count(const StringName &p_name);
+ static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg);
+ static String get_utility_function_argument_name(const StringName &p_name, int p_arg);
+ static bool has_utility_function_return_value(const StringName &p_name);
+ static Variant::Type get_utility_function_return_type(const StringName &p_name);
+ static bool is_utility_function_vararg(const StringName &p_name);
+
+ static void get_utility_function_list(List<StringName> *r_functions);
+
//argsVariant call()
bool operator==(const Variant &p_variant) const;
@@ -560,7 +644,6 @@ public:
String stringify(List<const void *> &stack) const;
void static_assign(const Variant &p_variant);
- static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);
static bool has_constant(Variant::Type p_type, const StringName &p_value);
static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr);
@@ -573,12 +656,13 @@ public:
void operator=(const Variant &p_variant); // only this is enough for all the other types
+ static void register_types();
+ static void unregister_types();
+
Variant(const Variant &p_variant);
_FORCE_INLINE_ Variant() {}
_FORCE_INLINE_ ~Variant() {
- if (type != Variant::NIL) {
- clear();
- }
+ clear();
}
};
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 37424f5ff9..f6fe642493 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -36,521 +36,382 @@
#include "core/io/compression.h"
#include "core/object/class_db.h"
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
#include "core/templates/oa_hash_map.h"
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) {
-}
-
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) {
- arr.push_back(p_str);
-}
-
-template <class... P>
-_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) {
- arr.push_back(p_str);
- sarray_add_str(arr, p_args...);
-}
-
-template <class... P>
-_FORCE_INLINE_ Vector<String> sarray(P... p_args) {
- Vector<String> arr;
- sarray_add_str(arr, p_args...);
- return arr;
-}
-
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
-struct _VariantCall {
- template <class T, class... P>
- class InternalMethod : public Variant::InternalMethod {
- public:
- void (T::*method)(P...);
- Vector<Variant> default_values;
-#ifdef DEBUG_ENABLED
- Vector<String> argument_names;
-#endif
+template <class T>
+struct TypeAdjust {
+ _FORCE_INLINE_ static void adjust(Variant *r_ret) {
+ VariantTypeChanger<typename GetSimpleTypeT<T>::type_t>::change(r_ret);
+ }
+};
- virtual int get_argument_count() const {
- return sizeof...(P);
- }
- virtual Variant::Type get_argument_type(int p_arg) const {
- return call_get_argument_type<P...>(p_arg);
- }
-#ifdef DEBUG_ENABLED
- virtual String get_argument_name(int p_arg) const {
- ERR_FAIL_INDEX_V(p_arg, argument_names.size(), String());
- return argument_names[p_arg];
- }
-#endif
- virtual Vector<Variant> get_default_arguments() const {
- return default_values;
- }
+template <> //do nothing for variant
+struct TypeAdjust<Variant> {
+ _FORCE_INLINE_ static void adjust(Variant *r_ret) {
+ }
+};
- virtual Variant::Type get_return_type() const {
- return Variant::NIL;
- }
- virtual uint32_t get_flags() const {
- return 0;
- }
+template <> //do nothing for variant
+struct TypeAdjust<Object *> {
+ _FORCE_INLINE_ static void adjust(Variant *r_ret) {
+ VariantInternal::clear(r_ret);
+ *r_ret = (Object *)nullptr;
+ }
+};
- virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
- call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, default_values);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_ret_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals);
+}
- virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
- call_with_validated_variant_args(base, method, p_args);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_retc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals);
+}
-#ifdef PTRCALL_ENABLED
- virtual void ptrcall(void *p_base, const void **p_args, void *r_ret) {
- call_with_ptr_args<T, P...>(reinterpret_cast<T *>(p_base), method, p_args);
- }
-#endif
- InternalMethod(void (T::*p_method)(P...), const Vector<Variant> &p_default_args
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_arg_names, const StringName &p_method_name, Variant::Type p_base_type
-#endif
- ) {
- method = p_method;
- default_values = p_default_args;
-#ifdef DEBUG_ENABLED
- argument_names = p_arg_names;
- method_name = p_method_name;
- base_type = p_base_type;
-#endif
- }
- };
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
+}
- template <class T, class R, class... P>
- class InternalMethodR : public Variant::InternalMethod {
- public:
- R(T::*method)
- (P...);
- Vector<Variant> default_values;
-#ifdef DEBUG_ENABLED
- Vector<String> argument_names;
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) {
+ call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals);
+}
- virtual int get_argument_count() const {
- return sizeof...(P);
- }
- virtual Variant::Type get_argument_type(int p_arg) const {
- return call_get_argument_type<P...>(p_arg);
- return Variant::NIL;
- }
-#ifdef DEBUG_ENABLED
- virtual String get_argument_name(int p_arg) const {
- ERR_FAIL_INDEX_V(p_arg, argument_names.size(), String());
- return argument_names[p_arg];
- }
-#endif
- virtual Vector<Variant> get_default_arguments() const {
- return default_values;
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_validated_call(R (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_ret(base, method, p_args, r_ret);
+}
- virtual Variant::Type get_return_type() const {
- return GetTypeInfo<R>::VARIANT_TYPE;
- }
- virtual uint32_t get_flags() const {
- uint32_t f = 0;
- if (get_return_type() == Variant::NIL) {
- f |= FLAG_RETURNS_VARIANT;
- }
- return f;
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_validated_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args_retc(base, method, p_args, r_ret);
+}
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_args(base, method, p_args);
+}
- virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
- call_with_variant_args_ret_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, default_values);
- }
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) {
+ call_with_validated_variant_argsc(base, method, p_args);
+}
- virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
- call_with_validated_variant_args_ret(base, method, p_args, r_ret);
- }
-#ifdef PTRCALL_ENABLED
- virtual void ptrcall(void *p_base, const void **p_args, void *r_ret) {
- call_with_ptr_args_ret<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
- }
-#endif
- InternalMethodR(R (T::*p_method)(P...), const Vector<Variant> &p_default_args
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_arg_names, const StringName &p_method_name, Variant::Type p_base_type
-#endif
- ) {
- method = p_method;
- default_values = p_default_args;
-#ifdef DEBUG_ENABLED
- argument_names = p_arg_names;
- method_name = p_method_name;
- base_type = p_base_type;
-#endif
- }
- };
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
+ call_with_ptr_args_ret(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
+}
- template <class T, class R, class... P>
- class InternalMethodRC : public Variant::InternalMethod {
- public:
- R(T::*method)
- (P...) const;
- Vector<Variant> default_values;
-#ifdef DEBUG_ENABLED
- Vector<String> argument_names;
-#endif
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
+ call_with_ptr_args_retc(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
+}
- virtual int get_argument_count() const {
- return sizeof...(P);
- }
- virtual Variant::Type get_argument_type(int p_arg) const {
- return call_get_argument_type<P...>(p_arg);
- }
-#ifdef DEBUG_ENABLED
- virtual String get_argument_name(int p_arg) const {
- ERR_FAIL_INDEX_V(p_arg, argument_names.size(), String());
- return argument_names[p_arg];
- }
-#endif
- virtual Vector<Variant> get_default_arguments() const {
- return default_values;
- }
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) {
+ call_with_ptr_args(reinterpret_cast<T *>(p_base), method, p_args);
+}
- virtual Variant::Type get_return_type() const {
- return GetTypeInfo<R>::VARIANT_TYPE;
- }
- virtual uint32_t get_flags() const {
- uint32_t f = FLAG_IS_CONST;
- if (get_return_type() == Variant::NIL) {
- f |= FLAG_RETURNS_VARIANT;
- }
- return f;
- }
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) {
+ call_with_ptr_argsc(reinterpret_cast<T *>(p_base), method, p_args);
+}
- virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
- call_with_variant_args_retc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, default_values);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_change_return_type(R (T::*method)(P...), Variant *v) {
+ TypeAdjust<R>::adjust(v);
+}
- virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
- call_with_validated_variant_args_retc(base, method, p_args, r_ret);
- }
-#ifdef PTRCALL_ENABLED
- virtual void ptrcall(void *p_base, const void **p_args, void *r_ret) {
- call_with_ptr_args_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
- }
-#endif
- InternalMethodRC(R (T::*p_method)(P...) const, const Vector<Variant> &p_default_args
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_arg_names, const StringName &p_method_name, Variant::Type p_base_type
-#endif
- ) {
- method = p_method;
- default_values = p_default_args;
-#ifdef DEBUG_ENABLED
- argument_names = p_arg_names;
- method_name = p_method_name;
- base_type = p_base_type;
-#endif
- }
- };
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_change_return_type(R (T::*method)(P...) const, Variant *v) {
+ TypeAdjust<R>::adjust(v);
+}
- template <class T, class R, class... P>
- class InternalMethodRS : public Variant::InternalMethod {
- public:
- R(*method)
- (T *, P...);
- Vector<Variant> default_values;
-#ifdef DEBUG_ENABLED
- Vector<String> argument_names;
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_change_return_type(void (T::*method)(P...), Variant *v) {
+ VariantInternal::clear(v);
+}
- virtual int get_argument_count() const {
- return sizeof...(P);
- }
- virtual Variant::Type get_argument_type(int p_arg) const {
- return call_get_argument_type<P...>(p_arg);
- }
-#ifdef DEBUG_ENABLED
- virtual String get_argument_name(int p_arg) const {
- ERR_FAIL_INDEX_V(p_arg, argument_names.size(), String());
- return argument_names[p_arg];
- }
-#endif
- virtual Vector<Variant> get_default_arguments() const {
- return default_values;
- }
+template <class T, class... P>
+static _FORCE_INLINE_ void vc_change_return_type(void (T::*method)(P...) const, Variant *v) {
+ VariantInternal::clear(v);
+}
- virtual Variant::Type get_return_type() const {
- return GetTypeInfo<R>::VARIANT_TYPE;
- }
- virtual uint32_t get_flags() const {
- uint32_t f = 0;
- if (get_return_type() == Variant::NIL) {
- f |= FLAG_RETURNS_VARIANT;
- }
- return f;
- }
+template <class R, class... P>
+static _FORCE_INLINE_ void vc_change_return_type(R (*method)(P...), Variant *v) {
+ TypeAdjust<R>::adjust(v);
+}
- virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
- const Variant **args = p_args;
-#ifdef DEBUG_ENABLED
- if ((size_t)p_argcount > sizeof...(P)) {
- r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
- r_error.argument = sizeof...(P);
- return;
- }
-#endif
- if ((size_t)p_argcount < sizeof...(P)) {
- size_t missing = sizeof...(P) - (size_t)p_argcount;
- if (missing <= (size_t)default_values.size()) {
- args = (const Variant **)alloca(sizeof...(P) * sizeof(const Variant *));
- // GCC fails to see that `sizeof...(P)` cannot be 0 here given the previous
- // conditions, so it raises a warning on the potential use of `i < 0` as the
- // execution condition.
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wtype-limits"
-#endif
- for (size_t i = 0; i < sizeof...(P); i++) {
- if (i < (size_t)p_argcount) {
- args[i] = p_args[i];
- } else {
- args[i] = &default_values[i - p_argcount + (default_values.size() - missing)];
- }
- }
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
- } else {
-#ifdef DEBUG_ENABLED
- r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
- r_error.argument = sizeof...(P);
-#endif
- return;
- }
- }
- call_with_variant_args_retc_static_helper(VariantGetInternalPtr<T>::get_ptr(base), method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{});
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...)) {
+ return sizeof...(P);
+}
+template <class R, class T, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...) const) {
+ return sizeof...(P);
+}
- virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
- call_with_validated_variant_args_static_retc(base, method, p_args, r_ret);
- }
-#ifdef PTRCALL_ENABLED
- virtual void ptrcall(void *p_base, const void **p_args, void *r_ret) {
- call_with_ptr_args_static_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
- }
-#endif
- InternalMethodRS(R (*p_method)(T *, P...), const Vector<Variant> &p_default_args
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_arg_names, const StringName &p_method_name, Variant::Type p_base_type
-#endif
- ) {
- method = p_method;
- default_values = p_default_args;
-#ifdef DEBUG_ENABLED
- argument_names = p_arg_names;
- method_name = p_method_name;
- base_type = p_base_type;
-#endif
- }
- };
+template <class T, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count(void (T::*method)(P...)) {
+ return sizeof...(P);
+}
- class InternalMethodVC : public Variant::InternalMethod {
- public:
- typedef void (*MethodVC)(Variant *, const Variant **, int, Variant &r_ret, Callable::CallError &);
- MethodVC methodvc = nullptr;
- uint32_t base_flags = 0;
- Vector<String> argument_names;
- Vector<Variant::Type> argument_types;
- Variant::Type return_type = Variant::NIL;
-
- virtual int get_argument_count() const {
- return argument_names.size();
- }
- virtual Variant::Type get_argument_type(int p_arg) const {
- ERR_FAIL_INDEX_V(p_arg, argument_types.size(), Variant::NIL);
- return argument_types[p_arg];
- }
-#ifdef DEBUG_ENABLED
- virtual String get_argument_name(int p_arg) const {
- ERR_FAIL_INDEX_V(p_arg, argument_names.size(), String());
- return argument_names[p_arg];
- }
-#endif
- virtual Vector<Variant> get_default_arguments() const {
- return Vector<Variant>();
- }
+template <class T, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count(void (T::*method)(P...) const) {
+ return sizeof...(P);
+}
- virtual Variant::Type get_return_type() const {
- return return_type;
- }
- virtual uint32_t get_flags() const {
- return base_flags | FLAG_NO_PTRCALL;
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ int vc_get_argument_count(R (*method)(T *, P...)) {
+ return sizeof...(P);
+}
- virtual void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
- methodvc(base, p_args, p_argcount, r_ret, r_error);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...) const, int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
- virtual void validated_call(Variant *base, const Variant **p_args, Variant *r_ret) {
- ERR_FAIL_MSG("No support for validated call");
- }
-#ifdef PTRCALL_ENABLED
- virtual void ptrcall(void *p_base, const void **p_args, void *r_ret) {
- ERR_FAIL_MSG("No support for ptrcall call");
- }
-#endif
- InternalMethodVC(MethodVC p_method, uint32_t p_flags, const Vector<Variant::Type> &p_argument_types, const Variant::Type &p_return_type
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_arg_names, const StringName &p_method_name, Variant::Type p_base_type
-#endif
- ) {
- methodvc = p_method;
- argument_types = p_argument_types;
- return_type = p_return_type;
- base_flags = p_flags;
-#ifdef DEBUG_ENABLED
- argument_names = p_arg_names;
- method_name = p_method_name;
- base_type = p_base_type;
-#endif
- }
- };
+template <class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type(void (T::*method)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
- typedef OAHashMap<StringName, Variant::InternalMethod *> MethodMap;
- static MethodMap *type_internal_methods;
- static List<StringName> *type_internal_method_names;
+template <class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type(void (T::*method)(P...) const, int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
- template <class T, class... P>
- static void _bind_method(const StringName &p_name, void (T::*p_method)(P...), const Vector<Variant> &p_default_args = Vector<Variant>()
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_argument_names = Vector<String>()
-#endif
- ) {
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (*method)(T *, P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_argument_names.size() != sizeof...(P), "Wrong argument name count supplied for method: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
- ERR_FAIL_COND(type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].has(p_name));
-#endif
-#ifdef DEBUG_ENABLED
- Variant::InternalMethod *m = memnew((InternalMethod<T, P...>)(p_method, p_default_args, p_argument_names, p_name, GetTypeInfo<T>::VARIANT_TYPE));
-#else
- Variant::InternalMethod *m = memnew((InternalMethod<T, P...>)(p_method, p_default_args));
-#endif
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...)) {
+ return GetTypeInfo<R>::VARIANT_TYPE;
+}
- type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].insert(p_name, m);
- type_internal_method_names[GetTypeInfo<T>::VARIANT_TYPE].push_back(p_name);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...) const) {
+ return GetTypeInfo<R>::VARIANT_TYPE;
+}
- template <class T, class R, class... P>
- static void _bind_method(const StringName &p_name, R (T::*p_method)(P...) const, const Vector<Variant> &p_default_args = Vector<Variant>()
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_argument_names = Vector<String>()
-#endif
- ) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_argument_names.size() != sizeof...(P), "Wrong argument name count supplied for method: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
- ERR_FAIL_COND_MSG(type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].has(p_name), " Method already registered: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
+template <class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (T::*method)(P...)) {
+ return Variant::NIL;
+}
-#endif
-#ifdef DEBUG_ENABLED
- Variant::InternalMethod *m = memnew((InternalMethodRC<T, R, P...>)(p_method, p_default_args, p_argument_names, p_name, GetTypeInfo<T>::VARIANT_TYPE));
-#else
- Variant::InternalMethod *m = memnew((InternalMethodRC<T, R, P...>)(p_method, p_default_args));
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (T::*method)(P...) const) {
+ return Variant::NIL;
+}
- type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].insert(p_name, m);
- type_internal_method_names[GetTypeInfo<T>::VARIANT_TYPE].push_back(p_name);
- }
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (*method)(P...)) {
+ return GetTypeInfo<R>::VARIANT_TYPE;
+}
- template <class T, class R, class... P>
- static void _bind_method(const StringName &p_name, R (T::*p_method)(P...), const Vector<Variant> &p_default_args = Vector<Variant>()
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_argument_names = Vector<String>()
-#endif
- ) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_argument_names.size() != sizeof...(P), "Wrong argument name count supplied for method: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
- ERR_FAIL_COND_MSG(type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].has(p_name), " Method already registered: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
-#endif
+template <class R, class T, class... P>
+static _FORCE_INLINE_ bool vc_has_return_type(R (T::*method)(P...)) {
+ return true;
+}
+template <class R, class T, class... P>
+static _FORCE_INLINE_ bool vc_has_return_type(R (T::*method)(P...) const) {
+ return true;
+}
-#ifdef DEBUG_ENABLED
- Variant::InternalMethod *m = memnew((InternalMethodR<T, R, P...>)(p_method, p_default_args, p_argument_names, p_name, GetTypeInfo<T>::VARIANT_TYPE));
-#else
- Variant::InternalMethod *m = memnew((InternalMethodR<T, R, P...>)(p_method, p_default_args));
-#endif
- type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].insert(p_name, m);
- type_internal_method_names[GetTypeInfo<T>::VARIANT_TYPE].push_back(p_name);
- }
+template <class T, class... P>
+static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...)) {
+ return false;
+}
-#ifdef DEBUG_ENABLED
-#define bind_method(m_type, m_method, m_arg_names, m_default_args) _VariantCall::_bind_method(#m_method, &m_type ::m_method, m_default_args, m_arg_names)
-#else
-#define bind_method(m_type, m_method, m_arg_names, m_default_args) _VariantCall::_bind_method(#m_method, &m_type ::m_method, m_default_args)
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...) const) {
+ return false;
+}
-#ifdef DEBUG_ENABLED
-#define bind_methodv(m_name, m_method, m_arg_names, m_default_args) _VariantCall::_bind_method(#m_name, m_method, m_default_args, m_arg_names)
-#else
-#define bind_methodv(m_name, m_method, m_arg_names, m_default_args) _VariantCall::_bind_method(#m_name, m_method, m_default_args)
-#endif
+template <class R, class T, class... P>
+static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...)) {
+ return false;
+}
+template <class R, class T, class... P>
+static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...) const) {
+ return true;
+}
- template <class T, class R, class... P>
- static void _bind_function(const StringName &p_name, R (*p_method)(T *, P...), const Vector<Variant> &p_default_args = Vector<Variant>()
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_argument_names = Vector<String>()
-#endif
- ) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_MSG(p_argument_names.size() != sizeof...(P), "Wrong argument name count supplied for method: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
- ERR_FAIL_COND_MSG(type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].has(p_name), " Method already registered: " + Variant::get_type_name(GetTypeInfo<T>::VARIANT_TYPE) + "::" + String(p_name));
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ bool vc_is_const(void (T::*method)(P...)) {
+ return false;
+}
-#ifdef DEBUG_ENABLED
- Variant::InternalMethod *m = memnew((InternalMethodRS<T, R, P...>)(p_method, p_default_args, p_argument_names, p_name, GetTypeInfo<T>::VARIANT_TYPE));
-#else
- Variant::InternalMethod *m = memnew((InternalMethodRS<T, R, P...>)(p_method, p_default_args));
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ bool vc_is_const(void (T::*method)(P...) const) {
+ return true;
+}
- type_internal_methods[GetTypeInfo<T>::VARIANT_TYPE].insert(p_name, m);
- type_internal_method_names[GetTypeInfo<T>::VARIANT_TYPE].push_back(p_name);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_base_type(R (T::*method)(P...)) {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+}
+template <class R, class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_base_type(R (T::*method)(P...) const) {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+}
-#ifdef DEBUG_ENABLED
-#define bind_function(m_name, m_method, m_arg_names, m_default_args) _VariantCall::_bind_function(m_name, m_method, m_default_args, m_arg_names)
-#else
-#define bind_function(m_name, m_method, m_arg_names, m_default_args) _VariantCall::_bind_function(m_name, m_method, m_default_args)
-#endif
+template <class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...)) {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+}
- static void _bind_custom(Variant::Type p_type, const StringName &p_name, InternalMethodVC::MethodVC p_method, uint32_t p_flags, const Vector<Variant::Type> &p_argument_types, const Variant::Type &p_return_type
-#ifdef DEBUG_ENABLED
- ,
- const Vector<String> &p_argument_names = Vector<String>()
-#endif
- ) {
+template <class T, class... P>
+static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) const) {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+}
-#ifdef DEBUG_ENABLED
- Variant::InternalMethod *m = memnew(InternalMethodVC(p_method, p_flags, p_argument_types, p_return_type, p_argument_names, p_name, p_type));
-#else
- Variant::InternalMethod *m = memnew(InternalMethodVC(p_method, p_flags, p_argument_types, p_return_type));
-#endif
+#define METHOD_CLASS(m_class, m_method_name, m_method_ptr) \
+ struct Method_##m_class##_##m_method_name { \
+ static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
+ vc_method_call(m_method_ptr, base, p_args, p_argcount, r_ret, p_defvals, r_error); \
+ } \
+ static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
+ vc_change_return_type(m_method_ptr, r_ret); \
+ vc_validated_call(m_method_ptr, base, p_args, r_ret); \
+ } \
+ static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
+ vc_ptrcall(m_method_ptr, p_base, p_args, r_ret); \
+ } \
+ static int get_argument_count() { \
+ return vc_get_argument_count(m_method_ptr); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return vc_get_argument_type(m_method_ptr, p_arg); \
+ } \
+ static Variant::Type get_return_type() { \
+ return vc_get_return_type(m_method_ptr); \
+ } \
+ static bool has_return_type() { \
+ return vc_has_return_type(m_method_ptr); \
+ } \
+ static bool is_const() { \
+ return vc_is_const(m_method_ptr); \
+ } \
+ static bool is_vararg() { \
+ return false; \
+ } \
+ static Variant::Type get_base_type() { \
+ return vc_get_base_type(m_method_ptr); \
+ } \
+ static StringName get_name() { \
+ return #m_method_name; \
+ } \
+ };
- type_internal_methods[p_type].insert(p_name, m);
- type_internal_method_names[p_type].push_back(p_name);
- }
+template <class R, class T, class... P>
+static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, const void **p_args, void *r_ret) {
+ call_with_ptr_args_static_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret);
+}
-#ifdef DEBUG_ENABLED
-#define bind_custom(m_type, m_name, m_method, m_flags, m_arg_types, m_ret_type, m_arg_names) _VariantCall::_bind_custom(m_type, m_name, m_method, m_flags, m_arg_types, m_ret_type, m_arg_names)
-#else
-#define bind_custom(m_type, m_name, m_method, m_flags, m_arg_types, m_ret_type, m_arg_names) _VariantCall::_bind_custom(m_type, m_name, m_method, m_flags, m_arg_types, m_ret_type)
-#endif
+#define FUNCTION_CLASS(m_class, m_method_name, m_method_ptr) \
+ struct Method_##m_class##_##m_method_name { \
+ static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
+ call_with_variant_args_retc_static_helper_dv(VariantGetInternalPtr<m_class>::get_ptr(base), m_method_ptr, p_args, p_argcount, r_ret, p_defvals, r_error); \
+ } \
+ static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
+ vc_change_return_type(m_method_ptr, r_ret); \
+ call_with_validated_variant_args_static_retc(base, m_method_ptr, p_args, r_ret); \
+ } \
+ static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
+ vc_ptrcall(m_method_ptr, p_base, p_args, r_ret); \
+ } \
+ static int get_argument_count() { \
+ return vc_get_argument_count(m_method_ptr); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return vc_get_argument_type(m_method_ptr, p_arg); \
+ } \
+ static Variant::Type get_return_type() { \
+ return vc_get_return_type(m_method_ptr); \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_const() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return false; \
+ } \
+ static Variant::Type get_base_type() { \
+ return GetTypeInfo<m_class>::VARIANT_TYPE; \
+ } \
+ static StringName get_name() { \
+ return #m_method_name; \
+ } \
+ };
+#define VARARG_CLASS(m_class, m_method_name, m_method_ptr, m_has_return, m_return_type) \
+ struct Method_##m_class##_##m_method_name { \
+ static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \
+ m_method_ptr(base, p_args, p_argcount, r_ret, r_error); \
+ } \
+ static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
+ Callable::CallError ce; \
+ m_method_ptr(base, p_args, p_argcount, *r_ret, ce); \
+ } \
+ static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
+ LocalVector<Variant> vars; \
+ vars.resize(p_argcount); \
+ LocalVector<const Variant *> vars_ptrs; \
+ vars_ptrs.resize(p_argcount); \
+ for (int i = 0; i < p_argcount; i++) { \
+ vars[i] = PtrToArg<Variant>::convert(p_args[i]); \
+ vars_ptrs[i] = &vars[i]; \
+ } \
+ Variant base = PtrToArg<m_class>::convert(p_base); \
+ Variant ret; \
+ Callable::CallError ce; \
+ m_method_ptr(&base, (const Variant **)&vars_ptrs[0], p_argcount, ret, ce); \
+ if (m_has_return) { \
+ m_return_type r = ret; \
+ PtrToArg<m_return_type>::encode(ret, r_ret); \
+ } \
+ } \
+ static int get_argument_count() { \
+ return 0; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return GetTypeInfo<m_return_type>::VARIANT_TYPE; \
+ } \
+ static bool has_return_type() { \
+ return m_has_return; \
+ } \
+ static bool is_const() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::Type get_base_type() { \
+ return GetTypeInfo<m_class>::VARIANT_TYPE; \
+ } \
+ static StringName get_name() { \
+ return #m_method_name; \
+ } \
+ };
+
+struct _VariantCall {
static String func_PackedByteArray_get_string_from_ascii(PackedByteArray *p_instance) {
String s;
if (p_instance->size() > 0) {
@@ -670,190 +531,6 @@ struct _VariantCall {
signal->emit(p_args, p_argcount);
}
- struct ConstructData {
- int arg_count;
- Vector<Variant::Type> arg_types;
- Vector<String> arg_names;
- VariantConstructFunc func;
- };
-
- struct ConstructFunc {
- List<ConstructData> constructors;
- };
-
- static ConstructFunc *construct_funcs;
-
- static void Vector2_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Vector2(*p_args[0], *p_args[1]);
- }
-
- static void Vector2i_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Vector2i(*p_args[0], *p_args[1]);
- }
-
- static void Rect2_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Rect2(*p_args[0], *p_args[1]);
- }
-
- static void Rect2_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Rect2(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
- }
-
- static void Rect2i_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Rect2i(*p_args[0], *p_args[1]);
- }
-
- static void Rect2i_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Rect2i(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
- }
-
- static void Transform2D_init2(Variant &r_ret, const Variant **p_args) {
- Transform2D m(*p_args[0], *p_args[1]);
- r_ret = m;
- }
-
- static void Transform2D_init3(Variant &r_ret, const Variant **p_args) {
- Transform2D m;
- m[0] = *p_args[0];
- m[1] = *p_args[1];
- m[2] = *p_args[2];
- r_ret = m;
- }
-
- static void Vector3_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Vector3(*p_args[0], *p_args[1], *p_args[2]);
- }
-
- static void Vector3i_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Vector3i(*p_args[0], *p_args[1], *p_args[2]);
- }
-
- static void Plane_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Plane(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
- }
-
- static void Plane_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Plane(*p_args[0], *p_args[1], *p_args[2]);
- }
-
- static void Plane_init3(Variant &r_ret, const Variant **p_args) {
- r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator real_t());
- }
- static void Plane_init4(Variant &r_ret, const Variant **p_args) {
- r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator Vector3());
- }
-
- static void Quat_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Quat(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
- }
-
- static void Quat_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Quat(((Vector3)(*p_args[0])), ((real_t)(*p_args[1])));
- }
-
- static void Quat_init3(Variant &r_ret, const Variant **p_args) {
- r_ret = Quat(((Vector3)(*p_args[0])));
- }
-
- static void Color_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = Color(*p_args[0], *p_args[1], *p_args[2], *p_args[3]);
- }
-
- static void Color_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Color(*p_args[0], *p_args[1], *p_args[2]);
- }
-
- static void Color_init3(Variant &r_ret, const Variant **p_args) {
- r_ret = Color::html(*p_args[0]);
- }
-
- static void Color_init4(Variant &r_ret, const Variant **p_args) {
- r_ret = Color::hex(*p_args[0]);
- }
-
- static void Color_init5(Variant &r_ret, const Variant **p_args) {
- r_ret = Color(((Color)(*p_args[0])), *p_args[1]);
- }
-
- static void AABB_init1(Variant &r_ret, const Variant **p_args) {
- r_ret = ::AABB(*p_args[0], *p_args[1]);
- }
-
- static void Basis_init1(Variant &r_ret, const Variant **p_args) {
- Basis m;
- m.set_axis(0, *p_args[0]);
- m.set_axis(1, *p_args[1]);
- m.set_axis(2, *p_args[2]);
- r_ret = m;
- }
-
- static void Basis_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Basis(p_args[0]->operator Vector3(), p_args[1]->operator real_t());
- }
-
- static void Transform_init1(Variant &r_ret, const Variant **p_args) {
- Transform t;
- t.basis.set_axis(0, *p_args[0]);
- t.basis.set_axis(1, *p_args[1]);
- t.basis.set_axis(2, *p_args[2]);
- t.origin = *p_args[3];
- r_ret = t;
- }
-
- static void Transform_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Transform(p_args[0]->operator Basis(), p_args[1]->operator Vector3());
- }
-
- static void Callable_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Callable(p_args[0]->operator ObjectID(), p_args[1]->operator String());
- }
-
- static void Signal_init2(Variant &r_ret, const Variant **p_args) {
- r_ret = Signal(p_args[0]->operator ObjectID(), p_args[1]->operator String());
- }
-
- static void add_constructor(VariantConstructFunc p_func, const Variant::Type p_type,
- const String &p_name1 = "", const Variant::Type p_type1 = Variant::NIL,
- const String &p_name2 = "", const Variant::Type p_type2 = Variant::NIL,
- const String &p_name3 = "", const Variant::Type p_type3 = Variant::NIL,
- const String &p_name4 = "", const Variant::Type p_type4 = Variant::NIL) {
- ConstructData cd;
- cd.func = p_func;
- cd.arg_count = 0;
-
- if (p_name1 == "") {
- goto end;
- }
- cd.arg_count++;
- cd.arg_names.push_back(p_name1);
- cd.arg_types.push_back(p_type1);
-
- if (p_name2 == "") {
- goto end;
- }
- cd.arg_count++;
- cd.arg_names.push_back(p_name2);
- cd.arg_types.push_back(p_type2);
-
- if (p_name3 == "") {
- goto end;
- }
- cd.arg_count++;
- cd.arg_names.push_back(p_name3);
- cd.arg_types.push_back(p_type3);
-
- if (p_name4 == "") {
- goto end;
- }
- cd.arg_count++;
- cd.arg_names.push_back(p_name4);
- cd.arg_types.push_back(p_type4);
-
- end:
-
- construct_funcs[p_type].constructors.push_back(cd);
- }
-
struct ConstantData {
Map<StringName, int> value;
#ifdef DEBUG_ENABLED
@@ -882,20 +559,62 @@ struct _VariantCall {
}
};
-_VariantCall::ConstructFunc *_VariantCall::construct_funcs = nullptr;
_VariantCall::ConstantData *_VariantCall::constant_data = nullptr;
-_VariantCall::MethodMap *_VariantCall::type_internal_methods = nullptr;
-List<StringName> *_VariantCall::type_internal_method_names = nullptr;
-Variant Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
- Variant ret;
- call_ptr(p_method, p_args, p_argcount, &ret, r_error);
- return ret;
-}
+struct VariantBuiltInMethodInfo {
+ void (*call)(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error);
+ Variant::ValidatedBuiltInMethod validated_call;
+ Variant::PTRBuiltInMethod ptrcall;
+
+ Vector<Variant> default_arguments;
+ Vector<String> argument_names;
+
+ bool is_const;
+ bool has_return_type;
+ bool is_vararg;
+ Variant::Type return_type;
+ int argument_count;
+ Variant::Type (*get_argument_type)(int p_arg);
+};
+
+typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap;
+static BuiltinMethodMap *builtin_method_info;
+static List<StringName> *builtin_method_names;
+
+template <class T>
+static void register_builtin_method(const Vector<String> &p_argnames, const Vector<Variant> &p_def_args) {
+ StringName name = T::get_name();
+
+ ERR_FAIL_COND(builtin_method_info[T::get_base_type()].has(name));
+
+ VariantBuiltInMethodInfo imi;
+
+ imi.call = T::call;
+ imi.validated_call = T::validated_call;
+ if (T::is_vararg()) {
+ imi.ptrcall = nullptr;
+ } else {
+ imi.ptrcall = T::ptrcall;
+ }
-void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p_argcount, Variant *r_ret, Callable::CallError &r_error) {
- Variant ret;
+ imi.default_arguments = p_def_args;
+ imi.argument_names = p_argnames;
+ imi.is_const = T::is_const();
+ imi.is_vararg = T::is_vararg();
+ imi.has_return_type = T::has_return_type();
+ imi.return_type = T::get_return_type();
+ imi.argument_count = T::get_argument_count();
+ imi.get_argument_type = T::get_argument_type;
+#ifdef DEBUG_METHODS_ENABLED
+ ERR_FAIL_COND(!imi.is_vararg && imi.argument_count != imi.argument_names.size());
+#endif
+
+ builtin_method_info[T::get_base_type()].insert(name, imi);
+ builtin_method_names[T::get_base_type()].push_back(name);
+}
+
+void Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
if (type == Variant::OBJECT) {
//call object
Object *obj = _get_obj().obj;
@@ -910,236 +629,21 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p
}
#endif
- ret = _get_obj().obj->call(p_method, p_args, p_argcount, r_error);
+ r_ret = _get_obj().obj->call(p_method, p_args, p_argcount, r_error);
//else if (type==Variant::METHOD) {
-
} else {
r_error.error = Callable::CallError::CALL_OK;
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[type].lookup_ptr(p_method);
+ const VariantBuiltInMethodInfo *imf = builtin_method_info[type].lookup_ptr(p_method);
- if (m) {
- (*m)->call((Variant *)this, p_args, p_argcount, ret, r_error);
- } else {
- //ok fail because not found
+ if (!imf) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
return;
}
- }
-
- if (r_error.error == Callable::CallError::CALL_OK && r_ret) {
- *r_ret = ret;
- }
-}
-
-#define VCALL(m_type, m_method) _VariantCall::_call_##m_type##_##m_method
-
-Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
- ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, Variant());
-
- r_error.error = Callable::CallError::CALL_OK;
- if (p_argcount == 0) { //generic construct
-
- switch (p_type) {
- case NIL:
- return Variant();
-
- // atomic types
- case BOOL:
- return Variant(false);
- case INT:
- return 0;
- case FLOAT:
- return 0.0f;
- case STRING:
- return String();
-
- // math types
- case VECTOR2:
- return Vector2();
- case VECTOR2I:
- return Vector2i();
- case RECT2:
- return Rect2();
- case RECT2I:
- return Rect2i();
- case VECTOR3:
- return Vector3();
- case VECTOR3I:
- return Vector3i();
- case TRANSFORM2D:
- return Transform2D();
- case PLANE:
- return Plane();
- case QUAT:
- return Quat();
- case AABB:
- return ::AABB();
- case BASIS:
- return Basis();
- case TRANSFORM:
- return Transform();
-
- // misc types
- case COLOR:
- return Color();
- case STRING_NAME:
- return StringName();
- case NODE_PATH:
- return NodePath();
- case _RID:
- return RID();
- case OBJECT:
- return (Object *)nullptr;
- case CALLABLE:
- return Callable();
- case SIGNAL:
- return Signal();
- case DICTIONARY:
- return Dictionary();
- case ARRAY:
- return Array();
- case PACKED_BYTE_ARRAY:
- return PackedByteArray();
- case PACKED_INT32_ARRAY:
- return PackedInt32Array();
- case PACKED_INT64_ARRAY:
- return PackedInt64Array();
- case PACKED_FLOAT32_ARRAY:
- return PackedFloat32Array();
- case PACKED_FLOAT64_ARRAY:
- return PackedFloat64Array();
- case PACKED_STRING_ARRAY:
- return PackedStringArray();
- case PACKED_VECTOR2_ARRAY:
- return PackedVector2Array();
- case PACKED_VECTOR3_ARRAY:
- return PackedVector3Array();
- case PACKED_COLOR_ARRAY:
- return PackedColorArray();
- default:
- return Variant();
- }
-
- } else if (p_argcount == 1 && p_args[0]->type == p_type) {
- return *p_args[0]; //copy construct
- } else if (p_argcount == 1 && (!p_strict || Variant::can_convert(p_args[0]->type, p_type))) {
- //near match construct
-
- switch (p_type) {
- case NIL: {
- return Variant();
- } break;
- case BOOL: {
- return Variant(bool(*p_args[0]));
- }
- case INT: {
- return (int64_t(*p_args[0]));
- }
- case FLOAT: {
- return double(*p_args[0]);
- }
- case STRING: {
- return String(*p_args[0]);
- }
- case VECTOR2: {
- return Vector2(*p_args[0]);
- }
- case VECTOR2I: {
- return Vector2i(*p_args[0]);
- }
- case RECT2:
- return (Rect2(*p_args[0]));
- case RECT2I:
- return (Rect2i(*p_args[0]));
- case VECTOR3:
- return (Vector3(*p_args[0]));
- case VECTOR3I:
- return (Vector3i(*p_args[0]));
- case TRANSFORM2D:
- return (Transform2D(p_args[0]->operator Transform2D()));
- case PLANE:
- return (Plane(*p_args[0]));
- case QUAT:
- return (p_args[0]->operator Quat());
- case AABB:
- return (::AABB(*p_args[0]));
- case BASIS:
- return (Basis(p_args[0]->operator Basis()));
- case TRANSFORM:
- return (Transform(p_args[0]->operator Transform()));
-
- // misc types
- case COLOR:
- return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]);
- case STRING_NAME:
- return (StringName(p_args[0]->operator StringName()));
- case NODE_PATH:
- return (NodePath(p_args[0]->operator NodePath()));
- case _RID:
- return (RID(*p_args[0]));
- case OBJECT:
- return ((Object *)(p_args[0]->operator Object *()));
- case CALLABLE:
- return ((Callable)(p_args[0]->operator Callable()));
- case SIGNAL:
- return ((Signal)(p_args[0]->operator Signal()));
- case DICTIONARY:
- return p_args[0]->operator Dictionary();
- case ARRAY:
- return p_args[0]->operator Array();
-
- // arrays
- case PACKED_BYTE_ARRAY:
- return (PackedByteArray(*p_args[0]));
- case PACKED_INT32_ARRAY:
- return (PackedInt32Array(*p_args[0]));
- case PACKED_INT64_ARRAY:
- return (PackedInt64Array(*p_args[0]));
- case PACKED_FLOAT32_ARRAY:
- return (PackedFloat32Array(*p_args[0]));
- case PACKED_FLOAT64_ARRAY:
- return (PackedFloat64Array(*p_args[0]));
- case PACKED_STRING_ARRAY:
- return (PackedStringArray(*p_args[0]));
- case PACKED_VECTOR2_ARRAY:
- return (PackedVector2Array(*p_args[0]));
- case PACKED_VECTOR3_ARRAY:
- return (PackedVector3Array(*p_args[0]));
- case PACKED_COLOR_ARRAY:
- return (PackedColorArray(*p_args[0]));
- default:
- return Variant();
- }
- } else if (p_argcount >= 1) {
- _VariantCall::ConstructFunc &c = _VariantCall::construct_funcs[p_type];
-
- for (List<_VariantCall::ConstructData>::Element *E = c.constructors.front(); E; E = E->next()) {
- const _VariantCall::ConstructData &cd = E->get();
-
- if (cd.arg_count != p_argcount) {
- continue;
- }
-
- //validate parameters
- for (int i = 0; i < cd.arg_count; i++) {
- if (!Variant::can_convert(p_args[i]->type, cd.arg_types[i])) {
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; //no such constructor
- r_error.argument = i;
- r_error.expected = cd.arg_types[i];
- return Variant();
- }
- }
- Variant v;
- cd.func(v, p_args);
- return v;
- }
+ imf->call(this, p_args, p_argcount, r_ret, imf->default_arguments, r_error);
}
- r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; //no such constructor
- return Variant();
}
bool Variant::has_method(const StringName &p_method) const {
@@ -1152,134 +656,143 @@ bool Variant::has_method(const StringName &p_method) const {
return obj->has_method(p_method);
}
- return _VariantCall::type_internal_methods[type].has(p_method);
+ return builtin_method_info[type].has(p_method);
}
-Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, const StringName &p_method) {
- Vector<Variant::Type> types;
+bool Variant::has_builtin_method(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ return builtin_method_info[p_type].has(p_method);
+}
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[p_type].lookup_ptr(p_method);
- if (*m) {
- types.resize((*m)->get_argument_count());
- for (int i = 0; i < (*m)->get_argument_count(); i++) {
- types.write[i] = (*m)->get_argument_type(i);
- }
- }
+Variant::ValidatedBuiltInMethod Variant::get_validated_builtin_method(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, nullptr);
+ return method->validated_call;
+}
- return types;
+Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, nullptr);
+ return method->ptrcall;
}
-bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) {
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[p_type].lookup_ptr(p_method);
- if (*m) {
- return (*m)->get_flags() & Variant::InternalMethod::FLAG_IS_CONST;
- }
- return false;
+int Variant::get_builtin_method_argument_count(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, 0);
+ return method->argument_count;
}
-Vector<StringName> Variant::get_method_argument_names(Variant::Type p_type, const StringName &p_method) {
- Vector<StringName> argnames;
+Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, Variant::NIL);
+ ERR_FAIL_INDEX_V(p_argument, method->argument_count, Variant::NIL);
+ return method->get_argument_type(p_argument);
+}
-#ifdef DEBUG_ENABLED
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[p_type].lookup_ptr(p_method);
- if (*m) {
- argnames.resize((*m)->get_argument_count());
- for (int i = 0; i < (*m)->get_argument_count(); i++) {
- argnames.write[i] = (*m)->get_argument_name(i);
- }
- }
+String Variant::get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String());
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, String());
+#ifdef DEBUG_METHODS_ENABLED
+ ERR_FAIL_INDEX_V(p_argument, method->argument_count, String());
+ return method->argument_names[p_argument];
+#else
+ return "arg" + itos(p_argument + 1);
#endif
- return argnames;
}
-Variant::Type Variant::get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return) {
- Variant::Type rt = Variant::NIL;
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[p_type].lookup_ptr(p_method);
- if (*m) {
- rt = (*m)->get_return_type();
- if (r_has_return) {
- *r_has_return = ((*m)->get_flags() & Variant::InternalMethod::FLAG_RETURNS_VARIANT) || rt != Variant::NIL;
- }
- }
- return rt;
+Vector<Variant> Variant::get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Vector<Variant>());
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, Vector<Variant>());
+ return method->default_arguments;
}
-Vector<Variant> Variant::get_method_default_arguments(Variant::Type p_type, const StringName &p_method) {
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[p_type].lookup_ptr(p_method);
- if (*m) {
- return (*m)->get_default_arguments();
+bool Variant::has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, false);
+ return method->has_return_type;
+}
+
+void Variant::get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list) {
+ ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
+ for (List<StringName>::Element *E = builtin_method_names[p_type].front(); E; E = E->next()) {
+ p_list->push_back(E->get());
}
- return Vector<Variant>();
+}
+
+Variant::Type Variant::get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, Variant::NIL);
+ return method->return_type;
+}
+
+bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, false);
+ return method->is_const;
+}
+
+bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false);
+ const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method);
+ ERR_FAIL_COND_V(!method, false);
+ return method->is_vararg;
}
void Variant::get_method_list(List<MethodInfo> *p_list) const {
- for (List<StringName>::Element *E = _VariantCall::type_internal_method_names[type].front(); E; E = E->next()) {
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[type].lookup_ptr(E->get());
- ERR_CONTINUE(!*m);
-
- MethodInfo mi;
- mi.name = E->get();
- mi.return_val.type = (*m)->get_return_type();
- if ((*m)->get_flags() & Variant::InternalMethod::FLAG_RETURNS_VARIANT) {
- mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- }
- if ((*m)->get_flags() & Variant::InternalMethod::FLAG_IS_CONST) {
- mi.flags |= METHOD_FLAG_CONST;
- }
- if ((*m)->get_flags() & Variant::InternalMethod::FLAG_VARARGS) {
- mi.flags |= METHOD_FLAG_VARARG;
+ if (type == OBJECT) {
+ Object *obj = get_validated_object();
+ if (obj) {
+ obj->get_method_list(p_list);
}
+ } else {
+ for (List<StringName>::Element *E = builtin_method_names[type].front(); E; E = E->next()) {
+ const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E->get());
+ ERR_CONTINUE(!method);
+
+ MethodInfo mi;
+ mi.name = E->get();
+
+ //return type
+ if (method->has_return_type) {
+ mi.return_val.type = method->return_type;
+ if (mi.return_val.type == Variant::NIL) {
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ }
- for (int i = 0; i < (*m)->get_argument_count(); i++) {
- PropertyInfo arg;
-#ifdef DEBUG_ENABLED
- arg.name = (*m)->get_argument_name(i);
+ if (method->is_const) {
+ mi.flags |= METHOD_FLAG_CONST;
+ }
+ if (method->is_vararg) {
+ mi.flags |= METHOD_FLAG_VARARG;
+ }
+
+ for (int i = 0; i < method->argument_count; i++) {
+ PropertyInfo pi;
+#ifdef DEBUG_METHODS_ENABLED
+ pi.name = method->argument_names[i];
#else
- arg.name = "arg" + itos(i + 1);
+ pi.name = "arg" + itos(i + 1);
#endif
- arg.type = (*m)->get_argument_type(i);
- mi.arguments.push_back(arg);
- }
-
- mi.default_arguments = (*m)->get_default_arguments();
- p_list->push_back(mi);
- }
-}
+ pi.type = method->get_argument_type(i);
+ if (pi.type == Variant::NIL) {
+ pi.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ }
+ mi.arguments.push_back(pi);
+ }
-void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list) {
- ERR_FAIL_INDEX(p_type, VARIANT_MAX);
-
- //custom constructors
- for (const List<_VariantCall::ConstructData>::Element *E = _VariantCall::construct_funcs[p_type].constructors.front(); E; E = E->next()) {
- const _VariantCall::ConstructData &cd = E->get();
- MethodInfo mi;
- mi.name = Variant::get_type_name(p_type);
- mi.return_val.type = p_type;
- for (int i = 0; i < cd.arg_count; i++) {
- PropertyInfo pi;
- pi.name = cd.arg_names[i];
- pi.type = cd.arg_types[i];
- mi.arguments.push_back(pi);
+ mi.default_arguments = method->default_arguments;
+ p_list->push_back(mi);
}
- p_list->push_back(mi);
- }
- //default constructors
- for (int i = 0; i < VARIANT_MAX; i++) {
- if (i == p_type) {
- continue;
- }
- if (!Variant::can_convert(Variant::Type(i), p_type)) {
- continue;
- }
-
- MethodInfo mi;
- mi.name = Variant::get_type_name(p_type);
- PropertyInfo pi;
- pi.name = "from";
- pi.type = Variant::Type(i);
- mi.arguments.push_back(pi);
- mi.return_val.type = p_type;
- p_list->push_back(mi);
}
}
@@ -1340,21 +853,44 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va
return E->get();
}
-Variant::InternalMethod *Variant::get_internal_method(Type p_type, const StringName &p_method_name) {
- ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr);
+#ifdef DEBUG_METHODS_ENABLED
+#define bind_method(m_type, m_method, m_arg_names, m_default_args) \
+ METHOD_CLASS(m_type, m_method, &m_type::m_method); \
+ register_builtin_method<Method_##m_type##_##m_method>(m_arg_names, m_default_args);
+#else
+#define bind_method(m_type, m_method, m_arg_names, m_default_args) \
+ METHOD_CLASS(m_type, m_method, &m_type ::m_method); \
+ register_builtin_method<Method_##m_type##_##m_method>(sarray(), m_default_args);
+#endif
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[p_type].lookup_ptr(p_method_name);
- if (*m) {
- return *m;
- }
- return nullptr;
-}
+#ifdef DEBUG_METHODS_ENABLED
+#define bind_methodv(m_type, m_name, m_method, m_arg_names, m_default_args) \
+ METHOD_CLASS(m_type, m_name, m_method); \
+ register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args);
+#else
+#define bind_methodv(m_type, m_name, m_method, m_arg_names, m_default_args) \
+ METHOD_CLASS(m_type, m_name, m_method); \
+ register_builtin_method<Method_##m_type##_##m_name>(sarray(), m_default_args);
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
+#define bind_function(m_type, m_name, m_method, m_arg_names, m_default_args) \
+ FUNCTION_CLASS(m_type, m_name, m_method); \
+ register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args);
+#else
+#define bind_function(m_type, m_name, m_method, m_arg_names, m_default_args) \
+ FUNCTION_CLASS(m_type, m_name, m_method); \
+ register_builtin_method<Method_##m_type##_##m_name>(sarray(), m_default_args);
+#endif
+
+#define bind_custom(m_type, m_name, m_method, m_has_return, m_ret_type) \
+ VARARG_CLASS(m_type, m_name, m_method, m_has_return, m_ret_type) \
+ register_builtin_method<Method_##m_type##_##m_name>(sarray(), Vector<Variant>());
-void register_variant_methods() {
- _VariantCall::type_internal_methods = memnew_arr(_VariantCall::MethodMap, Variant::VARIANT_MAX);
- _VariantCall::type_internal_method_names = memnew_arr(List<StringName>, Variant::VARIANT_MAX);
- _VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX);
+static void _register_variant_builtin_methods() {
_VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX);
+ builtin_method_info = memnew_arr(BuiltinMethodMap, Variant::VARIANT_MAX);
+ builtin_method_names = memnew_arr(List<StringName>, Variant::VARIANT_MAX);
/* String */
@@ -1363,7 +899,7 @@ void register_variant_methods() {
bind_method(String, naturalnocasecmp_to, sarray("to"), varray());
bind_method(String, length, sarray(), varray());
bind_method(String, substr, sarray("from", "len"), varray(-1));
- bind_methodv(find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0));
+ bind_methodv(String, find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0));
bind_method(String, count, sarray("what", "from", "to"), varray(0, 0));
bind_method(String, countn, sarray("what", "from", "to"), varray(0, 0));
bind_method(String, findn, sarray("what", "from"), varray(0));
@@ -1371,7 +907,7 @@ void register_variant_methods() {
bind_method(String, rfindn, sarray("what", "from"), varray(-1));
bind_method(String, match, sarray("expr"), varray());
bind_method(String, matchn, sarray("expr"), varray());
- bind_methodv(begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray());
+ bind_methodv(String, begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray());
bind_method(String, ends_with, sarray("text"), varray());
bind_method(String, is_subsequence_of, sarray("text"), varray());
bind_method(String, is_subsequence_ofi, sarray("text"), varray());
@@ -1379,7 +915,7 @@ void register_variant_methods() {
bind_method(String, similarity, sarray("text"), varray());
bind_method(String, format, sarray("values", "placeholder"), varray("{_}"));
- bind_methodv(replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray());
+ bind_methodv(String, replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray());
bind_method(String, replacen, sarray("what", "forwhat"), varray());
bind_method(String, repeat, sarray("count"), varray());
bind_method(String, insert, sarray("position", "what"), varray());
@@ -1510,7 +1046,7 @@ void register_variant_methods() {
bind_method(Rect2, merge, sarray("b"), varray());
bind_method(Rect2, expand, sarray("to"), varray());
bind_method(Rect2, grow, sarray("by"), varray());
- bind_methodv(grow_margin, &Rect2::grow_margin_bind, sarray("margin", "by"), varray());
+ bind_methodv(Rect2, grow_margin, &Rect2::grow_margin_bind, sarray("margin", "by"), varray());
bind_method(Rect2, grow_individual, sarray("left", "top", "right", "bottom"), varray());
bind_method(Rect2, abs, sarray(), varray());
@@ -1525,7 +1061,7 @@ void register_variant_methods() {
bind_method(Rect2i, merge, sarray("b"), varray());
bind_method(Rect2i, expand, sarray("to"), varray());
bind_method(Rect2i, grow, sarray("by"), varray());
- bind_methodv(grow_margin, &Rect2i::grow_margin_bind, sarray("margin", "by"), varray());
+ bind_methodv(Rect2i, grow_margin, &Rect2i::grow_margin_bind, sarray("margin", "by"), varray());
bind_method(Rect2i, grow_individual, sarray("left", "top", "right", "bottom"), varray());
bind_method(Rect2i, abs, sarray(), varray());
@@ -1581,9 +1117,9 @@ void register_variant_methods() {
bind_method(Plane, distance_to, sarray("point"), varray());
bind_method(Plane, has_point, sarray("point", "epsilon"), varray(CMP_EPSILON));
bind_method(Plane, project, sarray("point"), varray());
- bind_methodv(intersect_3, &Plane::intersect_3_bind, sarray("b", "c"), varray());
- bind_methodv(intersects_ray, &Plane::intersects_ray_bind, sarray("from", "dir"), varray());
- bind_methodv(intersects_segment, &Plane::intersects_segment_bind, sarray("from", "to"), varray());
+ bind_methodv(Plane, intersect_3, &Plane::intersect_3_bind, sarray("b", "c"), varray());
+ bind_methodv(Plane, intersects_ray, &Plane::intersects_ray_bind, sarray("from", "dir"), varray());
+ bind_methodv(Plane, intersects_segment, &Plane::intersects_segment_bind, sarray("from", "to"), varray());
/* Quat */
@@ -1649,9 +1185,9 @@ void register_variant_methods() {
bind_method(Callable, hash, sarray(), varray());
bind_method(Callable, unbind, sarray("argcount"), varray());
- bind_custom(Variant::CALLABLE, "call", _VariantCall::func_Callable_call, Variant::InternalMethod::FLAG_VARARGS | Variant::InternalMethod::FLAG_RETURNS_VARIANT, Vector<Variant::Type>(), Variant::NIL, sarray());
- bind_custom(Variant::CALLABLE, "call_deferred", _VariantCall::func_Callable_call_deferred, Variant::InternalMethod::FLAG_VARARGS, Vector<Variant::Type>(), Variant::NIL, sarray());
- bind_custom(Variant::CALLABLE, "bind", _VariantCall::func_Callable_bind, Variant::InternalMethod::FLAG_VARARGS, Vector<Variant::Type>(), Variant::CALLABLE, sarray());
+ bind_custom(Callable, call, _VariantCall::func_Callable_call, true, Variant);
+ bind_custom(Callable, call_deferred, _VariantCall::func_Callable_call_deferred, false, Variant);
+ bind_custom(Callable, bind, _VariantCall::func_Callable_bind, true, Callable);
/* Signal */
@@ -1665,7 +1201,7 @@ void register_variant_methods() {
bind_method(Signal, is_connected, sarray("callable"), varray());
bind_method(Signal, get_connections, sarray(), varray());
- bind_custom(Variant::SIGNAL, "emit", _VariantCall::func_Signal_emit, Variant::InternalMethod::FLAG_VARARGS, Vector<Variant::Type>(), Variant::NIL, sarray());
+ bind_custom(Signal, emit, _VariantCall::func_Signal_emit, false, Variant);
/* Transform2D */
@@ -1689,7 +1225,7 @@ void register_variant_methods() {
bind_method(Basis, transposed, sarray(), varray());
bind_method(Basis, orthonormalized, sarray(), varray());
bind_method(Basis, determinant, sarray(), varray());
- bind_methodv(rotated, static_cast<Basis (Basis::*)(const Vector3 &, float) const>(&Basis::rotated), sarray("axis", "phi"), varray());
+ bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, float) const>(&Basis::rotated), sarray("axis", "phi"), varray());
bind_method(Basis, scaled, sarray("scale"), varray());
bind_method(Basis, get_scale, sarray(), varray());
bind_method(Basis, get_euler, sarray(), varray());
@@ -1703,29 +1239,29 @@ void register_variant_methods() {
/* AABB */
- bind_method(::AABB, abs, sarray(), varray());
- bind_method(::AABB, get_area, sarray(), varray());
- bind_method(::AABB, has_no_area, sarray(), varray());
- bind_method(::AABB, has_no_surface, sarray(), varray());
- bind_method(::AABB, has_point, sarray("point"), varray());
- bind_method(::AABB, is_equal_approx, sarray("aabb"), varray());
- bind_method(::AABB, intersects, sarray("with"), varray());
- bind_method(::AABB, encloses, sarray("with"), varray());
- bind_method(::AABB, intersects_plane, sarray("plane"), varray());
- bind_method(::AABB, intersection, sarray("with"), varray());
- bind_method(::AABB, merge, sarray("with"), varray());
- bind_method(::AABB, expand, sarray("to_point"), varray());
- bind_method(::AABB, grow, sarray("by"), varray());
- bind_method(::AABB, get_support, sarray("dir"), varray());
- bind_method(::AABB, get_longest_axis, sarray(), varray());
- bind_method(::AABB, get_longest_axis_index, sarray(), varray());
- bind_method(::AABB, get_longest_axis_size, sarray(), varray());
- bind_method(::AABB, get_shortest_axis, sarray(), varray());
- bind_method(::AABB, get_shortest_axis_index, sarray(), varray());
- bind_method(::AABB, get_shortest_axis_size, sarray(), varray());
- bind_method(::AABB, get_endpoint, sarray("idx"), varray());
- bind_methodv(intersects_segment, &AABB::intersects_segment_bind, sarray("from", "to"), varray());
- bind_methodv(intersects_ray, &AABB::intersects_ray_bind, sarray("from", "dir"), varray());
+ bind_method(AABB, abs, sarray(), varray());
+ bind_method(AABB, get_area, sarray(), varray());
+ bind_method(AABB, has_no_area, sarray(), varray());
+ bind_method(AABB, has_no_surface, sarray(), varray());
+ bind_method(AABB, has_point, sarray("point"), varray());
+ bind_method(AABB, is_equal_approx, sarray("aabb"), varray());
+ bind_method(AABB, intersects, sarray("with"), varray());
+ bind_method(AABB, encloses, sarray("with"), varray());
+ bind_method(AABB, intersects_plane, sarray("plane"), varray());
+ bind_method(AABB, intersection, sarray("with"), varray());
+ bind_method(AABB, merge, sarray("with"), varray());
+ bind_method(AABB, expand, sarray("to_point"), varray());
+ bind_method(AABB, grow, sarray("by"), varray());
+ bind_method(AABB, get_support, sarray("dir"), varray());
+ bind_method(AABB, get_longest_axis, sarray(), varray());
+ bind_method(AABB, get_longest_axis_index, sarray(), varray());
+ bind_method(AABB, get_longest_axis_size, sarray(), varray());
+ bind_method(AABB, get_shortest_axis, sarray(), varray());
+ bind_method(AABB, get_shortest_axis_index, sarray(), varray());
+ bind_method(AABB, get_shortest_axis_size, sarray(), varray());
+ bind_method(AABB, get_endpoint, sarray("idx"), varray());
+ bind_methodv(AABB, intersects_segment, &AABB::intersects_segment_bind, sarray("from", "to"), varray());
+ bind_methodv(AABB, intersects_ray, &AABB::intersects_ray_bind, sarray("from", "dir"), varray());
/* Transform */
@@ -1762,6 +1298,7 @@ void register_variant_methods() {
bind_method(Array, push_back, sarray("value"), varray());
bind_method(Array, push_front, sarray("value"), varray());
bind_method(Array, append, sarray("value"), varray());
+ bind_method(Array, append_array, sarray("array"), varray());
bind_method(Array, resize, sarray("size"), varray());
bind_method(Array, insert, sarray("position", "value"), varray());
bind_method(Array, remove, sarray("position"), varray());
@@ -1801,14 +1338,14 @@ void register_variant_methods() {
bind_method(PackedByteArray, subarray, sarray("from", "to"), varray());
bind_method(PackedByteArray, sort, sarray(), varray());
- bind_function("get_string_from_ascii", _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
- bind_function("get_string_from_utf8", _VariantCall::func_PackedByteArray_get_string_from_utf8, sarray(), varray());
- bind_function("get_string_from_utf16", _VariantCall::func_PackedByteArray_get_string_from_utf16, sarray(), varray());
- bind_function("get_string_from_utf32", _VariantCall::func_PackedByteArray_get_string_from_utf32, sarray(), varray());
- bind_function("hex_encode", _VariantCall::func_PackedByteArray_hex_encode, sarray(), varray());
- bind_function("compress", _VariantCall::func_PackedByteArray_compress, sarray("compression_mode"), varray(0));
- bind_function("decompress", _VariantCall::func_PackedByteArray_decompress, sarray("buffer_size", "compression_mode"), varray(0));
- bind_function("decompress_dynamic", _VariantCall::func_PackedByteArray_decompress_dynamic, sarray("max_output_size", "compression_mode"), varray(0));
+ bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray());
+ bind_function(PackedByteArray, get_string_from_utf8, _VariantCall::func_PackedByteArray_get_string_from_utf8, sarray(), varray());
+ bind_function(PackedByteArray, get_string_from_utf16, _VariantCall::func_PackedByteArray_get_string_from_utf16, sarray(), varray());
+ bind_function(PackedByteArray, get_string_from_utf32, _VariantCall::func_PackedByteArray_get_string_from_utf32, sarray(), varray());
+ bind_function(PackedByteArray, hex_encode, _VariantCall::func_PackedByteArray_hex_encode, sarray(), varray());
+ bind_function(PackedByteArray, compress, _VariantCall::func_PackedByteArray_compress, sarray("compression_mode"), varray(0));
+ bind_function(PackedByteArray, decompress, _VariantCall::func_PackedByteArray_decompress, sarray("buffer_size", "compression_mode"), varray(0));
+ bind_function(PackedByteArray, decompress_dynamic, _VariantCall::func_PackedByteArray_decompress_dynamic, sarray("max_output_size", "compression_mode"), varray(0));
/* Int32 Array */
@@ -1946,47 +1483,6 @@ void register_variant_methods() {
bind_method(PackedColorArray, to_byte_array, sarray(), varray());
bind_method(PackedColorArray, sort, sarray(), varray());
- /* Register constructors */
-
- _VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::FLOAT, "y", Variant::FLOAT);
- _VariantCall::add_constructor(_VariantCall::Vector2i_init1, Variant::VECTOR2I, "x", Variant::INT, "y", Variant::INT);
-
- _VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
- _VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::FLOAT, "y", Variant::FLOAT, "width", Variant::FLOAT, "height", Variant::FLOAT);
-
- _VariantCall::add_constructor(_VariantCall::Rect2i_init1, Variant::RECT2I, "position", Variant::VECTOR2I, "size", Variant::VECTOR2I);
- _VariantCall::add_constructor(_VariantCall::Rect2i_init2, Variant::RECT2I, "x", Variant::INT, "y", Variant::INT, "width", Variant::INT, "height", Variant::INT);
-
- _VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::FLOAT, "position", Variant::VECTOR2);
- _VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2);
-
- _VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::FLOAT, "y", Variant::FLOAT, "z", Variant::FLOAT);
- _VariantCall::add_constructor(_VariantCall::Vector3i_init1, Variant::VECTOR3I, "x", Variant::INT, "y", Variant::INT, "z", Variant::INT);
-
- _VariantCall::add_constructor(_VariantCall::Plane_init1, Variant::PLANE, "a", Variant::FLOAT, "b", Variant::FLOAT, "c", Variant::FLOAT, "d", Variant::FLOAT);
- _VariantCall::add_constructor(_VariantCall::Plane_init2, Variant::PLANE, "v1", Variant::VECTOR3, "v2", Variant::VECTOR3, "v3", Variant::VECTOR3);
- _VariantCall::add_constructor(_VariantCall::Plane_init3, Variant::PLANE, "normal", Variant::VECTOR3, "d", Variant::FLOAT);
-
- _VariantCall::add_constructor(_VariantCall::Quat_init1, Variant::QUAT, "x", Variant::FLOAT, "y", Variant::FLOAT, "z", Variant::FLOAT, "w", Variant::FLOAT);
- _VariantCall::add_constructor(_VariantCall::Quat_init2, Variant::QUAT, "axis", Variant::VECTOR3, "angle", Variant::FLOAT);
- _VariantCall::add_constructor(_VariantCall::Quat_init3, Variant::QUAT, "euler", Variant::VECTOR3);
-
- _VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT, "a", Variant::FLOAT);
- _VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT);
- // init3 and init4 are the constructors for HTML hex strings and integers respectively which don't need binding here, so we skip to init5.
- _VariantCall::add_constructor(_VariantCall::Color_init5, Variant::COLOR, "c", Variant::COLOR, "a", Variant::FLOAT);
-
- _VariantCall::add_constructor(_VariantCall::AABB_init1, Variant::AABB, "position", Variant::VECTOR3, "size", Variant::VECTOR3);
-
- _VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
- _VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::FLOAT);
-
- _VariantCall::add_constructor(_VariantCall::Transform_init1, Variant::TRANSFORM, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3, "origin", Variant::VECTOR3);
- _VariantCall::add_constructor(_VariantCall::Transform_init2, Variant::TRANSFORM, "basis", Variant::BASIS, "origin", Variant::VECTOR3);
-
- _VariantCall::add_constructor(_VariantCall::Callable_init2, Variant::CALLABLE, "object", Variant::OBJECT, "method_name", Variant::STRING_NAME);
- _VariantCall::add_constructor(_VariantCall::Signal_init2, Variant::SIGNAL, "object", Variant::OBJECT, "signal_name", Variant::STRING_NAME);
-
/* Register constants */
int ncc = Color::get_named_color_count();
@@ -2071,19 +1567,13 @@ void register_variant_methods() {
_VariantCall::add_variant_constant(Variant::QUAT, "IDENTITY", Quat(0, 0, 0, 1));
}
-void unregister_variant_methods() {
- //clear methods
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- for (List<StringName>::Element *E = _VariantCall::type_internal_method_names[i].front(); E; E = E->next()) {
- Variant::InternalMethod **m = _VariantCall::type_internal_methods[i].lookup_ptr(E->get());
- if (*m) {
- memdelete(*m);
- }
- }
- }
+void Variant::_register_variant_methods() {
+ _register_variant_builtin_methods(); //needs to be out due to namespace
+}
- memdelete_arr(_VariantCall::type_internal_methods);
- memdelete_arr(_VariantCall::type_internal_method_names);
- memdelete_arr(_VariantCall::construct_funcs);
+void Variant::_unregister_variant_methods() {
+ //clear methods
+ memdelete_arr(builtin_method_names);
+ memdelete_arr(builtin_method_info);
memdelete_arr(_VariantCall::constant_data);
}
diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp
new file mode 100644
index 0000000000..01f5b7df59
--- /dev/null
+++ b/core/variant/variant_construct.cpp
@@ -0,0 +1,812 @@
+/*************************************************************************/
+/* variant_construct.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/crypto/crypto_core.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/io/compression.h"
+#include "core/object/class_db.h"
+#include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/oa_hash_map.h"
+
+template <class T, class... P>
+class VariantConstructor {
+ template <size_t... Is>
+ static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+
+#ifdef DEBUG_METHODS_ENABLED
+ base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...);
+#else
+ base = T(VariantCaster<P>::cast(*p_args[Is])...);
+#endif
+ }
+
+ template <size_t... Is>
+ static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) {
+ base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...);
+ }
+
+ template <size_t... Is>
+ static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) {
+ PtrToArg<T>::encode(T(PtrToArg<P>::convert(p_args[Is])...), base);
+ }
+
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ VariantTypeChanger<T>::change(&r_ret);
+ construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantTypeChanger<T>::change(&r_ret);
+ validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, BuildIndexSequence<sizeof...(P)>{});
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{});
+ }
+
+ static int get_argument_count() {
+ return sizeof...(P);
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+ }
+
+ static Variant::Type get_base_type() {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+ }
+};
+
+class VariantConstructorObject {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ VariantInternal::clear(&r_ret);
+ if (p_args[0]->get_type() == Variant::NIL) {
+ VariantInternal::object_assign_null(&r_ret);
+ r_error.error = Callable::CallError::CALL_OK;
+ } else if (p_args[0]->get_type() == Variant::OBJECT) {
+ VariantInternal::object_assign(&r_ret, p_args[0]);
+ r_error.error = Callable::CallError::CALL_OK;
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::OBJECT;
+ }
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantInternal::clear(&r_ret);
+ VariantInternal::object_assign(&r_ret, p_args[0]);
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<Object *>::encode(PtrToArg<Object *>::convert(p_args[0]), base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::OBJECT;
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::OBJECT;
+ }
+};
+
+class VariantConstructorNilObject {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != Variant::NIL) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ }
+
+ VariantInternal::clear(&r_ret);
+ VariantInternal::object_assign_null(&r_ret);
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantInternal::clear(&r_ret);
+ VariantInternal::object_assign_null(&r_ret);
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<Object *>::encode(nullptr, base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::NIL;
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::OBJECT;
+ }
+};
+
+class VariantConstructorCallableArgs {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ ObjectID object_id;
+ StringName method;
+
+ if (p_args[0]->get_type() == Variant::NIL) {
+ // leave as is
+ } else if (p_args[0]->get_type() == Variant::OBJECT) {
+ object_id = VariantInternal::get_object_id(p_args[0]);
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::OBJECT;
+ return;
+ }
+
+ if (p_args[1]->get_type() == Variant::STRING_NAME) {
+ method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
+ } else if (p_args[1]->get_type() == Variant::STRING) {
+ method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::STRING_NAME;
+ return;
+ }
+
+ VariantTypeChanger<Callable>::change(&r_ret);
+ *VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method);
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantTypeChanger<Callable>::change(&r_ret);
+ *VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<Callable>::encode(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
+ }
+
+ static int get_argument_count() {
+ return 2;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ if (p_arg == 0) {
+ return Variant::OBJECT;
+ } else {
+ return Variant::STRING_NAME;
+ }
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::CALLABLE;
+ }
+};
+
+class VariantConstructorSignalArgs {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ ObjectID object_id;
+ StringName method;
+
+ if (p_args[0]->get_type() == Variant::NIL) {
+ // leave as is
+ } else if (p_args[0]->get_type() == Variant::OBJECT) {
+ object_id = VariantInternal::get_object_id(p_args[0]);
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::OBJECT;
+ return;
+ }
+
+ if (p_args[1]->get_type() == Variant::STRING_NAME) {
+ method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]);
+ } else if (p_args[1]->get_type() == Variant::STRING) {
+ method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]);
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::STRING_NAME;
+ return;
+ }
+
+ VariantTypeChanger<Signal>::change(&r_ret);
+ *VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method);
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantTypeChanger<Signal>::change(&r_ret);
+ *VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]));
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<Signal>::encode(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base);
+ }
+
+ static int get_argument_count() {
+ return 2;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ if (p_arg == 0) {
+ return Variant::OBJECT;
+ } else {
+ return Variant::STRING_NAME;
+ }
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::SIGNAL;
+ }
+};
+
+template <class T>
+class VariantConstructorToArray {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = GetTypeInfo<T>::VARIANT_TYPE;
+ return;
+ }
+
+ VariantTypeChanger<Array>::change(&r_ret);
+ Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
+ const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
+
+ int size = src_arr.size();
+ dst_arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ dst_arr[i] = src_arr[i];
+ }
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantTypeChanger<Array>::change(&r_ret);
+ Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret);
+ const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]);
+
+ int size = src_arr.size();
+ dst_arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ dst_arr[i] = src_arr[i];
+ }
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ Array dst_arr;
+ T src_arr = PtrToArg<T>::convert(p_args[0]);
+
+ int size = src_arr.size();
+ dst_arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ dst_arr[i] = src_arr[i];
+ }
+
+ PtrToArg<Array>::encode(dst_arr, base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::ARRAY;
+ }
+};
+
+template <class T>
+class VariantConstructorFromArray {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != Variant::ARRAY) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::ARRAY;
+ return;
+ }
+
+ VariantTypeChanger<T>::change(&r_ret);
+ const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+ T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
+
+ int size = src_arr.size();
+ dst_arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ dst_arr.write[i] = src_arr[i];
+ }
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantTypeChanger<T>::change(&r_ret);
+ const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]);
+ T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret);
+
+ int size = src_arr.size();
+ dst_arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ dst_arr.write[i] = src_arr[i];
+ }
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ Array src_arr = PtrToArg<Array>::convert(p_args[0]);
+ T dst_arr;
+
+ int size = src_arr.size();
+ dst_arr.resize(size);
+ for (int i = 0; i < size; i++) {
+ dst_arr.write[i] = src_arr[i];
+ }
+
+ PtrToArg<T>::encode(dst_arr, base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::ARRAY;
+ }
+
+ static Variant::Type get_base_type() {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+ }
+};
+
+class VariantConstructorNil {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ if (p_args[0]->get_type() != Variant::NIL) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::NIL;
+ return;
+ }
+
+ r_error.error = Callable::CallError::CALL_OK;
+ VariantInternal::clear(&r_ret);
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantInternal::clear(&r_ret);
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<Variant>::encode(Variant(), base);
+ }
+
+ static int get_argument_count() {
+ return 1;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::NIL;
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::NIL;
+ }
+};
+
+template <class T>
+class VariantConstructNoArgs {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ VariantTypeChanger<T>::change_and_reset(&r_ret);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantTypeChanger<T>::change_and_reset(&r_ret);
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<T>::encode(T(), base);
+ }
+
+ static int get_argument_count() {
+ return 0;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::NIL;
+ }
+
+ static Variant::Type get_base_type() {
+ return GetTypeInfo<T>::VARIANT_TYPE;
+ }
+};
+
+class VariantConstructNoArgsNil {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ VariantInternal::clear(&r_ret);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantInternal::clear(&r_ret);
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ ERR_FAIL_MSG("can't ptrcall nil constructor");
+ }
+
+ static int get_argument_count() {
+ return 0;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::NIL;
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::NIL;
+ }
+};
+
+class VariantConstructNoArgsObject {
+public:
+ static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) {
+ VariantInternal::clear(&r_ret);
+ VariantInternal::object_assign_null(&r_ret);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static void validated_construct(Variant &r_ret, const Variant **p_args) {
+ VariantInternal::clear(&r_ret);
+ VariantInternal::object_assign_null(&r_ret);
+ }
+ static void ptr_construct(void *base, const void **p_args) {
+ PtrToArg<Object *>::encode(nullptr, base);
+ }
+
+ static int get_argument_count() {
+ return 0;
+ }
+
+ static Variant::Type get_argument_type(int p_arg) {
+ return Variant::NIL;
+ }
+
+ static Variant::Type get_base_type() {
+ return Variant::OBJECT;
+ }
+};
+
+struct VariantConstructData {
+ void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error);
+ Variant::ValidatedConstructor validated_construct;
+ Variant::PTRConstructor ptr_construct;
+ Variant::Type (*get_argument_type)(int);
+ int argument_count;
+ Vector<String> arg_names;
+};
+
+static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX];
+
+template <class T>
+static void add_constructor(const Vector<String> &arg_names) {
+ ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + ".");
+
+ VariantConstructData cd;
+ cd.construct = T::construct;
+ cd.validated_construct = T::validated_construct;
+ cd.ptr_construct = T::ptr_construct;
+ cd.get_argument_type = T::get_argument_type;
+ cd.argument_count = T::get_argument_count();
+ cd.arg_names = arg_names;
+ construct_data[T::get_base_type()].push_back(cd);
+}
+
+void Variant::_register_variant_constructors() {
+ add_constructor<VariantConstructNoArgsNil>(sarray());
+ add_constructor<VariantConstructorNil>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<bool>>(sarray());
+ add_constructor<VariantConstructor<bool, bool>>(sarray("from"));
+ add_constructor<VariantConstructor<bool, int64_t>>(sarray("from"));
+ add_constructor<VariantConstructor<bool, double>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<int64_t>>(sarray());
+ add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from"));
+ add_constructor<VariantConstructor<int64_t, double>>(sarray("from"));
+ add_constructor<VariantConstructor<int64_t, bool>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<double>>(sarray());
+ add_constructor<VariantConstructor<double, double>>(sarray("from"));
+ add_constructor<VariantConstructor<double, int64_t>>(sarray("from"));
+ add_constructor<VariantConstructor<double, bool>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<String>>(sarray());
+ add_constructor<VariantConstructor<String, String>>(sarray("from"));
+ add_constructor<VariantConstructor<String, StringName>>(sarray("from"));
+ add_constructor<VariantConstructor<String, NodePath>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<Vector2>>(sarray());
+ add_constructor<VariantConstructor<Vector2, Vector2>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector2, Vector2i>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector2, double, double>>(sarray("x", "y"));
+
+ add_constructor<VariantConstructNoArgs<Vector2i>>(sarray());
+ add_constructor<VariantConstructor<Vector2i, Vector2i>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector2i, Vector2>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector2i, int64_t, int64_t>>(sarray("x", "y"));
+
+ add_constructor<VariantConstructNoArgs<Rect2>>(sarray());
+ add_constructor<VariantConstructor<Rect2, Rect2>>(sarray("from"));
+ add_constructor<VariantConstructor<Rect2, Rect2i>>(sarray("from"));
+ add_constructor<VariantConstructor<Rect2, Vector2, Vector2>>(sarray("position", "size"));
+ add_constructor<VariantConstructor<Rect2, double, double, double, double>>(sarray("x", "y", "width", "height"));
+
+ add_constructor<VariantConstructNoArgs<Rect2i>>(sarray());
+ add_constructor<VariantConstructor<Rect2i, Rect2i>>(sarray("from"));
+ add_constructor<VariantConstructor<Rect2i, Rect2>>(sarray("from"));
+ add_constructor<VariantConstructor<Rect2i, Vector2i, Vector2i>>(sarray("position", "size"));
+ add_constructor<VariantConstructor<Rect2i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "width", "height"));
+
+ add_constructor<VariantConstructNoArgs<Vector3>>(sarray());
+ add_constructor<VariantConstructor<Vector3, Vector3>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector3, Vector3i>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector3, double, double, double>>(sarray("x", "y", "z"));
+
+ add_constructor<VariantConstructNoArgs<Vector3i>>(sarray());
+ add_constructor<VariantConstructor<Vector3i, Vector3i>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector3i, Vector3>>(sarray("from"));
+ add_constructor<VariantConstructor<Vector3i, int64_t, int64_t, int64_t>>(sarray("x", "y", "z"));
+
+ add_constructor<VariantConstructNoArgs<Transform2D>>(sarray());
+ add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from"));
+ add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position"));
+ add_constructor<VariantConstructor<Transform2D, Vector2, Vector2, Vector2>>(sarray("x_axis", "y_axis", "origin"));
+
+ add_constructor<VariantConstructNoArgs<Plane>>(sarray());
+ add_constructor<VariantConstructor<Plane, Plane>>(sarray("from"));
+ add_constructor<VariantConstructor<Plane, Vector3, double>>(sarray("normal", "d"));
+ add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("point", "normal"));
+ add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3"));
+ add_constructor<VariantConstructor<Plane, double, double, double, double>>(sarray("a", "b", "c", "d"));
+
+ add_constructor<VariantConstructNoArgs<Quat>>(sarray());
+ add_constructor<VariantConstructor<Quat, Quat>>(sarray("from"));
+ add_constructor<VariantConstructor<Quat, Basis>>(sarray("from"));
+ add_constructor<VariantConstructor<Quat, Vector3>>(sarray("euler"));
+ add_constructor<VariantConstructor<Quat, Vector3, double>>(sarray("axis", "angle"));
+ add_constructor<VariantConstructor<Quat, Vector3, Vector3>>(sarray("arc_from", "arc_to"));
+ add_constructor<VariantConstructor<Quat, double, double, double, double>>(sarray("x", "y", "z", "w"));
+
+ add_constructor<VariantConstructNoArgs<::AABB>>(sarray());
+ add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from"));
+ add_constructor<VariantConstructor<::AABB, Vector3, Vector3>>(sarray("position", "size"));
+
+ add_constructor<VariantConstructNoArgs<Basis>>(sarray());
+ add_constructor<VariantConstructor<Basis, Basis>>(sarray("from"));
+ add_constructor<VariantConstructor<Basis, Quat>>(sarray("from"));
+ add_constructor<VariantConstructor<Basis, Vector3>>(sarray("euler"));
+ add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "phi"));
+ add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis"));
+
+ add_constructor<VariantConstructNoArgs<Transform>>(sarray());
+ add_constructor<VariantConstructor<Transform, Transform>>(sarray("from"));
+ add_constructor<VariantConstructor<Transform, Basis, Vector3>>(sarray("basis", "origin"));
+ add_constructor<VariantConstructor<Transform, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin"));
+
+ add_constructor<VariantConstructNoArgs<Color>>(sarray());
+ add_constructor<VariantConstructor<Color, Color>>(sarray("from"));
+ add_constructor<VariantConstructor<Color, Color, double>>(sarray("from", "alpha"));
+ add_constructor<VariantConstructor<Color, double, double, double>>(sarray("r", "g", "b"));
+ add_constructor<VariantConstructor<Color, double, double, double, double>>(sarray("r", "g", "b", "a"));
+
+ add_constructor<VariantConstructNoArgs<StringName>>(sarray());
+ add_constructor<VariantConstructor<StringName, StringName>>(sarray("from"));
+ add_constructor<VariantConstructor<StringName, String>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<NodePath>>(sarray());
+ add_constructor<VariantConstructor<NodePath, NodePath>>(sarray("from"));
+ add_constructor<VariantConstructor<NodePath, String>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<::RID>>(sarray());
+ add_constructor<VariantConstructor<::RID, ::RID>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgsObject>(sarray());
+ add_constructor<VariantConstructorObject>(sarray("from"));
+ add_constructor<VariantConstructorNilObject>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<Callable>>(sarray());
+ add_constructor<VariantConstructor<Callable, Callable>>(sarray("from"));
+ add_constructor<VariantConstructorCallableArgs>(sarray("object", "method"));
+
+ add_constructor<VariantConstructNoArgs<Signal>>(sarray());
+ add_constructor<VariantConstructor<Signal, Signal>>(sarray("from"));
+ add_constructor<VariantConstructorSignalArgs>(sarray("object", "signal"));
+
+ add_constructor<VariantConstructNoArgs<Dictionary>>(sarray());
+ add_constructor<VariantConstructor<Dictionary, Dictionary>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<Array>>(sarray());
+ add_constructor<VariantConstructor<Array, Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedByteArray>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedInt32Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedInt64Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedFloat32Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedFloat64Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedStringArray>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedVector2Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedVector3Array>>(sarray("from"));
+ add_constructor<VariantConstructorToArray<PackedColorArray>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedByteArray>>(sarray());
+ add_constructor<VariantConstructor<PackedByteArray, PackedByteArray>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedByteArray>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedInt32Array>>(sarray());
+ add_constructor<VariantConstructor<PackedInt32Array, PackedInt32Array>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedInt32Array>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedInt64Array>>(sarray());
+ add_constructor<VariantConstructor<PackedInt64Array, PackedInt64Array>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedInt64Array>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedFloat32Array>>(sarray());
+ add_constructor<VariantConstructor<PackedFloat32Array, PackedFloat32Array>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedFloat32Array>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedFloat64Array>>(sarray());
+ add_constructor<VariantConstructor<PackedFloat64Array, PackedFloat64Array>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedFloat64Array>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedStringArray>>(sarray());
+ add_constructor<VariantConstructor<PackedStringArray, PackedStringArray>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedStringArray>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedVector2Array>>(sarray());
+ add_constructor<VariantConstructor<PackedVector2Array, PackedVector2Array>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedVector2Array>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedVector3Array>>(sarray());
+ add_constructor<VariantConstructor<PackedVector3Array, PackedVector3Array>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedVector3Array>>(sarray("from"));
+
+ add_constructor<VariantConstructNoArgs<PackedColorArray>>(sarray());
+ add_constructor<VariantConstructor<PackedColorArray, PackedColorArray>>(sarray("from"));
+ add_constructor<VariantConstructorFromArray<PackedColorArray>>(sarray("from"));
+}
+
+void Variant::_unregister_variant_constructors() {
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ construct_data[i].clear();
+ }
+}
+
+void Variant::construct(Variant::Type p_type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ uint32_t s = construct_data[p_type].size();
+ for (uint32_t i = 0; i < s; i++) {
+ int argc = construct_data[p_type][i].argument_count;
+ if (argc != p_argcount) {
+ continue;
+ }
+ bool args_match = true;
+ for (int j = 0; j < argc; j++) {
+ if (!Variant::can_convert_strict(p_args[j]->get_type(), construct_data[p_type][i].get_argument_type(j))) {
+ args_match = false;
+ break;
+ }
+ }
+
+ if (!args_match) {
+ continue;
+ }
+
+ construct_data[p_type][i].construct(base, p_args, r_error);
+ return;
+ }
+
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+}
+
+int Variant::get_constructor_count(Variant::Type p_type) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+ return construct_data[p_type].size();
+}
+
+Variant::ValidatedConstructor Variant::get_validated_constructor(Variant::Type p_type, int p_constructor) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+ ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr);
+ return construct_data[p_type][p_constructor].validated_construct;
+}
+
+Variant::PTRConstructor Variant::get_ptr_constructor(Variant::Type p_type, int p_constructor) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr);
+ ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr);
+ return construct_data[p_type][p_constructor].ptr_construct;
+}
+
+int Variant::get_constructor_argument_count(Variant::Type p_type, int p_constructor) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1);
+ ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), -1);
+ return construct_data[p_type][p_constructor].argument_count;
+}
+
+Variant::Type Variant::get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX);
+ ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), Variant::VARIANT_MAX);
+ return construct_data[p_type][p_constructor].get_argument_type(p_argument);
+}
+
+String Variant::get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument) {
+ ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String());
+ ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), String());
+ return construct_data[p_type][p_constructor].arg_names[p_argument];
+}
+
+void VariantInternal::object_assign(Variant *v, const Variant *o) {
+ if (o->_get_obj().obj && o->_get_obj().id.is_reference()) {
+ Reference *reference = static_cast<Reference *>(o->_get_obj().obj);
+ if (!reference->reference()) {
+ v->_get_obj().obj = nullptr;
+ v->_get_obj().id = ObjectID();
+ return;
+ }
+ }
+
+ v->_get_obj().obj = const_cast<Object *>(o->_get_obj().obj);
+ v->_get_obj().id = o->_get_obj().id;
+}
+
+void Variant::get_constructor_list(Type p_type, List<MethodInfo> *r_list) {
+ ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
+
+ MethodInfo mi;
+ mi.return_val.type = p_type;
+ mi.name = get_type_name(p_type);
+
+ for (int i = 0; i < get_constructor_count(p_type); i++) {
+ int ac = get_constructor_argument_count(p_type, i);
+ mi.arguments.clear();
+ for (int j = 0; j < ac; j++) {
+ PropertyInfo arg;
+ arg.name = get_constructor_argument_name(p_type, i, j);
+ arg.type = get_constructor_argument_type(p_type, i, j);
+ mi.arguments.push_back(arg);
+ }
+ r_list->push_back(mi);
+ }
+}
diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h
index 7893c6d382..3ac7f32dec 100644
--- a/core/variant/variant_internal.h
+++ b/core/variant/variant_internal.h
@@ -83,8 +83,8 @@ public:
_FORCE_INLINE_ static const StringName *get_string_name(const Variant *v) { return reinterpret_cast<const StringName *>(v->_data._mem); }
_FORCE_INLINE_ static NodePath *get_node_path(Variant *v) { return reinterpret_cast<NodePath *>(v->_data._mem); }
_FORCE_INLINE_ static const NodePath *get_node_path(const Variant *v) { return reinterpret_cast<const NodePath *>(v->_data._mem); }
- _FORCE_INLINE_ static RID *get_rid(Variant *v) { return reinterpret_cast<RID *>(v->_data._mem); }
- _FORCE_INLINE_ static const RID *get_rid(const Variant *v) { return reinterpret_cast<const RID *>(v->_data._mem); }
+ _FORCE_INLINE_ static ::RID *get_rid(Variant *v) { return reinterpret_cast<::RID *>(v->_data._mem); }
+ _FORCE_INLINE_ static const ::RID *get_rid(const Variant *v) { return reinterpret_cast<const ::RID *>(v->_data._mem); }
_FORCE_INLINE_ static Callable *get_callable(Variant *v) { return reinterpret_cast<Callable *>(v->_data._mem); }
_FORCE_INLINE_ static const Callable *get_callable(const Variant *v) { return reinterpret_cast<const Callable *>(v->_data._mem); }
_FORCE_INLINE_ static Signal *get_signal(Variant *v) { return reinterpret_cast<Signal *>(v->_data._mem); }
@@ -116,6 +116,106 @@ public:
_FORCE_INLINE_ static Object **get_object(Variant *v) { return (Object **)&v->_get_obj().obj; }
_FORCE_INLINE_ static const Object **get_object(const Variant *v) { return (const Object **)&v->_get_obj().obj; }
+
+ _FORCE_INLINE_ static const ObjectID get_object_id(const Variant *v) { return v->_get_obj().id; }
+
+ template <class T>
+ _FORCE_INLINE_ static void init_generic(Variant *v) {
+ v->type = GetTypeInfo<T>::VARIANT_TYPE;
+ }
+
+ _FORCE_INLINE_ static void init_string(Variant *v) {
+ memnew_placement(v->_data._mem, String);
+ v->type = Variant::STRING;
+ }
+
+ _FORCE_INLINE_ static void init_transform2d(Variant *v) {
+ v->_data._transform2d = memnew(Transform2D);
+ v->type = Variant::TRANSFORM2D;
+ }
+ _FORCE_INLINE_ static void init_aabb(Variant *v) {
+ v->_data._aabb = memnew(AABB);
+ v->type = Variant::AABB;
+ }
+ _FORCE_INLINE_ static void init_basis(Variant *v) {
+ v->_data._basis = memnew(Basis);
+ v->type = Variant::BASIS;
+ }
+ _FORCE_INLINE_ static void init_transform(Variant *v) {
+ v->_data._transform = memnew(Transform);
+ v->type = Variant::TRANSFORM;
+ }
+ _FORCE_INLINE_ static void init_string_name(Variant *v) {
+ memnew_placement(v->_data._mem, StringName);
+ v->type = Variant::STRING_NAME;
+ }
+ _FORCE_INLINE_ static void init_node_path(Variant *v) {
+ memnew_placement(v->_data._mem, NodePath);
+ v->type = Variant::NODE_PATH;
+ }
+ _FORCE_INLINE_ static void init_callable(Variant *v) {
+ memnew_placement(v->_data._mem, Callable);
+ v->type = Variant::CALLABLE;
+ }
+ _FORCE_INLINE_ static void init_signal(Variant *v) {
+ memnew_placement(v->_data._mem, Signal);
+ v->type = Variant::SIGNAL;
+ }
+ _FORCE_INLINE_ static void init_dictionary(Variant *v) {
+ memnew_placement(v->_data._mem, Dictionary);
+ v->type = Variant::DICTIONARY;
+ }
+ _FORCE_INLINE_ static void init_array(Variant *v) {
+ memnew_placement(v->_data._mem, Array);
+ v->type = Variant::ARRAY;
+ }
+ _FORCE_INLINE_ static void init_byte_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<uint8_t>::create(Vector<uint8_t>());
+ v->type = Variant::PACKED_BYTE_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_int32_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<int32_t>::create(Vector<int32_t>());
+ v->type = Variant::PACKED_INT32_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_int64_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<int64_t>::create(Vector<int64_t>());
+ v->type = Variant::PACKED_INT64_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_float32_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<float>::create(Vector<float>());
+ v->type = Variant::PACKED_FLOAT32_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_float64_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<double>::create(Vector<double>());
+ v->type = Variant::PACKED_FLOAT64_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_string_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<String>::create(Vector<String>());
+ v->type = Variant::PACKED_STRING_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_vector2_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<Vector2>::create(Vector<Vector2>());
+ v->type = Variant::PACKED_VECTOR2_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_vector3_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<Vector3>::create(Vector<Vector3>());
+ v->type = Variant::PACKED_VECTOR3_ARRAY;
+ }
+ _FORCE_INLINE_ static void init_color_array(Variant *v) {
+ v->_data.packed_array = Variant::PackedArrayRef<Color>::create(Vector<Color>());
+ v->type = Variant::PACKED_COLOR_ARRAY;
+ }
+
+ _FORCE_INLINE_ static void clear(Variant *v) {
+ v->clear();
+ }
+
+ static void object_assign(Variant *v, const Variant *o); //needs to use reference, do away
+
+ _FORCE_INLINE_ static void object_assign_null(Variant *v) {
+ v->_get_obj().obj = nullptr;
+ v->_get_obj().id = ObjectID();
+ }
};
template <class T>
@@ -305,9 +405,9 @@ struct VariantGetInternalPtr<NodePath> {
};
template <>
-struct VariantGetInternalPtr<RID> {
- static RID *get_ptr(Variant *v) { return VariantInternal::get_rid(v); }
- static const RID *get_ptr(const Variant *v) { return VariantInternal::get_rid(v); }
+struct VariantGetInternalPtr<::RID> {
+ static ::RID *get_ptr(Variant *v) { return VariantInternal::get_rid(v); }
+ static const ::RID *get_ptr(const Variant *v) { return VariantInternal::get_rid(v); }
};
template <>
@@ -532,9 +632,9 @@ struct VariantInternalAccessor<NodePath> {
};
template <>
-struct VariantInternalAccessor<RID> {
- static _FORCE_INLINE_ const RID &get(const Variant *v) { return *VariantInternal::get_rid(v); }
- static _FORCE_INLINE_ void set(Variant *v, const RID &p_value) { *VariantInternal::get_rid(v) = p_value; }
+struct VariantInternalAccessor<::RID> {
+ static _FORCE_INLINE_ const ::RID &get(const Variant *v) { return *VariantInternal::get_rid(v); }
+ static _FORCE_INLINE_ void set(Variant *v, const ::RID &p_value) { *VariantInternal::get_rid(v) = p_value; }
};
template <>
@@ -649,4 +749,383 @@ struct VariantInternalAccessor<Vector<Variant>> {
}
};
+template <class T>
+struct VariantInitializer {
+};
+
+template <>
+struct VariantInitializer<bool> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<bool>(v); }
+};
+
+#define INITIALIZER_INT(m_type) \
+ template <> \
+ struct VariantInitializer<m_type> { \
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<int64_t>(v); } \
+ };
+
+INITIALIZER_INT(uint8_t)
+INITIALIZER_INT(int8_t)
+INITIALIZER_INT(uint16_t)
+INITIALIZER_INT(int16_t)
+INITIALIZER_INT(uint32_t)
+INITIALIZER_INT(int32_t)
+INITIALIZER_INT(uint64_t)
+INITIALIZER_INT(int64_t)
+INITIALIZER_INT(char32_t)
+INITIALIZER_INT(Error)
+INITIALIZER_INT(ObjectID)
+
+template <>
+struct VariantInitializer<double> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<double>(v); }
+};
+
+template <>
+struct VariantInitializer<float> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<double>(v); }
+};
+
+template <>
+struct VariantInitializer<String> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string(v); }
+};
+
+template <>
+struct VariantInitializer<Vector2> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector2>(v); }
+};
+
+template <>
+struct VariantInitializer<Vector2i> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector2i>(v); }
+};
+
+template <>
+struct VariantInitializer<Rect2> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Rect2>(v); }
+};
+
+template <>
+struct VariantInitializer<Rect2i> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Rect2i>(v); }
+};
+
+template <>
+struct VariantInitializer<Vector3> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3>(v); }
+};
+
+template <>
+struct VariantInitializer<Vector3i> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3i>(v); }
+};
+
+template <>
+struct VariantInitializer<Transform2D> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform2d(v); }
+};
+
+template <>
+struct VariantInitializer<Plane> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Plane>(v); }
+};
+
+template <>
+struct VariantInitializer<Quat> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Quat>(v); }
+};
+
+template <>
+struct VariantInitializer<AABB> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_aabb(v); }
+};
+
+template <>
+struct VariantInitializer<Basis> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_basis(v); }
+};
+
+template <>
+struct VariantInitializer<Transform> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); }
+};
+
+template <>
+struct VariantInitializer<Color> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Color>(v); }
+};
+
+template <>
+struct VariantInitializer<StringName> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string_name(v); }
+};
+
+template <>
+struct VariantInitializer<NodePath> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_node_path(v); }
+};
+
+template <>
+struct VariantInitializer<::RID> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<::RID>(v); }
+};
+
+template <>
+struct VariantInitializer<Callable> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_callable(v); }
+};
+
+template <>
+struct VariantInitializer<Signal> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_signal(v); }
+};
+
+template <>
+struct VariantInitializer<Dictionary> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_dictionary(v); }
+};
+
+template <>
+struct VariantInitializer<Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedByteArray> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_byte_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedInt32Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_int32_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedInt64Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_int64_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedFloat32Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_float32_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedFloat64Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_float64_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedStringArray> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedVector2Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector2_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedVector3Array> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector3_array(v); }
+};
+
+template <>
+struct VariantInitializer<PackedColorArray> {
+ static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_color_array(v); }
+};
+
+template <class T>
+struct VariantZeroAssigner {
+};
+
+template <>
+struct VariantZeroAssigner<bool> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_bool(v) = false; }
+};
+
+template <>
+struct VariantZeroAssigner<int64_t> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_int(v) = 0; }
+};
+
+template <>
+struct VariantZeroAssigner<double> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float(v) = 0.0; }
+};
+
+template <>
+struct VariantZeroAssigner<float> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float(v) = 0.0; }
+};
+
+template <>
+struct VariantZeroAssigner<String> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<Vector2> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector2(v) = Vector2(); }
+};
+
+template <>
+struct VariantZeroAssigner<Vector2i> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector2i(v) = Vector2i(); }
+};
+
+template <>
+struct VariantZeroAssigner<Rect2> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_rect2(v) = Rect2(); }
+};
+
+template <>
+struct VariantZeroAssigner<Rect2i> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_rect2i(v) = Rect2i(); }
+};
+
+template <>
+struct VariantZeroAssigner<Vector3> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector3(v) = Vector3(); }
+};
+
+template <>
+struct VariantZeroAssigner<Vector3i> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector3i(v) = Vector3i(); }
+};
+
+template <>
+struct VariantZeroAssigner<Transform2D> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform2d(v) = Transform2D(); }
+};
+
+template <>
+struct VariantZeroAssigner<Plane> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_plane(v) = Plane(); }
+};
+
+template <>
+struct VariantZeroAssigner<Quat> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_quat(v) = Quat(); }
+};
+
+template <>
+struct VariantZeroAssigner<AABB> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_aabb(v) = AABB(); }
+};
+
+template <>
+struct VariantZeroAssigner<Basis> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_basis(v) = Basis(); }
+};
+
+template <>
+struct VariantZeroAssigner<Transform> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform(v) = Transform(); }
+};
+
+template <>
+struct VariantZeroAssigner<Color> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_color(v) = Color(); }
+};
+
+template <>
+struct VariantZeroAssigner<StringName> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<NodePath> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<::RID> {
+ static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_rid(v) = RID(); }
+};
+
+template <>
+struct VariantZeroAssigner<Callable> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<Signal> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<Dictionary> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedByteArray> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedInt32Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedInt64Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedFloat32Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedFloat64Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedStringArray> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedVector2Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedVector3Array> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <>
+struct VariantZeroAssigner<PackedColorArray> {
+ static _FORCE_INLINE_ void zero(Variant *v) {}
+};
+
+template <class T>
+struct VariantTypeChanger {
+ static _FORCE_INLINE_ void change(Variant *v) {
+ if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
+ VariantInternal::clear(v);
+ VariantInitializer<T>::init(v);
+ }
+ }
+ static _FORCE_INLINE_ void change_and_reset(Variant *v) {
+ if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer
+ VariantInternal::clear(v);
+ VariantInitializer<T>::init(v);
+ }
+
+ VariantZeroAssigner<T>::zero(v);
+ }
+};
+
#endif // VARIANT_INTERNAL_H
diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp
index 25ba66c9de..74ecbfb8d1 100644
--- a/core/variant/variant_op.cpp
+++ b/core/variant/variant_op.cpp
@@ -44,6 +44,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) + *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -64,6 +65,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) - *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -84,6 +86,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) * *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -104,6 +107,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<A>::get_ptr(left)->xform(*VariantGetInternalPtr<B>::get_ptr(right));
}
#ifdef PTRCALL_ENABLED
@@ -124,6 +128,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<B>::get_ptr(right)->xform_inv(*VariantGetInternalPtr<A>::get_ptr(left));
}
#ifdef PTRCALL_ENABLED
@@ -144,6 +149,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -169,6 +175,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -189,6 +196,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -214,6 +222,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -233,6 +242,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = -*VariantGetInternalPtr<A>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -252,6 +262,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -272,6 +283,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) << *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -292,6 +304,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >> *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -312,6 +325,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) | *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -352,6 +366,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) ^ *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -371,6 +386,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<R>::change(r_ret);
*VariantGetInternalPtr<R>::get_ptr(r_ret) = ~*VariantGetInternalPtr<A>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -391,6 +407,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) == *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -412,6 +429,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Object *a = left->get_validated_object();
const Object *b = right->get_validated_object();
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == b;
}
#ifdef PTRCALL_ENABLED
@@ -431,6 +449,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Object *a = left->get_validated_object();
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == nullptr;
}
#ifdef PTRCALL_ENABLED
@@ -450,6 +469,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Object *b = right->get_validated_object();
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr == b;
}
#ifdef PTRCALL_ENABLED
@@ -470,6 +490,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) != *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -491,6 +512,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *a = left->get_validated_object();
Object *b = right->get_validated_object();
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != b;
}
#ifdef PTRCALL_ENABLED
@@ -510,6 +532,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *a = left->get_validated_object();
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != nullptr;
}
#ifdef PTRCALL_ENABLED
@@ -529,6 +552,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
Object *b = right->get_validated_object();
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr != b;
}
#ifdef PTRCALL_ENABLED
@@ -549,6 +573,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) < *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -569,6 +594,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) <= *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -589,6 +615,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) > *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -609,6 +636,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >= *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -629,6 +657,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) && *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -650,6 +679,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) || *VariantGetInternalPtr<B>::get_ptr(right);
}
#ifdef PTRCALL_ENABLED
@@ -675,6 +705,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = xor_op(*VariantGetInternalPtr<A>::get_ptr(left), *VariantGetInternalPtr<B>::get_ptr(right));
}
#ifdef PTRCALL_ENABLED
@@ -695,6 +726,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<A>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -729,6 +761,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<Array>::change(r_ret);
_add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right));
}
#ifdef PTRCALL_ENABLED
@@ -754,6 +787,7 @@ public:
r_valid = true;
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<Vector<T>>::change(r_ret);
*VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector<T>>::get_ptr(left);
VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret)->append_array(*VariantGetInternalPtr<Vector<T>>::get_ptr(right));
}
@@ -787,6 +821,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<String>::change(r_ret);
*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr);
}
#ifdef PTRCALL_ENABLED
@@ -813,6 +848,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<String>::change(r_ret);
*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr);
}
#ifdef PTRCALL_ENABLED
@@ -842,6 +878,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<String>::change(r_ret);
*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr);
}
#ifdef PTRCALL_ENABLED
@@ -871,6 +908,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<String>::change(r_ret);
*VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr);
}
#ifdef PTRCALL_ENABLED
@@ -890,6 +928,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = true;
}
#ifdef PTRCALL_ENABLED
@@ -909,6 +948,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
}
#ifdef PTRCALL_ENABLED
@@ -962,6 +1002,7 @@ _FORCE_INLINE_ static bool _operate_get_object(const Variant *p_ptr) {
} \
\
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { \
+ VariantTypeChanger<bool>::change(r_ret); \
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \
} \
\
@@ -1002,6 +1043,7 @@ _FORCE_INLINE_ static bool _operate_get_ptr_object(const void *p_ptr) {
} \
\
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { \
+ VariantTypeChanger<bool>::change(r_ret); \
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \
} \
\
@@ -1168,6 +1210,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<bool>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -1187,6 +1230,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<int64_t>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -1206,6 +1250,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<double>::get_ptr(left);
}
#ifdef PTRCALL_ENABLED
@@ -1225,6 +1270,7 @@ public:
}
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = left->get_validated_object() == nullptr;
}
#ifdef PTRCALL_ENABLED
@@ -1251,6 +1297,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left);
const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1;
}
#ifdef PTRCALL_ENABLED
@@ -1275,6 +1322,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
const B &b = *VariantGetInternalPtr<B>::get_ptr(right);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(a) != -1;
}
#ifdef PTRCALL_ENABLED
@@ -1295,6 +1343,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(Variant()) != -1;
}
#ifdef PTRCALL_ENABLED
@@ -1315,6 +1364,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(*left) != -1;
}
#ifdef PTRCALL_ENABLED
@@ -1339,6 +1389,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
const A &a = *VariantGetInternalPtr<A>::get_ptr(left);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(a);
}
#ifdef PTRCALL_ENABLED
@@ -1360,6 +1411,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(Variant());
}
#ifdef PTRCALL_ENABLED
@@ -1381,6 +1433,7 @@ public:
static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(*left);
}
#ifdef PTRCALL_ENABLED
@@ -1414,6 +1467,7 @@ public:
bool valid;
l->get(a, &valid);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
}
#ifdef PTRCALL_ENABLED
@@ -1449,6 +1503,7 @@ public:
bool valid;
l->get(a, &valid);
+ VariantTypeChanger<bool>::change(r_ret);
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid;
}
#ifdef PTRCALL_ENABLED
@@ -1480,7 +1535,7 @@ void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p
#endif
}
-void register_variant_operators() {
+void Variant::_register_variant_operators() {
zeromem(operator_return_type_table, sizeof(operator_return_type_table));
zeromem(operator_evaluator_table, sizeof(operator_evaluator_table));
zeromem(validated_operator_evaluator_table, sizeof(validated_operator_evaluator_table));
@@ -1568,8 +1623,8 @@ void register_variant_operators() {
register_op<OperatorEvaluatorMul<Transform, Transform, Transform>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::TRANSFORM);
register_op<OperatorEvaluatorXForm<Vector3, Transform, Vector3>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::VECTOR3);
register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM);
- register_op<OperatorEvaluatorXForm<AABB, Transform, AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::AABB);
- register_op<OperatorEvaluatorXFormInv<AABB, AABB, Transform>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM);
+ register_op<OperatorEvaluatorXForm<::AABB, Transform, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::AABB);
+ register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM);
register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::PACKED_VECTOR3_ARRAY);
register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM);
@@ -1645,7 +1700,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE);
register_op<OperatorEvaluatorStringModT<Quat>>(Variant::OP_MODULE, Variant::STRING, Variant::QUAT);
- register_op<OperatorEvaluatorStringModT<AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB);
+ register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB);
register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS);
register_op<OperatorEvaluatorStringModT<Transform>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM);
@@ -1713,7 +1768,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorEqual<Transform2D, Transform2D>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorEqual<Plane, Plane>>(Variant::OP_EQUAL, Variant::PLANE, Variant::PLANE);
register_op<OperatorEvaluatorEqual<Quat, Quat>>(Variant::OP_EQUAL, Variant::QUAT, Variant::QUAT);
- register_op<OperatorEvaluatorEqual<AABB, AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB);
+ register_op<OperatorEvaluatorEqual<::AABB, ::AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB);
register_op<OperatorEvaluatorEqual<Basis, Basis>>(Variant::OP_EQUAL, Variant::BASIS, Variant::BASIS);
register_op<OperatorEvaluatorEqual<Transform, Transform>>(Variant::OP_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM);
register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR);
@@ -1723,7 +1778,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorEqual<StringName, StringName>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME);
register_op<OperatorEvaluatorEqual<NodePath, NodePath>>(Variant::OP_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH);
- register_op<OperatorEvaluatorEqual<RID, RID>>(Variant::OP_EQUAL, Variant::_RID, Variant::_RID);
+ register_op<OperatorEvaluatorEqual<::RID, ::RID>>(Variant::OP_EQUAL, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorEqualObject>(Variant::OP_EQUAL, Variant::OBJECT, Variant::OBJECT);
register_op<OperatorEvaluatorEqualObjectNil>(Variant::OP_EQUAL, Variant::OBJECT, Variant::NIL);
@@ -1759,7 +1814,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorNotEqual<Transform2D, Transform2D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D);
register_op<OperatorEvaluatorNotEqual<Plane, Plane>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::PLANE);
register_op<OperatorEvaluatorNotEqual<Quat, Quat>>(Variant::OP_NOT_EQUAL, Variant::QUAT, Variant::QUAT);
- register_op<OperatorEvaluatorNotEqual<AABB, AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB);
+ register_op<OperatorEvaluatorNotEqual<::AABB, ::AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB);
register_op<OperatorEvaluatorNotEqual<Basis, Basis>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::BASIS);
register_op<OperatorEvaluatorNotEqual<Transform, Transform>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM);
register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR);
@@ -1769,7 +1824,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorNotEqual<StringName, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME);
register_op<OperatorEvaluatorNotEqual<NodePath, NodePath>>(Variant::OP_NOT_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH);
- register_op<OperatorEvaluatorNotEqual<RID, RID>>(Variant::OP_NOT_EQUAL, Variant::_RID, Variant::_RID);
+ register_op<OperatorEvaluatorNotEqual<::RID, ::RID>>(Variant::OP_NOT_EQUAL, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorNotEqualObject>(Variant::OP_NOT_EQUAL, Variant::OBJECT, Variant::OBJECT);
register_op<OperatorEvaluatorNotEqualObjectNil>(Variant::OP_NOT_EQUAL, Variant::OBJECT, Variant::NIL);
@@ -1799,7 +1854,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorLess<Vector2i, Vector2i>>(Variant::OP_LESS, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorLess<Vector3, Vector3>>(Variant::OP_LESS, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorLess<Vector3i, Vector3i>>(Variant::OP_LESS, Variant::VECTOR3I, Variant::VECTOR3I);
- register_op<OperatorEvaluatorLess<RID, RID>>(Variant::OP_LESS, Variant::_RID, Variant::_RID);
+ register_op<OperatorEvaluatorLess<::RID, ::RID>>(Variant::OP_LESS, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorLess<Array, Array>>(Variant::OP_LESS, Variant::ARRAY, Variant::ARRAY);
register_op<OperatorEvaluatorLessEqual<int64_t, int64_t>>(Variant::OP_LESS_EQUAL, Variant::INT, Variant::INT);
@@ -1811,7 +1866,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorLessEqual<Vector2i, Vector2i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorLessEqual<Vector3, Vector3>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorLessEqual<Vector3i, Vector3i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
- register_op<OperatorEvaluatorLessEqual<RID, RID>>(Variant::OP_LESS_EQUAL, Variant::_RID, Variant::_RID);
+ register_op<OperatorEvaluatorLessEqual<::RID, ::RID>>(Variant::OP_LESS_EQUAL, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorLessEqual<Array, Array>>(Variant::OP_LESS_EQUAL, Variant::ARRAY, Variant::ARRAY);
register_op<OperatorEvaluatorGreater<bool, bool>>(Variant::OP_GREATER, Variant::BOOL, Variant::BOOL);
@@ -1824,7 +1879,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorGreater<Vector2i, Vector2i>>(Variant::OP_GREATER, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorGreater<Vector3, Vector3>>(Variant::OP_GREATER, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorGreater<Vector3i, Vector3i>>(Variant::OP_GREATER, Variant::VECTOR3I, Variant::VECTOR3I);
- register_op<OperatorEvaluatorGreater<RID, RID>>(Variant::OP_GREATER, Variant::_RID, Variant::_RID);
+ register_op<OperatorEvaluatorGreater<::RID, ::RID>>(Variant::OP_GREATER, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorGreater<Array, Array>>(Variant::OP_GREATER, Variant::ARRAY, Variant::ARRAY);
register_op<OperatorEvaluatorGreaterEqual<int64_t, int64_t>>(Variant::OP_GREATER_EQUAL, Variant::INT, Variant::INT);
@@ -1836,7 +1891,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorGreaterEqual<Vector2i, Vector2i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I);
register_op<OperatorEvaluatorGreaterEqual<Vector3, Vector3>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3, Variant::VECTOR3);
register_op<OperatorEvaluatorGreaterEqual<Vector3i, Vector3i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I);
- register_op<OperatorEvaluatorGreaterEqual<RID, RID>>(Variant::OP_GREATER_EQUAL, Variant::_RID, Variant::_RID);
+ register_op<OperatorEvaluatorGreaterEqual<::RID, ::RID>>(Variant::OP_GREATER_EQUAL, Variant::RID, Variant::RID);
register_op<OperatorEvaluatorGreaterEqual<Array, Array>>(Variant::OP_GREATER_EQUAL, Variant::ARRAY, Variant::ARRAY);
register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_OR, Variant::NIL, Variant::NIL>>(Variant::OP_OR, Variant::NIL, Variant::NIL);
@@ -1948,7 +2003,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorInDictionaryHas<Transform2D>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Plane>>(Variant::OP_IN, Variant::PLANE, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Quat>>(Variant::OP_IN, Variant::QUAT, Variant::DICTIONARY);
- register_op<OperatorEvaluatorInDictionaryHas<AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY);
+ register_op<OperatorEvaluatorInDictionaryHas<::AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Basis>>(Variant::OP_IN, Variant::BASIS, Variant::DICTIONARY);
register_op<OperatorEvaluatorInDictionaryHas<Transform>>(Variant::OP_IN, Variant::TRANSFORM, Variant::DICTIONARY);
@@ -1985,7 +2040,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorInArrayFind<Transform2D, Array>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Plane, Array>>(Variant::OP_IN, Variant::PLANE, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Quat, Array>>(Variant::OP_IN, Variant::QUAT, Variant::ARRAY);
- register_op<OperatorEvaluatorInArrayFind<AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY);
+ register_op<OperatorEvaluatorInArrayFind<::AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Basis, Array>>(Variant::OP_IN, Variant::BASIS, Variant::ARRAY);
register_op<OperatorEvaluatorInArrayFind<Transform, Array>>(Variant::OP_IN, Variant::TRANSFORM, Variant::ARRAY);
@@ -2034,7 +2089,7 @@ void register_variant_operators() {
register_op<OperatorEvaluatorObjectHasPropertyStringName>(Variant::OP_IN, Variant::STRING_NAME, Variant::OBJECT);
}
-void unregister_variant_operators() {
+void Variant::_unregister_variant_operators() {
}
void Variant::evaluate(const Operator &p_op, const Variant &p_a,
@@ -2090,8 +2145,8 @@ static const char *_op_names[Variant::OP_MAX] = {
"-",
"*",
"/",
- "- (negation)",
- "+ (positive)",
+ "-",
+ "+",
"%",
"<<",
">>",
@@ -2104,7 +2159,6 @@ static const char *_op_names[Variant::OP_MAX] = {
"xor",
"not",
"in"
-
};
String Variant::get_operator_name(Operator p_op) {
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index 59d18a8b9f..cf1941a40e 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -100,7 +100,6 @@ public:
};
enum Expecting {
-
EXPECT_OBJECT,
EXPECT_OBJECT_KEY,
EXPECT_COLON,
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index 6d9599a27e..05fe2b80d9 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -2385,7 +2385,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
r_dst = a;
}
return;
- case _RID: {
+ case RID: {
r_dst = a;
}
return;
@@ -2576,12 +2576,12 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
}
-void register_variant_setters_getters() {
+void Variant::_register_variant_setters_getters() {
register_named_setters_getters();
register_indexed_setters_getters();
register_keyed_setters_getters();
}
-void unregister_variant_setters_getters() {
+void Variant::_unregister_variant_setters_getters() {
unregister_named_setters_getters();
unregister_indexed_setters_getters();
}
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
new file mode 100644
index 0000000000..70edcd48c2
--- /dev/null
+++ b/core/variant/variant_utility.cpp
@@ -0,0 +1,1381 @@
+/*************************************************************************/
+/* variant_utility.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "variant.h"
+
+#include "core/core_string_names.h"
+#include "core/io/marshalls.h"
+#include "core/object/reference.h"
+#include "core/os/os.h"
+#include "core/templates/oa_hash_map.h"
+#include "core/variant/binder_common.h"
+#include "core/variant/variant_parser.h"
+
+struct VariantUtilityFunctions {
+ // Math
+
+ static inline double sin(double arg) {
+ return Math::sin(arg);
+ }
+
+ static inline double cos(double arg) {
+ return Math::cos(arg);
+ }
+
+ static inline double tan(double arg) {
+ return Math::tan(arg);
+ }
+
+ static inline double sinh(double arg) {
+ return Math::sinh(arg);
+ }
+
+ static inline double cosh(double arg) {
+ return Math::cosh(arg);
+ }
+
+ static inline double tanh(double arg) {
+ return Math::tanh(arg);
+ }
+
+ static inline double asin(double arg) {
+ return Math::asin(arg);
+ }
+
+ static inline double acos(double arg) {
+ return Math::acos(arg);
+ }
+
+ static inline double atan(double arg) {
+ return Math::atan(arg);
+ }
+
+ static inline double atan2(double y, double x) {
+ return Math::atan2(y, x);
+ }
+
+ static inline double sqrt(double x) {
+ return Math::sqrt(x);
+ }
+
+ static inline double fmod(double b, double r) {
+ return Math::fmod(b, r);
+ }
+
+ static inline double fposmod(double b, double r) {
+ return Math::fposmod(b, r);
+ }
+
+ static inline double floor(double x) {
+ return Math::floor(x);
+ }
+
+ static inline double ceil(double x) {
+ return Math::ceil(x);
+ }
+
+ static inline double round(double x) {
+ return Math::round(x);
+ }
+
+ static inline Variant abs(const Variant &x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return ABS(VariantInternalAccessor<int64_t>::get(&x));
+ } break;
+ case Variant::FLOAT: {
+ return Math::absd(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).abs();
+ } break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x).abs();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).abs();
+ } break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x).abs();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double absf(double x) {
+ return Math::absd(x);
+ }
+
+ static inline int64_t absi(int64_t x) {
+ return ABS(x);
+ }
+
+ static inline Variant sign(const Variant &x, Callable::CallError &r_error) {
+ r_error.error = Callable::CallError::CALL_OK;
+ switch (x.get_type()) {
+ case Variant::INT: {
+ return SGN(VariantInternalAccessor<int64_t>::get(&x));
+ } break;
+ case Variant::FLOAT: {
+ return SGN(VariantInternalAccessor<double>::get(&x));
+ } break;
+ case Variant::VECTOR2: {
+ return VariantInternalAccessor<Vector2>::get(&x).sign();
+ } break;
+ case Variant::VECTOR2I: {
+ return VariantInternalAccessor<Vector2i>::get(&x).sign();
+ } break;
+ case Variant::VECTOR3: {
+ return VariantInternalAccessor<Vector3>::get(&x).sign();
+ } break;
+ case Variant::VECTOR3I: {
+ return VariantInternalAccessor<Vector3i>::get(&x).sign();
+ } break;
+ default: {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+ }
+ }
+
+ static inline double signf(double x) {
+ return SGN(x);
+ }
+
+ static inline int64_t signi(int64_t x) {
+ return SGN(x);
+ }
+
+ static inline double pow(double x, double y) {
+ return Math::pow(x, y);
+ }
+
+ static inline double log(double x) {
+ return Math::log(x);
+ }
+
+ static inline double exp(double x) {
+ return Math::exp(x);
+ }
+
+ static inline bool is_nan(double x) {
+ return Math::is_nan(x);
+ }
+
+ static inline bool is_inf(double x) {
+ return Math::is_inf(x);
+ }
+
+ static inline bool is_equal_approx(double x, double y) {
+ return Math::is_equal_approx(x, y);
+ }
+
+ static inline bool is_zero_approx(double x) {
+ return Math::is_zero_approx(x);
+ }
+
+ static inline double ease(float x, float curve) {
+ return Math::ease(x, curve);
+ }
+
+ static inline int step_decimals(float step) {
+ return Math::step_decimals(step);
+ }
+
+ static inline int range_step_decimals(float step) {
+ return Math::range_step_decimals(step);
+ }
+
+ static inline double stepify(double value, double step) {
+ return Math::stepify(value, step);
+ }
+
+ static inline double lerp(double from, double to, double weight) {
+ return Math::lerp(from, to, weight);
+ }
+
+ static inline double lerp_angle(double from, double to, double weight) {
+ return Math::lerp_angle(from, to, weight);
+ }
+
+ static inline double inverse_lerp(double from, double to, double weight) {
+ return Math::inverse_lerp(from, to, weight);
+ }
+
+ static inline double range_lerp(double value, double istart, double istop, double ostart, double ostop) {
+ return Math::range_lerp(value, istart, istop, ostart, ostop);
+ }
+
+ static inline double smoothstep(double from, double to, double val) {
+ return Math::smoothstep(from, to, val);
+ }
+
+ static inline double move_toward(double from, double to, double delta) {
+ return Math::move_toward(from, to, delta);
+ }
+
+ static inline double dectime(double value, double amount, double step) {
+ return Math::dectime(value, amount, step);
+ }
+
+ static inline double deg2rad(double angle_deg) {
+ return Math::deg2rad(angle_deg);
+ }
+
+ static inline double rad2deg(double angle_rad) {
+ return Math::rad2deg(angle_rad);
+ }
+
+ static inline double linear2db(double linear) {
+ return Math::linear2db(linear);
+ }
+
+ static inline double db2linear(double db) {
+ return Math::db2linear(db);
+ }
+
+ static inline Vector2 polar2cartesian(double r, double th) {
+ return Vector2(r * Math::cos(th), r * Math::sin(th));
+ }
+
+ static inline Vector2 cartesian2polar(double x, double y) {
+ return Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x));
+ }
+
+ static inline int64_t wrapi(int64_t value, int64_t min, int64_t max) {
+ return Math::wrapi(value, min, max);
+ }
+
+ static inline double wrapf(double value, double min, double max) {
+ return Math::wrapf(value, min, max);
+ }
+
+ static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ if (p_argcount < 2) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.expected = 2;
+ return Variant();
+ }
+ Variant base = *p_args[0];
+ Variant ret;
+ for (int i = 1; i < p_argcount; i++) {
+ bool valid;
+ Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = base.get_type();
+ r_error.argument = i;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ base = *p_args[i];
+ }
+ }
+ r_error.error = Callable::CallError::CALL_OK;
+ return base;
+ }
+
+ static inline double maxf(double x, double y) {
+ return MAX(x, y);
+ }
+
+ static inline int64_t maxi(int64_t x, int64_t y) {
+ return MAX(x, y);
+ }
+
+ static inline Variant min(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ if (p_argcount < 2) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.expected = 2;
+ return Variant();
+ }
+ Variant base = *p_args[0];
+ Variant ret;
+ for (int i = 1; i < p_argcount; i++) {
+ bool valid;
+ Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = base.get_type();
+ r_error.argument = i;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ base = *p_args[i];
+ }
+ }
+ r_error.error = Callable::CallError::CALL_OK;
+ return base;
+ }
+
+ static inline double minf(double x, double y) {
+ return MIN(x, y);
+ }
+
+ static inline int64_t mini(int64_t x, int64_t y) {
+ return MIN(x, y);
+ }
+
+ static inline Variant clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error) {
+ Variant value = x;
+
+ Variant ret;
+
+ bool valid;
+ Variant::evaluate(Variant::OP_LESS, value, min, ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = value.get_type();
+ r_error.argument = 1;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ value = min;
+ }
+ Variant::evaluate(Variant::OP_GREATER, value, max, ret, valid);
+ if (!valid) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.expected = value.get_type();
+ r_error.argument = 2;
+ return Variant();
+ }
+ if (ret.booleanize()) {
+ value = max;
+ }
+
+ r_error.error = Callable::CallError::CALL_OK;
+
+ return value;
+ }
+
+ static inline double clampf(double x, double min, double max) {
+ return CLAMP(x, min, max);
+ }
+
+ static inline int64_t clampi(int64_t x, int64_t min, int64_t max) {
+ return CLAMP(x, min, max);
+ }
+
+ static inline int64_t nearest_po2(int64_t x) {
+ return nearest_power_of_2_templated(uint64_t(x));
+ }
+
+ // Random
+
+ static inline void randomize() {
+ Math::randomize();
+ }
+
+ static inline int64_t randi() {
+ return Math::rand();
+ }
+
+ static inline double randf() {
+ return Math::randf();
+ }
+
+ static inline int64_t randi_range(int64_t from, int64_t to) {
+ return Math::random((int32_t)from, (int32_t)to);
+ }
+
+ static inline double randf_range(double from, double to) {
+ return Math::random(from, to);
+ }
+
+ static inline void seed(int64_t s) {
+ return Math::seed(s);
+ }
+
+ static inline PackedInt64Array rand_from_seed(int64_t seed) {
+ uint64_t s = seed;
+ PackedInt64Array arr;
+ arr.resize(2);
+ arr.write[0] = Math::rand_from_seed(&s);
+ arr.write[1] = s;
+ return arr;
+ }
+
+ // Utility
+
+ static inline Variant weakref(const Variant &obj, Callable::CallError &r_error) {
+ if (obj.get_type() == Variant::OBJECT) {
+ r_error.error = Callable::CallError::CALL_OK;
+ if (obj.is_ref()) {
+ Ref<WeakRef> wref = memnew(WeakRef);
+ REF r = obj;
+ if (r.is_valid()) {
+ wref->set_ref(r);
+ }
+ return wref;
+ } else {
+ Ref<WeakRef> wref = memnew(WeakRef);
+ Object *o = obj.get_validated_object();
+ if (o) {
+ wref->set_obj(o);
+ }
+ return wref;
+ }
+ } else if (obj.get_type() == Variant::NIL) {
+ r_error.error = Callable::CallError::CALL_OK;
+ Ref<WeakRef> wref = memnew(WeakRef);
+ return wref;
+ } else {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 0;
+ r_error.expected = Variant::OBJECT;
+ return Variant();
+ }
+ }
+
+ static inline int64_t _typeof(const Variant &obj) {
+ return obj.get_type();
+ }
+
+ static inline String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ return String();
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ r_error.error = Callable::CallError::CALL_OK;
+
+ return str;
+ }
+
+ static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ print_line(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ print_error(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ if (i) {
+ str += "\t";
+ }
+ str += p_args[i]->operator String();
+ }
+
+ print_error(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ if (i) {
+ str += " ";
+ }
+ str += p_args[i]->operator String();
+ }
+
+ print_error(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ OS::get_singleton()->print("%s", str.utf8().get_data());
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ ERR_PRINT(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline void push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) {
+ if (p_arg_count < 1) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ }
+ String str;
+ for (int i = 0; i < p_arg_count; i++) {
+ String os = p_args[i]->operator String();
+
+ if (i == 0) {
+ str = os;
+ } else {
+ str += os;
+ }
+ }
+
+ WARN_PRINT(str);
+ r_error.error = Callable::CallError::CALL_OK;
+ }
+
+ static inline String var2str(const Variant &p_var) {
+ String vars;
+ VariantWriter::write_to_string(p_var, vars);
+ return vars;
+ }
+
+ static inline Variant str2var(const String &p_var) {
+ VariantParser::StreamString ss;
+ ss.s = p_var;
+
+ String errs;
+ int line;
+ Variant ret;
+ (void)VariantParser::parse(&ss, ret, errs, line);
+
+ return ret;
+ }
+
+ static inline PackedByteArray var2bytes(const Variant &p_var) {
+ int len;
+ Error err = encode_variant(p_var, nullptr, len, false);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+
+ PackedByteArray barr;
+ barr.resize(len);
+ {
+ uint8_t *w = barr.ptrw();
+ err = encode_variant(p_var, w, len, false);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+ }
+
+ return barr;
+ }
+
+ static inline PackedByteArray var2bytes_with_objects(const Variant &p_var) {
+ int len;
+ Error err = encode_variant(p_var, nullptr, len, true);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+
+ PackedByteArray barr;
+ barr.resize(len);
+ {
+ uint8_t *w = barr.ptrw();
+ err = encode_variant(p_var, w, len, true);
+ if (err != OK) {
+ return PackedByteArray();
+ }
+ }
+
+ return barr;
+ }
+
+ static inline Variant bytes2var(const PackedByteArray &p_arr) {
+ Variant ret;
+ {
+ const uint8_t *r = p_arr.ptr();
+ Error err = decode_variant(ret, r, p_arr.size(), nullptr, false);
+ if (err != OK) {
+ return Variant();
+ }
+ }
+ return ret;
+ }
+
+ static inline Variant bytes2var_with_objects(const PackedByteArray &p_arr) {
+ Variant ret;
+ {
+ const uint8_t *r = p_arr.ptr();
+ Error err = decode_variant(ret, r, p_arr.size(), nullptr, true);
+ if (err != OK) {
+ return Variant();
+ }
+ }
+ return ret;
+ }
+
+ static inline int64_t hash(const Variant &p_arr) {
+ return p_arr.hash();
+ }
+
+ static inline Object *instance_from_id(int64_t p_id) {
+ ObjectID id = ObjectID((uint64_t)p_id);
+ Object *ret = ObjectDB::get_instance(id);
+ return ret;
+ }
+
+ static inline bool is_instance_id_valid(int64_t p_id) {
+ return ObjectDB::get_instance(ObjectID((uint64_t)p_id)) != nullptr;
+ }
+
+ static inline bool is_instance_valid(const Variant &p_instance) {
+ if (p_instance.get_type() != Variant::OBJECT) {
+ return false;
+ }
+ return p_instance.get_validated_object() != nullptr;
+ }
+};
+
+#ifdef DEBUG_METHODS_ENABLED
+#define VCALLR *ret = p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...)
+#define VCALL p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...)
+#else
+#define VCALLR *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...)
+#define VCALL p_func(VariantCaster<P>::cast(*p_args[Is])...)
+#endif
+
+template <class R, class... P, size_t... Is>
+static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+ VCALLR;
+ (void)p_args; // avoid gcc warning
+ (void)r_error;
+}
+
+template <class R, class... P, size_t... Is>
+static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, IndexSequence<Is...>) {
+ *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...);
+ (void)p_args;
+}
+
+template <class R, class... P, size_t... Is>
+static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence<Is...>) {
+ PtrToArg<R>::encode(p_func(PtrToArg<P>::convert(p_args[Is])...), ret);
+ (void)p_args;
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) {
+ call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args) {
+ validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(P...), void *ret, const void **p_args) {
+ ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) {
+ return sizeof...(P);
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+
+template <class R, class... P>
+static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) {
+ return GetTypeInfo<R>::VARIANT_TYPE;
+}
+
+// WITHOUT RET
+
+template <class... P, size_t... Is>
+static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) {
+ r_error.error = Callable::CallError::CALL_OK;
+ VCALL;
+ (void)p_args;
+ (void)r_error;
+}
+
+template <class... P, size_t... Is>
+static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence<Is...>) {
+ p_func(VariantCaster<P>::cast(*p_args[Is])...);
+ (void)p_args;
+}
+
+template <class... P, size_t... Is>
+static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p_args, IndexSequence<Is...>) {
+ p_func(PtrToArg<P>::convert(p_args[Is])...);
+ (void)p_args;
+}
+
+template <class... P>
+static _FORCE_INLINE_ void call_helper(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error) {
+ call_helperp(p_func, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(P...), const Variant **p_args) {
+ validated_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(P...), const void **p_args) {
+ ptr_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{});
+}
+
+template <class... P>
+static _FORCE_INLINE_ int get_arg_count_helper(void (*p_func)(P...)) {
+ return sizeof...(P);
+}
+
+template <class... P>
+static _FORCE_INLINE_ Variant::Type get_arg_type_helper(void (*p_func)(P...), int p_arg) {
+ return call_get_argument_type<P...>(p_arg);
+}
+
+template <class... P>
+static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) {
+ return Variant::NIL;
+}
+
+#define FUNCBINDR(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args, r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ validated_call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ ptr_call_helperr(VariantUtilityFunctions::m_func, ret, p_args); \
+ } \
+ static int get_argument_count() { \
+ return get_arg_count_helperr(VariantUtilityFunctions::m_func); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return get_arg_type_helperr(VariantUtilityFunctions::m_func, p_arg); \
+ } \
+ static Variant::Type get_return_type() { \
+ return get_ret_type_helperr(VariantUtilityFunctions::m_func); \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::UtilityFunctionType get_type() { return m_category; } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVR(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantUtilityFunctions::m_func(*p_args[0], r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ *r_ret = VariantUtilityFunctions::m_func(*p_args[0], ce); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ PtrToArg<Variant>::encode(VariantUtilityFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), ce), ret); \
+ } \
+ static int get_argument_count() { \
+ return 1; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::UtilityFunctionType get_type() { return m_category; } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVR3(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], ce); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Callable::CallError ce; \
+ Variant r; \
+ r = VariantUtilityFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), PtrToArg<Variant>::convert(p_args[1]), PtrToArg<Variant>::convert(p_args[2]), ce); \
+ PtrToArg<Variant>::encode(r, ret); \
+ } \
+ static int get_argument_count() { \
+ return 3; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::UtilityFunctionType get_type() { return m_category; } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVARARG(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError c; \
+ *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, c); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Vector<Variant> args; \
+ for (int i = 0; i < p_argcount; i++) { \
+ args.push_back(PtrToArg<Variant>::convert(p_args[i])); \
+ } \
+ Vector<const Variant *> argsp; \
+ for (int i = 0; i < p_argcount; i++) { \
+ argsp.push_back(&args[i]); \
+ } \
+ Variant r; \
+ validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \
+ PtrToArg<Variant>::encode(r, ret); \
+ } \
+ static int get_argument_count() { \
+ return 2; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::UtilityFunctionType get_type() { \
+ return m_category; \
+ } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVARARGS(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError c; \
+ *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, c); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Vector<Variant> args; \
+ for (int i = 0; i < p_argcount; i++) { \
+ args.push_back(PtrToArg<Variant>::convert(p_args[i])); \
+ } \
+ Vector<const Variant *> argsp; \
+ for (int i = 0; i < p_argcount; i++) { \
+ argsp.push_back(&args[i]); \
+ } \
+ Variant r; \
+ validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \
+ PtrToArg<String>::encode(r.operator String(), ret); \
+ } \
+ static int get_argument_count() { \
+ return 1; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return Variant::STRING; \
+ } \
+ static bool has_return_type() { \
+ return true; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::UtilityFunctionType get_type() { \
+ return m_category; \
+ } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBINDVARARGV(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ r_error.error = Callable::CallError::CALL_OK; \
+ VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ Callable::CallError c; \
+ VariantUtilityFunctions::m_func(p_args, p_argcount, c); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ Vector<Variant> args; \
+ for (int i = 0; i < p_argcount; i++) { \
+ args.push_back(PtrToArg<Variant>::convert(p_args[i])); \
+ } \
+ Vector<const Variant *> argsp; \
+ for (int i = 0; i < p_argcount; i++) { \
+ argsp.push_back(&args[i]); \
+ } \
+ Variant r; \
+ validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \
+ } \
+ static int get_argument_count() { \
+ return 1; \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return Variant::NIL; \
+ } \
+ static Variant::Type get_return_type() { \
+ return Variant::NIL; \
+ } \
+ static bool has_return_type() { \
+ return false; \
+ } \
+ static bool is_vararg() { \
+ return true; \
+ } \
+ static Variant::UtilityFunctionType get_type() { \
+ return m_category; \
+ } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+#define FUNCBIND(m_func, m_args, m_category) \
+ class Func_##m_func { \
+ public: \
+ static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \
+ call_helper(VariantUtilityFunctions::m_func, p_args, r_error); \
+ } \
+ static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \
+ validated_call_helper(VariantUtilityFunctions::m_func, p_args); \
+ } \
+ static void ptrcall(void *ret, const void **p_args, int p_argcount) { \
+ ptr_call_helper(VariantUtilityFunctions::m_func, p_args); \
+ } \
+ static int get_argument_count() { \
+ return get_arg_count_helper(VariantUtilityFunctions::m_func); \
+ } \
+ static Variant::Type get_argument_type(int p_arg) { \
+ return get_arg_type_helper(VariantUtilityFunctions::m_func, p_arg); \
+ } \
+ static Variant::Type get_return_type() { \
+ return get_ret_type_helper(VariantUtilityFunctions::m_func); \
+ } \
+ static bool has_return_type() { \
+ return false; \
+ } \
+ static bool is_vararg() { return false; } \
+ static Variant::UtilityFunctionType get_type() { return m_category; } \
+ }; \
+ register_utility_function<Func_##m_func>(#m_func, m_args)
+
+struct VariantUtilityFunctionInfo {
+ void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ Variant::ValidatedUtilityFunction validated_call_utility;
+ Variant::PTRUtilityFunction ptr_call_utility;
+ Vector<String> argnames;
+ bool is_vararg;
+ bool returns_value;
+ int argcount;
+ Variant::Type (*get_arg_type)(int);
+ Variant::Type return_type;
+ Variant::UtilityFunctionType type;
+};
+
+static OAHashMap<StringName, VariantUtilityFunctionInfo> utility_function_table;
+static List<StringName> utility_function_name_table;
+
+template <class T>
+static void register_utility_function(const String &p_name, const Vector<String> &argnames) {
+ String name = p_name;
+ if (name.begins_with("_")) {
+ name = name.substr(1, name.length() - 1);
+ }
+ StringName sname = name;
+ ERR_FAIL_COND(utility_function_table.has(sname));
+
+ VariantUtilityFunctionInfo bfi;
+ bfi.call_utility = T::call;
+ bfi.validated_call_utility = T::validated_call;
+ bfi.ptr_call_utility = T::ptrcall;
+ bfi.is_vararg = T::is_vararg();
+ bfi.argnames = argnames;
+ bfi.argcount = T::get_argument_count();
+ if (!bfi.is_vararg) {
+ ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, "wrong number of arguments binding utility function: " + name);
+ }
+ bfi.get_arg_type = T::get_argument_type;
+ bfi.return_type = T::get_return_type();
+ bfi.type = T::get_type();
+ bfi.returns_value = T::has_return_type();
+
+ utility_function_table.insert(sname, bfi);
+ utility_function_name_table.push_back(sname);
+}
+
+void Variant::_register_variant_utility_functions() {
+ // Math
+
+ FUNCBINDR(sin, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(cos, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(tan, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(sinh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(cosh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(tanh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(asin, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(acos, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(atan, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(atan2, sarray("y", "x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(sqrt, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(fmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(fposmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(absf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(absi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVR(sign, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(pow, sarray("base", "exp"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(log, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(exp, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(is_nan, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(is_inf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(is_equal_approx, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(is_zero_approx, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(range_step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(stepify, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(range_lerp, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(dectime, sarray("value", "amount", "step"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(deg2rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(rad2deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(linear2db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(db2linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(polar2cartesian, sarray("r", "th"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(cartesian2polar, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVARARG(max, sarray(), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(maxi, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(maxf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVARARG(min, sarray(), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(mini, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(minf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDVR3(clamp, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(clampi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
+ FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH);
+
+ // Random
+
+ FUNCBIND(randomize, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randi, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randf, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randi_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBINDR(randf_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBIND(seed, sarray("base"), Variant::UTILITY_FUNC_TYPE_RANDOM);
+ FUNCBINDR(rand_from_seed, sarray("seed"), Variant::UTILITY_FUNC_TYPE_RANDOM);
+
+ // Utility
+
+ FUNCBINDVR(weakref, sarray("obj"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(_typeof, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGS(str, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(printerr, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(printraw, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL);
+
+ FUNCBINDR(var2str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(str2var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+
+ FUNCBINDR(var2bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(bytes2var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+
+ FUNCBINDR(var2bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(bytes2var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+
+ FUNCBINDR(hash, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+
+ FUNCBINDR(instance_from_id, sarray("instance_id"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(is_instance_id_valid, sarray("id"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+ FUNCBINDR(is_instance_valid, sarray("instance"), Variant::UTILITY_FUNC_TYPE_GENERAL);
+}
+
+void Variant::_unregister_variant_utility_functions() {
+ utility_function_table.clear();
+ utility_function_name_table.clear();
+}
+
+void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error.argument = 0;
+ r_error.expected = 0;
+ return;
+ }
+
+ if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 0;
+ r_error.expected = bfi->argcount;
+ return;
+ }
+
+ if (unlikely(!bfi->is_vararg && p_argcount > bfi->argcount)) {
+ r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 0;
+ r_error.expected = bfi->argcount;
+ return;
+ }
+
+ bfi->call_utility(r_ret, p_args, p_argcount, r_error);
+}
+
+bool Variant::has_utility_function(const StringName &p_name) {
+ return utility_function_table.has(p_name);
+}
+
+Variant::ValidatedUtilityFunction Variant::get_validated_utility_function(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return nullptr;
+ }
+
+ return bfi->validated_call_utility;
+}
+
+Variant::PTRUtilityFunction Variant::get_ptr_utility_function(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return nullptr;
+ }
+
+ return bfi->ptr_call_utility;
+}
+
+Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return Variant::UTILITY_FUNC_TYPE_MATH;
+ }
+
+ return bfi->type;
+}
+
+int Variant::get_utility_function_argument_count(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return 0;
+ }
+
+ return bfi->argcount;
+}
+
+Variant::Type Variant::get_utility_function_argument_type(const StringName &p_name, int p_arg) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return Variant::NIL;
+ }
+
+ return bfi->get_arg_type(p_arg);
+}
+
+String Variant::get_utility_function_argument_name(const StringName &p_name, int p_arg) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return String();
+ }
+ ERR_FAIL_COND_V(bfi->is_vararg, String());
+ ERR_FAIL_INDEX_V(p_arg, bfi->argnames.size(), String());
+ return bfi->argnames[p_arg];
+}
+
+bool Variant::has_utility_function_return_value(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return false;
+ }
+ return bfi->returns_value;
+}
+
+Variant::Type Variant::get_utility_function_return_type(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return Variant::NIL;
+ }
+
+ return bfi->return_type;
+}
+
+bool Variant::is_utility_function_vararg(const StringName &p_name) {
+ const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name);
+ if (!bfi) {
+ return false;
+ }
+
+ return bfi->is_vararg;
+}
+
+void Variant::get_utility_function_list(List<StringName> *r_functions) {
+ for (List<StringName>::Element *E = utility_function_name_table.front(); E; E = E->next()) {
+ r_functions->push_back(E->get());
+ }
+}