summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bind/core_bind.cpp78
-rw-r--r--core/bind/core_bind.h57
-rw-r--r--core/color.cpp131
-rw-r--r--core/color.h23
-rw-r--r--core/event_queue.cpp157
-rw-r--r--core/event_queue.h64
-rw-r--r--core/hash_map.h33
-rw-r--r--core/hashfuncs.h34
-rw-r--r--core/io/file_access_network.cpp2
-rw-r--r--core/io/resource_format_binary.cpp41
-rw-r--r--core/io/resource_format_binary.h2
-rw-r--r--core/math/a_star.cpp11
-rw-r--r--core/math/a_star.h1
-rw-r--r--core/math/camera_matrix.cpp3
-rw-r--r--core/math/triangle_mesh.cpp2
-rw-r--r--core/oa_hash_map.h593
-rw-r--r--core/object.cpp12
-rw-r--r--core/object.h5
-rw-r--r--core/os/dir_access.cpp7
-rw-r--r--core/os/dir_access.h2
-rw-r--r--core/os/file_access.h3
-rw-r--r--core/os/os.cpp2
-rw-r--r--core/os/os.h16
-rw-r--r--core/os/power.h42
-rw-r--r--core/project_settings.cpp58
-rw-r--r--core/reference.cpp13
-rw-r--r--core/reference.h2
-rw-r--r--core/register_core_types.cpp6
-rw-r--r--core/script_debugger_remote.cpp3
-rw-r--r--core/script_language.cpp1
-rw-r--r--core/undo_redo.cpp4
-rw-r--r--core/variant.cpp165
-rw-r--r--core/variant.h7
-rw-r--r--core/variant_call.cpp10
-rw-r--r--core/variant_op.cpp1666
35 files changed, 2125 insertions, 1131 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 0f217c8235..cfd7677d6b 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -33,6 +33,7 @@
#include "geometry.h"
#include "io/file_access_compressed.h"
#include "io/file_access_encrypted.h"
+#include "io/json.h"
#include "io/marshalls.h"
#include "os/keyboard.h"
#include "os/os.h"
@@ -440,8 +441,8 @@ bool _OS::is_vsync_enabled() const {
return OS::get_singleton()->is_vsync_enabled();
}
-PowerState _OS::get_power_state() {
- return OS::get_singleton()->get_power_state();
+_OS::PowerState _OS::get_power_state() {
+ return _OS::PowerState(OS::get_singleton()->get_power_state());
}
int _OS::get_power_seconds_left() {
@@ -2600,3 +2601,76 @@ _Engine *_Engine::singleton = NULL;
_Engine::_Engine() {
singleton = this;
}
+
+void JSONParseResult::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_error"), &JSONParseResult::get_error);
+ ClassDB::bind_method(D_METHOD("get_error_string"), &JSONParseResult::get_error_string);
+ ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParseResult::get_error_line);
+ ClassDB::bind_method(D_METHOD("get_result"), &JSONParseResult::get_result);
+
+ ClassDB::bind_method(D_METHOD("set_error", "error"), &JSONParseResult::set_error);
+ ClassDB::bind_method(D_METHOD("set_error_string", "error_string"), &JSONParseResult::set_error_string);
+ ClassDB::bind_method(D_METHOD("set_error_line", "error_line"), &JSONParseResult::set_error_line);
+ ClassDB::bind_method(D_METHOD("set_result", "result"), &JSONParseResult::set_result);
+
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
+}
+
+void JSONParseResult::set_error(Error p_error) {
+ error = p_error;
+}
+
+Error JSONParseResult::get_error() const {
+ return error;
+}
+
+void JSONParseResult::set_error_string(const String &p_error_string) {
+ error_string = p_error_string;
+}
+
+String JSONParseResult::get_error_string() const {
+ return error_string;
+}
+
+void JSONParseResult::set_error_line(int p_error_line) {
+ error_line = p_error_line;
+}
+
+int JSONParseResult::get_error_line() const {
+ return error_line;
+}
+
+void JSONParseResult::set_result(const Variant &p_result) {
+ result = p_result;
+}
+
+Variant JSONParseResult::get_result() const {
+ return result;
+}
+
+void _JSON::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("print", "value"), &_JSON::print);
+ ClassDB::bind_method(D_METHOD("parse", "json"), &_JSON::parse);
+}
+
+String _JSON::print(const Variant &p_value) {
+ return JSON::print(p_value);
+}
+
+Ref<JSONParseResult> _JSON::parse(const String &p_json) {
+ Ref<JSONParseResult> result;
+ result.instance();
+
+ result->error = JSON::parse(p_json, result->result, result->error_string, result->error_line);
+
+ return result;
+}
+
+_JSON *_JSON::singleton = NULL;
+
+_JSON::_JSON() {
+ singleton = this;
+}
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 1a3782c471..721acf657f 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -36,7 +36,7 @@
#include "io/resource_saver.h"
#include "os/dir_access.h"
#include "os/file_access.h"
-#include "os/power.h"
+#include "os/os.h"
#include "os/semaphore.h"
#include "os/thread.h"
@@ -97,6 +97,14 @@ protected:
static _OS *singleton;
public:
+ enum PowerState {
+ POWERSTATE_UNKNOWN, /**< cannot determine power status */
+ POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
+ POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
+ POWERSTATE_CHARGING, /**< Plugged in, charging battery */
+ POWERSTATE_CHARGED /**< Plugged in, battery charged */
+ };
+
enum Weekday {
DAY_SUNDAY,
DAY_MONDAY,
@@ -312,6 +320,7 @@ public:
_OS();
};
+VARIANT_ENUM_CAST(_OS::PowerState);
VARIANT_ENUM_CAST(_OS::Weekday);
VARIANT_ENUM_CAST(_OS::Month);
VARIANT_ENUM_CAST(_OS::SystemDir);
@@ -660,4 +669,50 @@ public:
_Engine();
};
+class _JSON;
+
+class JSONParseResult : public Reference {
+ GDCLASS(JSONParseResult, Reference)
+
+ friend class _JSON;
+
+ Error error;
+ String error_string;
+ int error_line;
+
+ Variant result;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_error(Error p_error);
+ Error get_error() const;
+
+ void set_error_string(const String &p_error_string);
+ String get_error_string() const;
+
+ void set_error_line(int p_error_line);
+ int get_error_line() const;
+
+ void set_result(const Variant &p_result);
+ Variant get_result() const;
+};
+
+class _JSON : public Object {
+ GDCLASS(_JSON, Object)
+
+protected:
+ static void _bind_methods();
+ static _JSON *singleton;
+
+public:
+ static _JSON *get_singleton() { return singleton; }
+
+ String print(const Variant &p_value);
+ Ref<JSONParseResult> parse(const String &p_json);
+
+ _JSON();
+};
+
#endif // CORE_BIND_H
diff --git a/core/color.cpp b/core/color.cpp
index 1f8934ed05..78b11a84df 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -34,7 +34,7 @@
#include "math_funcs.h"
#include "print_string.h"
-uint32_t Color::to_ARGB32() const {
+uint32_t Color::to_argb32() const {
uint32_t c = (uint8_t)(a * 255);
c <<= 8;
@@ -47,7 +47,7 @@ uint32_t Color::to_ARGB32() const {
return c;
}
-uint32_t Color::to_ABGR32() const {
+uint32_t Color::to_abgr32() const {
uint32_t c = (uint8_t)(a * 255);
c <<= 8;
c |= (uint8_t)(b * 255);
@@ -59,15 +59,15 @@ uint32_t Color::to_ABGR32() const {
return c;
}
-uint32_t Color::to_32() const {
+uint32_t Color::to_rgba32() const {
- uint32_t c = (uint8_t)(a * 255);
- c <<= 8;
- c |= (uint8_t)(r * 255);
+ uint32_t c = (uint8_t)(r * 255);
c <<= 8;
c |= (uint8_t)(g * 255);
c <<= 8;
c |= (uint8_t)(b * 255);
+ c <<= 8;
+ c |= (uint8_t)(a * 255);
return c;
}
@@ -408,3 +408,122 @@ Color::operator String() const {
return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
}
+
+Color Color::operator+(const Color &p_color) const {
+
+ return Color(
+ CLAMP(r + p_color.r, 0.0, 1.0),
+ CLAMP(g + p_color.g, 0.0, 1.0),
+ CLAMP(b + p_color.b, 0.0, 1.0),
+ CLAMP(a + p_color.a, 0.0, 1.0));
+}
+
+void Color::operator+=(const Color &p_color) {
+
+ r = CLAMP(r + p_color.r, 0.0, 1.0);
+ g = CLAMP(g + p_color.g, 0.0, 1.0);
+ b = CLAMP(b + p_color.b, 0.0, 1.0);
+ a = CLAMP(a + p_color.a, 0.0, 1.0);
+}
+
+Color Color::operator-(const Color &p_color) const {
+
+ return Color(
+ CLAMP(r - p_color.r, 0.0, 1.0),
+ CLAMP(g - p_color.g, 0.0, 1.0),
+ CLAMP(b - p_color.b, 0.0, 1.0),
+ CLAMP(a - p_color.a, 0.0, 1.0));
+}
+
+void Color::operator-=(const Color &p_color) {
+
+ r = CLAMP(r - p_color.r, 0.0, 1.0);
+ g = CLAMP(g - p_color.g, 0.0, 1.0);
+ b = CLAMP(b - p_color.b, 0.0, 1.0);
+ a = CLAMP(a - p_color.a, 0.0, 1.0);
+}
+
+Color Color::operator*(const Color &p_color) const {
+
+ return Color(
+ CLAMP(r * p_color.r, 0.0, 1.0),
+ CLAMP(g * p_color.g, 0.0, 1.0),
+ CLAMP(b * p_color.b, 0.0, 1.0),
+ CLAMP(a * p_color.a, 0.0, 1.0));
+}
+
+Color Color::operator*(const real_t &rvalue) const {
+
+ return Color(
+ CLAMP(r * rvalue, 0.0, 1.0),
+ CLAMP(g * rvalue, 0.0, 1.0),
+ CLAMP(b * rvalue, 0.0, 1.0),
+ CLAMP(a * rvalue, 0.0, 1.0));
+}
+
+void Color::operator*=(const Color &p_color) {
+
+ r = CLAMP(r * p_color.r, 0.0, 1.0);
+ g = CLAMP(g * p_color.g, 0.0, 1.0);
+ b = CLAMP(b * p_color.b, 0.0, 1.0);
+ a = CLAMP(a * p_color.a, 0.0, 1.0);
+}
+
+void Color::operator*=(const real_t &rvalue) {
+
+ r = CLAMP(r * rvalue, 0.0, 1.0);
+ g = CLAMP(g * rvalue, 0.0, 1.0);
+ b = CLAMP(b * rvalue, 0.0, 1.0);
+ a = CLAMP(a * rvalue, 0.0, 1.0);
+};
+
+Color Color::operator/(const Color &p_color) const {
+
+ return Color(
+ p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0),
+ p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0),
+ p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0),
+ p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0));
+}
+
+Color Color::operator/(const real_t &rvalue) const {
+
+ if (rvalue == 0) return Color(1.0, 1.0, 1.0, 1.0);
+ return Color(
+ CLAMP(r / rvalue, 0.0, 1.0),
+ CLAMP(g / rvalue, 0.0, 1.0),
+ CLAMP(b / rvalue, 0.0, 1.0),
+ CLAMP(a / rvalue, 0.0, 1.0));
+}
+
+void Color::operator/=(const Color &p_color) {
+
+ r = p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0);
+ g = p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0);
+ b = p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0);
+ a = p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0);
+}
+
+void Color::operator/=(const real_t &rvalue) {
+
+ if (rvalue == 0) {
+ r = 1.0;
+ g = 1.0;
+ b = 1.0;
+ a = 1.0;
+ } else {
+ r = CLAMP(r / rvalue, 0.0, 1.0);
+ g = CLAMP(g / rvalue, 0.0, 1.0);
+ b = CLAMP(b / rvalue, 0.0, 1.0);
+ a = CLAMP(a / rvalue, 0.0, 1.0);
+ }
+};
+
+Color Color::operator-() const {
+
+ return Color(
+ CLAMP(1.0 - r, 0.0, 1.0),
+ CLAMP(1.0 - g, 0.0, 1.0),
+ CLAMP(1.0 - b, 0.0, 1.0),
+ CLAMP(1.0 - a, 0.0, 1.0));
+}
diff --git a/core/color.h b/core/color.h
index cd5510cf01..972b6a1b33 100644
--- a/core/color.h
+++ b/core/color.h
@@ -51,9 +51,9 @@ struct Color {
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_32() const;
- uint32_t to_ARGB32() const;
- uint32_t to_ABGR32() const;
+ uint32_t to_rgba32() const;
+ uint32_t to_argb32() const;
+ uint32_t to_abgr32() const;
float gray() const;
float get_h() const;
float get_s() const;
@@ -67,6 +67,23 @@ struct Color {
return components[idx];
}
+ 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*(const real_t &rvalue) const;
+ void operator*=(const Color &p_color);
+ void operator*=(const real_t &rvalue);
+
+ Color operator/(const Color &p_color) const;
+ Color operator/(const real_t &rvalue) const;
+ void operator/=(const Color &p_color);
+ void operator/=(const real_t &rvalue);
+
void invert();
void contrast();
Color inverted() const;
diff --git a/core/event_queue.cpp b/core/event_queue.cpp
deleted file mode 100644
index 12f9942a07..0000000000
--- a/core/event_queue.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*************************************************************************/
-/* event_queue.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 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 "event_queue.h"
-
-Error EventQueue::push_call(uint32_t p_instance_ID, const StringName &p_method, VARIANT_ARG_DECLARE) {
-
- uint8_t room_needed = sizeof(Event);
- int args = 0;
- if (p_arg5.get_type() != Variant::NIL)
- args = 5;
- else if (p_arg4.get_type() != Variant::NIL)
- args = 4;
- else if (p_arg3.get_type() != Variant::NIL)
- args = 3;
- else if (p_arg2.get_type() != Variant::NIL)
- args = 2;
- else if (p_arg1.get_type() != Variant::NIL)
- args = 1;
- else
- args = 0;
-
- room_needed += sizeof(Variant) * args;
-
- ERR_FAIL_COND_V((buffer_end + room_needed) >= buffer_size, ERR_OUT_OF_MEMORY);
- Event *ev = memnew_placement(&event_buffer[buffer_end], Event);
- ev->args = args;
- ev->instance_ID = p_instance_ID;
- ev->method = p_method;
-
- buffer_end += sizeof(Event);
-
- if (args >= 1) {
-
- Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
- buffer_end += sizeof(Variant);
- *v = p_arg1;
- }
-
- if (args >= 2) {
-
- Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
- buffer_end += sizeof(Variant);
- *v = p_arg2;
- }
-
- if (args >= 3) {
-
- Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
- buffer_end += sizeof(Variant);
- *v = p_arg3;
- }
-
- if (args >= 4) {
-
- Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
- buffer_end += sizeof(Variant);
- *v = p_arg4;
- }
-
- if (args >= 5) {
-
- Variant *v = memnew_placement(&event_buffer[buffer_end], Variant);
- buffer_end += sizeof(Variant);
- *v = p_arg5;
- }
-
- if (buffer_end > buffer_max_used)
- buffer_max_used = buffer_end;
-
- return OK;
-}
-
-void EventQueue::flush_events() {
-
- uint32_t read_pos = 0;
-
- while (read_pos < buffer_end) {
-
- Event *event = (Event *)&event_buffer[read_pos];
- Variant *args = (Variant *)(event + 1);
- Object *obj = ObjectDB::get_instance(event->instance_ID);
-
- if (obj) {
- // events don't expect a return value
- obj->call(event->method,
- (event->args >= 1) ? args[0] : Variant(),
- (event->args >= 2) ? args[1] : Variant(),
- (event->args >= 3) ? args[2] : Variant(),
- (event->args >= 4) ? args[3] : Variant(),
- (event->args >= 5) ? args[4] : Variant());
- }
-
- if (event->args >= 1) args[0].~Variant();
- if (event->args >= 2) args[1].~Variant();
- if (event->args >= 3) args[2].~Variant();
- if (event->args >= 4) args[3].~Variant();
- if (event->args >= 5) args[4].~Variant();
- event->~Event();
-
- read_pos += sizeof(Event) + sizeof(Variant) * event->args;
- }
-
- buffer_end = 0; // reset buffer
-}
-
-EventQueue::EventQueue(uint32_t p_buffer_size) {
-
- buffer_end = 0;
- buffer_max_used = 0;
- buffer_size = p_buffer_size;
- event_buffer = memnew_arr(uint8_t, buffer_size);
-}
-EventQueue::~EventQueue() {
-
- uint32_t read_pos = 0;
-
- while (read_pos < buffer_end) {
-
- Event *event = (Event *)&event_buffer[read_pos];
- Variant *args = (Variant *)(event + 1);
- for (int i = 0; i < event->args; i++)
- args[i].~Variant();
- event->~Event();
-
- read_pos += sizeof(Event) + sizeof(Variant) * event->args;
- }
-
- memdelete_arr(event_buffer);
- event_buffer = NULL;
-}
diff --git a/core/event_queue.h b/core/event_queue.h
deleted file mode 100644
index af1a760945..0000000000
--- a/core/event_queue.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*************************************************************************/
-/* event_queue.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 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. */
-/*************************************************************************/
-#ifndef EVENT_QUEUE_H
-#define EVENT_QUEUE_H
-
-#include "object.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class EventQueue {
-
- enum {
-
- DEFAULT_EVENT_QUEUE_SIZE_KB = 256
- };
-
- struct Event {
-
- uint32_t instance_ID;
- StringName method;
- int args;
- };
-
- uint8_t *event_buffer;
- uint32_t buffer_end;
- uint32_t buffer_max_used;
- uint32_t buffer_size;
-
-public:
- Error push_call(uint32_t p_instance_ID, const StringName &p_method, VARIANT_ARG_LIST);
- void flush_events();
-
- EventQueue(uint32_t p_buffer_size = DEFAULT_EVENT_QUEUE_SIZE_KB * 1024);
- ~EventQueue();
-};
-
-#endif
diff --git a/core/hash_map.h b/core/hash_map.h
index 37391a4c83..e100d7a904 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -37,39 +37,6 @@
#include "os/memory.h"
#include "ustring.h"
-struct HashMapHasherDefault {
- static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
- static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
- static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
-
- static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
- static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
- static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
- static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
- static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
- static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
- //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
-};
-
-template <typename T>
-struct HashMapComparatorDefault {
- static bool compare(const T &p_lhs, const T &p_rhs) {
- return p_lhs == p_rhs;
- }
-
- bool compare(const float &p_lhs, const float &p_rhs) {
- return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
- }
-
- bool compare(const double &p_lhs, const double &p_rhs) {
- return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
- }
-};
-
/**
* @class HashMap
* @author Juan Linietsky <reduzio@gmail.com>
diff --git a/core/hashfuncs.h b/core/hashfuncs.h
index 56d40f1dd7..2880cc451e 100644
--- a/core/hashfuncs.h
+++ b/core/hashfuncs.h
@@ -33,6 +33,7 @@
#include "math_defs.h"
#include "math_funcs.h"
#include "typedefs.h"
+#include "ustring.h"
/**
* Hashing functions
@@ -128,4 +129,37 @@ static inline uint64_t make_uint64_t(T p_in) {
return _u._u64;
}
+struct HashMapHasherDefault {
+ static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
+ static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
+ static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
+
+ static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); }
+ static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); }
+ static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); }
+ static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; }
+ static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; }
+ //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); }
+};
+
+template <typename T>
+struct HashMapComparatorDefault {
+ static bool compare(const T &p_lhs, const T &p_rhs) {
+ return p_lhs == p_rhs;
+ }
+
+ bool compare(const float &p_lhs, const float &p_rhs) {
+ return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
+ }
+
+ bool compare(const double &p_lhs, const double &p_rhs) {
+ return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs));
+ }
+};
+
#endif
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index d8b8c8c200..58ca2d4c58 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -87,6 +87,8 @@ void FileAccessNetworkClient::_thread_func() {
DEBUG_PRINT("SEM WAIT - " + itos(sem->get()));
Error err = sem->wait();
+ if (err != OK)
+ ERR_PRINT("sem->wait() failed");
DEBUG_TIME("sem_unlock");
//DEBUG_PRINT("semwait returned "+itos(werr));
DEBUG_PRINT("MUTEX LOCK " + itos(lockcount));
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 661eba2106..16ec6cd3c5 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -37,7 +37,7 @@
#include "core/version.h"
//#define print_bl(m_what) print_line(m_what)
-#define print_bl(m_what)
+#define print_bl(m_what) (void)(m_what)
enum {
@@ -854,12 +854,6 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
}
bool big_endian = f->get_32();
-#ifdef BIG_ENDIAN_ENABLED
- endian_swap = !big_endian;
-#else
- bool endian_swap = big_endian;
-#endif
-
bool use_real64 = f->get_32();
f->set_endian_swap(big_endian != 0); //read big endian if saved as big endian
@@ -869,7 +863,11 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
uint32_t ver_format = f->get_32();
print_bl("big endian: " + itos(big_endian));
- print_bl("endian swap: " + itos(endian_swap));
+#ifdef BIG_ENDIAN_ENABLED
+ print_bl("endian swap: " + itos(!big_endian));
+#else
+ print_bl("endian swap: " + itos(big_endian));
+#endif
print_bl("real64: " + itos(use_real64));
print_bl("major: " + itos(ver_major));
print_bl("minor: " + itos(ver_minor));
@@ -964,18 +962,12 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {
}
bool big_endian = f->get_32();
-#ifdef BIG_ENDIAN_ENABLED
- endian_swap = !big_endian;
-#else
- bool endian_swap = big_endian;
-#endif
-
- bool use_real64 = f->get_32();
+ f->get_32(); // use_real64
f->set_endian_swap(big_endian != 0); //read big endian if saved as big endian
uint32_t ver_major = f->get_32();
- uint32_t ver_minor = f->get_32();
+ f->get_32(); // ver_minor
uint32_t ver_format = f->get_32();
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
@@ -993,8 +985,6 @@ ResourceInteractiveLoaderBinary::ResourceInteractiveLoaderBinary() {
f = NULL;
stage = 0;
- endian_swap = false;
- use_real64 = false;
error = OK;
translation_remapped = false;
}
@@ -1123,16 +1113,14 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
}
bool big_endian = f->get_32();
-#ifdef BIG_ENDIAN_ENABLED
- endian_swap = !big_endian;
-#else
- bool endian_swap = big_endian;
-#endif
-
bool use_real64 = f->get_32();
f->set_endian_swap(big_endian != 0); //read big endian if saved as big endian
- fw->store_32(endian_swap);
+#ifdef BIG_ENDIAN_ENABLED
+ fw->store_32(!big_endian);
+#else
+ fw->store_32(big_endian);
+#endif
fw->set_endian_swap(big_endian != 0);
fw->store_32(use_real64); //use real64
@@ -1793,8 +1781,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
}
save_unicode_string(p_resource->get_class());
- uint64_t md_at = f->get_pos();
- f->store_64(0); //offset to impoty metadata
+ f->store_64(0); //offset to import metadata
for (int i = 0; i < 14; i++)
f->store_32(0); // reserved
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index ab77c2c9d3..2316f05b3c 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -44,8 +44,6 @@ class ResourceInteractiveLoaderBinary : public ResourceInteractiveLoader {
FileAccess *f;
- bool endian_swap;
- bool use_real64;
uint64_t importmd_ofs;
Vector<char> str_buf;
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 21516ac768..d1afcec18f 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -129,6 +129,16 @@ bool AStar::has_point(int p_id) const {
return points.has(p_id);
}
+Array AStar::get_points() {
+ Array point_list;
+
+ for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) {
+ point_list.push_back(E->key());
+ }
+
+ return point_list;
+}
+
bool AStar::are_points_connected(int p_id, int p_with_id) const {
Segment s(p_id, p_with_id);
@@ -407,6 +417,7 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar::get_point_weight_scale);
ClassDB::bind_method(D_METHOD("remove_point", "id"), &AStar::remove_point);
ClassDB::bind_method(D_METHOD("has_point", "id"), &AStar::has_point);
+ ClassDB::bind_method(D_METHOD("get_points"), &AStar::get_points);
ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar::connect_points, DEFVAL(true));
ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id"), &AStar::disconnect_points);
diff --git a/core/math/a_star.h b/core/math/a_star.h
index 75b860d0a4..38d13d510b 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -105,6 +105,7 @@ public:
real_t get_point_weight_scale(int p_id) const;
void remove_point(int p_id);
bool has_point(int p_id) const;
+ Array get_points();
void connect_points(int p_id, int p_with_id, bool bidirectional = true);
void disconnect_points(int p_id, int p_with_id);
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index b7a929c8e0..2c587762e8 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -131,7 +131,6 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_
void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_dist, real_t p_display_width, real_t p_display_to_lens, real_t p_oversample, real_t p_z_near, real_t p_z_far) {
// we first calculate our base frustum on our values without taking our lens magnification into account.
- real_t display_to_eye = 2.0 * p_display_to_lens;
real_t f1 = (p_intraocular_dist * 0.5) / p_display_to_lens;
real_t f2 = ((p_display_width - p_intraocular_dist) * 0.5) / p_display_to_lens;
real_t f3 = (p_display_width / 4.0) / p_display_to_lens;
@@ -578,7 +577,7 @@ real_t CameraMatrix::get_fov() const {
if ((matrix[8] == 0) && (matrix[9] == 0)) {
return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0;
} else {
- // our frustum is asymetrical need to calculate the left planes angle seperately..
+ // our frustum is asymmetrical need to calculate the left planes angle separately..
Plane left_plane = Plane(matrix[3] + matrix[0],
matrix[7] + matrix[4],
matrix[11] + matrix[8],
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 614104f698..3b246cb183 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -158,7 +158,7 @@ void TriangleMesh::create(const PoolVector<Vector3> &p_faces) {
max_depth = 0;
int max_alloc = fc;
- int max = _create_bvh(bw.ptr(), bwp.ptr(), 0, fc, 1, max_depth, max_alloc);
+ _create_bvh(bw.ptr(), bwp.ptr(), 0, fc, 1, max_depth, max_alloc);
bw = PoolVector<BVH>::Write(); //clearup
bvh.resize(max_alloc); //resize back
diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h
new file mode 100644
index 0000000000..66a1e348a1
--- /dev/null
+++ b/core/oa_hash_map.h
@@ -0,0 +1,593 @@
+/*************************************************************************/
+/* oa_hash_map.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 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. */
+/*************************************************************************/
+#ifndef OA_HASH_MAP_H
+#define OA_HASH_MAP_H
+
+#include "hashfuncs.h"
+#include "math_funcs.h"
+#include "os/copymem.h"
+#include "os/memory.h"
+
+// uncomment this to disable intial local storage.
+#define OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+
+/**
+ * This class implements a hash map datastructure that uses open addressing with
+ * local probing.
+ *
+ * It can give huge performance improvements over a chained HashMap because of
+ * the increased data locality.
+ *
+ * Because of that locality property it's important to not use "large" value
+ * types as the "TData" type. If TData values are too big it can cause more
+ * cache misses then chaining. If larger values are needed then storing those
+ * in a separate array and using pointers or indices to reference them is the
+ * better solution.
+ *
+ * This hash map also implements real-time incremental rehashing.
+ *
+ */
+template <class TKey, class TData,
+ uint16_t INITIAL_NUM_ELEMENTS = 64,
+ class Hasher = HashMapHasherDefault,
+ class Comparator = HashMapComparatorDefault<TKey> >
+class OAHashMap {
+
+private:
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ TData local_data[INITIAL_NUM_ELEMENTS];
+ TKey local_keys[INITIAL_NUM_ELEMENTS];
+ uint32_t local_hashes[INITIAL_NUM_ELEMENTS];
+ uint8_t local_flags[INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)];
+#endif
+
+ struct {
+ TData *data;
+ TKey *keys;
+ uint32_t *hashes;
+
+ // This is actually an array of bits, 4 bit pairs per octet.
+ // | ba ba ba ba | ba ba ba ba | ....
+ //
+ // if a is set it means that there is an element present.
+ // if b is set it means that an element was deleted. This is needed for
+ // the local probing to work without relocating any succeeding and
+ // colliding entries.
+ uint8_t *flags;
+
+ uint32_t capacity;
+ } table, old_table;
+
+ bool is_rehashing;
+ uint32_t rehash_position;
+ uint32_t rehash_amount;
+
+ uint32_t elements;
+
+ /* Methods */
+
+ // returns true if the value already existed, false if it's a new entry
+ bool _raw_set_with_hash(uint32_t p_hash, const TKey &p_key, const TData &p_data) {
+ for (int i = 0; i < table.capacity; i++) {
+
+ int pos = (p_hash + i) % table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset));
+ bool is_deleted_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1));
+
+ if (is_filled_flag) {
+ if (table.hashes[pos] == p_hash && Comparator::compare(table.keys[pos], p_key)) {
+ table.data[pos] = p_data;
+ return true;
+ }
+ continue;
+ }
+
+ table.keys[pos] = p_key;
+ table.data[pos] = p_data;
+ table.hashes[pos] = p_hash;
+
+ table.flags[flags_pos] |= (1 << (2 * flags_pos_offset));
+ table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset + 1));
+
+ return false;
+ }
+ return false;
+ }
+
+public:
+ _FORCE_INLINE_ uint32_t get_capacity() const { return table.capacity; }
+ _FORCE_INLINE_ uint32_t get_num_elements() const { return elements; }
+
+ void set(const TKey &p_key, const TData &p_data) {
+
+ uint32_t hash = Hasher::hash(p_key);
+
+ // We don't progress the rehashing if the table just got resized
+ // to keep the cost of this function low.
+ if (is_rehashing) {
+
+ // rehash progress
+
+ for (int i = 0; i <= rehash_amount && rehash_position < old_table.capacity; rehash_position++) {
+
+ int flags_pos = rehash_position / 4;
+ int flags_pos_offset = rehash_position % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ _raw_set_with_hash(old_table.hashes[rehash_position], old_table.keys[rehash_position], old_table.data[rehash_position]);
+
+ old_table.keys[rehash_position].~TKey();
+ old_table.data[rehash_position].~TData();
+
+ memnew_placement(&old_table.keys[rehash_position], TKey);
+ memnew_placement(&old_table.data[rehash_position], TData);
+
+ old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset));
+ old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1));
+ }
+ }
+
+ if (rehash_position >= old_table.capacity) {
+
+ // wohooo, we can get rid of the old table.
+ is_rehashing = false;
+
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ if (old_table.data == local_data) {
+ // Everything is local, so no cleanup :P
+ } else
+#endif
+ {
+ memdelete_arr(old_table.data);
+ memdelete_arr(old_table.keys);
+ memdelete_arr(old_table.hashes);
+ memdelete_arr(old_table.flags);
+ }
+ }
+ }
+
+ // Table is almost full, resize and start rehashing process.
+ if (elements >= table.capacity * 0.7) {
+
+ old_table.capacity = table.capacity;
+ old_table.data = table.data;
+ old_table.flags = table.flags;
+ old_table.hashes = table.hashes;
+ old_table.keys = table.keys;
+
+ table.capacity = old_table.capacity * 2;
+
+ table.data = memnew_arr(TData, table.capacity);
+ table.flags = memnew_arr(uint8_t, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0));
+ table.hashes = memnew_arr(uint32_t, table.capacity);
+ table.keys = memnew_arr(TKey, table.capacity);
+
+ zeromem(table.flags, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0));
+
+ is_rehashing = true;
+ rehash_position = 0;
+ rehash_amount = (elements * 2) / (table.capacity * 0.7 - old_table.capacity);
+ }
+
+ if (!_raw_set_with_hash(hash, p_key, p_data))
+ elements++;
+ }
+
+ /**
+ * returns true if the value was found, false otherwise.
+ *
+ * if r_data is not NULL then the value will be written to the object
+ * it points to.
+ */
+ bool lookup(const TKey &p_key, TData *r_data) {
+
+ uint32_t hash = Hasher::hash(p_key);
+
+ bool check_old_table = is_rehashing;
+ bool check_new_table = true;
+
+ // search for the key and return the value associated with it
+ //
+ // if we're rehashing we need to check both the old and the
+ // current table. If we find a value in the old table we still
+ // need to continue searching in the new table as it might have
+ // been added after
+
+ TData *value = NULL;
+
+ for (int i = 0; i < table.capacity; i++) {
+
+ if (!check_new_table && !check_old_table) {
+
+ break;
+ }
+
+ // if we're rehashing check the old table
+ if (check_old_table && i < old_table.capacity) {
+
+ int pos = (hash + i) % old_table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) {
+ value = &old_table.data[pos];
+ check_old_table = false;
+ }
+ } else if (!is_deleted_flag) {
+
+ // we hit an empty field here, we don't
+ // need to further check this old table
+ // because we know it's not in here.
+
+ check_old_table = false;
+ }
+ }
+
+ if (check_new_table) {
+
+ int pos = (hash + i) % table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) {
+ if (r_data != NULL)
+ *r_data = table.data[pos];
+ return true;
+ }
+ continue;
+ } else if (is_deleted_flag) {
+ continue;
+ } else if (value != NULL) {
+
+ // We found a value in the old table
+ if (r_data != NULL)
+ *r_data = *value;
+ return true;
+ } else {
+ check_new_table = false;
+ }
+ }
+ }
+
+ if (value != NULL) {
+ if (r_data != NULL)
+ *r_data = *value;
+ return true;
+ }
+ return false;
+ }
+
+ _FORCE_INLINE_ bool has(const TKey &p_key) {
+ return lookup(p_key, NULL);
+ }
+
+ void remove(const TKey &p_key) {
+ uint32_t hash = Hasher::hash(p_key);
+
+ bool check_old_table = is_rehashing;
+ bool check_new_table = true;
+
+ for (int i = 0; i < table.capacity; i++) {
+
+ if (!check_new_table && !check_old_table) {
+ return;
+ }
+
+ // if we're rehashing check the old table
+ if (check_old_table && i < old_table.capacity) {
+
+ int pos = (hash + i) % old_table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) {
+ old_table.keys[pos].~TKey();
+ old_table.data[pos].~TData();
+
+ memnew_placement(&old_table.keys[pos], TKey);
+ memnew_placement(&old_table.data[pos], TData);
+
+ old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset));
+ old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1));
+
+ elements--;
+ return;
+ }
+ } else if (!is_deleted_flag) {
+
+ // we hit an empty field here, we don't
+ // need to further check this old table
+ // because we know it's not in here.
+
+ check_old_table = false;
+ }
+ }
+
+ if (check_new_table) {
+
+ int pos = (hash + i) % table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) {
+ table.keys[pos].~TKey();
+ table.data[pos].~TData();
+
+ memnew_placement(&table.keys[pos], TKey);
+ memnew_placement(&table.data[pos], TData);
+
+ table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset));
+ table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1));
+
+ // don't return here, this value might still be in the old table
+ // if it was already relocated.
+
+ elements--;
+ return;
+ }
+ continue;
+ } else if (is_deleted_flag) {
+ continue;
+ } else {
+ check_new_table = false;
+ }
+ }
+ }
+ }
+
+ struct Iterator {
+ bool valid;
+
+ uint32_t hash;
+
+ const TKey *key;
+ const TData *data;
+
+ private:
+ friend class OAHashMap;
+ bool was_from_old_table;
+ };
+
+ Iterator iter() const {
+ Iterator it;
+
+ it.valid = false;
+ it.was_from_old_table = false;
+
+ bool check_old_table = is_rehashing;
+
+ for (int i = 0; i < table.capacity; i++) {
+
+ // if we're rehashing check the old table first
+ if (check_old_table && i < old_table.capacity) {
+
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = old_table.hashes[pos];
+ it.data = &old_table.data[pos];
+ it.key = &old_table.keys[pos];
+
+ it.was_from_old_table = true;
+
+ return it;
+ }
+ }
+
+ {
+
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = table.hashes[pos];
+ it.data = &table.data[pos];
+ it.key = &table.keys[pos];
+
+ return it;
+ }
+ }
+ }
+
+ return it;
+ }
+
+ Iterator next_iter(const Iterator &p_iter) const {
+ if (!p_iter.valid) {
+ return p_iter;
+ }
+
+ Iterator it;
+
+ it.valid = false;
+ it.was_from_old_table = false;
+
+ bool check_old_table = is_rehashing;
+
+ // we use this to skip the first check or not
+ bool was_from_old_table = p_iter.was_from_old_table;
+
+ int prev_index = (p_iter.data - (p_iter.was_from_old_table ? old_table.data : table.data));
+
+ if (!was_from_old_table) {
+ prev_index++;
+ }
+
+ for (int i = prev_index; i < table.capacity; i++) {
+
+ // if we're rehashing check the old table first
+ if (check_old_table && i < old_table.capacity && !was_from_old_table) {
+
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = old_table.hashes[pos];
+ it.data = &old_table.data[pos];
+ it.key = &old_table.keys[pos];
+
+ it.was_from_old_table = true;
+
+ return it;
+ }
+ }
+
+ was_from_old_table = false;
+
+ {
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = table.hashes[pos];
+ it.data = &table.data[pos];
+ it.key = &table.keys[pos];
+
+ return it;
+ }
+ }
+ }
+
+ return it;
+ }
+
+ OAHashMap(uint32_t p_initial_capacity = INITIAL_NUM_ELEMENTS) {
+
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+
+ if (p_initial_capacity <= INITIAL_NUM_ELEMENTS) {
+ table.data = local_data;
+ table.keys = local_keys;
+ table.hashes = local_hashes;
+ table.flags = local_flags;
+
+ zeromem(table.flags, INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0));
+
+ table.capacity = INITIAL_NUM_ELEMENTS;
+ elements = 0;
+ } else
+#endif
+ {
+ table.data = memnew_arr(TData, p_initial_capacity);
+ table.keys = memnew_arr(TKey, p_initial_capacity);
+ table.hashes = memnew_arr(uint32_t, p_initial_capacity);
+ table.flags = memnew_arr(uint8_t, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0));
+
+ zeromem(table.flags, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0));
+
+ table.capacity = p_initial_capacity;
+ elements = 0;
+ }
+
+ is_rehashing = false;
+ rehash_position = 0;
+ }
+
+ ~OAHashMap() {
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ if (table.capacity <= INITIAL_NUM_ELEMENTS) {
+ return; // Everything is local, so no cleanup :P
+ }
+#endif
+ if (is_rehashing) {
+
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ if (old_table.data == local_data) {
+ // Everything is local, so no cleanup :P
+ } else
+#endif
+ {
+ memdelete_arr(old_table.data);
+ memdelete_arr(old_table.keys);
+ memdelete_arr(old_table.hashes);
+ memdelete_arr(old_table.flags);
+ }
+ }
+
+ memdelete_arr(table.data);
+ memdelete_arr(table.keys);
+ memdelete_arr(table.hashes);
+ memdelete_arr(table.flags);
+ }
+};
+
+#endif
diff --git a/core/object.cpp b/core/object.cpp
index 23e32a214a..b1770f1d7a 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -277,32 +277,32 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name)
: name(p_name),
flags(METHOD_FLAG_NORMAL),
+ return_val(p_ret),
id(0) {
- return_val = p_ret;
}
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
}
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
}
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
arguments.push_back(p_param3);
@@ -310,9 +310,9 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
arguments.push_back(p_param3);
@@ -321,9 +321,9 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
arguments.push_back(p_param3);
diff --git a/core/object.h b/core/object.h
index 644e2b8270..3070439138 100644
--- a/core/object.h
+++ b/core/object.h
@@ -148,6 +148,7 @@ struct PropertyInfo {
hint(PROPERTY_HINT_NONE),
usage(PROPERTY_USAGE_DEFAULT) {
}
+
PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = StringName())
: type(p_type),
name(p_name),
@@ -161,12 +162,12 @@ struct PropertyInfo {
class_name = p_class_name;
}
}
+
PropertyInfo(const StringName &p_class_name)
: type(Variant::OBJECT),
+ class_name(p_class_name),
hint(PROPERTY_HINT_NONE),
usage(PROPERTY_USAGE_DEFAULT) {
-
- class_name = p_class_name;
}
bool operator<(const PropertyInfo &p_info) const {
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index f24d6d16ca..1437e7cdfc 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -292,7 +292,7 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
return full;
}
-Error DirAccess::copy(String p_from, String p_to) {
+Error DirAccess::copy(String p_from, String p_to, int chmod_flags) {
//printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
Error err;
@@ -329,6 +329,11 @@ Error DirAccess::copy(String p_from, String p_to) {
fdst->store_8(fsrc->get_8());
}
+ if (err == OK && chmod_flags != -1) {
+ fdst->close();
+ err = fdst->_chmod(p_to, chmod_flags);
+ }
+
memdelete(fsrc);
memdelete(fdst);
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 6ad8b4c49b..7fa3ce5cf1 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -89,7 +89,7 @@ public:
static bool exists(String p_dir);
virtual size_t get_space_left() = 0;
- virtual Error copy(String p_from, String p_to);
+ virtual Error copy(String p_from, String p_to, int chmod_flags = -1);
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 8393f0530b..63692cb290 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -140,6 +140,8 @@ public:
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
+ virtual Error _chmod(const String &p_path, int p_mod) { return FAILED; }
+
static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static FileAccess *create_for_path(const String &p_path);
static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files.
@@ -174,6 +176,7 @@ struct FileAccessRef {
operator bool() const { return f != NULL; }
FileAccess *f;
+ operator FileAccess *() { return f; }
FileAccessRef(FileAccess *fa) { f = fa; }
~FileAccessRef() {
if (f) memdelete(f);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 764f7fe6e6..437ce01a5e 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -485,7 +485,7 @@ bool OS::is_vsync_enabled() const {
return true;
}
-PowerState OS::get_power_state() {
+OS::PowerState OS::get_power_state() {
return POWERSTATE_UNKNOWN;
}
int OS::get_power_seconds_left() {
diff --git a/core/os/os.h b/core/os/os.h
index 258708eea2..2fc87e44a0 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -34,7 +34,6 @@
#include "image.h"
#include "list.h"
#include "os/main_loop.h"
-#include "power.h"
#include "ustring.h"
#include "vector.h"
#include <stdarg.h>
@@ -65,6 +64,14 @@ class OS {
public:
typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection);
+ enum PowerState {
+ POWERSTATE_UNKNOWN, /**< cannot determine power status */
+ POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
+ POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
+ POWERSTATE_CHARGING, /**< Plugged in, charging battery */
+ POWERSTATE_CHARGED /**< Plugged in, battery charged */
+ };
+
enum RenderThreadMode {
RENDER_THREAD_UNSAFE,
@@ -279,6 +286,9 @@ public:
bool is_stdout_verbose() const;
+ virtual void disable_crash_handler() {}
+ virtual bool is_disable_crash_handler() const { return false; }
+
enum CursorShape {
CURSOR_ARROW,
CURSOR_IBEAM,
@@ -410,7 +420,7 @@ public:
virtual void set_use_vsync(bool p_enable);
virtual bool is_vsync_enabled() const;
- virtual PowerState get_power_state();
+ virtual OS::PowerState get_power_state();
virtual int get_power_seconds_left();
virtual int get_power_percent_left();
@@ -428,6 +438,6 @@ public:
virtual ~OS();
};
-VARIANT_ENUM_CAST(PowerState);
+VARIANT_ENUM_CAST(OS::PowerState);
#endif
diff --git a/core/os/power.h b/core/os/power.h
deleted file mode 100644
index 59a091012e..0000000000
--- a/core/os/power.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*************************************************************************/
-/* power.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 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. */
-/*************************************************************************/
-
-#ifndef CORE_OS_POWER_H_
-#define CORE_OS_POWER_H_
-
-typedef enum {
- POWERSTATE_UNKNOWN, /**< cannot determine power status */
- POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
- POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
- POWERSTATE_CHARGING, /**< Plugged in, charging battery */
- POWERSTATE_CHARGED /**< Plugged in, battery charged */
-} PowerState;
-
-#endif /* CORE_OS_POWER_H_ */
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index 23e4961138..7ea0d563a6 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -270,6 +270,11 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
_load_settings("res://override.cfg");
+#ifdef DEBUG_ENABLED
+ } else {
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Couldn't open project over network");
+#endif
}
return OK;
@@ -287,6 +292,12 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
//load override from location of the main pack
_load_settings(p_main_pack.get_base_dir().plus_file("override.cfg"));
+#ifdef DEBUG_ENABLED
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Successfully loaded " + p_main_pack + "/project.godot or project.binary");
+ } else {
+ print_line("Couldn't load/find " + p_main_pack + "/project.godot or project.binary");
+#endif
}
return OK;
@@ -294,12 +305,43 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
//Attempt with execname.pck
if (exec_path != "") {
+ bool found = false;
+
+ // get our filename without our path (note, using exec_path.get_file before get_basename anymore because not all file systems have dots in their file names!)
+ String filebase_name = exec_path.get_file().get_basename();
- if (_load_resource_pack(exec_path.get_basename() + ".pck")) {
+ // try to open at the location of executable
+ String datapack_name = exec_path.get_base_dir().plus_file(filebase_name) + ".pck";
+ if (_load_resource_pack(datapack_name)) {
+ found = true;
+ } else {
+#ifdef DEBUG_ENABLED
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Couldn't open " + datapack_name);
+#endif
+ datapack_name = filebase_name + ".pck";
+ if (_load_resource_pack(datapack_name)) {
+ found = true;
+#ifdef DEBUG_ENABLED
+ } else {
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Couldn't open " + datapack_name);
+#endif
+ }
+ }
+ // if we opened our package, try and load our project...
+ if (found) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
- //load override from location of executable
+ // load override from location of executable
_load_settings(exec_path.get_base_dir().plus_file("override.cfg"));
+
+#ifdef DEBUG_ENABLED
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Successfully loaded " + datapack_name + "/project.godot or project.binary");
+ } else {
+ print_line("Couldn't load/find " + datapack_name + "/project.godot or project.binary");
+#endif
}
return OK;
@@ -320,6 +362,12 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (_load_settings("res://project.godot") == OK || _load_settings_binary("res://project.binary") == OK) {
_load_settings("res://override.cfg");
+#ifdef DEBUG_ENABLED
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Successfully loaded " + resource_path + "/project.godot or project.binary");
+ } else {
+ print_line("Couldn't load/find " + resource_path + "/project.godot or project.binary");
+#endif
}
return OK;
@@ -345,6 +393,12 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
candidate = current_dir;
found = true;
break;
+#ifdef DEBUG_ENABLED
+ // when debug version of godot is used, provide some feedback to the developer
+ print_line("Successfully loaded " + current_dir + "/project.godot or project.binary");
+ } else {
+ print_line("Couldn't load/find " + current_dir + "/project.godot or project.binary");
+#endif
}
d->change_dir("..");
diff --git a/core/reference.cpp b/core/reference.cpp
index bb70628cbe..7f93922d22 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -33,7 +33,7 @@
bool Reference::init_ref() {
- if (refcount.ref()) {
+ if (reference()) {
// this may fail in the scenario of two threads assigning the pointer for the FIRST TIME
// at the same time, which is never likely to happen (would be crazy to do)
@@ -41,7 +41,7 @@ bool Reference::init_ref() {
if (refcount_init.get() > 0) {
refcount_init.unref();
- refcount.unref(); // first referencing is already 1, so compensate for the ref above
+ unreference(); // first referencing is already 1, so compensate for the ref above
}
return true;
@@ -62,13 +62,16 @@ int Reference::reference_get_count() const {
return refcount.get();
}
-void Reference::reference() {
+bool Reference::reference() {
+ bool success = refcount.ref();
- refcount.ref();
- if (get_script_instance()) {
+ if (success && get_script_instance()) {
get_script_instance()->refcount_incremented();
}
+
+ return success;
}
+
bool Reference::unreference() {
bool die = refcount.unref();
diff --git a/core/reference.h b/core/reference.h
index ca3ae60418..bafc164276 100644
--- a/core/reference.h
+++ b/core/reference.h
@@ -51,7 +51,7 @@ protected:
public:
_FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() < 1; }
bool init_ref();
- void reference();
+ bool reference(); // returns false if refcount is at zero and didn't get increased
bool unreference();
int reference_get_count() const;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 27c31127a4..0e34a3eea5 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -68,6 +68,7 @@ static _Engine *_engine = NULL;
static _ClassDB *_classdb = NULL;
static _Marshalls *_marshalls = NULL;
static TranslationLoaderPO *resource_format_po = NULL;
+static _JSON *_json = NULL;
static IP *ip = NULL;
@@ -162,6 +163,8 @@ void register_core_types() {
ClassDB::register_class<AStar>();
ClassDB::register_class<EncodedObjectAsID>();
+ ClassDB::register_class<JSONParseResult>();
+
ip = IP::create();
_geometry = memnew(_Geometry);
@@ -172,6 +175,7 @@ void register_core_types() {
_engine = memnew(_Engine);
_classdb = memnew(_ClassDB);
_marshalls = memnew(_Marshalls);
+ _json = memnew(_JSON);
}
void register_core_settings() {
@@ -193,6 +197,7 @@ void register_core_singletons() {
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("TranslationServer", TranslationServer::get_singleton()));
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Input", Input::get_singleton()));
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("InputMap", InputMap::get_singleton()));
+ ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JSON", _JSON::get_singleton()));
}
void unregister_core_types() {
@@ -203,6 +208,7 @@ void unregister_core_types() {
memdelete(_engine);
memdelete(_classdb);
memdelete(_marshalls);
+ memdelete(_json);
memdelete(_geometry);
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 8875732b8e..f0097054b1 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -125,6 +125,9 @@ void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_
packet_peer_stream->put_var(p_name);
int len = 0;
Error err = encode_variant(p_variable, NULL, len);
+ if (err != OK)
+ ERR_PRINT("Failed to encode variant");
+
if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
packet_peer_stream->put_var(Variant());
} else {
diff --git a/core/script_language.cpp b/core/script_language.cpp
index bde80a30bc..5ead91f26e 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -184,7 +184,6 @@ void ScriptInstance::call_multilevel(const StringName &p_method, VARIANT_ARG_DEC
argc++;
}
- Variant::CallError error;
call_multilevel(p_method, argptr, argc);
}
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 4760047959..27fc73ec63 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -503,6 +503,10 @@ void UndoRedo::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history);
ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name);
ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version);
+ ClassDB::bind_method(D_METHOD("set_max_steps", "max_steps"), &UndoRedo::set_max_steps);
+ ClassDB::bind_method(D_METHOD("get_max_steps"), &UndoRedo::get_max_steps);
+ ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
+ ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
BIND_ENUM_CONSTANT(MERGE_DISABLE);
BIND_ENUM_CONSTANT(MERGE_ENDS);
diff --git a/core/variant.cpp b/core/variant.cpp
index 74f6b6a711..52bdd4e22d 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -903,9 +903,6 @@ bool Variant::is_one() const {
void Variant::reference(const Variant &p_variant) {
- if (this == &p_variant)
- return;
-
clear();
type = p_variant.type;
@@ -924,17 +921,14 @@ void Variant::reference(const Variant &p_variant) {
case INT: {
_data._int = p_variant._data._int;
-
} break;
case REAL: {
_data._real = p_variant._data._real;
-
} break;
case STRING: {
memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem)));
-
} break;
// math types
@@ -942,33 +936,24 @@ void Variant::reference(const Variant &p_variant) {
case VECTOR2: {
memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem)));
-
} break;
case RECT2: {
memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem)));
-
} break;
case TRANSFORM2D: {
_data._transform2d = memnew(Transform2D(*p_variant._data._transform2d));
-
} break;
case VECTOR3: {
memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem)));
-
} break;
case PLANE: {
memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem)));
-
} break;
- /*
- case QUAT: {
-
- } break;*/
case RECT3: {
_data._rect3 = memnew(Rect3(*p_variant._data._rect3));
@@ -986,7 +971,6 @@ void Variant::reference(const Variant &p_variant) {
case TRANSFORM: {
_data._transform = memnew(Transform(*p_variant._data._transform));
-
} break;
// misc types
@@ -1058,6 +1042,7 @@ void Variant::reference(const Variant &p_variant) {
default: {}
}
}
+
void Variant::zero() {
switch (type) {
case NIL: break;
@@ -1073,6 +1058,7 @@ void Variant::zero() {
default: this->clear(); break;
}
}
+
void Variant::clear() {
switch (type) {
@@ -1092,12 +1078,10 @@ void Variant::clear() {
case TRANSFORM2D: {
memdelete(_data._transform2d);
-
} break;
case RECT3: {
memdelete(_data._rect3);
-
} break;
case BASIS: {
@@ -1106,14 +1090,12 @@ void Variant::clear() {
case TRANSFORM: {
memdelete(_data._transform);
-
} break;
// misc types
case NODE_PATH: {
reinterpret_cast<NodePath *>(_data._mem)->~NodePath();
-
} break;
case OBJECT: {
@@ -1127,48 +1109,39 @@ void Variant::clear() {
case DICTIONARY: {
reinterpret_cast<Dictionary *>(_data._mem)->~Dictionary();
-
} break;
case ARRAY: {
reinterpret_cast<Array *>(_data._mem)->~Array();
-
} break;
// arrays
case POOL_BYTE_ARRAY: {
reinterpret_cast<PoolVector<uint8_t> *>(_data._mem)->~PoolVector<uint8_t>();
-
} break;
case POOL_INT_ARRAY: {
reinterpret_cast<PoolVector<int> *>(_data._mem)->~PoolVector<int>();
-
} break;
case POOL_REAL_ARRAY: {
reinterpret_cast<PoolVector<real_t> *>(_data._mem)->~PoolVector<real_t>();
-
} break;
case POOL_STRING_ARRAY: {
reinterpret_cast<PoolVector<String> *>(_data._mem)->~PoolVector<String>();
-
} break;
case POOL_VECTOR2_ARRAY: {
reinterpret_cast<PoolVector<Vector2> *>(_data._mem)->~PoolVector<Vector2>();
-
} break;
case POOL_VECTOR3_ARRAY: {
reinterpret_cast<PoolVector<Vector3> *>(_data._mem)->~PoolVector<Vector3>();
-
} break;
case POOL_COLOR_ARRAY: {
reinterpret_cast<PoolVector<Color> *>(_data._mem)->~PoolVector<Color>();
-
} break;
default: {} /* not needed */
}
@@ -2259,8 +2232,8 @@ Variant::Variant(const RefPtr &p_resource) {
type = OBJECT;
memnew_placement(_data._mem, ObjData);
- REF ref = p_resource;
- _get_obj().obj = ref.ptr();
+ REF *ref = reinterpret_cast<REF *>(p_resource.get_data());
+ _get_obj().obj = ref->ptr();
_get_obj().ref = p_resource;
}
@@ -2496,7 +2469,135 @@ Variant::Variant(const Vector<Color> &p_array) {
void Variant::operator=(const Variant &p_variant) {
- reference(p_variant);
+ if (this == &p_variant)
+ return;
+
+ if (type != p_variant.type) {
+ reference(p_variant);
+ return;
+ }
+
+ switch (p_variant.type) {
+ case NIL: {
+
+ // none
+ } break;
+
+ // atomic types
+ case BOOL: {
+
+ _data._bool = p_variant._data._bool;
+ } break;
+ case INT: {
+
+ _data._int = p_variant._data._int;
+ } break;
+ case REAL: {
+
+ _data._real = p_variant._data._real;
+ } break;
+ case STRING: {
+
+ *reinterpret_cast<String *>(_data._mem) = *reinterpret_cast<const String *>(p_variant._data._mem);
+ } break;
+
+ // math types
+
+ case VECTOR2: {
+
+ *reinterpret_cast<Vector2 *>(_data._mem) = *reinterpret_cast<const Vector2 *>(p_variant._data._mem);
+ } break;
+ case RECT2: {
+
+ *reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem);
+ } break;
+ case TRANSFORM2D: {
+
+ *_data._transform2d = *(p_variant._data._transform2d);
+ } break;
+ case VECTOR3: {
+
+ *reinterpret_cast<Vector3 *>(_data._mem) = *reinterpret_cast<const Vector3 *>(p_variant._data._mem);
+ } break;
+ case PLANE: {
+
+ *reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem);
+ } break;
+
+ case RECT3: {
+
+ *_data._rect3 = *(p_variant._data._rect3);
+ } break;
+ case QUAT: {
+
+ *reinterpret_cast<Quat *>(_data._mem) = *reinterpret_cast<const Quat *>(p_variant._data._mem);
+ } break;
+ case BASIS: {
+
+ *_data._basis = *(p_variant._data._basis);
+ } break;
+ case TRANSFORM: {
+
+ *_data._transform = *(p_variant._data._transform);
+ } break;
+
+ // misc types
+ 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);
+ } break;
+ case OBJECT: {
+
+ *reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj();
+ } break;
+ case NODE_PATH: {
+
+ *reinterpret_cast<NodePath *>(_data._mem) = *reinterpret_cast<const NodePath *>(p_variant._data._mem);
+ } break;
+ case DICTIONARY: {
+
+ *reinterpret_cast<Dictionary *>(_data._mem) = *reinterpret_cast<const Dictionary *>(p_variant._data._mem);
+ } break;
+ case ARRAY: {
+
+ *reinterpret_cast<Array *>(_data._mem) = *reinterpret_cast<const Array *>(p_variant._data._mem);
+ } break;
+
+ // arrays
+ case POOL_BYTE_ARRAY: {
+
+ *reinterpret_cast<PoolVector<uint8_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<uint8_t> *>(p_variant._data._mem);
+ } break;
+ case POOL_INT_ARRAY: {
+
+ *reinterpret_cast<PoolVector<int> *>(_data._mem) = *reinterpret_cast<const PoolVector<int> *>(p_variant._data._mem);
+ } break;
+ case POOL_REAL_ARRAY: {
+
+ *reinterpret_cast<PoolVector<real_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<real_t> *>(p_variant._data._mem);
+ } break;
+ case POOL_STRING_ARRAY: {
+
+ *reinterpret_cast<PoolVector<String> *>(_data._mem) = *reinterpret_cast<const PoolVector<String> *>(p_variant._data._mem);
+ } break;
+ case POOL_VECTOR2_ARRAY: {
+
+ *reinterpret_cast<PoolVector<Vector2> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector2> *>(p_variant._data._mem);
+ } break;
+ case POOL_VECTOR3_ARRAY: {
+
+ *reinterpret_cast<PoolVector<Vector3> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector3> *>(p_variant._data._mem);
+ } break;
+ case POOL_COLOR_ARRAY: {
+
+ *reinterpret_cast<PoolVector<Color> *>(_data._mem) = *reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem);
+ } break;
+ default: {}
+ }
}
Variant::Variant(const IP_Address &p_address) {
diff --git a/core/variant.h b/core/variant.h
index c44608ebfa..5ea540a63f 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -43,7 +43,6 @@
#include "math_2d.h"
#include "matrix3.h"
#include "node_path.h"
-#include "os/power.h"
#include "plane.h"
#include "quat.h"
#include "rect3.h"
@@ -71,6 +70,7 @@ typedef PoolVector<Color> PoolColorArray;
class Variant {
public:
+ // If this changes the table in variant_op must be updated
enum Type {
NIL,
@@ -289,6 +289,7 @@ public:
Variant(const IP_Address &p_address);
+ // If this changes the table in variant_op must be updated
enum Operator {
//comparation
@@ -300,7 +301,7 @@ public:
OP_GREATER_EQUAL,
//mathematic
OP_ADD,
- OP_SUBSTRACT,
+ OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_NEGATE,
@@ -389,7 +390,7 @@ public:
uint32_t hash() const;
bool hash_compare(const Variant &p_variant) const;
- bool booleanize(bool &valid) const;
+ bool booleanize() const;
void static_assign(const Variant &p_variant);
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index dc1c24d234..19d9b0297f 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -428,8 +428,8 @@ struct _VariantCall {
VCALL_LOCALMEM2R(Quat, slerpni);
VCALL_LOCALMEM4R(Quat, cubic_slerp);
- VCALL_LOCALMEM0R(Color, to_32);
- VCALL_LOCALMEM0R(Color, to_ARGB32);
+ VCALL_LOCALMEM0R(Color, to_rgba32);
+ VCALL_LOCALMEM0R(Color, to_argb32);
VCALL_LOCALMEM0R(Color, gray);
VCALL_LOCALMEM0R(Color, inverted);
VCALL_LOCALMEM0R(Color, contrasted);
@@ -1524,8 +1524,8 @@ void register_variant_methods() {
ADDFUNC2(QUAT, QUAT, Quat, slerpni, QUAT, "b", REAL, "t", varray());
ADDFUNC4(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", REAL, "t", varray());
- ADDFUNC0(COLOR, INT, Color, to_32, varray());
- ADDFUNC0(COLOR, INT, Color, to_ARGB32, varray());
+ ADDFUNC0(COLOR, INT, Color, to_rgba32, varray());
+ ADDFUNC0(COLOR, INT, Color, to_argb32, varray());
ADDFUNC0(COLOR, REAL, Color, gray, varray());
ADDFUNC0(COLOR, COLOR, Color, inverted, varray());
ADDFUNC0(COLOR, COLOR, Color, contrasted, varray());
@@ -1623,7 +1623,7 @@ void register_variant_methods() {
ADDFUNC2(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_STRING_ARRAY, NIL, PoolStringArray, invert, varray());
- ADDFUNC1(POOL_STRING_ARRAY, STRING, PoolStringArray, join, STRING, "string", varray());
+ ADDFUNC1(POOL_STRING_ARRAY, STRING, PoolStringArray, join, STRING, "delimiter", varray());
ADDFUNC0(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray());
ADDFUNC2(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, set, INT, "idx", VECTOR2, "vector2", varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index b6e114b853..5d47936679 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -33,49 +33,123 @@
#include "object.h"
#include "script_language.h"
-Variant::operator bool() const {
-
- bool b;
- return booleanize(b);
+#define CASE_TYPE_ALL(PREFIX, OP) \
+ CASE_TYPE(PREFIX, OP, INT) \
+ CASE_TYPE_ALL_BUT_INT(PREFIX, OP)
+
+#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \
+ CASE_TYPE(PREFIX, OP, NIL) \
+ CASE_TYPE(PREFIX, OP, BOOL) \
+ CASE_TYPE(PREFIX, OP, REAL) \
+ CASE_TYPE(PREFIX, OP, STRING) \
+ CASE_TYPE(PREFIX, OP, VECTOR2) \
+ CASE_TYPE(PREFIX, OP, RECT2) \
+ CASE_TYPE(PREFIX, OP, VECTOR3) \
+ CASE_TYPE(PREFIX, OP, TRANSFORM2D) \
+ CASE_TYPE(PREFIX, OP, PLANE) \
+ CASE_TYPE(PREFIX, OP, QUAT) \
+ CASE_TYPE(PREFIX, OP, RECT3) \
+ CASE_TYPE(PREFIX, OP, BASIS) \
+ CASE_TYPE(PREFIX, OP, TRANSFORM) \
+ CASE_TYPE(PREFIX, OP, COLOR) \
+ CASE_TYPE(PREFIX, OP, NODE_PATH) \
+ CASE_TYPE(PREFIX, OP, _RID) \
+ CASE_TYPE(PREFIX, OP, OBJECT) \
+ CASE_TYPE(PREFIX, OP, DICTIONARY) \
+ CASE_TYPE(PREFIX, OP, ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_BYTE_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_INT_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_REAL_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_STRING_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_COLOR_ARRAY)
+
+#ifdef __GNUC__
+#define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE
+
+/* clang-format off */
+#define TYPES(PREFIX, OP) { \
+ TYPE(PREFIX, OP, NIL), \
+ TYPE(PREFIX, OP, BOOL), \
+ TYPE(PREFIX, OP, INT), \
+ TYPE(PREFIX, OP, REAL), \
+ TYPE(PREFIX, OP, STRING), \
+ TYPE(PREFIX, OP, VECTOR2), \
+ TYPE(PREFIX, OP, RECT2), \
+ TYPE(PREFIX, OP, VECTOR3), \
+ TYPE(PREFIX, OP, TRANSFORM2D), \
+ TYPE(PREFIX, OP, PLANE), \
+ TYPE(PREFIX, OP, QUAT), \
+ TYPE(PREFIX, OP, RECT3), \
+ TYPE(PREFIX, OP, BASIS), \
+ TYPE(PREFIX, OP, TRANSFORM), \
+ TYPE(PREFIX, OP, COLOR), \
+ TYPE(PREFIX, OP, NODE_PATH), \
+ TYPE(PREFIX, OP, _RID), \
+ TYPE(PREFIX, OP, OBJECT), \
+ TYPE(PREFIX, OP, DICTIONARY), \
+ TYPE(PREFIX, OP, ARRAY), \
+ TYPE(PREFIX, OP, POOL_BYTE_ARRAY), \
+ TYPE(PREFIX, OP, POOL_INT_ARRAY), \
+ TYPE(PREFIX, OP, POOL_REAL_ARRAY), \
+ TYPE(PREFIX, OP, POOL_STRING_ARRAY), \
+ TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY), \
+ TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY), \
+ TYPE(PREFIX, OP, POOL_COLOR_ARRAY), \
+}
+/* clang-format on */
+
+#define CASES(PREFIX) static void *switch_table_##PREFIX[25][27] = { \
+ TYPES(PREFIX, OP_EQUAL), \
+ TYPES(PREFIX, OP_NOT_EQUAL), \
+ TYPES(PREFIX, OP_LESS), \
+ TYPES(PREFIX, OP_LESS_EQUAL), \
+ TYPES(PREFIX, OP_GREATER), \
+ TYPES(PREFIX, OP_GREATER_EQUAL), \
+ TYPES(PREFIX, OP_ADD), \
+ TYPES(PREFIX, OP_SUBTRACT), \
+ TYPES(PREFIX, OP_MULTIPLY), \
+ TYPES(PREFIX, OP_DIVIDE), \
+ TYPES(PREFIX, OP_NEGATE), \
+ TYPES(PREFIX, OP_POSITIVE), \
+ TYPES(PREFIX, OP_MODULE), \
+ TYPES(PREFIX, OP_STRING_CONCAT), \
+ TYPES(PREFIX, OP_SHIFT_LEFT), \
+ TYPES(PREFIX, OP_SHIFT_RIGHT), \
+ TYPES(PREFIX, OP_BIT_AND), \
+ TYPES(PREFIX, OP_BIT_OR), \
+ TYPES(PREFIX, OP_BIT_XOR), \
+ TYPES(PREFIX, OP_BIT_NEGATE), \
+ TYPES(PREFIX, OP_AND), \
+ TYPES(PREFIX, OP_OR), \
+ TYPES(PREFIX, OP_XOR), \
+ TYPES(PREFIX, OP_NOT), \
+ TYPES(PREFIX, OP_IN), \
}
-bool Variant::booleanize(bool &r_valid) const {
+#define SWITCH(PREFIX, op, val) goto *switch_table_##PREFIX[op][val];
+#define SWITCH_OP(PREFIX, OP, val)
+#define CASE_TYPE(PREFIX, OP, TYPE) PREFIX##_##OP##_##TYPE:
+
+#else
+#define CASES(PREFIX)
+#define SWITCH(PREFIX, op, val) switch (op)
+#define SWITCH_OP(PREFIX, OP, val) \
+ case OP: \
+ switch (val)
+#define CASE_TYPE(PREFIX, OP, TYPE) case TYPE:
+#endif
- r_valid = true;
- switch (type) {
- case NIL: return false;
- case BOOL: return _data._bool;
- case INT: return _data._int;
- case REAL: return _data._real;
- case STRING: return (*reinterpret_cast<const String *>(_data._mem)) != "";
- case VECTOR2:
- case RECT2:
- case TRANSFORM2D:
- case VECTOR3:
- case PLANE:
- case RECT3:
- case QUAT:
- case BASIS:
- case TRANSFORM:
- case COLOR:
- case _RID: return (*reinterpret_cast<const RID *>(_data._mem)).is_valid();
- case OBJECT: return _get_obj().obj;
- case NODE_PATH: return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath();
- case DICTIONARY:
- case ARRAY:
- case POOL_BYTE_ARRAY:
- case POOL_INT_ARRAY:
- case POOL_REAL_ARRAY:
- case POOL_STRING_ARRAY:
- case POOL_VECTOR2_ARRAY:
- case POOL_VECTOR3_ARRAY:
- case POOL_COLOR_ARRAY:
- r_valid = false;
- return false;
- default: {}
- }
+Variant::operator bool() const {
- return false;
+ return booleanize();
+}
+
+// We consider all unitialized or empty types to be false based on the type's
+// zeroiness.
+bool Variant::booleanize() const {
+ return !is_zero();
}
#define _RETURN(m_what) \
@@ -84,10 +158,15 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
}
-#define DEFAULT_OP_NUM(m_op, m_name, m_type) \
- case m_name: { \
+#define _RETURN_FAIL \
+ { \
+ r_valid = false; \
+ return; \
+ }
+
+#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
switch (p_b.type) { \
- case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \
case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \
case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \
default: {} \
@@ -96,22 +175,55 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
};
-#define DEFAULT_OP_NUM_NEG(m_name, m_type) \
- case m_name: { \
- \
- _RETURN(-p_a._data.m_type); \
+#ifdef DEBUG_ENABLED
+#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ switch (p_b.type) { \
+ case INT: { \
+ if (p_b._data._int == 0) { \
+ r_valid = false; \
+ _RETURN("Division By Zero"); \
+ } \
+ _RETURN(p_a._data.m_type / p_b._data._int); \
+ } \
+ case REAL: { \
+ if (p_b._data._real == 0) { \
+ r_valid = false; \
+ _RETURN("Division By Zero"); \
+ } \
+ _RETURN(p_a._data.m_type / p_b._data._real); \
+ } \
+ default: {} \
+ } \
+ r_valid = false; \
+ return; \
+ };
+#else
+#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ switch (p_b.type) { \
+ case INT: _RETURN(p_a._data.m_type / p_b._data._int); \
+ case REAL: _RETURN(p_a._data.m_type / p_b._data._real); \
+ default: {} \
+ } \
+ r_valid = false; \
+ return; \
};
+#endif
-#define DEFAULT_OP_NUM_POS(m_name, m_type) \
- case m_name: { \
- \
- _RETURN(p_a._data.m_type); \
+#define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ _RETURN(-p_a._data.m_type); \
};
-#define DEFAULT_OP_NUM_VEC(m_op, m_name, m_type) \
- case m_name: { \
+#define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ _RETURN(p_a._data.m_type); \
+ };
+
+#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
switch (p_b.type) { \
- case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \
case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \
case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \
case VECTOR2: _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
@@ -122,8 +234,19 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
};
-#define DEFAULT_OP_STR(m_op, m_name, m_type) \
- case m_name: { \
+#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ switch (p_b.type) { \
+ case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \
+ case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \
+ default: {} \
+ } \
+ r_valid = false; \
+ return; \
+ };
+
+#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
switch (p_b.type) { \
case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
@@ -133,31 +256,36 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
};
-#define DEFAULT_OP_LOCALMEM(m_op, m_name, m_type) \
- case m_name: { \
- switch (p_b.type) { \
- case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
- default: {} \
- } \
- r_valid = false; \
- return; \
- }
+#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const m_type *>(p_a._data._mem)); \
+ r_valid = false; \
+ return; \
+ };
+
+#define DEFAULT_OP_LOCALMEM(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
+ r_valid = false; \
+ return; \
+ };
-#define DEFAULT_OP_LOCALMEM_NEG(m_name, m_type) \
- case m_name: { \
+#define DEFAULT_OP_LOCALMEM_NEG(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
_RETURN(-*reinterpret_cast<const m_type *>(p_a._data._mem)); \
}
-#define DEFAULT_OP_LOCALMEM_POS(m_name, m_type) \
- case m_name: { \
- _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \
+#define DEFAULT_OP_LOCALMEM_POS(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \
}
-#define DEFAULT_OP_LOCALMEM_NUM(m_op, m_name, m_type) \
- case m_name: { \
+#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
switch (p_b.type) { \
case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
- case BOOL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._bool); \
case INT: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \
case REAL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._real); \
default: {} \
@@ -176,50 +304,51 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
}
-#define DEFAULT_OP_PTRREF(m_op, m_name, m_sub) \
- case m_name: { \
- switch (p_b.type) { \
- case m_name: _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define DEFAULT_OP_PTRREF(m_prefix, m_op_name, m_name, m_op, m_sub) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \
+ r_valid = false; \
+ return; \
}
-#define DEFAULT_OP_ARRAY_EQ(m_name, m_type) \
- DEFAULT_OP_ARRAY_OP(m_name, m_type, !=, !=, true, false, false)
-
-#define DEFAULT_OP_ARRAY_LT(m_name, m_type) \
- DEFAULT_OP_ARRAY_OP(m_name, m_type, <, !=, false, a_len < array_b.size(), true)
-
-#define DEFAULT_OP_ARRAY_OP(m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
- case m_name: { \
- if (p_a.type != p_b.type) { \
- r_valid = false; \
- return; \
- } \
- const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \
- const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \
- \
- int a_len = array_a.size(); \
- if (a_len m_opa array_b.size()) { \
- _RETURN(m_ret_s); \
- } else { \
- \
- PoolVector<m_type>::Read ra = array_a.read(); \
- PoolVector<m_type>::Read rb = array_b.read(); \
- \
- for (int i = 0; i < a_len; i++) { \
- if (ra[i] m_opb rb[i]) \
- _RETURN(m_ret_f); \
- } \
- \
- _RETURN(m_ret_def); \
- } \
+#define DEFAULT_OP_ARRAY_EQ(m_prefix, m_op_name, m_name, m_type) \
+ DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, !=, !=, true, false, false)
+
+#define DEFAULT_OP_ARRAY_LT(m_prefix, m_op_name, m_name, m_type) \
+ DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, <, !=, false, a_len < array_b.size(), true)
+
+#define DEFAULT_OP_ARRAY_GT(m_prefix, m_op_name, m_name, m_type) \
+ DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, >, !=, false, a_len < array_b.size(), true)
+
+#define DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_a.type != p_b.type) { \
+ r_valid = false; \
+ return; \
+ } \
+ const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \
+ const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \
+ \
+ int a_len = array_a.size(); \
+ if (a_len m_opa array_b.size()) { \
+ _RETURN(m_ret_s); \
+ } else { \
+ \
+ PoolVector<m_type>::Read ra = array_a.read(); \
+ PoolVector<m_type>::Read rb = array_b.read(); \
+ \
+ for (int i = 0; i < a_len; i++) { \
+ if (ra[i] m_opb rb[i]) \
+ _RETURN(m_ret_f); \
+ } \
+ \
+ _RETURN(m_ret_def); \
+ } \
}
-#define DEFAULT_OP_ARRAY_ADD(m_name, m_type) \
- case m_name: { \
+#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
if (p_a.type != p_b.type) { \
r_valid = false; \
_RETURN(NIL); \
@@ -231,595 +360,646 @@ bool Variant::booleanize(bool &r_valid) const {
_RETURN(sum); \
}
-#define DEFAULT_OP_FAIL(m_name) \
- case m_name: { \
- r_valid = false; \
- return; \
- }
-
-void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid) {
+void Variant::evaluate(const Operator &p_op, const Variant &p_a,
+ const Variant &p_b, Variant &r_ret, bool &r_valid) {
+ CASES(math);
r_valid = true;
- switch (p_op) {
+ SWITCH(math, p_op, p_a.type) {
+ SWITCH_OP(math, OP_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_EQUAL, NIL) {
+ if (p_b.type == NIL) _RETURN(true);
+ if (p_b.type == OBJECT)
+ _RETURN(p_b._get_obj().obj == NULL);
+ _RETURN_FAIL;
+ }
- case OP_EQUAL: {
+ CASE_TYPE(math, OP_EQUAL, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
+ _RETURN(p_a._data._bool == p_b._data._bool);
+ }
- if ((int(p_a.type) * int(p_b.type)) == 0) {
- //null case is an exception, one of both is null
- if (p_a.type == p_b.type) //null against null is true
- _RETURN(true);
- //only against object is allowed
- if (p_a.type == Variant::OBJECT) {
+ CASE_TYPE(math, OP_EQUAL, OBJECT) {
+ if (p_b.type == OBJECT)
+ _RETURN((p_a._get_obj().obj == p_b._get_obj().obj));
+ if (p_b.type == NIL)
_RETURN(p_a._get_obj().obj == NULL);
- } else if (p_b.type == Variant::OBJECT) {
- _RETURN(p_b._get_obj().obj == NULL);
- }
- //otherwise, always false
- _RETURN(false);
+ _RETURN_FAIL;
}
- switch (p_a.type) {
+ CASE_TYPE(math, OP_EQUAL, DICTIONARY) {
+ if (p_b.type != DICTIONARY)
+ _RETURN_FAIL;
+
+ const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
+ const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
+
+ _RETURN(*arr_a == *arr_b);
+ }
- case NIL: {
+ CASE_TYPE(math, OP_EQUAL, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- _RETURN(p_b.type == NIL || (p_b.type == Variant::OBJECT && !p_b._get_obj().obj));
- } break;
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- DEFAULT_OP_NUM(==, BOOL, _bool);
- DEFAULT_OP_NUM(==, INT, _int);
- DEFAULT_OP_NUM(==, REAL, _real);
- DEFAULT_OP_STR(==, STRING, String);
- DEFAULT_OP_LOCALMEM(==, VECTOR2, Vector2);
- DEFAULT_OP_LOCALMEM(==, RECT2, Rect2);
- DEFAULT_OP_PTRREF(==, TRANSFORM2D, _transform2d);
- DEFAULT_OP_LOCALMEM(==, VECTOR3, Vector3);
- DEFAULT_OP_LOCALMEM(==, PLANE, Plane);
- DEFAULT_OP_LOCALMEM(==, QUAT, Quat);
- DEFAULT_OP_PTRREF(==, RECT3, _rect3);
- DEFAULT_OP_PTRREF(==, BASIS, _basis);
- DEFAULT_OP_PTRREF(==, TRANSFORM, _transform);
+ int l = arr_a->size();
+ if (arr_b->size() != l)
+ _RETURN(false);
+ for (int i = 0; i < l; i++) {
+ if (!((*arr_a)[i] == (*arr_b)[i])) {
+ _RETURN(false);
+ }
+ }
- DEFAULT_OP_LOCALMEM(==, COLOR, Color);
- DEFAULT_OP_STR(==, NODE_PATH, NodePath);
- DEFAULT_OP_LOCALMEM(==, _RID, RID);
- case OBJECT: {
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM(math, OP_EQUAL, INT, ==, _int);
+ DEFAULT_OP_NUM(math, OP_EQUAL, REAL, ==, _real);
+ DEFAULT_OP_STR(math, OP_EQUAL, STRING, ==, String);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, VECTOR2, ==, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, RECT2, ==, Rect2);
+ DEFAULT_OP_PTRREF(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, VECTOR3, ==, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, PLANE, ==, Plane);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, QUAT, ==, Quat);
+ DEFAULT_OP_PTRREF(math, OP_EQUAL, RECT3, ==, _rect3);
+ DEFAULT_OP_PTRREF(math, OP_EQUAL, BASIS, ==, _basis);
+ DEFAULT_OP_PTRREF(math, OP_EQUAL, TRANSFORM, ==, _transform);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, COLOR, ==, Color);
+ DEFAULT_OP_STR(math, OP_EQUAL, NODE_PATH, ==, NodePath);
+ DEFAULT_OP_LOCALMEM(math, OP_EQUAL, _RID, ==, RID);
+
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR2_ARRAY, Vector2);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_COLOR_ARRAY, Color);
+ }
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj == p_b._get_obj().obj));
- if (p_b.type == NIL)
- _RETURN(!p_a._get_obj().obj);
- } break;
+ SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_NOT_EQUAL, NIL) {
+ if (p_b.type == NIL) _RETURN(false);
+ if (p_b.type == OBJECT)
+ _RETURN(p_b._get_obj().obj != NULL);
+ _RETURN_FAIL;
+ }
- case DICTIONARY: {
+ CASE_TYPE(math, OP_NOT_EQUAL, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
+ _RETURN(p_a._data._bool != p_b._data._bool);
+ }
- if (p_b.type != DICTIONARY)
- _RETURN(false);
+ CASE_TYPE(math, OP_NOT_EQUAL, OBJECT) {
+ if (p_b.type == OBJECT)
+ _RETURN((p_a._get_obj().obj != p_b._get_obj().obj));
+ if (p_b.type == NIL)
+ _RETURN(p_a._get_obj().obj != NULL);
+ _RETURN_FAIL;
+ }
- const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
- const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
+ CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) {
+ if (p_b.type != DICTIONARY)
+ _RETURN_FAIL;
- _RETURN(*arr_a == *arr_b);
+ const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
+ const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
- } break;
- case ARRAY: {
+ _RETURN((*arr_a == *arr_b) == false);
+ }
- if (p_b.type != ARRAY)
- _RETURN(false);
+ CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
- const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- int l = arr_a->size();
- if (arr_b->size() != l)
+ int l = arr_a->size();
+ if (arr_b->size() != l)
+ _RETURN(true);
+ for (int i = 0; i < l; i++) {
+ if (((*arr_a)[i] == (*arr_b)[i])) {
_RETURN(false);
- for (int i = 0; i < l; i++) {
- if (!((*arr_a)[i] == (*arr_b)[i])) {
- _RETURN(false);
- }
}
+ }
- _RETURN(true);
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM(math, OP_NOT_EQUAL, INT, !=, _int);
+ DEFAULT_OP_NUM(math, OP_NOT_EQUAL, REAL, !=, _real);
+ DEFAULT_OP_STR(math, OP_NOT_EQUAL, STRING, !=, String);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, RECT2, !=, Rect2);
+ DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, PLANE, !=, Plane);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, QUAT, !=, Quat);
+ DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, RECT3, !=, _rect3);
+ DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, BASIS, !=, _basis);
+ DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, COLOR, !=, Color);
+ DEFAULT_OP_STR(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath);
+ DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, _RID, !=, RID);
+
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_NOT_EQUAL, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
+ SWITCH_OP(math, OP_LESS, p_a.type) {
+ CASE_TYPE(math, OP_LESS, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
- DEFAULT_OP_ARRAY_EQ(POOL_BYTE_ARRAY, uint8_t);
- DEFAULT_OP_ARRAY_EQ(POOL_INT_ARRAY, int);
- DEFAULT_OP_ARRAY_EQ(POOL_REAL_ARRAY, real_t);
- DEFAULT_OP_ARRAY_EQ(POOL_STRING_ARRAY, String);
- DEFAULT_OP_ARRAY_EQ(POOL_VECTOR2_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_EQ(POOL_VECTOR3_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_EQ(POOL_COLOR_ARRAY, Color);
+ if (p_a._data._bool == p_b._data._bool)
+ _RETURN(false);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ if (p_a._data._bool && !p_b._data._bool)
+ _RETURN(false);
- } break;
+ _RETURN(true);
}
- } break;
- case OP_NOT_EQUAL: {
- Variant res;
- evaluate(OP_EQUAL, p_a, p_b, res, r_valid);
- if (!r_valid)
- return;
- if (res.type == BOOL)
- res._data._bool = !res._data._bool;
- _RETURN(res);
-
- } break;
- case OP_LESS: {
-
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(<, BOOL, _bool);
- DEFAULT_OP_NUM(<, INT, _int);
- DEFAULT_OP_NUM(<, REAL, _real);
- DEFAULT_OP_STR(<, STRING, String);
- DEFAULT_OP_LOCALMEM(<, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(<, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_FAIL(QUAT);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_LOCALMEM(<, _RID, RID);
- case OBJECT: {
-
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
- } break;
- DEFAULT_OP_FAIL(DICTIONARY);
- case ARRAY: {
-
- if (p_b.type != ARRAY)
- _RETURN(false);
- const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
- const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
-
- int l = arr_a->size();
- if (arr_b->size() < l)
- _RETURN(false);
- for (int i = 0; i < l; i++) {
- if (!((*arr_a)[i] < (*arr_b)[i])) {
- _RETURN(true);
- }
- }
+ CASE_TYPE(math, OP_LESS, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
+ }
- _RETURN(false);
+ CASE_TYPE(math, OP_LESS, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- } break;
- DEFAULT_OP_ARRAY_LT(POOL_BYTE_ARRAY, uint8_t);
- DEFAULT_OP_ARRAY_LT(POOL_INT_ARRAY, int);
- DEFAULT_OP_ARRAY_LT(POOL_REAL_ARRAY, real_t);
- DEFAULT_OP_ARRAY_LT(POOL_STRING_ARRAY, String);
- DEFAULT_OP_ARRAY_LT(POOL_VECTOR2_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_LT(POOL_VECTOR3_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_LT(POOL_COLOR_ARRAY, Color);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- } break;
- }
-
- } break;
- case OP_LESS_EQUAL: {
-
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(<=, BOOL, _bool);
- DEFAULT_OP_NUM(<=, INT, _int);
- DEFAULT_OP_NUM(<=, REAL, _real);
- DEFAULT_OP_STR(<=, STRING, String);
- DEFAULT_OP_LOCALMEM(<=, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(<=, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_FAIL(QUAT);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_LOCALMEM(<=, _RID, RID);
- case OBJECT: {
-
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj));
- } break;
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ int l = arr_a->size();
+ if (arr_b->size() < l)
+ _RETURN(false);
+ for (int i = 0; i < l; i++) {
+ if (!((*arr_a)[i] < (*arr_b)[i])) {
+ _RETURN(true);
+ }
+ }
- } break;
+ _RETURN(false);
}
- } break;
- case OP_GREATER: {
+ DEFAULT_OP_NUM(math, OP_LESS, INT, <, _int);
+ DEFAULT_OP_NUM(math, OP_LESS, REAL, <, _real);
+ DEFAULT_OP_STR(math, OP_LESS, STRING, <, String);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR2_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_COLOR_ARRAY, Color);
+
+ CASE_TYPE(math, OP_LESS, NIL)
+ CASE_TYPE(math, OP_LESS, RECT2)
+ CASE_TYPE(math, OP_LESS, TRANSFORM2D)
+ CASE_TYPE(math, OP_LESS, PLANE)
+ CASE_TYPE(math, OP_LESS, QUAT)
+ CASE_TYPE(math, OP_LESS, RECT3)
+ CASE_TYPE(math, OP_LESS, BASIS)
+ CASE_TYPE(math, OP_LESS, TRANSFORM)
+ CASE_TYPE(math, OP_LESS, COLOR)
+ CASE_TYPE(math, OP_LESS, NODE_PATH)
+ CASE_TYPE(math, OP_LESS, DICTIONARY)
+ _RETURN_FAIL;
+ }
- Variant res;
- evaluate(OP_LESS, p_b, p_a, res, r_valid);
- if (!r_valid)
- return;
- _RETURN(res);
+ SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj));
+ }
+
+ DEFAULT_OP_NUM(math, OP_LESS_EQUAL, INT, <=, _int);
+ DEFAULT_OP_NUM(math, OP_LESS_EQUAL, REAL, <=, _real);
+ DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID);
+
+ CASE_TYPE(math, OP_LESS_EQUAL, NIL)
+ CASE_TYPE(math, OP_LESS_EQUAL, BOOL)
+ CASE_TYPE(math, OP_LESS_EQUAL, RECT2)
+ CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D)
+ CASE_TYPE(math, OP_LESS_EQUAL, PLANE)
+ CASE_TYPE(math, OP_LESS_EQUAL, QUAT)
+ CASE_TYPE(math, OP_LESS_EQUAL, RECT3)
+ CASE_TYPE(math, OP_LESS_EQUAL, BASIS)
+ CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM)
+ CASE_TYPE(math, OP_LESS_EQUAL, COLOR)
+ CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH)
+ CASE_TYPE(math, OP_LESS_EQUAL, DICTIONARY)
+ CASE_TYPE(math, OP_LESS_EQUAL, ARRAY)
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
- case OP_GREATER_EQUAL: {
+ SWITCH_OP(math, OP_GREATER, p_a.type) {
+ CASE_TYPE(math, OP_GREATER, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
- Variant res;
- evaluate(OP_LESS_EQUAL, p_b, p_a, res, r_valid);
- if (!r_valid)
- return;
- _RETURN(res);
- } break;
- //mathematic
- case OP_ADD: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(+, BOOL, _bool);
- DEFAULT_OP_NUM(+, INT, _int);
- DEFAULT_OP_NUM(+, REAL, _real);
- DEFAULT_OP_STR(+, STRING, String);
- DEFAULT_OP_LOCALMEM(+, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(+, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_LOCALMEM(+, QUAT, Quat);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
-
- case ARRAY: {
- if (p_a.type != p_b.type) {
- r_valid = false;
- return;
- }
- const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem);
- const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem);
- Array sum;
- int asize = array_a.size();
- int bsize = array_b.size();
- sum.resize(asize + bsize);
- for (int i = 0; i < asize; i++)
- sum[i] = array_a[i];
- for (int i = 0; i < bsize; i++)
- sum[i + asize] = array_b[i];
- _RETURN(sum);
- }
- DEFAULT_OP_ARRAY_ADD(POOL_BYTE_ARRAY, uint8_t);
- DEFAULT_OP_ARRAY_ADD(POOL_INT_ARRAY, int);
- DEFAULT_OP_ARRAY_ADD(POOL_REAL_ARRAY, real_t);
- DEFAULT_OP_ARRAY_ADD(POOL_STRING_ARRAY, String);
- DEFAULT_OP_ARRAY_ADD(POOL_VECTOR2_ARRAY, Vector2);
- DEFAULT_OP_ARRAY_ADD(POOL_VECTOR3_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_ADD(POOL_COLOR_ARRAY, Color);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ if (p_a._data._bool == p_b._data._bool)
+ _RETURN(false);
- } break;
- }
- } break;
- case OP_SUBSTRACT: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(-, BOOL, _bool);
- DEFAULT_OP_NUM(-, INT, _int);
- DEFAULT_OP_NUM(-, REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM(-, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(-, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_LOCALMEM(-, QUAT, Quat);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ if (!p_a._data._bool && p_b._data._bool)
+ _RETURN(false);
- } break;
+ _RETURN(true);
}
- } break;
- case OP_MULTIPLY: {
- switch (p_a.type) {
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(*, BOOL, _bool);
- DEFAULT_OP_NUM_VEC(*, INT, _int);
- DEFAULT_OP_NUM_VEC(*, REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM_NUM(*, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- case TRANSFORM2D: {
+ CASE_TYPE(math, OP_GREATER, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj > p_b._get_obj().obj));
+ }
- if (p_b.type == TRANSFORM2D) {
- _RETURN(*p_a._data._transform2d * *p_b._data._transform2d);
- };
- if (p_b.type == VECTOR2) {
- _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem));
- };
- r_valid = false;
- return;
- } break;
- DEFAULT_OP_LOCALMEM_NUM(*, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- case QUAT: {
-
- switch (p_b.type) {
- case VECTOR3: {
-
- _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem));
- } break;
- case QUAT: {
-
- _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem));
- } break;
- case REAL: {
- _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real);
- } break;
- default: {}
- };
- r_valid = false;
- return;
- } break;
- DEFAULT_OP_FAIL(RECT3);
- case BASIS: {
+ CASE_TYPE(math, OP_GREATER, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- switch (p_b.type) {
- case VECTOR3: {
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem));
- };
- case BASIS: {
+ int l = arr_a->size();
+ if (arr_b->size() > l)
+ _RETURN(false);
+ for (int i = 0; i < l; i++) {
+ if (((*arr_a)[i] < (*arr_b)[i])) {
+ _RETURN(false);
+ }
+ }
- _RETURN(*p_a._data._basis * *p_b._data._basis);
- };
- default: {}
- };
- r_valid = false;
- return;
- } break;
- case TRANSFORM: {
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM(math, OP_GREATER, INT, >, _int);
+ DEFAULT_OP_NUM(math, OP_GREATER, REAL, >, _real);
+ DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR2_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_COLOR_ARRAY, Color);
+
+ CASE_TYPE(math, OP_GREATER, NIL)
+ CASE_TYPE(math, OP_GREATER, RECT2)
+ CASE_TYPE(math, OP_GREATER, TRANSFORM2D)
+ CASE_TYPE(math, OP_GREATER, PLANE)
+ CASE_TYPE(math, OP_GREATER, QUAT)
+ CASE_TYPE(math, OP_GREATER, RECT3)
+ CASE_TYPE(math, OP_GREATER, BASIS)
+ CASE_TYPE(math, OP_GREATER, TRANSFORM)
+ CASE_TYPE(math, OP_GREATER, COLOR)
+ CASE_TYPE(math, OP_GREATER, NODE_PATH)
+ CASE_TYPE(math, OP_GREATER, DICTIONARY)
+ _RETURN_FAIL;
+ }
- switch (p_b.type) {
- case VECTOR3: {
+ SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj >= p_b._get_obj().obj));
+ }
+
+ DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, INT, >=, _int);
+ DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, REAL, >=, _real);
+ DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID);
+
+ CASE_TYPE(math, OP_GREATER_EQUAL, NIL)
+ CASE_TYPE(math, OP_GREATER_EQUAL, BOOL)
+ CASE_TYPE(math, OP_GREATER_EQUAL, RECT2)
+ CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D)
+ CASE_TYPE(math, OP_GREATER_EQUAL, PLANE)
+ CASE_TYPE(math, OP_GREATER_EQUAL, QUAT)
+ CASE_TYPE(math, OP_GREATER_EQUAL, RECT3)
+ CASE_TYPE(math, OP_GREATER_EQUAL, BASIS)
+ CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM)
+ CASE_TYPE(math, OP_GREATER_EQUAL, COLOR)
+ CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH)
+ CASE_TYPE(math, OP_GREATER_EQUAL, DICTIONARY)
+ CASE_TYPE(math, OP_GREATER_EQUAL, ARRAY)
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
- };
- case TRANSFORM: {
+ SWITCH_OP(math, OP_ADD, p_a.type) {
+ CASE_TYPE(math, OP_ADD, ARRAY) {
+ if (p_a.type != p_b.type)
+ _RETURN_FAIL;
+
+ const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem);
+ Array sum;
+ int asize = array_a.size();
+ int bsize = array_b.size();
+ sum.resize(asize + bsize);
+ for (int i = 0; i < asize; i++)
+ sum[i] = array_a[i];
+ for (int i = 0; i < bsize; i++)
+ sum[i + asize] = array_b[i];
+ _RETURN(sum);
+ }
+
+ DEFAULT_OP_NUM(math, OP_ADD, INT, +, _int);
+ DEFAULT_OP_NUM(math, OP_ADD, REAL, +, _real);
+ DEFAULT_OP_STR(math, OP_ADD, STRING, +, String);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color);
+
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR2_ARRAY, Vector2);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_COLOR_ARRAY, Color);
+
+ CASE_TYPE(math, OP_ADD, NIL)
+ CASE_TYPE(math, OP_ADD, BOOL)
+ CASE_TYPE(math, OP_ADD, RECT2)
+ CASE_TYPE(math, OP_ADD, TRANSFORM2D)
+ CASE_TYPE(math, OP_ADD, PLANE)
+ CASE_TYPE(math, OP_ADD, RECT3)
+ CASE_TYPE(math, OP_ADD, BASIS)
+ CASE_TYPE(math, OP_ADD, TRANSFORM)
+ CASE_TYPE(math, OP_ADD, NODE_PATH)
+ CASE_TYPE(math, OP_ADD, _RID)
+ CASE_TYPE(math, OP_ADD, OBJECT)
+ CASE_TYPE(math, OP_ADD, DICTIONARY)
+ _RETURN_FAIL;
+ }
- _RETURN(*p_a._data._transform * *p_b._data._transform);
- };
- default: {}
- };
- r_valid = false;
- return;
- } break;
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ SWITCH_OP(math, OP_SUBTRACT, p_a.type) {
+ DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int);
+ DEFAULT_OP_NUM(math, OP_SUBTRACT, REAL, -, _real);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color);
+
+ CASE_TYPE(math, OP_SUBTRACT, NIL)
+ CASE_TYPE(math, OP_SUBTRACT, BOOL)
+ CASE_TYPE(math, OP_SUBTRACT, STRING)
+ CASE_TYPE(math, OP_SUBTRACT, RECT2)
+ CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D)
+ CASE_TYPE(math, OP_SUBTRACT, PLANE)
+ CASE_TYPE(math, OP_SUBTRACT, RECT3)
+ CASE_TYPE(math, OP_SUBTRACT, BASIS)
+ CASE_TYPE(math, OP_SUBTRACT, TRANSFORM)
+ CASE_TYPE(math, OP_SUBTRACT, NODE_PATH)
+ CASE_TYPE(math, OP_SUBTRACT, _RID)
+ CASE_TYPE(math, OP_SUBTRACT, OBJECT)
+ CASE_TYPE(math, OP_SUBTRACT, DICTIONARY)
+ CASE_TYPE(math, OP_SUBTRACT, ARRAY)
+ CASE_TYPE(math, OP_SUBTRACT, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
+ SWITCH_OP(math, OP_MULTIPLY, p_a.type) {
+ CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) {
+ switch (p_b.type) {
+ case TRANSFORM2D: {
+ _RETURN(*p_a._data._transform2d * *p_b._data._transform2d);
+ }
+ case VECTOR2: {
+ _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem));
+ }
+ default: _RETURN_FAIL;
+ }
}
- } break;
- case OP_DIVIDE: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(/, BOOL, _bool);
- case INT: {
- switch (p_b.type) {
- case BOOL: {
- int64_t b = p_b._data._bool;
- if (b == 0) {
- r_valid = false;
- _RETURN("Division By False");
- }
- _RETURN(p_a._data._int / b);
-
- } break;
- case INT: {
- int64_t b = p_b._data._int;
- if (b == 0) {
+ CASE_TYPE(math, OP_MULTIPLY, QUAT) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem));
+ }
+ case QUAT: {
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem));
+ }
+ case REAL: {
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real);
+ }
+ default: _RETURN_FAIL;
+ }
+ }
- r_valid = false;
- _RETURN("Division By Zero");
- }
- _RETURN(p_a._data._int / b);
+ CASE_TYPE(math, OP_MULTIPLY, BASIS) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem));
+ }
+ case BASIS: {
+ _RETURN(*p_a._data._basis * *p_b._data._basis);
+ }
+ default: _RETURN_FAIL;
+ }
+ }
- } break;
- case REAL: _RETURN(p_a._data._int / p_b._data._real);
- default: {}
+ CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
}
- r_valid = false;
- return;
- };
- DEFAULT_OP_NUM(/, REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM_NUM(/, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM_NUM(/, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- case QUAT: {
- if (p_b.type != REAL) {
- r_valid = false;
- return;
+ case TRANSFORM: {
+ _RETURN(*p_a._data._transform * *p_b._data._transform);
}
- _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real);
- } break;
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ default: _RETURN_FAIL;
+ }
+ }
- } break;
- }
-
- } break;
- case OP_POSITIVE: {
- // Simple case when user defines variable as +value.
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
- DEFAULT_OP_NUM_POS(BOOL, _bool);
- DEFAULT_OP_NUM_POS(INT, _int);
- DEFAULT_OP_NUM_POS(REAL, _real);
- DEFAULT_OP_LOCALMEM_POS(VECTOR3, Vector3);
- DEFAULT_OP_LOCALMEM_POS(PLANE, Plane);
- DEFAULT_OP_LOCALMEM_POS(QUAT, Quat);
- DEFAULT_OP_LOCALMEM_POS(VECTOR2, Vector2);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int);
+ DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, REAL, *, _real);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color);
+
+ CASE_TYPE(math, OP_MULTIPLY, NIL)
+ CASE_TYPE(math, OP_MULTIPLY, BOOL)
+ CASE_TYPE(math, OP_MULTIPLY, STRING)
+ CASE_TYPE(math, OP_MULTIPLY, RECT2)
+ CASE_TYPE(math, OP_MULTIPLY, PLANE)
+ CASE_TYPE(math, OP_MULTIPLY, RECT3)
+ CASE_TYPE(math, OP_MULTIPLY, NODE_PATH)
+ CASE_TYPE(math, OP_MULTIPLY, _RID)
+ CASE_TYPE(math, OP_MULTIPLY, OBJECT)
+ CASE_TYPE(math, OP_MULTIPLY, DICTIONARY)
+ CASE_TYPE(math, OP_MULTIPLY, ARRAY)
+ CASE_TYPE(math, OP_MULTIPLY, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
- }
- } break;
- case OP_NEGATE: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM_NEG(BOOL, _bool);
- DEFAULT_OP_NUM_NEG(INT, _int);
- DEFAULT_OP_NUM_NEG(REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM_NEG(VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM_NEG(VECTOR3, Vector3);
- DEFAULT_OP_LOCALMEM_NEG(PLANE, Plane);
- DEFAULT_OP_LOCALMEM_NEG(QUAT, Quat);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
+ SWITCH_OP(math, OP_DIVIDE, p_a.type) {
+ CASE_TYPE(math, OP_DIVIDE, QUAT) {
+ if (p_b.type != REAL)
+ _RETURN_FAIL;
+#ifdef DEBUG_ENABLED
+ if (p_b._data._real == 0) {
r_valid = false;
- return;
+ _RETURN("Division By Zero");
+ }
+#endif
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real);
+ }
+
+ DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int);
+ DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, REAL, _real);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color);
+
+ CASE_TYPE(math, OP_DIVIDE, NIL)
+ CASE_TYPE(math, OP_DIVIDE, BOOL)
+ CASE_TYPE(math, OP_DIVIDE, STRING)
+ CASE_TYPE(math, OP_DIVIDE, RECT2)
+ CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D)
+ CASE_TYPE(math, OP_DIVIDE, PLANE)
+ CASE_TYPE(math, OP_DIVIDE, RECT3)
+ CASE_TYPE(math, OP_DIVIDE, BASIS)
+ CASE_TYPE(math, OP_DIVIDE, TRANSFORM)
+ CASE_TYPE(math, OP_DIVIDE, NODE_PATH)
+ CASE_TYPE(math, OP_DIVIDE, _RID)
+ CASE_TYPE(math, OP_DIVIDE, OBJECT)
+ CASE_TYPE(math, OP_DIVIDE, DICTIONARY)
+ CASE_TYPE(math, OP_DIVIDE, ARRAY)
+ CASE_TYPE(math, OP_DIVIDE, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
- }
- } break;
- case OP_MODULE: {
- if (p_a.type == INT && p_b.type == INT) {
+ SWITCH_OP(math, OP_POSITIVE, p_a.type) {
+ DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int);
+ DEFAULT_OP_NUM_POS(math, OP_POSITIVE, REAL, _real);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2);
+
+ CASE_TYPE(math, OP_POSITIVE, NIL)
+ CASE_TYPE(math, OP_POSITIVE, BOOL)
+ CASE_TYPE(math, OP_POSITIVE, STRING)
+ CASE_TYPE(math, OP_POSITIVE, RECT2)
+ CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D)
+ CASE_TYPE(math, OP_POSITIVE, RECT3)
+ CASE_TYPE(math, OP_POSITIVE, BASIS)
+ CASE_TYPE(math, OP_POSITIVE, TRANSFORM)
+ CASE_TYPE(math, OP_POSITIVE, COLOR)
+ CASE_TYPE(math, OP_POSITIVE, NODE_PATH)
+ CASE_TYPE(math, OP_POSITIVE, _RID)
+ CASE_TYPE(math, OP_POSITIVE, OBJECT)
+ CASE_TYPE(math, OP_POSITIVE, DICTIONARY)
+ CASE_TYPE(math, OP_POSITIVE, ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_BYTE_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_INT_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_REAL_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_STRING_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR2_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR3_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_COLOR_ARRAY)
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_NEGATE, p_a.type) {
+ DEFAULT_OP_NUM_NEG(math, OP_NEGATE, INT, _int);
+ DEFAULT_OP_NUM_NEG(math, OP_NEGATE, REAL, _real);
+
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color);
+
+ CASE_TYPE(math, OP_NEGATE, NIL)
+ CASE_TYPE(math, OP_NEGATE, BOOL)
+ CASE_TYPE(math, OP_NEGATE, STRING)
+ CASE_TYPE(math, OP_NEGATE, RECT2)
+ CASE_TYPE(math, OP_NEGATE, TRANSFORM2D)
+ CASE_TYPE(math, OP_NEGATE, RECT3)
+ CASE_TYPE(math, OP_NEGATE, BASIS)
+ CASE_TYPE(math, OP_NEGATE, TRANSFORM)
+ CASE_TYPE(math, OP_NEGATE, NODE_PATH)
+ CASE_TYPE(math, OP_NEGATE, _RID)
+ CASE_TYPE(math, OP_NEGATE, OBJECT)
+ CASE_TYPE(math, OP_NEGATE, DICTIONARY)
+ CASE_TYPE(math, OP_NEGATE, ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_BYTE_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_INT_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_REAL_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_STRING_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_VECTOR2_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_VECTOR3_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_COLOR_ARRAY)
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_MODULE, p_a.type) {
+ CASE_TYPE(math, OP_MODULE, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
#ifdef DEBUG_ENABLED
if (p_b._data._int == 0) {
r_valid = false;
@@ -827,8 +1007,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
}
#endif
_RETURN(p_a._data._int % p_b._data._int);
+ }
- } else if (p_a.type == STRING) {
+ CASE_TYPE(math, OP_MODULE, STRING) {
const String *format = reinterpret_cast<const String *>(p_a._data._mem);
String result;
@@ -847,119 +1028,143 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
_RETURN(result);
}
- r_valid = false;
- return;
+ CASE_TYPE(math, OP_MODULE, NIL)
+ CASE_TYPE(math, OP_MODULE, BOOL)
+ CASE_TYPE(math, OP_MODULE, REAL)
+ CASE_TYPE(math, OP_MODULE, VECTOR2)
+ CASE_TYPE(math, OP_MODULE, RECT2)
+ CASE_TYPE(math, OP_MODULE, VECTOR3)
+ CASE_TYPE(math, OP_MODULE, TRANSFORM2D)
+ CASE_TYPE(math, OP_MODULE, PLANE)
+ CASE_TYPE(math, OP_MODULE, QUAT)
+ CASE_TYPE(math, OP_MODULE, RECT3)
+ CASE_TYPE(math, OP_MODULE, BASIS)
+ CASE_TYPE(math, OP_MODULE, TRANSFORM)
+ CASE_TYPE(math, OP_MODULE, COLOR)
+ CASE_TYPE(math, OP_MODULE, NODE_PATH)
+ CASE_TYPE(math, OP_MODULE, _RID)
+ CASE_TYPE(math, OP_MODULE, OBJECT)
+ CASE_TYPE(math, OP_MODULE, DICTIONARY)
+ CASE_TYPE(math, OP_MODULE, ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_BYTE_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_INT_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_REAL_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_STRING_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_VECTOR2_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_VECTOR3_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_COLOR_ARRAY)
+ _RETURN_FAIL;
+ }
- } break;
- case OP_STRING_CONCAT: {
+ SWITCH_OP(math, OP_STRING_CONCAT, p_a.type) {
+ CASE_TYPE_ALL(math, OP_STRING_CONCAT)
_RETURN(p_a.operator String() + p_b.operator String());
- } break;
- //bitwise
- case OP_SHIFT_LEFT: {
- if (p_a.type == INT && p_b.type == INT)
+ }
+
+ SWITCH_OP(math, OP_SHIFT_LEFT, p_a.type) {
+ CASE_TYPE(math, OP_SHIFT_LEFT, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int << p_b._data._int);
+ }
- r_valid = false;
- return;
+ CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT)
+ _RETURN_FAIL;
+ }
- } break;
- case OP_SHIFT_RIGHT: {
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_SHIFT_RIGHT, p_a.type) {
+ CASE_TYPE(math, OP_SHIFT_RIGHT, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int >> p_b._data._int);
+ }
- r_valid = false;
- return;
+ CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT)
+ _RETURN_FAIL;
+ }
- } break;
- case OP_BIT_AND: {
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_BIT_AND, p_a.type) {
+ CASE_TYPE(math, OP_BIT_AND, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int & p_b._data._int);
+ }
- r_valid = false;
- return;
-
- } break;
- case OP_BIT_OR: {
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND)
+ _RETURN_FAIL;
+ }
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_BIT_OR, p_a.type) {
+ CASE_TYPE(math, OP_BIT_OR, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int | p_b._data._int);
+ }
- r_valid = false;
- return;
-
- } break;
- case OP_BIT_XOR: {
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR)
+ _RETURN_FAIL;
+ }
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_BIT_XOR, p_a.type) {
+ CASE_TYPE(math, OP_BIT_XOR, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int ^ p_b._data._int);
+ }
- r_valid = false;
- return;
-
- } break;
- case OP_BIT_NEGATE: {
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR)
+ _RETURN_FAIL;
+ }
- if (p_a.type == INT)
+ SWITCH_OP(math, OP_BIT_NEGATE, p_a.type) {
+ CASE_TYPE(math, OP_BIT_NEGATE, INT) {
_RETURN(~p_a._data._int);
+ }
- r_valid = false;
- return;
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE)
+ _RETURN_FAIL;
+ }
- } break;
- //logic
- case OP_AND: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- bool r = p_b.booleanize(r_valid);
- if (!r_valid)
- return;
+ SWITCH_OP(math, OP_AND, p_a.type) {
+ CASE_TYPE_ALL(math, OP_AND) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
- _RETURN(l && r);
- } break;
- case OP_OR: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- bool r = p_b.booleanize(r_valid);
- if (!r_valid)
- return;
+ _RETURN(l && r);
+ }
+ }
- _RETURN(l || r);
+ SWITCH_OP(math, OP_OR, p_a.type) {
+ CASE_TYPE_ALL(math, OP_OR) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
- } break;
- case OP_XOR: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- bool r = p_b.booleanize(r_valid);
- if (!r_valid)
- return;
+ _RETURN(l || r);
+ }
+ }
- _RETURN((l || r) && !(l && r));
- } break;
- case OP_NOT: {
+ SWITCH_OP(math, OP_XOR, p_a.type) {
+ CASE_TYPE_ALL(math, OP_XOR) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- _RETURN(!l);
+ _RETURN((l || r) && !(l && r));
+ }
+ }
- } break;
- case OP_IN: {
+ SWITCH_OP(math, OP_NOT, p_a.type) {
+ CASE_TYPE_ALL(math, OP_NOT) {
+ bool l = p_a.booleanize();
+ _RETURN(!l);
+ }
+ }
+ SWITCH_OP(math, OP_IN, p_a.type) {
+ CASE_TYPE_ALL(math, OP_IN)
_RETURN(p_b.in(p_a, &r_valid));
-
- } break;
- case OP_MAX: {
-
- r_valid = false;
- ERR_FAIL();
}
}
-
- r_valid = false;
}
void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) {
@@ -1512,7 +1717,8 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
DEFAULT_OP_DVECTOR_SET(POOL_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) // 25
DEFAULT_OP_DVECTOR_SET(POOL_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3)
DEFAULT_OP_DVECTOR_SET(POOL_COLOR_ARRAY, Color, p_value.type != Variant::COLOR)
- default: return;
+ default:
+ return;
}
}
@@ -1885,7 +2091,8 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
DEFAULT_OP_DVECTOR_GET(POOL_VECTOR2_ARRAY, Vector2) // 25
DEFAULT_OP_DVECTOR_GET(POOL_VECTOR3_ARRAY, Vector3)
DEFAULT_OP_DVECTOR_GET(POOL_COLOR_ARRAY, Color)
- default: return Variant();
+ default:
+ return Variant();
}
return Variant();
@@ -2374,7 +2581,8 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
return true;
} break;
- default: {}
+ default: {
+ }
}
valid = false;
@@ -2401,7 +2609,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
return true;
} break;
case VECTOR2: {
- int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y;
+ int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y;
int64_t idx = r_iter;
idx++;
@@ -2793,7 +3001,9 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst)
r_dst = Color(r, g, b, a);
}
return;
- default: { r_dst = c < 0.5 ? a : b; }
+ default: {
+ r_dst = c < 0.5 ? a : b;
+ }
return;
}
}