summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/SCsub21
-rw-r--r--core/array.cpp26
-rw-r--r--core/array.h8
-rw-r--r--core/bind/core_bind.cpp129
-rw-r--r--core/bind/core_bind.h66
-rw-r--r--core/class_db.cpp36
-rw-r--r--core/class_db.h9
-rw-r--r--core/color.cpp145
-rw-r--r--core/color.h25
-rw-r--r--core/command_queue_mt.h46
-rw-r--r--core/core_string_names.cpp23
-rw-r--r--core/core_string_names.h27
-rw-r--r--core/engine.cpp4
-rw-r--r--core/engine.h8
-rw-r--r--core/error_list.h2
-rw-r--r--core/error_macros.cpp10
-rw-r--r--core/error_macros.h56
-rw-r--r--core/event_queue.cpp157
-rw-r--r--core/global_constants.cpp152
-rw-r--r--core/hash_map.h123
-rw-r--r--core/hashfuncs.h34
-rw-r--r--core/helper/math_fieldwise.cpp2
-rw-r--r--core/helper/math_fieldwise.h2
-rw-r--r--core/image.cpp18
-rw-r--r--core/io/SCsub1
-rw-r--r--core/io/compression.cpp22
-rw-r--r--core/io/compression.h2
-rw-r--r--core/io/file_access_buffered.cpp2
-rw-r--r--core/io/file_access_buffered.h2
-rw-r--r--core/io/file_access_buffered_fa.h5
-rw-r--r--core/io/file_access_compressed.cpp11
-rw-r--r--core/io/file_access_compressed.h13
-rw-r--r--core/io/file_access_encrypted.cpp18
-rw-r--r--core/io/file_access_encrypted.h5
-rw-r--r--core/io/file_access_memory.cpp6
-rw-r--r--core/io/file_access_memory.h3
-rw-r--r--core/io/file_access_network.cpp12
-rw-r--r--core/io/file_access_network.h7
-rw-r--r--core/io/file_access_pack.cpp17
-rw-r--r--core/io/file_access_pack.h3
-rw-r--r--core/io/file_access_zip.cpp11
-rw-r--r--core/io/file_access_zip.h3
-rw-r--r--core/io/http_client.cpp14
-rw-r--r--core/io/http_client.h2
-rw-r--r--core/io/logger.cpp266
-rw-r--r--core/io/logger.h107
-rw-r--r--core/io/marshalls.cpp13
-rw-r--r--core/io/pck_packer.cpp8
-rw-r--r--core/io/resource_format_binary.cpp89
-rw-r--r--core/io/resource_format_binary.h4
-rw-r--r--core/io/resource_import.cpp57
-rw-r--r--core/io/resource_import.h10
-rw-r--r--core/io/resource_loader.cpp134
-rw-r--r--core/io/resource_loader.h10
-rw-r--r--core/io/stream_peer.cpp9
-rw-r--r--core/io/stream_peer.h2
-rw-r--r--core/io/translation_loader_po.cpp4
-rw-r--r--core/io/xml_parser.cpp4
-rw-r--r--core/io/xml_parser.h2
-rw-r--r--core/io/zip_io.h4
-rw-r--r--core/list.h52
-rw-r--r--core/make_binders.py2
-rw-r--r--core/map.h319
-rw-r--r--core/math/a_star.cpp79
-rw-r--r--core/math/a_star.h13
-rw-r--r--core/math/camera_matrix.cpp87
-rw-r--r--core/math/camera_matrix.h1
-rw-r--r--core/math/face3.cpp2
-rw-r--r--core/math/math_funcs.h57
-rw-r--r--core/math/matrix3.cpp96
-rw-r--r--core/math/matrix3.h22
-rw-r--r--core/math/quick_hull.cpp10
-rw-r--r--core/math/transform.cpp12
-rw-r--r--core/math/triangle_mesh.cpp2
-rw-r--r--core/method_bind.h3
-rw-r--r--core/oa_hash_map.h593
-rw-r--r--core/object.cpp61
-rw-r--r--core/object.h29
-rw-r--r--core/ordered_hash_map.h315
-rw-r--r--core/os/dir_access.cpp9
-rw-r--r--core/os/dir_access.h2
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/file_access.h6
-rw-r--r--core/os/input.cpp3
-rw-r--r--core/os/input.h2
-rw-r--r--core/os/input_event.cpp4
-rw-r--r--core/os/input_event.h4
-rw-r--r--core/os/keyboard.cpp22
-rw-r--r--core/os/main_loop.cpp1
-rw-r--r--core/os/os.cpp50
-rw-r--r--core/os/os.h51
-rw-r--r--core/packed_data_container.cpp8
-rw-r--r--core/pair.h10
-rw-r--r--core/pool_allocator.cpp6
-rw-r--r--core/project_settings.cpp75
-rw-r--r--core/project_settings.h9
-rw-r--r--core/reference.cpp13
-rw-r--r--core/reference.h4
-rw-r--r--core/register_core_types.cpp24
-rw-r--r--core/resource.cpp3
-rw-r--r--core/safe_refcount.cpp148
-rw-r--r--core/safe_refcount.h135
-rw-r--r--core/script_debugger_local.cpp10
-rw-r--r--core/script_debugger_local.h4
-rw-r--r--core/script_debugger_remote.cpp29
-rw-r--r--core/script_debugger_remote.h4
-rw-r--r--core/script_language.cpp3
-rw-r--r--core/script_language.h6
-rw-r--r--core/set.h311
-rw-r--r--core/string_buffer.cpp102
-rw-r--r--core/string_buffer.h (renamed from core/os/power.h)62
-rw-r--r--core/string_builder.cpp94
-rw-r--r--core/string_builder.h (renamed from core/event_queue.h)65
-rw-r--r--core/string_db.h3
-rw-r--r--core/translation.cpp151
-rw-r--r--core/translation.h7
-rw-r--r--core/type_info.h110
-rw-r--r--core/typedefs.h12
-rw-r--r--core/undo_redo.cpp4
-rw-r--r--core/ustring.cpp56
-rw-r--r--core/ustring.h4
-rw-r--r--core/variant.cpp165
-rw-r--r--core/variant.h16
-rw-r--r--core/variant_call.cpp665
-rw-r--r--core/variant_op.cpp2271
-rw-r--r--core/variant_parser.cpp22
-rw-r--r--core/vmap.h6
-rw-r--r--core/vset.h7
128 files changed, 5873 insertions, 2673 deletions
diff --git a/core/SCsub b/core/SCsub
index c1e57f6840..e9b21bc71b 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -83,24 +83,8 @@ thirdparty_minizip_sources = [
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env.add_source_files(env.core_sources, thirdparty_minizip_sources)
-thirdparty_zstd_dir = "#thirdparty/zstd/"
-thirdparty_zstd_sources = [
- "common/entropy_common.c",
- "common/error_private.c",
- "common/fse_decompress.c",
- "common/pool.c",
- "common/threading.c",
- "common/xxhash.c",
- "common/zstd_common.c",
- "compress/fse_compress.c",
- "compress/huf_compress.c",
- "compress/zstd_compress.c",
- "compress/zstdmt_compress.c",
- "decompress/huf_decompress.c",
- "decompress/zstd_decompress.c",
-]
-thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
-env.add_source_files(env.core_sources, thirdparty_zstd_sources)
+if 'builtin_zstd' in env and env['builtin_zstd']:
+ SConscript("#thirdparty/zstd/SCsub")
# Godot's own sources
@@ -123,5 +107,4 @@ SConscript('helper/SCsub')
# Build it all as a library
lib = env.Library("core", env.core_sources)
env.Prepend(LIBS=[lib])
-env.Append(CPPPATH=["#thirdparty/zstd", "#thirdparty/zstd/common"])
Export('env')
diff --git a/core/array.cpp b/core/array.cpp
index c35bf5bf0c..171c11776c 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -47,11 +47,11 @@ void Array::_ref(const Array &p_from) const {
ERR_FAIL_COND(!_fp); // should NOT happen.
if (_fp == _p)
- return; //wathever it is, nothing to do here move along
+ return; // whatever it is, nothing to do here move along
bool success = _fp->refcount.ref();
- ERR_FAIL_COND(!success); //should really not happen either
+ ERR_FAIL_COND(!success); // should really not happen either
_unref();
@@ -210,6 +210,17 @@ const Variant &Array::get(int p_idx) const {
return operator[](p_idx);
}
+Array Array::duplicate() const {
+
+ Array new_arr;
+ int element_count = size();
+ new_arr.resize(element_count);
+ for (int i = 0; i < element_count; i++) {
+ new_arr[i] = get(i);
+ }
+
+ return new_arr;
+}
struct _ArrayVariantSort {
_FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const {
@@ -222,9 +233,10 @@ struct _ArrayVariantSort {
}
};
-void Array::sort() {
+Array &Array::sort() {
_p->array.sort_custom<_ArrayVariantSort>();
+ return *this;
}
struct _ArrayVariantSortCustom {
@@ -242,19 +254,21 @@ struct _ArrayVariantSortCustom {
return res;
}
};
-void Array::sort_custom(Object *p_obj, const StringName &p_function) {
+Array &Array::sort_custom(Object *p_obj, const StringName &p_function) {
- ERR_FAIL_NULL(p_obj);
+ ERR_FAIL_NULL_V(p_obj, *this);
SortArray<Variant, _ArrayVariantSortCustom> avs;
avs.compare.obj = p_obj;
avs.compare.func = p_function;
avs.sort(_p->array.ptr(), _p->array.size());
+ return *this;
}
-void Array::invert() {
+Array &Array::invert() {
_p->array.invert();
+ return *this;
}
void Array::push_front(const Variant &p_value) {
diff --git a/core/array.h b/core/array.h
index 777116ab56..2c29103108 100644
--- a/core/array.h
+++ b/core/array.h
@@ -68,9 +68,9 @@ public:
Variant front() const;
Variant back() const;
- void sort();
- void sort_custom(Object *p_obj, const StringName &p_function);
- void invert();
+ Array &sort();
+ Array &sort_custom(Object *p_obj, const StringName &p_function);
+ Array &invert();
int find(const Variant &p_value, int p_from = 0) const;
int rfind(const Variant &p_value, int p_from = -1) const;
@@ -84,6 +84,8 @@ public:
Variant pop_back();
Variant pop_front();
+ Array duplicate() const;
+
Array(const Array &p_from);
Array();
~Array();
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index abe8b9b715..12b892d873 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"
@@ -412,6 +413,7 @@ String _OS::get_latin_keyboard_variant() const {
case OS::LATIN_KEYBOARD_QZERTY: return "QZERTY";
case OS::LATIN_KEYBOARD_DVORAK: return "DVORAK";
case OS::LATIN_KEYBOARD_NEO: return "NEO";
+ case OS::LATIN_KEYBOARD_COLEMAK: return "COLEMAK";
default: return "ERROR";
}
}
@@ -440,8 +442,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() {
@@ -452,6 +454,11 @@ int _OS::get_power_percent_left() {
return OS::get_singleton()->get_power_percent_left();
}
+bool _OS::has_feature(const String &p_feature) const {
+
+ return OS::get_singleton()->has_feature(p_feature);
+}
+
/*
enum Weekday {
DAY_SUNDAY,
@@ -568,7 +575,7 @@ Dictionary _OS::get_time(bool utc) const {
}
/**
- * Get a epoch time value from a dictionary of time values
+ * Get an epoch time value from a dictionary of time values
* @p datetime must be populated with the following keys:
* day, hour, minute, month, second, year. (dst is ignored).
*
@@ -754,6 +761,11 @@ bool _OS::can_draw() const {
return OS::get_singleton()->can_draw();
}
+bool _OS::is_userfs_persistent() const {
+
+ return OS::get_singleton()->is_userfs_persistent();
+}
+
int _OS::get_processor_count() const {
return OS::get_singleton()->get_processor_count();
@@ -857,6 +869,10 @@ void _OS::hide_virtual_keyboard() {
OS::get_singleton()->hide_virtual_keyboard();
}
+int _OS::get_virtual_keyboard_height() {
+ return OS::get_singleton()->get_virtual_keyboard_height();
+}
+
void _OS::print_all_resources(const String &p_to_file) {
OS::get_singleton()->print_all_resources(p_to_file);
@@ -1032,10 +1048,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_time", "utc"), &_OS::get_time, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_time_zone_info"), &_OS::get_time_zone_info);
ClassDB::bind_method(D_METHOD("get_unix_time"), &_OS::get_unix_time);
- ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"),
- &_OS::get_datetime_from_unix_time);
- ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"),
- &_OS::get_unix_time_from_datetime);
+ ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"), &_OS::get_datetime_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"), &_OS::get_unix_time_from_datetime);
ClassDB::bind_method(D_METHOD("get_system_time_secs"), &_OS::get_system_time_secs);
ClassDB::bind_method(D_METHOD("set_icon", "icon"), &_OS::set_icon);
@@ -1052,6 +1066,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_model_name"), &_OS::get_model_name);
ClassDB::bind_method(D_METHOD("can_draw"), &_OS::can_draw);
+ ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &_OS::is_userfs_persistent);
ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &_OS::is_stdout_verbose);
ClassDB::bind_method(D_METHOD("can_use_threads"), &_OS::can_use_threads);
@@ -1065,6 +1080,7 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_virtual_keyboard"), &_OS::has_virtual_keyboard);
ClassDB::bind_method(D_METHOD("show_virtual_keyboard", "existing_text"), &_OS::show_virtual_keyboard, DEFVAL(""));
ClassDB::bind_method(D_METHOD("hide_virtual_keyboard"), &_OS::hide_virtual_keyboard);
+ ClassDB::bind_method(D_METHOD("get_virtual_keyboard_height"), &_OS::get_virtual_keyboard_height);
ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &_OS::print_resources_in_use, DEFVAL(false));
ClassDB::bind_method(D_METHOD("print_all_resources", "tofile"), &_OS::print_all_resources, DEFVAL(""));
@@ -1100,6 +1116,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_vsync", "enable"), &_OS::set_use_vsync);
ClassDB::bind_method(D_METHOD("is_vsync_enabled"), &_OS::is_vsync_enabled);
+ ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &_OS::has_feature);
+
ClassDB::bind_method(D_METHOD("get_power_state"), &_OS::get_power_state);
ClassDB::bind_method(D_METHOD("get_power_seconds_left"), &_OS::get_power_seconds_left);
ClassDB::bind_method(D_METHOD("get_power_percent_left"), &_OS::get_power_percent_left);
@@ -1336,7 +1354,7 @@ void _Geometry::_bind_methods() {
ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &_Geometry::build_box_planes);
ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &_Geometry::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z));
ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry::build_capsule_planes, DEFVAL(Vector3::AXIS_Z));
- ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_pos", "circle_radius"), &_Geometry::segment_intersects_circle);
+ ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &_Geometry::segment_intersects_circle);
ClassDB::bind_method(D_METHOD("segment_intersects_segment_2d", "from_a", "to_a", "from_b", "to_b"), &_Geometry::segment_intersects_segment_2d);
ClassDB::bind_method(D_METHOD("get_closest_points_between_segments_2d", "p1", "q1", "p2", "q2"), &_Geometry::get_closest_points_between_segments_2d);
@@ -1352,7 +1370,7 @@ void _Geometry::_bind_methods() {
ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &_Geometry::ray_intersects_triangle);
ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &_Geometry::segment_intersects_triangle);
- ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "spos", "sradius"), &_Geometry::segment_intersects_sphere);
+ ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &_Geometry::segment_intersects_sphere);
ClassDB::bind_method(D_METHOD("segment_intersects_cylinder", "from", "to", "height", "radius"), &_Geometry::segment_intersects_cylinder);
ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &_Geometry::segment_intersects_convex);
ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry::point_is_inside_triangle);
@@ -1451,10 +1469,10 @@ void _File::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f);
f->seek_end(p_position);
}
-int64_t _File::get_pos() const {
+int64_t _File::get_position() const {
ERR_FAIL_COND_V(!f, 0);
- return f->get_pos();
+ return f->get_position();
}
int64_t _File::get_len() const {
@@ -1533,7 +1551,7 @@ String _File::get_as_text() const {
ERR_FAIL_COND_V(!f, String());
String text;
- size_t original_pos = f->get_pos();
+ size_t original_pos = f->get_position();
f->seek(0);
String l = get_line();
@@ -1705,7 +1723,7 @@ Variant _File::get_var() const {
ERR_FAIL_COND_V(!f, Variant());
uint32_t len = get_32();
PoolVector<uint8_t> buff = get_buffer(len);
- ERR_FAIL_COND_V(buff.size() != len, Variant());
+ ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
PoolVector<uint8_t>::Read r = buff.read();
@@ -1730,9 +1748,9 @@ void _File::_bind_methods() {
ClassDB::bind_method(D_METHOD("open", "path", "flags"), &_File::open);
ClassDB::bind_method(D_METHOD("close"), &_File::close);
ClassDB::bind_method(D_METHOD("is_open"), &_File::is_open);
- ClassDB::bind_method(D_METHOD("seek", "pos"), &_File::seek);
- ClassDB::bind_method(D_METHOD("seek_end", "pos"), &_File::seek_end, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("get_pos"), &_File::get_pos);
+ ClassDB::bind_method(D_METHOD("seek", "position"), &_File::seek);
+ ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_position"), &_File::get_position);
ClassDB::bind_method(D_METHOD("get_len"), &_File::get_len);
ClassDB::bind_method(D_METHOD("eof_reached"), &_File::eof_reached);
ClassDB::bind_method(D_METHOD("get_8"), &_File::get_8);
@@ -2558,8 +2576,8 @@ Dictionary _Engine::get_version_info() const {
return Engine::get_singleton()->get_version_info();
}
-bool _Engine::is_in_fixed_frame() const {
- return Engine::get_singleton()->is_in_fixed_frame();
+bool _Engine::is_in_physics_frame() const {
+ return Engine::get_singleton()->is_in_physics_frame();
}
void _Engine::set_editor_hint(bool p_enabled) {
@@ -2589,7 +2607,7 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_version_info"), &_Engine::get_version_info);
- ClassDB::bind_method(D_METHOD("is_in_fixed_frame"), &_Engine::is_in_fixed_frame);
+ ClassDB::bind_method(D_METHOD("is_in_physics_frame"), &_Engine::is_in_physics_frame);
ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &_Engine::set_editor_hint);
ClassDB::bind_method(D_METHOD("is_editor_hint"), &_Engine::is_editor_hint);
@@ -2600,3 +2618,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..7f8c734e36 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,
@@ -196,6 +204,7 @@ public:
bool has_virtual_keyboard() const;
void show_virtual_keyboard(const String &p_existing_text = "");
void hide_virtual_keyboard();
+ int get_virtual_keyboard_height();
void print_resources_in_use(bool p_short = false);
void print_all_resources(const String &p_to_file);
@@ -258,6 +267,8 @@ public:
bool can_draw() const;
+ bool is_userfs_persistent() const;
+
bool is_stdout_verbose() const;
int get_processor_count() const;
@@ -307,11 +318,14 @@ public:
int get_power_seconds_left();
int get_power_percent_left();
+ bool has_feature(const String &p_feature) const;
+
static _OS *get_singleton() { return singleton; }
_OS();
};
+VARIANT_ENUM_CAST(_OS::PowerState);
VARIANT_ENUM_CAST(_OS::Weekday);
VARIANT_ENUM_CAST(_OS::Month);
VARIANT_ENUM_CAST(_OS::SystemDir);
@@ -390,7 +404,7 @@ public:
void seek(int64_t p_position); ///< seek to a given position
void seek_end(int64_t p_position = 0); ///< seek from the end of file
- int64_t get_pos() const; ///< get position in the file
+ int64_t get_position() const; ///< get position in the file
int64_t get_len() const; ///< get size of the file
bool eof_reached() const; ///< reading passed EOF
@@ -652,7 +666,7 @@ public:
Dictionary get_version_info() const;
- bool is_in_fixed_frame() const;
+ bool is_in_physics_frame() const;
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
@@ -660,4 +674,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/class_db.cpp b/core/class_db.cpp
index 481b1c398a..57e88044b5 100644
--- a/core/class_db.cpp
+++ b/core/class_db.cpp
@@ -187,6 +187,25 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
return md;
}
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11) {
+
+ MethodDefinition md;
+ md.name = StaticCString::create(p_name);
+ md.args.resize(11);
+ md.args[0] = StaticCString::create(p_arg1);
+ md.args[1] = StaticCString::create(p_arg2);
+ md.args[2] = StaticCString::create(p_arg3);
+ md.args[3] = StaticCString::create(p_arg4);
+ md.args[4] = StaticCString::create(p_arg5);
+ md.args[5] = StaticCString::create(p_arg6);
+ md.args[6] = StaticCString::create(p_arg7);
+ md.args[7] = StaticCString::create(p_arg8);
+ md.args[8] = StaticCString::create(p_arg9);
+ md.args[9] = StaticCString::create(p_arg10);
+ md.args[10] = StaticCString::create(p_arg11);
+ return md;
+}
+
#endif
ClassDB::APIType ClassDB::current_api = API_CORE;
@@ -205,6 +224,7 @@ ClassDB::ClassInfo::ClassInfo() {
creation_func = NULL;
inherits_ptr = NULL;
disabled = false;
+ exposed = false;
}
ClassDB::ClassInfo::~ClassInfo() {
}
@@ -534,8 +554,13 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b
}
minfo.return_val = method->get_return_info();
-
minfo.flags = method->get_hint_flags();
+
+ for (int i = 0; i < method->get_argument_count(); i++) {
+ if (method->has_default_argument(i))
+ minfo.default_arguments.push_back(method->get_default_argument(i));
+ }
+
p_methods->push_back(minfo);
}
@@ -1279,6 +1304,15 @@ bool ClassDB::is_class_enabled(StringName p_class) {
return !ti->disabled;
}
+bool ClassDB::is_class_exposed(StringName p_class) {
+
+ OBJTYPE_RLOCK;
+
+ ClassInfo *ti = classes.getptr(p_class);
+ ERR_FAIL_COND_V(!ti, false);
+ return ti->exposed;
+}
+
StringName ClassDB::get_category(const StringName &p_node) {
ERR_FAIL_COND_V(!classes.has(p_node), StringName());
diff --git a/core/class_db.h b/core/class_db.h
index f6b97748b0..24db4c61bb 100644
--- a/core/class_db.h
+++ b/core/class_db.h
@@ -66,6 +66,7 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9);
MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10);
+MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2, const char *p_arg3, const char *p_arg4, const char *p_arg5, const char *p_arg6, const char *p_arg7, const char *p_arg8, const char *p_arg9, const char *p_arg10, const char *p_arg11);
#else
@@ -127,6 +128,7 @@ public:
StringName inherits;
StringName name;
bool disabled;
+ bool exposed;
Object *(*creation_func)();
ClassInfo();
~ClassInfo();
@@ -168,6 +170,7 @@ public:
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &creator<T>;
+ t->exposed = true;
T::register_custom_data_to_otdb();
}
@@ -176,6 +179,9 @@ public:
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
+ ClassInfo *t = classes.getptr(T::get_class_static());
+ ERR_FAIL_COND(!t);
+ t->exposed = true;
//nothing
}
@@ -193,6 +199,7 @@ public:
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &_create_ptr_func<T>;
+ t->exposed = true;
T::register_custom_data_to_otdb();
}
@@ -347,6 +354,8 @@ public:
static void set_class_enabled(StringName p_class, bool p_enable);
static bool is_class_enabled(StringName p_class);
+ static bool is_class_exposed(StringName p_class);
+
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
diff --git a/core/color.cpp b/core/color.cpp
index 356e8c168c..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,15 +47,27 @@ uint32_t Color::to_ARGB32() const {
return c;
}
-uint32_t Color::to_32() const {
-
+uint32_t Color::to_abgr32() const {
uint32_t c = (uint8_t)(a * 255);
c <<= 8;
+ c |= (uint8_t)(b * 255);
+ c <<= 8;
+ c |= (uint8_t)(g * 255);
+ c <<= 8;
c |= (uint8_t)(r * 255);
+
+ return c;
+}
+
+uint32_t Color::to_rgba32() const {
+
+ 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;
}
@@ -238,6 +250,14 @@ Color Color::html(const String &p_color) {
return Color();
if (color[0] == '#')
color = color.substr(1, color.length() - 1);
+ if (color.length() == 3 || color.length() == 4) {
+ String exp_color;
+ for (int i = 0; i < color.length(); i++) {
+ exp_color += color[i];
+ exp_color += color[i];
+ }
+ color = exp_color;
+ }
bool alpha = false;
@@ -388,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 6df114f2f2..972b6a1b33 100644
--- a/core/color.h
+++ b/core/color.h
@@ -51,8 +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_rgba32() const;
+ uint32_t to_argb32() const;
+ uint32_t to_abgr32() const;
float gray() const;
float get_h() const;
float get_s() const;
@@ -66,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;
@@ -148,8 +166,7 @@ struct Color {
b < 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
}
- static Color
- hex(uint32_t p_hex);
+ static Color hex(uint32_t p_hex);
static Color html(const String &p_color);
static bool html_is_valid(const String &p_color);
static Color named(const String &p_name);
diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h
index f99e16da15..e37d593f9f 100644
--- a/core/command_queue_mt.h
+++ b/core/command_queue_mt.h
@@ -227,6 +227,27 @@ class CommandQueueMT {
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); }
};
+ template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
+ struct Command12 : public CommandBase {
+
+ T *instance;
+ M method;
+ typename GetSimpleTypeT<P1>::type_t p1;
+ typename GetSimpleTypeT<P2>::type_t p2;
+ typename GetSimpleTypeT<P3>::type_t p3;
+ typename GetSimpleTypeT<P4>::type_t p4;
+ typename GetSimpleTypeT<P5>::type_t p5;
+ typename GetSimpleTypeT<P6>::type_t p6;
+ typename GetSimpleTypeT<P7>::type_t p7;
+ typename GetSimpleTypeT<P8>::type_t p8;
+ typename GetSimpleTypeT<P9>::type_t p9;
+ typename GetSimpleTypeT<P10>::type_t p10;
+ typename GetSimpleTypeT<P11>::type_t p11;
+ typename GetSimpleTypeT<P12>::type_t p12;
+
+ virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); }
+ };
+
/* comands that return */
template <class T, class M, class R>
@@ -906,6 +927,31 @@ public:
if (sync) sync->post();
}
+ template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>
+ void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {
+
+ Command12<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> *cmd = allocate_and_lock<Command12<T, M, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12> >();
+
+ cmd->instance = p_instance;
+ cmd->method = p_method;
+ cmd->p1 = p1;
+ cmd->p2 = p2;
+ cmd->p3 = p3;
+ cmd->p4 = p4;
+ cmd->p5 = p5;
+ cmd->p6 = p6;
+ cmd->p7 = p7;
+ cmd->p8 = p8;
+ cmd->p9 = p9;
+ cmd->p10 = p10;
+ cmd->p11 = p11;
+ cmd->p12 = p12;
+
+ unlock();
+
+ if (sync) sync->post();
+ }
+
/*** PUSH AND RET COMMANDS ***/
template <class T, class M, class R>
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index ef9346253f..feee39225f 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -47,4 +47,27 @@ CoreStringNames::CoreStringNames()
_sections_unfolded(StaticCString::create("_sections_unfolded")),
#endif
_custom_features(StaticCString::create("_custom_features")) {
+
+ x = StaticCString::create("x");
+ y = StaticCString::create("y");
+ z = StaticCString::create("z");
+ w = StaticCString::create("w");
+ r = StaticCString::create("r");
+ g = StaticCString::create("g");
+ b = StaticCString::create("b");
+ a = StaticCString::create("a");
+ position = StaticCString::create("position");
+ size = StaticCString::create("size");
+ end = StaticCString::create("end");
+ basis = StaticCString::create("basis");
+ origin = StaticCString::create("origin");
+ normal = StaticCString::create("normal");
+ d = StaticCString::create("d");
+ h = StaticCString::create("h");
+ s = StaticCString::create("s");
+ v = StaticCString::create("v");
+ r8 = StaticCString::create("r8");
+ g8 = StaticCString::create("g8");
+ b8 = StaticCString::create("b8");
+ a8 = StaticCString::create("a8");
}
diff --git a/core/core_string_names.h b/core/core_string_names.h
index 2eb2b703ae..6fcc773169 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -37,8 +37,6 @@ class CoreStringNames {
friend void register_core_types();
friend void unregister_core_types();
- static CoreStringNames *singleton;
-
static void create() { singleton = memnew(CoreStringNames); }
static void free() {
memdelete(singleton);
@@ -50,6 +48,8 @@ class CoreStringNames {
public:
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
+ static CoreStringNames *singleton;
+
StringName _free;
StringName changed;
StringName _meta;
@@ -65,6 +65,29 @@ public:
StringName _sections_unfolded;
#endif
StringName _custom_features;
+
+ StringName x;
+ StringName y;
+ StringName z;
+ StringName w;
+ StringName r;
+ StringName g;
+ StringName b;
+ StringName a;
+ StringName position;
+ StringName size;
+ StringName end;
+ StringName basis;
+ StringName origin;
+ StringName normal;
+ StringName d;
+ StringName h;
+ StringName s;
+ StringName v;
+ StringName r8;
+ StringName g8;
+ StringName b8;
+ StringName a8;
};
#endif // SCENE_STRING_NAMES_H
diff --git a/core/engine.cpp b/core/engine.cpp
index d73693dc12..c609ae9520 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -116,9 +116,9 @@ Engine::Engine() {
_target_fps = 0;
_time_scale = 1.0;
_pixel_snap = false;
- _fixed_frames = 0;
+ _physics_frames = 0;
_idle_frames = 0;
- _in_fixed = false;
+ _in_physics = false;
_frame_ticks = 0;
_frame_step = 0;
editor_hint = false;
diff --git a/core/engine.h b/core/engine.h
index 6f46ec8923..3b4979582f 100644
--- a/core/engine.h
+++ b/core/engine.h
@@ -49,10 +49,10 @@ class Engine {
int _target_fps;
float _time_scale;
bool _pixel_snap;
- uint64_t _fixed_frames;
+ uint64_t _physics_frames;
uint64_t _idle_frames;
- bool _in_fixed;
+ bool _in_physics;
bool editor_hint;
@@ -71,9 +71,9 @@ public:
uint64_t get_frames_drawn();
- uint64_t get_fixed_frames() const { return _fixed_frames; }
+ uint64_t get_physics_frames() const { return _physics_frames; }
uint64_t get_idle_frames() const { return _idle_frames; }
- bool is_in_fixed_frame() const { return _in_fixed; }
+ bool is_in_physics_frame() const { return _in_physics; }
uint64_t get_idle_frame_ticks() const { return _frame_ticks; }
float get_idle_frame_step() const { return _frame_step; }
diff --git a/core/error_list.h b/core/error_list.h
index bc65ad0ee4..50d248b3d0 100644
--- a/core/error_list.h
+++ b/core/error_list.h
@@ -66,7 +66,7 @@ enum Error {
ERR_CANT_CONNECT, // (25)
ERR_CANT_RESOLVE,
ERR_CONNECTION_ERROR,
- ERR_CANT_AQUIRE_RESOURCE,
+ ERR_CANT_ACQUIRE_RESOURCE,
ERR_CANT_FORK,
ERR_INVALID_DATA, ///< Data passed is invalid (30)
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
diff --git a/core/error_macros.cpp b/core/error_macros.cpp
index 5919d38375..7d85aa9001 100644
--- a/core/error_macros.cpp
+++ b/core/error_macros.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "error_macros.h"
+#include "io/logger.h"
#include "os/os.h"
bool _err_error_exists = false;
@@ -79,7 +80,7 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
- OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (OS::ErrorType)p_type);
+ OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (Logger::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;
@@ -96,3 +97,10 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
_err_error_exists = false;
}
}
+
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal) {
+
+ String fstr(fatal ? "FATAL: " : "");
+ String err(fstr + "Index" + p_index_str + "=" + itos(p_index) + " out of size (" + p_size_str + "=" + itos(p_size) + ")");
+ _err_print_error(p_function, p_file, p_line, err.utf8().get_data());
+}
diff --git a/core/error_macros.h b/core/error_macros.h
index 005b0e32a3..8d2f588706 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -30,6 +30,7 @@
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
+#include "typedefs.h"
/**
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the
@@ -75,6 +76,7 @@ void add_error_handler(ErrorHandlerList *p_handler);
void remove_error_handler(ErrorHandlerList *p_handler);
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR);
+void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, bool fatal = false);
#ifndef _STR
#define _STR(m_x) #m_x
@@ -128,13 +130,13 @@ extern bool _err_error_exists;
// (*): See https://stackoverflow.com/questions/257418/do-while-0-what-is-it-good-for
-#define ERR_FAIL_INDEX(m_index, m_size) \
- do { \
- if ((m_index) < 0 || (m_index) >= (m_size)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
- return; \
- } else \
- _err_error_exists = false; \
+#define ERR_FAIL_INDEX(m_index, m_size) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return; \
+ } else \
+ _err_error_exists = false; \
} while (0); // (*)
/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
@@ -142,24 +144,24 @@ extern bool _err_error_exists;
* appropriate error condition from error_macros.h
*/
-#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
- do { \
- if ((m_index) < 0 || (m_index) >= (m_size)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
- return m_retval; \
- } else \
- _err_error_exists = false; \
+#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size)); \
+ return m_retval; \
+ } else \
+ _err_error_exists = false; \
} while (0); // (*)
/** Use this one if there is no sensible fallback, that is, the error is unrecoverable.
* We'll return a null reference and try to keep running.
*/
-#define CRASH_BAD_INDEX(m_index, m_size) \
- do { \
- if ((m_index) < 0 || (m_index) >= (m_size)) { \
- _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
- GENERATE_TRAP \
- } \
+#define CRASH_BAD_INDEX(m_index, m_size) \
+ do { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
+ _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), true); \
+ GENERATE_TRAP \
+ } \
} while (0); // (*)
/** An error condition happened (m_cond tested true) (WARNING this is the opposite as assert().
@@ -168,7 +170,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_NULL(m_param) \
{ \
- if (!m_param) { \
+ if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
return; \
} else \
@@ -177,7 +179,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_NULL_V(m_param, m_retval) \
{ \
- if (!m_param) { \
+ if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
return m_retval; \
} else \
@@ -190,7 +192,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_COND(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
return; \
} else \
@@ -202,7 +204,7 @@ extern bool _err_error_exists;
#define CRASH_COND(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \
GENERATE_TRAP \
} \
@@ -216,7 +218,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_COND_V(m_cond, m_retval) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
return m_retval; \
} else \
@@ -229,7 +231,7 @@ extern bool _err_error_exists;
#define ERR_CONTINUE(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
continue; \
} else \
@@ -242,7 +244,7 @@ extern bool _err_error_exists;
#define ERR_BREAK(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
break; \
} else \
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/global_constants.cpp b/core/global_constants.cpp
index 224ee0e0aa..8bddeae69a 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -86,6 +86,8 @@ static Vector<_GlobalConstant> _global_constants;
VARIANT_ENUM_CAST(KeyList);
VARIANT_ENUM_CAST(KeyModifierMask);
+VARIANT_ENUM_CAST(ButtonList);
+VARIANT_ENUM_CAST(JoystickList);
void register_global_constants() {
@@ -367,82 +369,82 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH);
// mouse
- BIND_GLOBAL_CONSTANT(BUTTON_LEFT);
- BIND_GLOBAL_CONSTANT(BUTTON_RIGHT);
- BIND_GLOBAL_CONSTANT(BUTTON_MIDDLE);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_UP);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_DOWN);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_LEFT);
- BIND_GLOBAL_CONSTANT(BUTTON_WHEEL_RIGHT);
- BIND_GLOBAL_CONSTANT(BUTTON_MASK_LEFT);
- BIND_GLOBAL_CONSTANT(BUTTON_MASK_RIGHT);
- BIND_GLOBAL_CONSTANT(BUTTON_MASK_MIDDLE);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MIDDLE);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_UP);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_DOWN);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_MIDDLE);
//joypads
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_0);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_1);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_2);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_3);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_4);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_5);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_6);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_7);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_8);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_9);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_10);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_11);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_12);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_13);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_14);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_15);
- BIND_GLOBAL_CONSTANT(JOY_BUTTON_MAX);
-
- BIND_GLOBAL_CONSTANT(JOY_SONY_CIRCLE);
- BIND_GLOBAL_CONSTANT(JOY_SONY_X);
- BIND_GLOBAL_CONSTANT(JOY_SONY_SQUARE);
- BIND_GLOBAL_CONSTANT(JOY_SONY_TRIANGLE);
-
- BIND_GLOBAL_CONSTANT(JOY_XBOX_B);
- BIND_GLOBAL_CONSTANT(JOY_XBOX_A);
- BIND_GLOBAL_CONSTANT(JOY_XBOX_X);
- BIND_GLOBAL_CONSTANT(JOY_XBOX_Y);
-
- BIND_GLOBAL_CONSTANT(JOY_DS_A);
- BIND_GLOBAL_CONSTANT(JOY_DS_B);
- BIND_GLOBAL_CONSTANT(JOY_DS_X);
- BIND_GLOBAL_CONSTANT(JOY_DS_Y);
-
- BIND_GLOBAL_CONSTANT(JOY_SELECT);
- BIND_GLOBAL_CONSTANT(JOY_START);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_UP);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_DOWN);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_LEFT);
- BIND_GLOBAL_CONSTANT(JOY_DPAD_RIGHT);
- BIND_GLOBAL_CONSTANT(JOY_L);
- BIND_GLOBAL_CONSTANT(JOY_L2);
- BIND_GLOBAL_CONSTANT(JOY_L3);
- BIND_GLOBAL_CONSTANT(JOY_R);
- BIND_GLOBAL_CONSTANT(JOY_R2);
- BIND_GLOBAL_CONSTANT(JOY_R3);
-
- BIND_GLOBAL_CONSTANT(JOY_AXIS_0);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_1);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_2);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_3);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_4);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_5);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_6);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_7);
- BIND_GLOBAL_CONSTANT(JOY_AXIS_MAX);
-
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_LX);
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_LY);
-
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_RX);
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_RY);
-
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_L2);
- BIND_GLOBAL_CONSTANT(JOY_ANALOG_R2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_0);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_1);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_3);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_4);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_5);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_6);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_7);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_8);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_9);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_10);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_11);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_12);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_13);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_14);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_15);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_MAX);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_CIRCLE);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_X);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_SQUARE);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_TRIANGLE);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_B);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_A);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_X);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_Y);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_A);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_B);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_X);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DS_Y);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_SELECT);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_START);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_UP);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_DOWN);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_LEFT);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_DPAD_RIGHT);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_L);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_L2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_L3);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_R);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_R2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_R3);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_0);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_1);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_3);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_4);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_5);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_6);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_7);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_MAX);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_LX);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_LY);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_RX);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_RY);
+
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2);
+ BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2);
// error list
@@ -472,7 +474,7 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_IN_USE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED); ///< resource is locked
BIND_GLOBAL_ENUM_CONSTANT(ERR_TIMEOUT);
- BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_AQUIRE_RESOURCE);
+ BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); ///< Data passed is invalid
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER); ///< Parameter passed is invalid
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS); ///< When adding ), item already exists
diff --git a/core/hash_map.h b/core/hash_map.h
index b22c6378b0..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>
@@ -102,17 +69,31 @@ public:
}
};
-private:
- struct Entry {
+ struct Element {
+ private:
+ friend class HashMap;
uint32_t hash;
- Entry *next;
+ Element *next;
+ Element() { next = 0; }
Pair pair;
- Entry() { next = 0; }
+ public:
+ const TKey &key() const {
+ return pair.key;
+ }
+
+ TData &value() {
+ return pair.data;
+ }
+
+ const TData &value() const {
+ return pair.value();
+ }
};
- Entry **hash_table;
+private:
+ Element **hash_table;
uint8_t hash_table_power;
uint32_t elements;
@@ -120,7 +101,7 @@ private:
ERR_FAIL_COND(hash_table);
- hash_table = memnew_arr(Entry *, (1 << MIN_HASH_TABLE_POWER));
+ hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER));
hash_table_power = MIN_HASH_TABLE_POWER;
elements = 0;
@@ -168,7 +149,7 @@ private:
if (new_hash_table_power == -1)
return;
- Entry **new_hash_table = memnew_arr(Entry *, (1 << new_hash_table_power));
+ Element **new_hash_table = memnew_arr(Element *, (1 << new_hash_table_power));
if (!new_hash_table) {
ERR_PRINT("Out of Memory");
@@ -184,7 +165,7 @@ private:
while (hash_table[i]) {
- Entry *se = hash_table[i];
+ Element *se = hash_table[i];
hash_table[i] = se->next;
int new_pos = se->hash & ((1 << new_hash_table_power) - 1);
se->next = new_hash_table[new_pos];
@@ -199,12 +180,12 @@ private:
}
/* I want to have only one function.. */
- _FORCE_INLINE_ const Entry *get_entry(const TKey &p_key) const {
+ _FORCE_INLINE_ const Element *get_element(const TKey &p_key) const {
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
- Entry *e = hash_table[index];
+ Element *e = hash_table[index];
while (e) {
@@ -221,10 +202,10 @@ private:
return NULL;
}
- Entry *create_entry(const TKey &p_key) {
+ Element *create_element(const TKey &p_key) {
- /* if entry doesn't exist, create it */
- Entry *e = memnew(Entry);
+ /* if element doesn't exist, create it */
+ Element *e = memnew(Element);
ERR_FAIL_COND_V(!e, NULL); /* out of memory */
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
@@ -248,7 +229,7 @@ private:
if (!p_t.hash_table || p_t.hash_table_power == 0)
return; /* not copying from empty table */
- hash_table = memnew_arr(Entry *, 1 << p_t.hash_table_power);
+ hash_table = memnew_arr(Element *, 1 << p_t.hash_table_power);
hash_table_power = p_t.hash_table_power;
elements = p_t.elements;
@@ -256,11 +237,11 @@ private:
hash_table[i] = NULL;
- const Entry *e = p_t.hash_table[i];
+ const Element *e = p_t.hash_table[i];
while (e) {
- Entry *le = memnew(Entry); /* local entry */
+ Element *le = memnew(Element); /* local element */
*le = *e; /* copy data */
@@ -274,30 +255,30 @@ private:
}
public:
- void set(const TKey &p_key, const TData &p_data) {
-
- set(Pair(p_key, p_data));
+ Element *set(const TKey &p_key, const TData &p_data) {
+ return set(Pair(p_key, p_data));
}
- void set(const Pair &p_pair) {
+ Element *set(const Pair &p_pair) {
- Entry *e = NULL;
+ Element *e = NULL;
if (!hash_table)
make_hash_table(); // if no table, make one
else
- e = const_cast<Entry *>(get_entry(p_pair.key));
+ e = const_cast<Element *>(get_element(p_pair.key));
/* if we made it up to here, the pair doesn't exist, create and assign */
if (!e) {
- e = create_entry(p_pair.key);
+ e = create_element(p_pair.key);
if (!e)
- return;
+ return NULL;
check_hash_table(); // perform mantenience routine
}
e->pair.data = p_pair.data;
+ return e;
}
bool has(const TKey &p_key) const {
@@ -335,7 +316,7 @@ public:
if (!hash_table)
return NULL;
- Entry *e = const_cast<Entry *>(get_entry(p_key));
+ Element *e = const_cast<Element *>(get_element(p_key));
if (e)
return &e->pair.data;
@@ -348,7 +329,7 @@ public:
if (!hash_table)
return NULL;
- const Entry *e = const_cast<Entry *>(get_entry(p_key));
+ const Element *e = const_cast<Element *>(get_element(p_key));
if (e)
return &e->pair.data;
@@ -370,7 +351,7 @@ public:
uint32_t hash = p_custom_hash;
uint32_t index = hash & ((1 << hash_table_power) - 1);
- Entry *e = hash_table[index];
+ Element *e = hash_table[index];
while (e) {
@@ -396,7 +377,7 @@ public:
uint32_t hash = p_custom_hash;
uint32_t index = hash & ((1 << hash_table_power) - 1);
- const Entry *e = hash_table[index];
+ const Element *e = hash_table[index];
while (e) {
@@ -425,8 +406,8 @@ public:
uint32_t hash = Hasher::hash(p_key);
uint32_t index = hash & ((1 << hash_table_power) - 1);
- Entry *e = hash_table[index];
- Entry *p = NULL;
+ Element *e = hash_table[index];
+ Element *p = NULL;
while (e) {
/* checking hash first avoids comparing key, which may take longer */
@@ -463,16 +444,16 @@ public:
}
inline TData &operator[](const TKey &p_key) { //assignment
- Entry *e = NULL;
+ Element *e = NULL;
if (!hash_table)
make_hash_table(); // if no table, make one
else
- e = const_cast<Entry *>(get_entry(p_key));
+ e = const_cast<Element *>(get_element(p_key));
/* if we made it up to here, the pair doesn't exist, create */
if (!e) {
- e = create_entry(p_key);
+ e = create_element(p_key);
CRASH_COND(!e);
check_hash_table(); // perform mantenience routine
}
@@ -510,14 +491,14 @@ public:
} else { /* get the next key */
- const Entry *e = get_entry(*p_key);
+ const Element *e = get_element(*p_key);
ERR_FAIL_COND_V(!e, NULL); /* invalid key supplied */
if (e->next) {
/* if there is a "next" in the list, return that */
return &e->next->pair.key;
} else {
- /* go to next entries */
+ /* go to next elements */
uint32_t index = e->hash & ((1 << hash_table_power) - 1);
index++;
for (int i = index; i < (1 << hash_table_power); i++) {
@@ -552,7 +533,7 @@ public:
while (hash_table[i]) {
- Entry *e = hash_table[i];
+ Element *e = hash_table[i];
hash_table[i] = e->next;
memdelete(e);
}
@@ -582,7 +563,7 @@ public:
return;
for (int i = 0; i < (1 << hash_table_power); i++) {
- Entry *e = hash_table[i];
+ Element *e = hash_table[i];
while (e) {
*p_pairs = &e->pair;
p_pairs++;
@@ -596,7 +577,7 @@ public:
return;
for (int i = 0; i < (1 << hash_table_power); i++) {
- Entry *e = hash_table[i];
+ Element *e = hash_table[i];
while (e) {
p_keys->push_back(e->pair.key);
e = e->next;
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/helper/math_fieldwise.cpp b/core/helper/math_fieldwise.cpp
index 2ce2a70866..228611f8b3 100644
--- a/core/helper/math_fieldwise.cpp
+++ b/core/helper/math_fieldwise.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* fieldwise.cpp */
+/* math_fieldwise.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/core/helper/math_fieldwise.h b/core/helper/math_fieldwise.h
index 4671703f41..400df040a4 100644
--- a/core/helper/math_fieldwise.h
+++ b/core/helper/math_fieldwise.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* fieldwise.h */
+/* math_fieldwise.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/core/image.cpp b/core/image.cpp
index bb1ce2cee3..42684e7ea7 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -530,7 +530,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
int height = p_src_height;
double xfac = (double)width / p_dst_width;
double yfac = (double)height / p_dst_height;
- // coordinates of source points and cooefficiens
+ // coordinates of source points and coefficients
double ox, oy, dx, dy, k1, k2;
int ox1, oy1, ox2, oy2;
// destination pixel values
@@ -561,7 +561,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
}
for (int n = -1; n < 3; n++) {
- // get Y cooefficient
+ // get Y coefficient
k1 = _bicubic_interp_kernel(dy - (double)n);
oy2 = oy1 + n;
@@ -571,7 +571,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
oy2 = ymax;
for (int m = -1; m < 3; m++) {
- // get X cooefficient
+ // get X coefficient
k2 = k1 * _bicubic_interp_kernel((double)m - dx);
ox2 = ox1 + m;
@@ -1013,8 +1013,8 @@ void Image::shrink_x2() {
copymem(w.ptr(), &r[ofs], new_size);
}
- width /= 2;
- height /= 2;
+ width = MAX(width / 2, 1);
+ height = MAX(height / 2, 1);
data = new_img;
} else {
@@ -1061,7 +1061,6 @@ Error Image::generate_mipmaps() {
int size = _get_dst_image_size(width, height, format, mmcount);
data.resize(size);
- print_line("to gen mipmaps w " + itos(width) + " h " + itos(height) + " format " + get_format_name(format) + " mipmaps " + itos(mmcount) + " new size is: " + itos(size));
PoolVector<uint8_t>::Write wp = data.write();
@@ -1256,9 +1255,9 @@ void Image::create(const char **p_xpm) {
if (*line_ptr == '#') {
line_ptr++;
- uint8_t col_r;
- uint8_t col_g;
- uint8_t col_b;
+ uint8_t col_r = 0;
+ uint8_t col_g = 0;
+ uint8_t col_b = 0;
//uint8_t col_a=255;
for (int i = 0; i < 6; i++) {
@@ -2474,6 +2473,7 @@ void Image::fix_alpha_edges() {
if (rp[3] < alpha_threshold)
continue;
+ closest_dist = dist;
closest_color[0] = rp[0];
closest_color[1] = rp[1];
closest_color[2] = rp[2];
diff --git a/core/io/SCsub b/core/io/SCsub
index 4efc902717..79b56cb716 100644
--- a/core/io/SCsub
+++ b/core/io/SCsub
@@ -5,3 +5,4 @@ Import('env')
env.add_source_files(env.core_sources, "*.cpp")
Export('env')
+
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 44fa65e11d..51d48901cf 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -33,9 +33,9 @@
#include "zip_io.h"
#include "thirdparty/misc/fastlz.h"
-#include "thirdparty/zstd/zstd.h"
#include <zlib.h>
+#include <zstd.h>
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
@@ -78,9 +78,16 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,
} break;
case MODE_ZSTD: {
-
+ ZSTD_CCtx *cctx = ZSTD_createCCtx();
+ ZSTD_CCtx_setParameter(cctx, ZSTD_p_compressionLevel, zstd_level);
+ if (zstd_long_distance_matching) {
+ ZSTD_CCtx_setParameter(cctx, ZSTD_p_enableLongDistanceMatching, 1);
+ ZSTD_CCtx_setParameter(cctx, ZSTD_p_windowLog, zstd_window_log_size);
+ }
int max_dst_size = get_max_compressed_buffer_size(p_src_size, MODE_ZSTD);
- return ZSTD_compress(p_dst, max_dst_size, p_src, p_src_size, zstd_level);
+ int ret = ZSTD_compressCCtx(cctx, p_dst, max_dst_size, p_src, p_src_size, zstd_level);
+ ZSTD_freeCCtx(cctx);
+ return ret;
} break;
}
@@ -165,8 +172,11 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
return total;
} break;
case MODE_ZSTD: {
-
- return ZSTD_decompress(p_dst, p_dst_max_size, p_src, p_src_size);
+ ZSTD_DCtx *dctx = ZSTD_createDCtx();
+ if (zstd_long_distance_matching) ZSTD_DCtx_setMaxWindowSize(dctx, 1 << zstd_window_log_size);
+ int ret = ZSTD_decompressDCtx(dctx, p_dst, p_dst_max_size, p_src, p_src_size);
+ ZSTD_freeDCtx(dctx);
+ return ret;
} break;
}
@@ -176,3 +186,5 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p
int Compression::zlib_level = Z_DEFAULT_COMPRESSION;
int Compression::gzip_level = Z_DEFAULT_COMPRESSION;
int Compression::zstd_level = 3;
+bool Compression::zstd_long_distance_matching = false;
+int Compression::zstd_window_log_size = 27;
diff --git a/core/io/compression.h b/core/io/compression.h
index 22d8109d4f..5a9aedec31 100644
--- a/core/io/compression.h
+++ b/core/io/compression.h
@@ -38,6 +38,8 @@ public:
static int zlib_level;
static int gzip_level;
static int zstd_level;
+ static bool zstd_long_distance_matching;
+ static int zstd_window_log_size;
enum Mode {
MODE_FASTLZ,
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
index 859f2e3f8c..9ec03bf32b 100644
--- a/core/io/file_access_buffered.cpp
+++ b/core/io/file_access_buffered.cpp
@@ -76,7 +76,7 @@ void FileAccessBuffered::seek_end(int64_t p_position) {
file.offset = file.size + p_position;
};
-size_t FileAccessBuffered::get_pos() const {
+size_t FileAccessBuffered::get_position() const {
return file.offset;
};
diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h
index d3137058fb..70aaeb8ae0 100644
--- a/core/io/file_access_buffered.h
+++ b/core/io/file_access_buffered.h
@@ -72,7 +72,7 @@ protected:
int get_cache_size();
public:
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual void seek(size_t p_position); ///< seek to a given position
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index 9e41834561..309fc16d09 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -76,6 +76,11 @@ protected:
};
public:
+ void flush() {
+
+ f.flush();
+ };
+
void store_8(uint8_t p_dest) {
f.store_8(p_dest);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 70430ca5d3..514e3c65f0 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -62,7 +62,7 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
block_size = f->get_32();
read_total = f->get_32();
int bc = (read_total / block_size) + 1;
- int acc_ofs = f->get_pos() + bc * 4;
+ int acc_ofs = f->get_position() + bc * 4;
int max_bs = 0;
for (int i = 0; i < bc; i++) {
@@ -232,7 +232,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
seek(read_total + p_position);
}
}
-size_t FileAccessCompressed::get_pos() const {
+size_t FileAccessCompressed::get_position() const {
ERR_FAIL_COND_V(!f, 0);
if (writing) {
@@ -338,6 +338,13 @@ Error FileAccessCompressed::get_error() const {
return read_eof ? ERR_FILE_EOF : OK;
}
+void FileAccessCompressed::flush() {
+ ERR_FAIL_COND(!f);
+ ERR_FAIL_COND(!writing);
+
+ // compressed files keep data in memory till close()
+}
+
void FileAccessCompressed::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 2fe1428752..1d99e5bfd4 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -37,11 +37,11 @@ class FileAccessCompressed : public FileAccess {
Compression::Mode cmode;
bool writing;
- int write_pos;
+ uint32_t write_pos;
uint8_t *write_ptr;
- int write_buffer_size;
- int write_max;
- int block_size;
+ uint32_t write_buffer_size;
+ uint32_t write_max;
+ uint32_t block_size;
mutable bool read_eof;
mutable bool at_end;
@@ -57,7 +57,7 @@ class FileAccessCompressed : public FileAccess {
mutable int read_block_size;
mutable int read_pos;
Vector<ReadBlock> read_blocks;
- int read_total;
+ uint32_t read_total;
String magic;
mutable Vector<uint8_t> buffer;
@@ -74,7 +74,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -84,6 +84,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index cf82d04ac5..e5da307153 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -62,25 +62,25 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
writing = false;
key = p_key;
uint32_t magic = p_base->get_32();
- print_line("MAGIC: " + itos(magic));
ERR_FAIL_COND_V(magic != COMP_MAGIC, ERR_FILE_UNRECOGNIZED);
+
mode = Mode(p_base->get_32());
ERR_FAIL_INDEX_V(mode, MODE_MAX, ERR_FILE_CORRUPT);
ERR_FAIL_COND_V(mode == 0, ERR_FILE_CORRUPT);
- print_line("MODE: " + itos(mode));
+
unsigned char md5d[16];
p_base->get_buffer(md5d, 16);
length = p_base->get_64();
- base = p_base->get_pos();
+ base = p_base->get_position();
ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT);
- int ds = length;
+ uint32_t ds = length;
if (ds % 16) {
ds += 16 - (ds % 16);
}
data.resize(ds);
- int blen = p_base->get_buffer(data.ptr(), ds);
+ uint32_t blen = p_base->get_buffer(data.ptr(), ds);
ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT);
aes256_context ctx;
@@ -199,7 +199,7 @@ void FileAccessEncrypted::seek_end(int64_t p_position) {
seek(data.size() + p_position);
}
-size_t FileAccessEncrypted::get_pos() const {
+size_t FileAccessEncrypted::get_position() const {
return pos;
}
@@ -268,6 +268,12 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
}
}
+void FileAccessEncrypted::flush() {
+ ERR_FAIL_COND(!writing);
+
+ // encrypted files keep data in memory till close()
+}
+
void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!writing);
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index 3df2806a7a..d83fed3e0e 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -48,7 +48,7 @@ private:
size_t base;
size_t length;
Vector<uint8_t> data;
- mutable size_t pos;
+ mutable int pos;
mutable bool eofed;
public:
@@ -61,7 +61,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -71,6 +71,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 5b186b7798..0a5815fca8 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -120,7 +120,7 @@ void FileAccessMemory::seek_end(int64_t p_position) {
pos = length + p_position;
}
-size_t FileAccessMemory::get_pos() const {
+size_t FileAccessMemory::get_position() const {
ERR_FAIL_COND_V(!data, 0);
return pos;
@@ -170,6 +170,10 @@ Error FileAccessMemory::get_error() const {
return pos >= length ? ERR_FILE_EOF : OK;
}
+void FileAccessMemory::flush() {
+ ERR_FAIL_COND(!data);
+}
+
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_COND(!data);
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 7feb16461b..23392719b4 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -51,7 +51,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -62,6 +62,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_byte); ///< store a byte
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index be31076557..a224abd9e7 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));
@@ -244,14 +246,14 @@ FileAccessNetworkClient::~FileAccessNetworkClient() {
memdelete(sem);
}
-void FileAccessNetwork::_set_block(size_t p_offset, const Vector<uint8_t> &p_block) {
+void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) {
int page = p_offset / page_size;
ERR_FAIL_INDEX(page, pages.size());
if (page < pages.size() - 1) {
ERR_FAIL_COND(p_block.size() != page_size);
} else {
- ERR_FAIL_COND((p_block.size() != (total_size % page_size)));
+ ERR_FAIL_COND((p_block.size() != (int)(total_size % page_size)));
}
buffer_mutex->lock();
@@ -348,7 +350,7 @@ void FileAccessNetwork::seek_end(int64_t p_position) {
seek(total_size + p_position);
}
-size_t FileAccessNetwork::get_pos() const {
+size_t FileAccessNetwork::get_position() const {
ERR_FAIL_COND_V(!opened, 0);
return pos;
@@ -454,6 +456,10 @@ Error FileAccessNetwork::get_error() const {
return pos == total_size ? ERR_FILE_EOF : OK;
}
+void FileAccessNetwork::flush() {
+ ERR_FAIL();
+}
+
void FileAccessNetwork::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index d6010cdbac..20614476d0 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -97,7 +97,7 @@ class FileAccessNetwork : public FileAccess {
mutable int last_page;
mutable uint8_t *last_page_buff;
- uint32_t page_size;
+ int page_size;
int read_ahead;
int max_pages;
@@ -121,7 +121,7 @@ class FileAccessNetwork : public FileAccess {
friend class FileAccessNetworkClient;
void _queue_page(int p_page) const;
void _respond(size_t p_len, Error p_status);
- void _set_block(size_t p_offset, const Vector<uint8_t> &p_block);
+ void _set_block(int p_offset, const Vector<uint8_t> &p_block);
public:
enum Command {
@@ -145,7 +145,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -155,6 +155,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index e36ff28220..a7eb8ce6a9 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -140,17 +140,17 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
if (magic != 0x43504447) {
//maybe at he end.... self contained exe
f->seek_end();
- f->seek(f->get_pos() - 4);
+ f->seek(f->get_position() - 4);
magic = f->get_32();
if (magic != 0x43504447) {
memdelete(f);
return false;
}
- f->seek(f->get_pos() - 12);
+ f->seek(f->get_position() - 12);
uint64_t ds = f->get_64();
- f->seek(f->get_pos() - ds - 8);
+ f->seek(f->get_position() - ds - 8);
magic = f->get_32();
if (magic != 0x43504447) {
@@ -166,9 +166,9 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
uint32_t ver_rev = f->get_32();
ERR_EXPLAIN("Pack version unsupported: " + itos(version));
- ERR_FAIL_COND_V(version != PACK_VERSION, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(version != PACK_VERSION, false);
ERR_EXPLAIN("Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "." + itos(ver_rev));
- ERR_FAIL_COND_V(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false);
for (int i = 0; i < 16; i++) {
//reserved
@@ -236,7 +236,7 @@ void FileAccessPack::seek_end(int64_t p_position) {
seek(pf.size + p_position);
}
-size_t FileAccessPack::get_pos() const {
+size_t FileAccessPack::get_position() const {
return pos;
}
@@ -293,6 +293,11 @@ Error FileAccessPack::get_error() const {
return OK;
}
+void FileAccessPack::flush() {
+
+ ERR_FAIL();
+}
+
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 758e9afa8e..12187a353a 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -148,7 +148,7 @@ public:
virtual void seek(size_t p_position);
virtual void seek_end(int64_t p_position = 0);
- virtual size_t get_pos() const;
+ virtual size_t get_position() const;
virtual size_t get_len() const;
virtual bool eof_reached() const;
@@ -161,6 +161,7 @@ public:
virtual Error get_error() const;
+ virtual void flush();
virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src, int p_length);
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 8c99ef2983..ec809011a9 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -65,7 +65,7 @@ static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong si
static long godot_tell(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)opaque;
- return f->get_pos();
+ return f->get_position();
};
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
@@ -76,7 +76,7 @@ static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_pos() + offset;
+ pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
@@ -301,7 +301,7 @@ void FileAccessZip::seek_end(int64_t p_position) {
unzSeekCurrentFile(zfile, get_len() + p_position);
};
-size_t FileAccessZip::get_pos() const {
+size_t FileAccessZip::get_position() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
@@ -353,6 +353,11 @@ Error FileAccessZip::get_error() const {
return OK;
};
+void FileAccessZip::flush() {
+
+ ERR_FAIL();
+}
+
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 2a8ec3fca5..0977b241ee 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -98,7 +98,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -108,6 +108,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index dd56db9bf9..46d52384e5 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -189,16 +189,6 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str
return OK;
}
-Error HTTPClient::send_body_text(const String &p_body) {
-
- return OK;
-}
-
-Error HTTPClient::send_body_data(const PoolByteArray &p_body) {
-
- return OK;
-}
-
bool HTTPClient::has_response() const {
return response_headers.size() != 0;
@@ -297,7 +287,7 @@ Error HTTPClient::poll() {
case StreamPeerTCP::STATUS_CONNECTED: {
if (ssl) {
Ref<StreamPeerSSL> ssl = StreamPeerSSL::create();
- Error err = ssl->connect_to_stream(tcp_connection, true, ssl_verify_host ? conn_host : String());
+ Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, ssl_verify_host ? conn_host : String());
if (err != OK) {
close();
status = STATUS_SSL_HANDSHAKE_ERROR;
@@ -629,8 +619,6 @@ void HTTPClient::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection);
ClassDB::bind_method(D_METHOD("request_raw", "method", "url", "headers", "body"), &HTTPClient::request_raw);
ClassDB::bind_method(D_METHOD("request", "method", "url", "headers", "body"), &HTTPClient::request, DEFVAL(String()));
- ClassDB::bind_method(D_METHOD("send_body_text", "body"), &HTTPClient::send_body_text);
- ClassDB::bind_method(D_METHOD("send_body_data", "body"), &HTTPClient::send_body_data);
ClassDB::bind_method(D_METHOD("close"), &HTTPClient::close);
ClassDB::bind_method(D_METHOD("has_response"), &HTTPClient::has_response);
diff --git a/core/io/http_client.h b/core/io/http_client.h
index 023370ae81..f8a3349e6e 100644
--- a/core/io/http_client.h
+++ b/core/io/http_client.h
@@ -169,8 +169,6 @@ public:
Error request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const PoolVector<uint8_t> &p_body);
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String());
- Error send_body_text(const String &p_body);
- Error send_body_data(const PoolByteArray &p_body);
void close();
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
new file mode 100644
index 0000000000..ce2ce44b1d
--- /dev/null
+++ b/core/io/logger.cpp
@@ -0,0 +1,266 @@
+/*************************************************************************/
+/* logger.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 "logger.h"
+#include "os/dir_access.h"
+#include "os/os.h"
+#include "print_string.h"
+
+// va_copy was defined in the C99, but not in C++ standards before C++11.
+// When you compile C++ without --std=c++<XX> option, compilers still define
+// va_copy, otherwise you have to use the internal version (__va_copy).
+#if !defined(va_copy)
+#if defined(__GNUC__)
+#define va_copy(d, s) __va_copy(d, s)
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
+bool Logger::should_log(bool p_err) {
+ return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
+}
+
+void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ const char *err_type = "**ERROR**";
+ switch (p_type) {
+ case ERR_ERROR: err_type = "**ERROR**"; break;
+ case ERR_WARNING: err_type = "**WARNING**"; break;
+ case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
+ case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
+ default: ERR_PRINT("Unknown error type"); break;
+ }
+
+ const char *err_details;
+ if (p_rationale && *p_rationale)
+ err_details = p_rationale;
+ else
+ err_details = p_code;
+
+ logf_error("%s: %s\n", err_type, err_details);
+ logf_error(" At: %s:%i:%s() - %s\n", p_file, p_line, p_function, p_code);
+}
+
+void Logger::logf(const char *p_format, ...) {
+ if (!should_log(false)) {
+ return;
+ }
+
+ va_list argp;
+ va_start(argp, p_format);
+
+ logv(p_format, argp, false);
+
+ va_end(argp);
+}
+
+void Logger::logf_error(const char *p_format, ...) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ va_list argp;
+ va_start(argp, p_format);
+
+ logv(p_format, argp, true);
+
+ va_end(argp);
+}
+
+Logger::~Logger() {}
+
+void RotatedFileLogger::close_file() {
+ if (file) {
+ memdelete(file);
+ file = NULL;
+ }
+}
+
+void RotatedFileLogger::clear_old_backups() {
+ int max_backups = max_files - 1; // -1 for the current file
+
+ String basename = base_path.get_file().get_basename();
+ String extension = "." + base_path.get_extension();
+
+ DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ if (!da) {
+ return;
+ }
+
+ da->list_dir_begin();
+ String f = da->get_next();
+ Set<String> backups;
+ while (f != String()) {
+ if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path.get_file()) {
+ backups.insert(f);
+ }
+ f = da->get_next();
+ }
+ da->list_dir_end();
+
+ if (backups.size() > max_backups) {
+ // since backups are appended with timestamp and Set iterates them in sorted order,
+ // first backups are the oldest
+ int to_delete = backups.size() - max_backups;
+ for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) {
+ da->remove(E->get());
+ }
+ }
+
+ memdelete(da);
+}
+
+void RotatedFileLogger::rotate_file() {
+ close_file();
+
+ if (FileAccess::exists(base_path)) {
+ if (max_files > 1) {
+ char timestamp[21];
+ OS::Date date = OS::get_singleton()->get_date();
+ OS::Time time = OS::get_singleton()->get_time();
+ sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day, time.hour, time.min, time.sec);
+
+ String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
+
+ DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ if (da) {
+ da->copy(base_path, backup_name);
+ memdelete(da);
+ }
+ clear_old_backups();
+ }
+ } else {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
+ if (da) {
+ da->make_dir_recursive(base_path.get_base_dir());
+ memdelete(da);
+ }
+ }
+
+ file = FileAccess::open(base_path, FileAccess::WRITE);
+}
+
+RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
+ file = NULL;
+ base_path = p_base_path.simplify_path();
+ max_files = p_max_files > 0 ? p_max_files : 1;
+
+ rotate_file();
+}
+
+void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ if (file) {
+ const int static_buf_size = 512;
+ char static_buf[static_buf_size];
+ char *buf = static_buf;
+ va_list list_copy;
+ va_copy(list_copy, p_list);
+ int len = vsnprintf(buf, static_buf_size, p_format, p_list);
+ if (len >= static_buf_size) {
+ buf = (char *)Memory::alloc_static(len + 1);
+ vsnprintf(buf, len + 1, p_format, list_copy);
+ }
+ va_end(list_copy);
+ file->store_buffer((uint8_t *)buf, len);
+ if (len >= static_buf_size) {
+ Memory::free_static(buf);
+ }
+#ifdef DEBUG_ENABLED
+ const bool need_flush = true;
+#else
+ bool need_flush = p_err;
+#endif
+ if (need_flush) {
+ file->flush();
+ }
+ }
+}
+
+RotatedFileLogger::~RotatedFileLogger() {
+ close_file();
+}
+
+void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ if (p_err) {
+ vfprintf(stderr, p_format, p_list);
+ } else {
+ vprintf(p_format, p_list);
+#ifdef DEBUG_ENABLED
+ fflush(stdout);
+#endif
+ }
+}
+
+StdLogger::~StdLogger() {}
+
+CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
+ loggers = p_loggers;
+}
+
+void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ for (int i = 0; i < loggers.size(); ++i) {
+ va_list list_copy;
+ va_copy(list_copy, p_list);
+ loggers[i]->logv(p_format, list_copy, p_err);
+ va_end(list_copy);
+ }
+}
+
+void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ for (int i = 0; i < loggers.size(); ++i) {
+ loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+ }
+}
+
+CompositeLogger::~CompositeLogger() {
+ for (int i = 0; i < loggers.size(); ++i) {
+ memdelete(loggers[i]);
+ }
+}
diff --git a/core/io/logger.h b/core/io/logger.h
new file mode 100644
index 0000000000..cf0cc7699f
--- /dev/null
+++ b/core/io/logger.h
@@ -0,0 +1,107 @@
+/*************************************************************************/
+/* logger.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 LOGGER_H
+#define LOGGER_H
+
+#include "os/file_access.h"
+#include "ustring.h"
+#include "vector.h"
+#include <stdarg.h>
+
+class Logger {
+protected:
+ bool should_log(bool p_err);
+
+public:
+ enum ErrorType {
+ ERR_ERROR,
+ ERR_WARNING,
+ ERR_SCRIPT,
+ ERR_SHADER
+ };
+
+ virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0;
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+
+ void logf(const char *p_format, ...);
+ void logf_error(const char *p_format, ...);
+
+ virtual ~Logger();
+};
+
+/**
+ * Writes messages to stdout/stderr.
+ */
+class StdLogger : public Logger {
+
+public:
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+ virtual ~StdLogger();
+};
+
+/**
+ * Writes messages to the specified file. If the file already exists, creates a copy (backup)
+ * of it with timestamp appended to the file name. Maximum number of backups is configurable.
+ * When maximum is reached, the oldest backups are erased. With the maximum being equal to 1,
+ * it acts as a simple file logger.
+ */
+class RotatedFileLogger : public Logger {
+ String base_path;
+ int max_files;
+
+ FileAccess *file;
+
+ void rotate_file_without_closing();
+ void close_file();
+ void clear_old_backups();
+ void rotate_file();
+
+public:
+ RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
+
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+
+ virtual ~RotatedFileLogger();
+};
+
+class CompositeLogger : public Logger {
+ Vector<Logger *> loggers;
+
+public:
+ CompositeLogger(Vector<Logger *> p_loggers);
+
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+
+ virtual ~CompositeLogger();
+};
+
+#endif \ No newline at end of file
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index af7db904e9..d388a622de 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -333,14 +333,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
len -= 12;
buf += 12;
- int total = namecount + subnamecount;
+ uint32_t total = namecount + subnamecount;
if (flags & 2)
total++;
if (r_len)
(*r_len) += 12;
- for (int i = 0; i < total; i++) {
+ for (uint32_t i = 0; i < total; i++) {
ERR_FAIL_COND_V((int)len < 4, ERR_INVALID_DATA);
strlen = decode_uint32(buf);
@@ -566,7 +566,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
if (count) {
data.resize(count);
PoolVector<uint8_t>::Write w = data.write();
- for (int i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < count; i++) {
w[i] = buf[i];
}
@@ -597,7 +597,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
//const int*rbuf=(const int*)buf;
data.resize(count);
PoolVector<int>::Write w = data.write();
- for (int i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < count; i++) {
w[i] = decode_uint32(&buf[i * 4]);
}
@@ -624,7 +624,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int
//const float*rbuf=(const float*)buf;
data.resize(count);
PoolVector<float>::Write w = data.write();
- for (int i = 0; i < count; i++) {
+ for (uint32_t i = 0; i < count; i++) {
w[i] = decode_float(&buf[i * 4]);
}
@@ -1140,8 +1140,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
if (buf) {
encode_uint32(0, buf);
buf += 4;
- r_len += 4;
}
+ r_len += 4;
+
} else {
_encode_string(obj->get_class(), buf, r_len);
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index f1f5b6f538..23e86580d1 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -119,7 +119,7 @@ Error PCKPacker::flush(bool p_verbose) {
for (int i = 0; i < files.size(); i++) {
file->store_pascal_string(files[i].path);
- files[i].offset_offset = file->get_pos();
+ files[i].offset_offset = file->get_position();
file->store_64(0); // offset
file->store_64(files[i].size); // size
@@ -130,10 +130,10 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_32(0);
};
- uint64_t ofs = file->get_pos();
+ uint64_t ofs = file->get_position();
ofs = _align(ofs, alignment);
- _pad(file, ofs - file->get_pos());
+ _pad(file, ofs - file->get_position());
const uint32_t buf_max = 65536;
uint8_t *buf = memnew_arr(uint8_t, buf_max);
@@ -150,7 +150,7 @@ Error PCKPacker::flush(bool p_verbose) {
to_write -= read;
};
- uint64_t pos = file->get_pos();
+ uint64_t pos = file->get_position();
file->seek(files[i].offset_offset); // go back to store the file's offset
file->store_64(ofs);
file->seek(pos);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 965d11e414..03c3c5f615 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 {
@@ -102,7 +102,7 @@ StringName ResourceInteractiveLoaderBinary::_get_string() {
uint32_t id = f->get_32();
if (id & 0x80000000) {
- uint32_t len = id & 0x7FFFFFFF;
+ int len = id & 0x7FFFFFFF;
if (len > str_buf.size()) {
str_buf.resize(len);
}
@@ -282,7 +282,6 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
property = _get_string();
NodePath np = NodePath(names, subnames, absolute, property);
- //print_line("got path: "+String(np));
r_v = np;
@@ -336,9 +335,9 @@ Error ResourceInteractiveLoaderBinary::parse_variant(Variant &r_v) {
} break;
case OBJECT_EXTERNAL_RESOURCE_INDEX: {
//new file format, just refers to an index in the external list
- uint32_t erindex = f->get_32();
+ int erindex = f->get_32();
- if (erindex >= external_resources.size()) {
+ if (erindex < 0 || erindex >= external_resources.size()) {
WARN_PRINT("Broken external resource! (index out of size");
r_v = Variant();
} else {
@@ -640,7 +639,6 @@ Error ResourceInteractiveLoaderBinary::poll() {
String path = external_resources[s].path;
- print_line("load external res: " + path);
if (remaps.has(path)) {
path = remaps[path];
}
@@ -706,8 +704,6 @@ Error ResourceInteractiveLoaderBinary::poll() {
String t = get_unicode_string();
- // print_line("loading resource of type "+t+" path is "+path);
-
Object *obj = ClassDB::instance(t);
if (!obj) {
error = ERR_FILE_CORRUPT;
@@ -854,12 +850,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 +859,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));
@@ -878,7 +872,7 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
f->close();
- ERR_EXPLAIN("File Format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a a new engine version: " + local_path);
+ ERR_EXPLAIN("File Format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path);
ERR_FAIL();
}
@@ -909,20 +903,6 @@ void ResourceInteractiveLoaderBinary::open(FileAccess *p_f) {
external_resources.push_back(er);
}
- //see if the exporter has different set of external resources for more efficient loading
- /*
- String preload_depts = "deps/"+res_path.md5_text();
- if (Globals::get_singleton()->has(preload_depts)) {
- external_resources.clear();
- //ignore external resources and use these
- NodePath depts=Globals::get_singleton()->get(preload_depts);
- external_resources.resize(depts.get_name_count());
- for(int i=0;i<depts.get_name_count();i++) {
- external_resources[i].path=depts.get_name(i);
- }
- print_line(res_path+" - EXTERNAL RESOURCES: "+itos(external_resources.size()));
- }*/
-
print_bl("ext resources: " + itos(ext_resources_size));
uint32_t int_resources_size = f->get_32();
@@ -964,18 +944,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 +967,6 @@ ResourceInteractiveLoaderBinary::ResourceInteractiveLoaderBinary() {
f = NULL;
stage = 0;
- endian_swap = false;
- use_real64 = false;
error = OK;
translation_remapped = false;
}
@@ -1005,7 +977,7 @@ ResourceInteractiveLoaderBinary::~ResourceInteractiveLoaderBinary() {
memdelete(f);
}
-Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path, Error *r_error) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) {
if (r_error)
*r_error = ERR_FILE_CANT_OPEN;
@@ -1019,7 +991,8 @@ Ref<ResourceInteractiveLoader> ResourceFormatLoaderBinary::load_interactive(cons
}
Ref<ResourceInteractiveLoaderBinary> ria = memnew(ResourceInteractiveLoaderBinary);
- ria->local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ String path = p_original_path != "" ? p_original_path : p_path;
+ ria->local_path = ProjectSettings::get_singleton()->localize_path(path);
ria->res_path = ria->local_path;
//ria->set_local_path( Globals::get_singleton()->localize_path(p_path) );
ria->open(f);
@@ -1116,19 +1089,20 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
memdelete(f);
}
ERR_FAIL_COND_V(!fw, ERR_CANT_CREATE);
+
+ uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
+ fw->store_buffer(magic, 4);
}
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
@@ -1177,7 +1151,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
memdelete(f);
memdelete(fw);
- ERR_EXPLAIN("File Format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a a new engine version: " + local_path);
+ ERR_EXPLAIN("File Format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path);
ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
}
@@ -1187,7 +1161,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
save_ustring(fw, get_ustring(f)); //type
- size_t md_ofs = f->get_pos();
+ size_t md_ofs = f->get_position();
size_t importmd_ofs = f->get_64();
fw->store_64(0); //metadata offset
@@ -1235,7 +1209,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
save_ustring(fw, path);
}
- int64_t size_diff = (int64_t)fw->get_pos() - (int64_t)f->get_pos();
+ int64_t size_diff = (int64_t)fw->get_position() - (int64_t)f->get_position();
//internal resources
uint32_t int_resources_size = f->get_32();
@@ -1789,8 +1763,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
@@ -1810,11 +1783,11 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
if (skip_editor && F->get().name.begins_with("__editor"))
continue;
- if (F->get().usage & PROPERTY_USAGE_STORAGE) {
+ if ((F->get().usage & PROPERTY_USAGE_STORAGE)) {
Property p;
p.name_idx = get_string_index(F->get().name);
p.value = E->get()->get(F->get().name);
- if ((F->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero()) || (F->get().usage & PROPERTY_USAGE_STORE_IF_NONONE && p.value.is_one()))
+ if (((F->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO) && p.value.is_zero()) || ((F->get().usage & PROPERTY_USAGE_STORE_IF_NONONE) && p.value.is_one()))
continue;
p.pi = F->get();
@@ -1889,7 +1862,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
} else {
save_unicode_string(r->get_path()); //actual external
}
- ofs_pos.push_back(f->get_pos());
+ ofs_pos.push_back(f->get_position());
f->store_64(0); //offset in 64 bits
}
@@ -1900,7 +1873,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
ResourceData &rd = E->get();
- ofs_table.push_back(f->get_pos());
+ ofs_table.push_back(f->get_position());
save_unicode_string(rd.type);
f->store_32(rd.properties.size());
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 1bd0d333c6..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;
@@ -101,7 +99,7 @@ public:
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
public:
- virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
+ virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp
index 5a4f29fe67..401d704222 100644
--- a/core/io/resource_import.cpp
+++ b/core/io/resource_import.cpp
@@ -32,13 +32,17 @@
#include "os/os.h"
#include "variant_parser.h"
-Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type) const {
+Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid) const {
Error err;
FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
- if (!f)
+ if (!f) {
+ if (r_valid) {
+ *r_valid = false;
+ }
return err;
+ }
VariantParser::StreamFile stream;
stream.f = f;
@@ -47,6 +51,10 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
Variant value;
VariantParser::Tag next_tag;
+ if (r_valid) {
+ *r_valid = true;
+ }
+
int lines = 0;
String error_text;
bool path_found = false; //first match must have priority
@@ -69,7 +77,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
if (assign != String()) {
if (!path_found && assign.begins_with("path.") && r_path_and_type.path == String()) {
String feature = assign.get_slicec('.', 1);
- if (OS::get_singleton()->check_feature_support(feature)) {
+ if (OS::get_singleton()->has_feature(feature)) {
r_path_and_type.path = value;
path_found = true; //first match must have priority
}
@@ -79,6 +87,12 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
path_found = true; //first match must have priority
} else if (assign == "type") {
r_path_and_type.type = value;
+ } else if (assign == "importer") {
+ r_path_and_type.importer = value;
+ } else if (assign == "valid") {
+ if (r_valid) {
+ *r_valid = value;
+ }
}
} else if (next_tag.name != "remap") {
@@ -107,7 +121,7 @@ RES ResourceFormatImporter::load(const String &p_path, const String &p_original_
return RES();
}
- RES res = ResourceLoader::load(pat.path, pat.type, false, r_error);
+ RES res = ResourceLoader::_load(pat.path, p_path, pat.type, false, r_error);
#ifdef TOOLS_ENABLED
if (res.is_valid()) {
@@ -172,6 +186,29 @@ bool ResourceFormatImporter::can_be_imported(const String &p_path) const {
return ResourceFormatLoader::recognize_path(p_path);
}
+int ResourceFormatImporter::get_import_order(const String &p_path) const {
+
+ Ref<ResourceImporter> importer;
+
+ if (FileAccess::exists(p_path + ".import")) {
+
+ PathAndType pat;
+ Error err = _get_path_and_type(p_path, pat);
+
+ if (err == OK) {
+ importer = get_importer_by_name(pat.importer);
+ }
+ } else {
+
+ importer = get_importer_by_extension(p_path.get_extension().to_lower());
+ }
+
+ if (importer.is_valid())
+ return importer->get_import_order();
+
+ return 0;
+}
+
bool ResourceFormatImporter::handles_type(const String &p_type) const {
for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
@@ -245,6 +282,14 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
memdelete(f);
}
+bool ResourceFormatImporter::is_import_valid(const String &p_path) const {
+
+ bool valid = true;
+ PathAndType pat;
+ _get_path_and_type(p_path, pat, &valid);
+ return valid;
+}
+
String ResourceFormatImporter::get_resource_type(const String &p_path) const {
PathAndType pat;
@@ -271,7 +316,7 @@ void ResourceFormatImporter::get_dependencies(const String &p_path, List<String>
return ResourceLoader::get_dependencies(pat.path, p_dependencies, p_add_types);
}
-Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) {
+Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) const {
for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
if (E->get()->get_importer_name() == p_name) {
@@ -295,7 +340,7 @@ void ResourceFormatImporter::get_importers_for_extension(const String &p_extensi
}
}
-Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) {
+Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) const {
Ref<ResourceImporter> importer;
float priority = 0;
diff --git a/core/io/resource_import.h b/core/io/resource_import.h
index bf0bf3987a..28489b5d34 100644
--- a/core/io/resource_import.h
+++ b/core/io/resource_import.h
@@ -38,9 +38,10 @@ class ResourceFormatImporter : public ResourceFormatLoader {
struct PathAndType {
String path;
String type;
+ String importer;
};
- Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type) const;
+ Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid = NULL) const;
static ResourceFormatImporter *singleton;
@@ -54,17 +55,19 @@ public:
virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual bool is_import_valid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual bool can_be_imported(const String &p_path) const;
+ virtual int get_import_order(const String &p_path) const;
String get_internal_resource_path(const String &p_path) const;
void get_internal_resource_path_list(const String &p_path, List<String> *r_paths);
void add_importer(const Ref<ResourceImporter> &p_importer) { importers.insert(p_importer); }
void remove_importer(const Ref<ResourceImporter> &p_importer) { importers.erase(p_importer); }
- Ref<ResourceImporter> get_importer_by_name(const String &p_name);
- Ref<ResourceImporter> get_importer_by_extension(const String &p_extension);
+ Ref<ResourceImporter> get_importer_by_name(const String &p_name) const;
+ Ref<ResourceImporter> get_importer_by_extension(const String &p_extension) const;
void get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter> > *r_importers);
String get_import_base_path(const String &p_for_file) const;
@@ -81,6 +84,7 @@ public:
virtual String get_save_extension() const = 0;
virtual String get_resource_type() const = 0;
virtual float get_priority() const { return 1.0; }
+ virtual int get_import_order() const { return 0; }
struct ImportOption {
PropertyInfo option;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index f0e804e2fa..ed0d491679 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -109,10 +109,10 @@ public:
ResourceInteractiveLoaderDefault() {}
};
-Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, Error *r_error) {
+Ref<ResourceInteractiveLoader> ResourceFormatLoader::load_interactive(const String &p_path, const String &p_original_path, Error *r_error) {
//either this
- Ref<Resource> res = load(p_path, p_path, r_error);
+ Ref<Resource> res = load(p_path, p_original_path, r_error);
if (res.is_null())
return Ref<ResourceInteractiveLoader>();
@@ -126,7 +126,7 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa
String path = p_path;
//or this must be implemented
- Ref<ResourceInteractiveLoader> ril = load_interactive(p_path, r_error);
+ Ref<ResourceInteractiveLoader> ril = load_interactive(p_path, p_original_path, r_error);
if (!ril.is_valid())
return RES();
ril->set_local_path(p_original_path);
@@ -157,6 +157,34 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *
///////////////////////////////////
+RES ResourceLoader::_load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
+
+ bool found = false;
+
+ // Try all loaders and pick the first match for the type hint
+ for (int i = 0; i < loader_count; i++) {
+
+ if (!loader[i]->recognize_path(p_path, p_type_hint)) {
+ continue;
+ }
+ found = true;
+ RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error);
+ if (res.is_null()) {
+ continue;
+ }
+
+ return res;
+ }
+
+ if (found) {
+ ERR_EXPLAIN("Failed loading resource: " + p_path);
+ } else {
+ ERR_EXPLAIN("No loader found for resource: " + p_path);
+ }
+ ERR_FAIL_V(RES());
+ return RES();
+}
+
RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
if (r_error)
@@ -183,45 +211,29 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p
if (OS::get_singleton()->is_stdout_verbose())
print_line("load resource: " + path);
- bool found = false;
- // Try all loaders and pick the first match for the type hint
- for (int i = 0; i < loader_count; i++) {
+ RES res = _load(path, local_path, p_type_hint, p_no_cache, r_error);
- if (!loader[i]->recognize_path(path, p_type_hint)) {
- continue;
- }
- found = true;
- RES res = loader[i]->load(path, path, r_error);
- if (res.is_null()) {
- continue;
- }
- if (!p_no_cache)
- res->set_path(local_path);
+ if (res.is_null()) {
+ return RES();
+ }
+ if (!p_no_cache)
+ res->set_path(local_path);
- if (xl_remapped)
- res->set_as_translation_remapped(true);
+ if (xl_remapped)
+ res->set_as_translation_remapped(true);
#ifdef TOOLS_ENABLED
- res->set_edited(false);
- if (timestamp_on_load) {
- uint64_t mt = FileAccess::get_modified_time(path);
- //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt);
- res->set_last_modified_time(mt);
- }
-#endif
-
- return res;
+ res->set_edited(false);
+ if (timestamp_on_load) {
+ uint64_t mt = FileAccess::get_modified_time(path);
+ //printf("mt %s: %lli\n",remapped_path.utf8().get_data(),mt);
+ res->set_last_modified_time(mt);
}
+#endif
- if (found) {
- ERR_EXPLAIN("Failed loading resource: " + path);
- } else {
- ERR_EXPLAIN("No loader found for resource: " + path);
- }
- ERR_FAIL_V(RES());
- return RES();
+ return res;
}
Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) {
@@ -262,7 +274,7 @@ Ref<ResourceInteractiveLoader> ResourceLoader::load_interactive(const String &p_
if (!loader[i]->recognize_path(path, p_type_hint))
continue;
found = true;
- Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(path, r_error);
+ Ref<ResourceInteractiveLoader> ril = loader[i]->load_interactive(path, local_path, r_error);
if (ril.is_null())
continue;
if (!p_no_cache)
@@ -296,6 +308,56 @@ void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_l
}
}
+int ResourceLoader::get_import_order(const String &p_path) {
+
+ String path = _path_remap(p_path);
+
+ String local_path;
+ if (path.is_rel_path())
+ local_path = "res://" + path;
+ else
+ local_path = ProjectSettings::get_singleton()->localize_path(path);
+
+ for (int i = 0; i < loader_count; i++) {
+
+ if (!loader[i]->recognize_path(local_path))
+ continue;
+ /*
+ if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
+ continue;
+ */
+
+ return loader[i]->get_import_order(p_path);
+ }
+
+ return 0;
+}
+
+bool ResourceLoader::is_import_valid(const String &p_path) {
+
+ String path = _path_remap(p_path);
+
+ String local_path;
+ if (path.is_rel_path())
+ local_path = "res://" + path;
+ else
+ local_path = ProjectSettings::get_singleton()->localize_path(path);
+
+ for (int i = 0; i < loader_count; i++) {
+
+ if (!loader[i]->recognize_path(local_path))
+ continue;
+ /*
+ if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
+ continue;
+ */
+
+ return loader[i]->is_import_valid(p_path);
+ }
+
+ return false; //not found
+}
+
void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
String path = _path_remap(p_path);
@@ -430,7 +492,7 @@ void ResourceLoader::reload_translation_remaps() {
void ResourceLoader::load_translation_remaps() {
- if (!ProjectSettings::get_singleton()->has("locale/translation_remaps"))
+ if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps"))
return;
Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index 9e059c2977..5deffbca1a 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -57,7 +57,7 @@ public:
class ResourceFormatLoader {
public:
- virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, Error *r_error = NULL);
+ virtual Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const;
@@ -66,6 +66,8 @@ public:
virtual String get_resource_type(const String &p_path) const = 0;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map) { return OK; }
+ virtual bool is_import_valid(const String &p_path) const { return true; }
+ virtual int get_import_order(const String &p_path) const { return 0; }
virtual ~ResourceFormatLoader() {}
};
@@ -95,6 +97,10 @@ class ResourceLoader {
static SelfList<Resource>::List remapped_list;
+ friend class ResourceFormatImporter;
+ //internal load function
+ static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, bool p_no_cache, Error *r_error);
+
public:
static Ref<ResourceInteractiveLoader> load_interactive(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);
static RES load(const String &p_path, const String &p_type_hint = "", bool p_no_cache = false, Error *r_error = NULL);
@@ -104,6 +110,8 @@ public:
static String get_resource_type(const String &p_path);
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
+ static bool is_import_valid(const String &p_path);
+ static int get_import_order(const String &p_path);
static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load = p_timestamp; }
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index 1006158003..2583eb369d 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -405,9 +405,9 @@ void StreamPeer::_bind_methods() {
void StreamPeerBuffer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("seek", "pos"), &StreamPeerBuffer::seek);
+ ClassDB::bind_method(D_METHOD("seek", "position"), &StreamPeerBuffer::seek);
ClassDB::bind_method(D_METHOD("get_size"), &StreamPeerBuffer::get_size);
- ClassDB::bind_method(D_METHOD("get_pos"), &StreamPeerBuffer::get_pos);
+ ClassDB::bind_method(D_METHOD("get_position"), &StreamPeerBuffer::get_position);
ClassDB::bind_method(D_METHOD("resize", "size"), &StreamPeerBuffer::resize);
ClassDB::bind_method(D_METHOD("set_data_array", "data"), &StreamPeerBuffer::set_data_array);
ClassDB::bind_method(D_METHOD("get_data_array"), &StreamPeerBuffer::get_data_array);
@@ -446,6 +446,7 @@ Error StreamPeerBuffer::get_data(uint8_t *p_buffer, int p_bytes) {
return OK;
}
+
Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) {
if (pointer + p_bytes > data.size()) {
@@ -463,6 +464,8 @@ Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_
pointer += r_received;
// FIXME: return what? OK or ERR_*
+ // return OK for now so we don't maybe return garbage
+ return OK;
}
int StreamPeerBuffer::get_available_bytes() const {
@@ -481,7 +484,7 @@ int StreamPeerBuffer::get_size() const {
return data.size();
}
-int StreamPeerBuffer::get_pos() const {
+int StreamPeerBuffer::get_position() const {
return pointer;
}
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index 1ee997c123..b120d18501 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -111,7 +111,7 @@ public:
void seek(int p_pos);
int get_size() const;
- int get_pos() const;
+ int get_position() const;
void resize(int p_size);
void set_data_array(const PoolVector<uint8_t> &p_data);
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 353eabea45..92af247823 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -51,8 +51,8 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S
Ref<Translation> translation = Ref<Translation>(memnew(Translation));
int line = 1;
- bool skip_this;
- bool skip_next;
+ bool skip_this = false;
+ bool skip_next = false;
while (true) {
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 62110bfe24..8ae68183d7 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -369,7 +369,7 @@ void XMLParser::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_empty"), &XMLParser::is_empty);
ClassDB::bind_method(D_METHOD("get_current_line"), &XMLParser::get_current_line);
ClassDB::bind_method(D_METHOD("skip_section"), &XMLParser::skip_section);
- ClassDB::bind_method(D_METHOD("seek", "pos"), &XMLParser::seek);
+ ClassDB::bind_method(D_METHOD("seek", "position"), &XMLParser::seek);
ClassDB::bind_method(D_METHOD("open", "file"), &XMLParser::open);
ClassDB::bind_method(D_METHOD("open_buffer", "buffer"), &XMLParser::open_buffer);
@@ -385,7 +385,7 @@ void XMLParser::_bind_methods() {
Error XMLParser::read() {
// if not end reached, parse the node
- if (P && (P - data) < length - 1 && *P != 0) {
+ if (P && (P - data) < (int64_t)length - 1 && *P != 0) {
_parse_current_node();
return OK;
}
diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h
index 28c57b567f..26616ed94a 100644
--- a/core/io/xml_parser.h
+++ b/core/io/xml_parser.h
@@ -67,7 +67,7 @@ public:
private:
char *data;
char *P;
- int length;
+ uint64_t length;
void unescape(String &p_str);
Vector<String> special_characters;
String node_name;
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 8cf971ee08..ce3c919b77 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -72,7 +72,7 @@ static uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong si
static long zipio_tell(voidpf opaque, voidpf stream) {
FileAccess *f = *(FileAccess **)opaque;
- return f->get_pos();
+ return f->get_position();
};
static long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
@@ -83,7 +83,7 @@ static long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_pos() + offset;
+ pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
diff --git a/core/list.h b/core/list.h
index 0cad6038ff..da201e9868 100644
--- a/core/list.h
+++ b/core/list.h
@@ -180,7 +180,7 @@ private:
public:
/**
- * return an const iterator to the beginning of the list.
+ * return a const iterator to the beginning of the list.
*/
_FORCE_INLINE_ const Element *front() const {
@@ -195,7 +195,7 @@ public:
};
/**
- * return an const iterator to the last member of the list.
+ * return a const iterator to the last member of the list.
*/
_FORCE_INLINE_ const Element *back() const {
@@ -291,6 +291,54 @@ public:
erase(_data->first);
}
+ Element *insert_after(Element *p_element, const T &p_value) {
+ CRASH_COND(p_element && (!_data || p_element->data != _data));
+
+ if (!p_element) {
+ return push_back(p_value);
+ }
+
+ Element *n = memnew_allocator(Element, A);
+ n->value = (T &)p_value;
+ n->prev_ptr = p_element;
+ n->next_ptr = p_element->next_ptr;
+ n->data = _data;
+
+ if (!p_element->next_ptr) {
+ _data->last = n;
+ }
+
+ p_element->next_ptr = n;
+
+ _data->size_cache++;
+
+ return n;
+ }
+
+ Element *insert_before(Element *p_element, const T &p_value) {
+ CRASH_COND(p_element && (!_data || p_element->data != _data));
+
+ if (!p_element) {
+ return push_back(p_value);
+ }
+
+ Element *n = memnew_allocator(Element, A);
+ n->value = (T &)p_value;
+ n->prev_ptr = p_element->prev_ptr;
+ n->next_ptr = p_element;
+ n->data = _data;
+
+ if (!p_element->prev_ptr) {
+ _data->first = n;
+ }
+
+ p_element->prev_ptr = n;
+
+ _data->size_cache++;
+
+ return n;
+ }
+
/**
* find an element in the list,
*/
diff --git a/core/make_binders.py b/core/make_binders.py
index 6468c029f0..6f42c6e8eb 100644
--- a/core/make_binders.py
+++ b/core/make_binders.py
@@ -244,7 +244,7 @@ def make_version(template, nargs, argmax, const, ret):
def run(target, source, env):
- versions = 10
+ versions = 11
versions_ext = 6
text = ""
text_ext = ""
diff --git a/core/map.h b/core/map.h
index 75a38a3440..fb24a5868c 100644
--- a/core/map.h
+++ b/core/map.h
@@ -31,6 +31,7 @@
#define MAP_H
#include "set.h"
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -52,7 +53,6 @@ public:
private:
friend class Map<K, V, C, A>;
- //Color color;
int color;
Element *right;
Element *left;
@@ -61,7 +61,6 @@ public:
Element *_prev;
K _key;
V _value;
-
//_Data *data;
public:
@@ -147,7 +146,6 @@ private:
#ifdef GLOBALNIL_DISABLED
memdelete_allocator<Element, A>(_nil);
#endif
- //memdelete_allocator<Element,A>(_root);
}
};
@@ -158,6 +156,7 @@ private:
ERR_FAIL_COND(p_node == _data._nil && p_color == RED);
p_node->color = p_color;
}
+
inline void _rotate_left(Element *p_node) {
Element *r = p_node->right;
@@ -206,8 +205,9 @@ private:
while (node == node->parent->right) {
node = node->parent;
}
+
if (node->parent == _data._root)
- return NULL;
+ return NULL; // No successor, as p_node = last node
return node->parent;
}
}
@@ -225,10 +225,11 @@ private:
} else {
while (node == node->parent->left) {
- if (node->parent == _data._root)
- return NULL;
node = node->parent;
}
+
+ if (node == _data._root)
+ return NULL; // No predecessor, as p_node = first node
return node->parent;
}
}
@@ -239,16 +240,15 @@ private:
C less;
while (node != _data._nil) {
-
if (less(p_key, node->_key))
node = node->left;
else if (less(node->_key, p_key))
node = node->right;
else
- break; // found
+ return node; // found
}
- return (node != _data._nil) ? node : NULL;
+ return NULL;
}
Element *_find_closest(const K &p_key) const {
@@ -265,24 +265,68 @@ private:
else if (less(node->_key, p_key))
node = node->right;
else
- break; // found
+ return node; // found
}
- if (node == _data._nil) {
- if (prev == NULL)
- return NULL;
- if (less(p_key, prev->_key)) {
+ if (prev == NULL)
+ return NULL; // tree empty
- prev = prev->_prev;
- }
+ if (less(p_key, prev->_key))
+ prev = prev->_prev;
- return prev;
+ return prev;
+ }
- } else
- return node;
+ void _insert_rb_fix(Element *p_new_node) {
+
+ Element *node = p_new_node;
+ Element *nparent = node->parent;
+ Element *ngrand_parent;
+
+ while (nparent->color == RED) {
+ ngrand_parent = nparent->parent;
+
+ if (nparent == ngrand_parent->left) {
+ if (ngrand_parent->right->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->right, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->right) {
+ _rotate_left(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_right(ngrand_parent);
+ }
+ } else {
+ if (ngrand_parent->left->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->left, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->left) {
+ _rotate_right(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_left(ngrand_parent);
+ }
+ }
+ }
+
+ _set_color(_data._root->left, BLACK);
}
- Element *_insert(const K &p_key, bool &r_exists) {
+ Element *_insert(const K &p_key, const V &p_value) {
Element *new_parent = _data._root;
Element *node = _data._root->left;
@@ -297,27 +341,25 @@ private:
else if (less(node->_key, p_key))
node = node->right;
else {
- r_exists = true;
- return node;
+ node->_value = p_value;
+ return node; // Return existing node with new value
}
}
Element *new_node = memnew_allocator(Element, A);
-
new_node->parent = new_parent;
new_node->right = _data._nil;
new_node->left = _data._nil;
new_node->_key = p_key;
+ new_node->_value = p_value;
//new_node->data=_data;
- if (new_parent == _data._root || less(p_key, new_parent->_key)) {
+ if (new_parent == _data._root || less(p_key, new_parent->_key)) {
new_parent->left = new_node;
} else {
new_parent->right = new_node;
}
- r_exists = false;
-
new_node->_next = _successor(new_node);
new_node->_prev = _predecessor(new_node);
if (new_node->_next)
@@ -325,167 +367,112 @@ private:
if (new_node->_prev)
new_node->_prev->_next = new_node;
- return new_node;
- }
-
- Element *_insert_rb(const K &p_key, const V &p_value) {
-
- bool exists = false;
- Element *new_node = _insert(p_key, exists);
-
- if (new_node) {
- new_node->_value = p_value;
- }
- if (exists)
- return new_node;
-
- Element *node = new_node;
_data.size_cache++;
-
- while (node->parent->color == RED) {
-
- if (node->parent == node->parent->parent->left) {
-
- Element *aux = node->parent->parent->right;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->right) {
- node = node->parent;
- _rotate_left(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_right(node->parent->parent);
- }
- } else {
- Element *aux = node->parent->parent->left;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->left) {
- node = node->parent;
- _rotate_right(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_left(node->parent->parent);
- }
- }
- }
- _set_color(_data._root->left, BLACK);
+ _insert_rb_fix(new_node);
return new_node;
}
- void _erase_fix(Element *p_node) {
+ void _erase_fix_rb(Element *p_node) {
Element *root = _data._root->left;
- Element *node = p_node;
-
- while ((node->color == BLACK) && (root != node)) {
- if (node == node->parent->left) {
- Element *aux = node->parent->right;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_left(node->parent);
- aux = node->parent->right;
- }
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ Element *node = _data._nil;
+ Element *sibling = p_node;
+ Element *parent = sibling->parent;
+
+ while (node != root) { // If red node found, will exit at a break
+ if (sibling->color == RED) {
+ _set_color(sibling, BLACK);
+ _set_color(parent, RED);
+ if (sibling == parent->right) {
+ sibling = sibling->left;
+ _rotate_left(parent);
} else {
- if (aux->right->color == BLACK) {
- _set_color(aux->left, BLACK);
- _set_color(aux, RED);
- _rotate_right(aux);
- aux = node->parent->right;
- }
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->right, BLACK);
- _rotate_left(node->parent);
- node = root; /* this is to exit while loop */
+ sibling = sibling->right;
+ _rotate_right(parent);
}
- } else { /* the code below is has left and right switched from above */
- Element *aux = node->parent->left;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_right(node->parent);
- aux = node->parent->left;
+ }
+ if ((sibling->left->color == BLACK) && (sibling->right->color == BLACK)) {
+ _set_color(sibling, RED);
+ if (parent->color == RED) {
+ _set_color(parent, BLACK);
+ break;
+ } else { // loop: haven't found any red nodes yet
+ node = parent;
+ parent = node->parent;
+ sibling = (node == parent->left) ? parent->right : parent->left;
}
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ } else {
+ if (sibling == parent->right) {
+ if (sibling->right->color == BLACK) {
+ _set_color(sibling->left, BLACK);
+ _set_color(sibling, RED);
+ _rotate_right(sibling);
+ sibling = sibling->parent;
+ }
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->right, BLACK);
+ _rotate_left(parent);
+ break;
} else {
- if (aux->left->color == BLACK) {
- _set_color(aux->right, BLACK);
- _set_color(aux, RED);
- _rotate_left(aux);
- aux = node->parent->left;
+ if (sibling->left->color == BLACK) {
+ _set_color(sibling->right, BLACK);
+ _set_color(sibling, RED);
+ _rotate_left(sibling);
+ sibling = sibling->parent;
}
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->left, BLACK);
- _rotate_right(node->parent);
- node = root;
+
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->left, BLACK);
+ _rotate_right(parent);
+ break;
}
}
}
- _set_color(node, BLACK);
-
ERR_FAIL_COND(_data._nil->color != BLACK);
}
void _erase(Element *p_node) {
- Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : _successor(p_node);
- if (!rp)
- rp = _data._nil;
+ Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- if (_data._root == (node->parent = rp->parent)) {
- _data._root->left = node;
+ Element *sibling;
+ if (rp == rp->parent->left) {
+ rp->parent->left = node;
+ sibling = rp->parent->right;
} else {
- if (rp == rp->parent->left) {
- rp->parent->left = node;
- } else {
- rp->parent->right = node;
- }
+ rp->parent->right = node;
+ sibling = rp->parent->left;
+ }
+
+ if (node->color == RED) {
+ node->parent = rp->parent;
+ _set_color(node, BLACK);
+ } else if (rp->color == BLACK && rp->parent != _data._root) {
+ _erase_fix_rb(sibling);
}
if (rp != p_node) {
ERR_FAIL_COND(rp == _data._nil);
- if (rp->color == BLACK)
- _erase_fix(node);
-
rp->left = p_node->left;
rp->right = p_node->right;
rp->parent = p_node->parent;
rp->color = p_node->color;
- p_node->left->parent = rp;
- p_node->right->parent = rp;
+ if (p_node->left != _data._nil)
+ p_node->left->parent = rp;
+ if (p_node->right != _data._nil)
+ p_node->right->parent = rp;
if (p_node == p_node->parent->left) {
p_node->parent->left = rp;
} else {
p_node->parent->right = rp;
}
- } else {
- if (p_node->color == BLACK)
- _erase_fix(node);
}
if (p_node->_next)
@@ -500,11 +487,12 @@ private:
void _calculate_depth(Element *p_element, int &max_d, int d) const {
- if (p_element == _data._nil) {
+ if (p_element == _data._nil)
return;
- }
+
_calculate_depth(p_element->left, max_d, d + 1);
_calculate_depth(p_element->right, max_d, d + 1);
+
if (d > max_d)
max_d = d;
}
@@ -543,6 +531,7 @@ public:
if (!_data._root)
return NULL;
+
Element *res = _find(p_key);
return res;
}
@@ -551,6 +540,7 @@ public:
if (!_data._root)
return NULL;
+
const Element *res = _find_closest(p_key);
return res;
}
@@ -559,21 +549,28 @@ public:
if (!_data._root)
return NULL;
+
Element *res = _find_closest(p_key);
return res;
}
+ bool has(const K &p_key) const {
+
+ return find(p_key) != NULL;
+ }
+
Element *insert(const K &p_key, const V &p_value) {
if (!_data._root)
_data._create_root();
- return _insert_rb(p_key, p_value);
+ return _insert(p_key, p_value);
}
void erase(Element *p_element) {
- if (!_data._root)
+ if (!_data._root || !p_element)
return;
+
_erase(p_element);
if (_data.size_cache == 0 && _data._root)
_data._free_root();
@@ -583,20 +580,17 @@ public:
if (!_data._root)
return false;
+
Element *e = find(p_key);
if (!e)
return false;
+
_erase(e);
+ if (_data.size_cache == 0 && _data._root)
+ _data._free_root();
return true;
}
- bool has(const K &p_key) const {
-
- if (!_data._root)
- return false;
- return find(p_key) != NULL;
- }
-
const V &operator[](const K &p_key) const {
CRASH_COND(!_data._root);
@@ -604,6 +598,7 @@ public:
CRASH_COND(!e);
return e->_value;
}
+
V &operator[](const K &p_key) {
if (!_data._root)
@@ -613,7 +608,6 @@ public:
if (!e)
e = insert(p_key, V());
- CRASH_COND(!e);
return e->_value;
}
@@ -636,6 +630,7 @@ public:
if (!_data._root)
return NULL;
+
Element *e = _data._root->left;
if (e == _data._nil)
return NULL;
@@ -648,10 +643,12 @@ public:
inline bool empty() const { return _data.size_cache == 0; }
inline int size() const { return _data.size_cache; }
+
int calculate_depth() const {
// used for debug mostly
if (!_data._root)
return 0;
+
int max_d = 0;
_calculate_depth(_data._root->left, max_d, 0);
return max_d;
@@ -661,10 +658,10 @@ public:
if (!_data._root)
return;
+
_cleanup_tree(_data._root->left);
_data._root->left = _data._nil;
_data.size_cache = 0;
- _data._nil->parent = _data._nil;
_data._free_root();
}
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index 21516ac768..f43af49754 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -42,8 +42,10 @@ int AStar::get_available_point_id() const {
}
void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
+
ERR_FAIL_COND(p_id < 0);
ERR_FAIL_COND(p_weight_scale < 1);
+
if (!points.has(p_id)) {
Point *pt = memnew(Point);
pt->id = p_id;
@@ -58,18 +60,35 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
}
}
-Vector3 AStar::get_point_pos(int p_id) const {
+Vector3 AStar::get_point_position(int p_id) const {
ERR_FAIL_COND_V(!points.has(p_id), Vector3());
return points[p_id]->pos;
}
+
+void AStar::set_point_position(int p_id, const Vector3 &p_pos) {
+
+ ERR_FAIL_COND(!points.has(p_id));
+
+ points[p_id]->pos = p_pos;
+}
+
real_t AStar::get_point_weight_scale(int p_id) const {
ERR_FAIL_COND_V(!points.has(p_id), 0);
return points[p_id]->weight_scale;
}
+
+void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) {
+
+ ERR_FAIL_COND(!points.has(p_id));
+ ERR_FAIL_COND(p_weight_scale < 1);
+
+ points[p_id]->weight_scale = p_weight_scale;
+}
+
void AStar::remove_point(int p_id) {
ERR_FAIL_COND(!points.has(p_id));
@@ -129,6 +148,17 @@ 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);
@@ -161,7 +191,8 @@ int AStar::get_closest_point(const Vector3 &p_point) const {
return closest_id;
}
-Vector3 AStar::get_closest_pos_in_segment(const Vector3 &p_point) const {
+
+Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
real_t closest_dist = 1e20;
bool found = false;
@@ -212,15 +243,15 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
while (!found_route) {
if (open_list.first() == NULL) {
- //could not find path sadly
+ // No path found
break;
}
- //check open list
+ // Check open list
SelfList<Point> *least_cost_point = NULL;
real_t least_cost = 1e30;
- //this could be faster (cache previous results)
+ // TODO: Cache previous results
for (SelfList<Point> *E = open_list.first(); E; E = E->next()) {
Point *p = E->self();
@@ -236,7 +267,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
}
Point *p = least_cost_point->self();
- //open the neighbours for search
+ // Open the neighbours for search
int es = p->neighbours.size();
for (int i = 0; i < es; i++) {
@@ -246,7 +277,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
real_t distance = _compute_cost(p->id, e->id) * e->weight_scale + p->distance;
if (e->last_pass == pass) {
- //oh this was visited already, can we win the cost?
+ // Already visited, is this cheaper?
if (e->distance > distance) {
@@ -254,15 +285,15 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
e->distance = distance;
}
} else {
- //add to open neighbours
+ // Add to open neighbours
e->prev_point = p;
e->distance = distance;
- e->last_pass = pass; //mark as used
+ e->last_pass = pass; // Mark as used
open_list.add(&e->list);
if (e == end_point) {
- //oh my reached end! stop algorithm
+ // End reached; stop algorithm
found_route = true;
break;
}
@@ -275,7 +306,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
open_list.remove(least_cost_point);
}
- //clear the openf list
+ // Clear the openf list
while (open_list.first()) {
open_list.remove(open_list.first());
}
@@ -284,6 +315,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) {
}
float AStar::_estimate_cost(int p_from_id, int p_to_id) {
+
if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost))
return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id);
@@ -291,6 +323,7 @@ float AStar::_estimate_cost(int p_from_id, int p_to_id) {
}
float AStar::_compute_cost(int p_from_id, int p_to_id) {
+
if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost))
return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id);
@@ -321,9 +354,9 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
if (!found_route)
return PoolVector<Vector3>();
- //midpoints
+ // Midpoints
Point *p = end_point;
- int pc = 1; //begin point
+ int pc = 1; // Begin point
while (p != begin_point) {
pc++;
p = p->prev_point;
@@ -342,7 +375,7 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
p = p->prev_point;
}
- w[0] = p->pos; //assign first
+ w[0] = p->pos; // Assign first
}
return path;
@@ -372,9 +405,9 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
if (!found_route)
return PoolVector<int>();
- //midpoints
+ // Midpoints
Point *p = end_point;
- int pc = 1; //begin point
+ int pc = 1; // Begin point
while (p != begin_point) {
pc++;
p = p->prev_point;
@@ -393,7 +426,7 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
p = p->prev_point;
}
- w[0] = p->id; //assign first
+ w[0] = p->id; // Assign first
}
return path;
@@ -402,11 +435,14 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_available_point_id"), &AStar::get_available_point_id);
- ClassDB::bind_method(D_METHOD("add_point", "id", "pos", "weight_scale"), &AStar::add_point, DEFVAL(1.0));
- ClassDB::bind_method(D_METHOD("get_point_pos", "id"), &AStar::get_point_pos);
+ ClassDB::bind_method(D_METHOD("add_point", "id", "position", "weight_scale"), &AStar::add_point, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar::get_point_position);
+ ClassDB::bind_method(D_METHOD("set_point_position", "id", "position"), &AStar::set_point_position);
ClassDB::bind_method(D_METHOD("get_point_weight_scale", "id"), &AStar::get_point_weight_scale);
+ ClassDB::bind_method(D_METHOD("set_point_weight_scale", "id", "weight_scale"), &AStar::set_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);
@@ -414,8 +450,8 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &AStar::clear);
- ClassDB::bind_method(D_METHOD("get_closest_point", "to_pos"), &AStar::get_closest_point);
- ClassDB::bind_method(D_METHOD("get_closest_pos_in_segment", "to_pos"), &AStar::get_closest_pos_in_segment);
+ ClassDB::bind_method(D_METHOD("get_closest_point", "to_position"), &AStar::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar::get_closest_position_in_segment);
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar::get_point_path);
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar::get_id_path);
@@ -432,4 +468,5 @@ AStar::AStar() {
AStar::~AStar() {
pass = 1;
+ clear();
}
diff --git a/core/math/a_star.h b/core/math/a_star.h
index d2d2166719..23773e82e2 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* a_star.h */
+/* a_star.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -33,6 +33,8 @@
#include "reference.h"
#include "self_list.h"
/**
+ A* pathfinding algorithm
+
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -53,7 +55,7 @@ class AStar : public Reference {
Vector<Point *> neighbours;
- //used for pathfinding
+ // Used for pathfinding
Point *prev_point;
real_t distance;
@@ -101,10 +103,13 @@ public:
int get_available_point_id() const;
void add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale = 1);
- Vector3 get_point_pos(int p_id) const;
+ Vector3 get_point_position(int p_id) const;
+ void set_point_position(int p_id, const Vector3 &p_pos);
real_t get_point_weight_scale(int p_id) const;
+ void set_point_weight_scale(int p_id, real_t p_weight_scale);
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);
@@ -113,7 +118,7 @@ public:
void clear();
int get_closest_point(const Vector3 &p_point) const;
- Vector3 get_closest_pos_in_segment(const Vector3 &p_point) const;
+ Vector3 get_closest_position_in_segment(const Vector3 &p_point) const;
PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id);
PoolVector<int> get_id_path(int p_from_id, int p_to_id);
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 0512cdd798..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;
@@ -265,75 +264,26 @@ void CameraMatrix::get_viewport_size(real_t &r_width, real_t &r_height) const {
bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const {
- const real_t *matrix = (const real_t *)this->matrix;
-
- ///////--- Near Plane ---///////
- Plane near_plane = Plane(matrix[3] + matrix[2],
- matrix[7] + matrix[6],
- matrix[11] + matrix[10],
- -matrix[15] - matrix[14]);
- near_plane.normalize();
-
- ///////--- Far Plane ---///////
- Plane far_plane = Plane(matrix[2] - matrix[3],
- matrix[6] - matrix[7],
- matrix[10] - matrix[11],
- matrix[15] - matrix[14]);
- far_plane.normalize();
-
- ///////--- Right Plane ---///////
- Plane right_plane = Plane(matrix[0] - matrix[3],
- matrix[4] - matrix[7],
- matrix[8] - matrix[11],
- -matrix[15] + matrix[12]);
- right_plane.normalize();
-
- ///////--- Top Plane ---///////
- Plane top_plane = Plane(matrix[1] - matrix[3],
- matrix[5] - matrix[7],
- matrix[9] - matrix[11],
- -matrix[15] + matrix[13]);
- top_plane.normalize();
-
- Vector3 near_endpoint_left, near_endpoint_right;
- Vector3 far_endpoint_left, far_endpoint_right;
-
- bool res = near_plane.intersect_3(right_plane, top_plane, &near_endpoint_right);
- ERR_FAIL_COND_V(!res, false);
-
- res = far_plane.intersect_3(right_plane, top_plane, &far_endpoint_right);
- ERR_FAIL_COND_V(!res, false);
-
- if ((matrix[8] == 0) && (matrix[9] == 0)) {
- near_endpoint_left = near_endpoint_right;
- near_endpoint_left.x = -near_endpoint_left.x;
-
- far_endpoint_left = far_endpoint_right;
- far_endpoint_left.x = -far_endpoint_left.x;
- } else {
- ///////--- Left Plane ---///////
- Plane left_plane = Plane(matrix[0] + matrix[3],
- matrix[4] + matrix[7],
- matrix[8] + matrix[11],
- -matrix[15] - matrix[12]);
- left_plane.normalize();
+ Vector<Plane> planes = get_projection_planes(Transform());
+ const Planes intersections[8][3] = {
+ { PLANE_FAR, PLANE_LEFT, PLANE_TOP },
+ { PLANE_FAR, PLANE_LEFT, PLANE_BOTTOM },
+ { PLANE_FAR, PLANE_RIGHT, PLANE_TOP },
+ { PLANE_FAR, PLANE_RIGHT, PLANE_BOTTOM },
+ { PLANE_NEAR, PLANE_LEFT, PLANE_TOP },
+ { PLANE_NEAR, PLANE_LEFT, PLANE_BOTTOM },
+ { PLANE_NEAR, PLANE_RIGHT, PLANE_TOP },
+ { PLANE_NEAR, PLANE_RIGHT, PLANE_BOTTOM },
+ };
- res = near_plane.intersect_3(left_plane, top_plane, &near_endpoint_left);
- ERR_FAIL_COND_V(!res, false);
+ for (int i = 0; i < 8; i++) {
- res = far_plane.intersect_3(left_plane, top_plane, &far_endpoint_left);
+ Vector3 point;
+ bool res = planes[intersections[i][0]].intersect_3(planes[intersections[i][1]], planes[intersections[i][2]], &point);
ERR_FAIL_COND_V(!res, false);
+ p_8points[i] = p_transform.xform(point);
}
- p_8points[0] = p_transform.xform(Vector3(near_endpoint_right.x, near_endpoint_right.y, near_endpoint_right.z));
- p_8points[1] = p_transform.xform(Vector3(near_endpoint_right.x, -near_endpoint_right.y, near_endpoint_right.z));
- p_8points[2] = p_transform.xform(Vector3(near_endpoint_left.x, near_endpoint_left.y, near_endpoint_left.z));
- p_8points[3] = p_transform.xform(Vector3(near_endpoint_left.x, -near_endpoint_left.y, near_endpoint_left.z));
- p_8points[4] = p_transform.xform(Vector3(far_endpoint_right.x, far_endpoint_right.y, far_endpoint_right.z));
- p_8points[5] = p_transform.xform(Vector3(far_endpoint_right.x, -far_endpoint_right.y, far_endpoint_right.z));
- p_8points[6] = p_transform.xform(Vector3(far_endpoint_left.x, far_endpoint_left.y, far_endpoint_left.z));
- p_8points[7] = p_transform.xform(Vector3(far_endpoint_left.x, -far_endpoint_left.y, far_endpoint_left.z));
-
return true;
}
@@ -610,6 +560,11 @@ int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const {
return int((result.x * 0.5 + 0.5) * p_for_pixel_width);
}
+bool CameraMatrix::is_orthogonal() const {
+
+ return matrix[3][3] == 1.0;
+}
+
real_t CameraMatrix::get_fov() const {
const real_t *matrix = (const real_t *)this->matrix;
@@ -622,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/camera_matrix.h b/core/math/camera_matrix.h
index 175d0cdb1b..3145d73356 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -69,6 +69,7 @@ struct CameraMatrix {
real_t get_z_near() const;
real_t get_aspect() const;
real_t get_fov() const;
+ bool is_orthogonal() const;
Vector<Plane> get_projection_planes(const Transform &p_transform) const;
diff --git a/core/math/face3.cpp b/core/math/face3.cpp
index 748faad28f..e1b172e491 100644
--- a/core/math/face3.cpp
+++ b/core/math/face3.cpp
@@ -296,7 +296,7 @@ void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, V
/** FIND SUPPORT VERTEX **/
int vert_support_idx = -1;
- real_t support_max;
+ real_t support_max = 0;
for (int i = 0; i < 3; i++) {
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 9651e37f3e..65b2ffb0df 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -104,8 +104,44 @@ public:
static _ALWAYS_INLINE_ double exp(double p_x) { return ::exp(p_x); }
static _ALWAYS_INLINE_ float exp(float p_x) { return ::expf(p_x); }
- static _ALWAYS_INLINE_ bool is_nan(double p_val) { return (p_val != p_val); }
- static _ALWAYS_INLINE_ bool is_nan(float p_val) { return (p_val != p_val); }
+ static _ALWAYS_INLINE_ bool is_nan(double p_val) {
+#ifdef _MSC_VER
+ return _isnan(p_val);
+#elif defined(__GNUC__) && __GNUC__ < 6
+ union {
+ uint64_t u;
+ double f;
+ } ieee754;
+ ieee754.f = p_val;
+ // (unsigned)(0x7ff0000000000001 >> 32) : 0x7ff00000
+ return ((((unsigned)(ieee754.u >> 32) & 0x7fffffff) + ((unsigned)ieee754.u != 0)) > 0x7ff00000);
+#else
+ return isnan(p_val);
+#endif
+ }
+
+ static _ALWAYS_INLINE_ bool is_nan(float p_val) {
+#ifdef _MSC_VER
+ return _isnan(p_val);
+#elif defined(__GNUC__) && __GNUC__ < 6
+ union {
+ uint32_t u;
+ float f;
+ } ieee754;
+ ieee754.f = p_val;
+ // -----------------------------------
+ // (single-precision floating-point)
+ // NaN : s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
+ // : (> 0x7f800000)
+ // where,
+ // s : sign
+ // x : non-zero number
+ // -----------------------------------
+ return ((ieee754.u & 0x7fffffff) > 0x7f800000);
+#else
+ return isnan(p_val);
+#endif
+ }
static _ALWAYS_INLINE_ bool is_inf(double p_val) {
#ifdef _MSC_VER
@@ -351,6 +387,23 @@ public:
return hf;
}
+
+ static _ALWAYS_INLINE_ float snap_scalar(float p_offset, float p_step, float p_target) {
+ return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target;
+ }
+
+ static _ALWAYS_INLINE_ float snap_scalar_seperation(float p_offset, float p_step, float p_target, float p_separation) {
+ if (p_step != 0) {
+ float a = Math::stepify(p_target - p_offset, p_step + p_separation) + p_offset;
+ float b = a;
+ if (p_target >= 0)
+ b -= p_separation;
+ else
+ b += p_step;
+ return (Math::abs(p_target - a) < Math::abs(p_target - b)) ? a : b;
+ }
+ return p_target;
+ }
};
#endif // MATH_FUNCS_H
diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp
index c7e2a8f307..85421c074b 100644
--- a/core/math/matrix3.cpp
+++ b/core/math/matrix3.cpp
@@ -107,6 +107,13 @@ bool Basis::is_orthogonal() const {
return is_equal_approx(id, m);
}
+bool Basis::is_diagonal() const {
+ return (
+ Math::is_equal_approx(elements[0][1], 0) && Math::is_equal_approx(elements[0][2], 0) &&
+ Math::is_equal_approx(elements[1][0], 0) && Math::is_equal_approx(elements[1][2], 0) &&
+ Math::is_equal_approx(elements[2][0], 0) && Math::is_equal_approx(elements[2][1], 0));
+}
+
bool Basis::is_rotation() const {
return Math::is_equal_approx(determinant(), 1) && is_orthogonal();
}
@@ -227,7 +234,22 @@ Basis Basis::scaled(const Vector3 &p_scale) const {
return m;
}
+void Basis::set_scale(const Vector3 &p_scale) {
+
+ set_axis(0, get_axis(0).normalized() * p_scale.x);
+ set_axis(1, get_axis(1).normalized() * p_scale.y);
+ set_axis(2, get_axis(2).normalized() * p_scale.z);
+}
+
Vector3 Basis::get_scale() const {
+
+ return Vector3(
+ Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
+ Vector3(elements[0][1], elements[1][1], elements[2][1]).length(),
+ Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
+}
+
+Vector3 Basis::get_signed_scale() const {
// FIXME: We are assuming M = R.S (R is rotation and S is scaling), and use polar decomposition to extract R and S.
// A polar decomposition is M = O.P, where O is an orthogonal matrix (meaning rotation and reflection) and
// P is a positive semi-definite matrix (meaning it contains absolute values of scaling along its diagonal).
@@ -241,12 +263,13 @@ Vector3 Basis::get_scale() const {
// This may lead to confusion for some users though.
//
// The convention we use here is to absorb the sign flip into the scaling matrix.
- // The same convention is also used in other similar functions such as set_scale,
- // get_rotation_axis_angle, get_rotation, set_rotation_axis_angle, set_rotation_euler, ...
+ // The same convention is also used in other similar functions such as get_rotation_axis_angle, get_rotation, ...
//
// A proper way to get rid of this issue would be to store the scaling values (or at least their signs)
// as a part of Basis. However, if we go that path, we need to disable direct (write) access to the
// matrix elements.
+ //
+ // The rotation part of this decomposition is returned by get_rotation* functions.
real_t det_sign = determinant() > 0 ? 1 : -1;
return det_sign * Vector3(
Vector3(elements[0][0], elements[1][0], elements[2][0]).length(),
@@ -254,15 +277,24 @@ Vector3 Basis::get_scale() const {
Vector3(elements[0][2], elements[1][2], elements[2][2]).length());
}
-// Sets scaling while preserving rotation.
-// This requires some care when working with matrices with negative determinant,
-// since we're using a particular convention for "polar" decomposition in get_scale and get_rotation.
-// For details, see the explanation in get_scale.
-void Basis::set_scale(const Vector3 &p_scale) {
- Vector3 e = get_euler();
- Basis(); // reset to identity
- scale(p_scale);
- rotate(e);
+// Decomposes a Basis into a rotation-reflection matrix (an element of the group O(3)) and a positive scaling matrix as B = O.S.
+// Returns the rotation-reflection matrix via reference argument, and scaling information is returned as a Vector3.
+// This (internal) function is too specıfıc and named too ugly to expose to users, and probably there's no need to do so.
+Vector3 Basis::rotref_posscale_decomposition(Basis &rotref) const {
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V(determinant() == 0, Vector3());
+
+ Basis m = transposed() * (*this);
+ ERR_FAIL_COND_V(m.is_diagonal() == false, Vector3());
+#endif
+ Vector3 scale = get_scale();
+ Basis inv_scale = Basis().scaled(scale.inverse()); // this will also absorb the sign of scale
+ rotref = (*this) * inv_scale;
+
+#ifdef MATH_CHECKS
+ ERR_FAIL_COND_V(rotref.is_orthogonal() == false, Vector3());
+#endif
+ return scale.abs();
}
// Multiplies the matrix from left by the rotation matrix: M -> R.M
@@ -316,28 +348,6 @@ void Basis::get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const {
m.get_axis_angle(p_axis, p_angle);
}
-// Sets rotation while preserving scaling.
-// This requires some care when working with matrices with negative determinant,
-// since we're using a particular convention for "polar" decomposition in get_scale and get_rotation.
-// For details, see the explanation in get_scale.
-void Basis::set_rotation_euler(const Vector3 &p_euler) {
- Vector3 s = get_scale();
- Basis(); // reset to identity
- scale(s);
- rotate(p_euler);
-}
-
-// Sets rotation while preserving scaling.
-// This requires some care when working with matrices with negative determinant,
-// since we're using a particular convention for "polar" decomposition in get_scale and get_rotation.
-// For details, see the explanation in get_scale.
-void Basis::set_rotation_axis_angle(const Vector3 &p_axis, real_t p_angle) {
- Vector3 s = get_scale();
- Basis(); // reset to identity
- scale(s);
- rotate(p_axis, p_angle);
-}
-
// get_euler_xyz returns a vector containing the Euler angles in the format
// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last
// (following the convention they are commonly defined in the literature).
@@ -364,8 +374,9 @@ Vector3 Basis::get_euler_xyz() const {
euler.y = Math::asin(elements[0][2]);
if (euler.y < Math_PI * 0.5) {
if (euler.y > -Math_PI * 0.5) {
- //if rotation is Y-only, return a proper -pi,pi range like in x or z for the same case.
+ // is this a pure Y rotation?
if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) {
+ // return the simplest form
euler.x = 0;
euler.y = atan2(elements[0][2], elements[0][0]);
euler.z = 0;
@@ -432,7 +443,9 @@ Vector3 Basis::get_euler_yxz() const {
if (m12 < 1) {
if (m12 > -1) {
- if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) { // use pure x rotation
+ // is this a pure X rotation?
+ if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) {
+ // return the simplest form
euler.x = atan2(-m12, elements[1][1]);
euler.y = 0;
euler.z = 0;
@@ -525,7 +538,7 @@ Basis::operator String() const {
return mtx;
}
-Basis::operator Quat() const {
+Quat Basis::get_quat() const {
//commenting this check because precision issues cause it to fail when it shouldn't
//#ifdef MATH_CHECKS
//ERR_FAIL_COND_V(is_rotation() == false, Quat());
@@ -697,12 +710,7 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const {
r_angle = angle;
}
-Basis::Basis(const Vector3 &p_euler) {
-
- set_euler(p_euler);
-}
-
-Basis::Basis(const Quat &p_quat) {
+void Basis::set_quat(const Quat &p_quat) {
real_t d = p_quat.length_squared();
real_t s = 2.0 / d;
@@ -737,7 +745,3 @@ void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_phi) {
elements[2][1] = p_axis.y * p_axis.z * (1.0 - cosine) + p_axis.x * sine;
elements[2][2] = axis_sq.z + cosine * (1.0 - axis_sq.z);
}
-
-Basis::Basis(const Vector3 &p_axis, real_t p_phi) {
- set_axis_angle(p_axis, p_phi);
-}
diff --git a/core/math/matrix3.h b/core/math/matrix3.h
index be85c244bd..9a33b8203d 100644
--- a/core/math/matrix3.h
+++ b/core/math/matrix3.h
@@ -81,16 +81,18 @@ public:
Vector3 get_rotation() const;
void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
- void set_rotation_euler(const Vector3 &p_euler);
- void set_rotation_axis_angle(const Vector3 &p_axis, real_t p_angle);
+ Vector3 rotref_posscale_decomposition(Basis &rotref) const;
Vector3 get_euler_xyz() const;
void set_euler_xyz(const Vector3 &p_euler);
Vector3 get_euler_yxz() const;
void set_euler_yxz(const Vector3 &p_euler);
- Vector3 get_euler() const { return get_euler_yxz(); };
- void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); };
+ Quat get_quat() const;
+ void set_quat(const Quat &p_quat);
+
+ Vector3 get_euler() const { return get_euler_yxz(); }
+ void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }
void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const;
void set_axis_angle(const Vector3 &p_axis, real_t p_phi);
@@ -98,8 +100,9 @@ public:
void scale(const Vector3 &p_scale);
Basis scaled(const Vector3 &p_scale) const;
- Vector3 get_scale() const;
void set_scale(const Vector3 &p_scale);
+ Vector3 get_scale() const;
+ Vector3 get_signed_scale() const;
// transposed dot products
_FORCE_INLINE_ real_t tdotx(const Vector3 &v) const {
@@ -132,6 +135,7 @@ public:
void set_orthogonal_index(int p_index);
bool is_orthogonal() const;
+ bool is_diagonal() const;
bool is_rotation() const;
operator String() const;
@@ -204,11 +208,11 @@ public:
bool is_symmetric() const;
Basis diagonalize();
- operator Quat() const;
+ operator Quat() const { return get_quat(); }
- Basis(const Quat &p_quat); // euler
- Basis(const Vector3 &p_euler); // euler
- Basis(const Vector3 &p_axis, real_t p_phi);
+ Basis(const Quat &p_quat) { set_quat(p_quat); };
+ Basis(const Vector3 &p_euler) { set_euler(p_euler); }
+ Basis(const Vector3 &p_axis, real_t p_phi) { set_axis_angle(p_axis, p_phi); }
_FORCE_INLINE_ Basis(const Vector3 &row0, const Vector3 &row1, const Vector3 &row2) {
elements[0] = row0;
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index e9a383df40..e0137b6921 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -76,7 +76,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
int simplex[4];
{
- real_t max, min;
+ real_t max = 0, min = 0;
for (int i = 0; i < p_points.size(); i++) {
@@ -99,7 +99,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
//third vertex is one most further away from the line
{
- real_t maxd;
+ real_t maxd = 0;
Vector3 rel12 = p_points[simplex[0]] - p_points[simplex[1]];
for (int i = 0; i < p_points.size(); i++) {
@@ -121,7 +121,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
//fourth vertex is the one most further away from the plane
{
- real_t maxd;
+ real_t maxd = 0;
Plane p(p_points[simplex[0]], p_points[simplex[1]], p_points[simplex[2]]);
for (int i = 0; i < p_points.size(); i++) {
@@ -389,8 +389,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
for (int i = 0; i < f.indices.size(); i++) {
- uint32_t a = E->get().indices[i];
- uint32_t b = E->get().indices[(i + 1) % f.indices.size()];
+ int a = E->get().indices[i];
+ int b = E->get().indices[(i + 1) % f.indices.size()];
Edge e(a, b);
Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e);
diff --git a/core/math/transform.cpp b/core/math/transform.cpp
index 60df69a509..638a39ab73 100644
--- a/core/math/transform.cpp
+++ b/core/math/transform.cpp
@@ -118,17 +118,17 @@ Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c)
/* not sure if very "efficient" but good enough? */
- Vector3 src_scale = basis.get_scale();
- Quat src_rot = basis;
+ Vector3 src_scale = basis.get_signed_scale();
+ Quat src_rot = basis.orthonormalized();
Vector3 src_loc = origin;
- Vector3 dst_scale = p_transform.basis.get_scale();
+ Vector3 dst_scale = p_transform.basis.get_signed_scale();
Quat dst_rot = p_transform.basis;
Vector3 dst_loc = p_transform.origin;
- Transform dst;
- dst.basis = src_rot.slerp(dst_rot, p_c);
- dst.basis.scale(src_scale.linear_interpolate(dst_scale, p_c));
+ Transform dst; //this could be made faster by using a single function in Basis..
+ dst.basis = src_rot.slerp(dst_rot, p_c).normalized();
+ dst.basis.set_scale(src_scale.linear_interpolate(dst_scale, p_c));
dst.origin = src_loc.linear_interpolate(dst_loc, p_c);
return dst;
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/method_bind.h b/core/method_bind.h
index f6cae6f34d..3c43f86b54 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -334,6 +334,7 @@ public:
}
argument_types = at;
arguments = p_info;
+ arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
#endif
}
@@ -368,7 +369,7 @@ MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, i
// tale of an amazing hack.. //
-// if you declare an nonexistent class..
+// if you declare a nonexistent class..
class __UnexistingClass;
#include "method_bind.gen.inc"
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 b220dc0563..823cbe14d4 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -274,6 +274,63 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn
arguments.push_back(p_param5);
}
+MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name)
+ : name(p_name),
+ flags(METHOD_FLAG_NORMAL),
+ return_val(p_ret),
+ id(0) {
+}
+
+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) {
+ 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) {
+ 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) {
+ arguments.push_back(p_param1);
+ arguments.push_back(p_param2);
+ arguments.push_back(p_param3);
+}
+
+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) {
+ arguments.push_back(p_param1);
+ arguments.push_back(p_param2);
+ arguments.push_back(p_param3);
+ arguments.push_back(p_param4);
+}
+
+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) {
+ arguments.push_back(p_param1);
+ arguments.push_back(p_param2);
+ arguments.push_back(p_param3);
+ arguments.push_back(p_param4);
+ arguments.push_back(p_param5);
+}
+
Object::Connection::operator Variant() const {
Dictionary d;
@@ -995,7 +1052,7 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Variant::Ca
Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
if (_block_signals)
- return ERR_CANT_AQUIRE_RESOURCE; //no emit, signals blocked
+ return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
Signal *s = signal_map.getptr(p_name);
if (!s) {
@@ -1529,7 +1586,7 @@ void Object::_bind_methods() {
ADD_SIGNAL(MethodInfo("script_changed"));
BIND_VMETHOD(MethodInfo("_notification", PropertyInfo(Variant::INT, "what")));
- BIND_VMETHOD(MethodInfo("_set:bool", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING, "property"), PropertyInfo(Variant::NIL, "value")));
#ifdef TOOLS_ENABLED
MethodInfo miget("_get", PropertyInfo(Variant::STRING, "property"));
miget.return_val.name = "Variant";
diff --git a/core/object.h b/core/object.h
index 8b13477480..7af2c78fc3 100644
--- a/core/object.h
+++ b/core/object.h
@@ -64,9 +64,9 @@ enum PropertyHint {
PROPERTY_HINT_LAYERS_3D_RENDER,
PROPERTY_HINT_LAYERS_3D_PHYSICS,
PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
- PROPERTY_HINT_DIR, ///< a directort path must be passed
+ PROPERTY_HINT_DIR, ///< a directory path must be passed
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
- PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed
+ PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
@@ -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 {
@@ -205,6 +206,12 @@ struct MethodInfo {
MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4);
MethodInfo(Variant::Type 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);
+ MethodInfo(const PropertyInfo &p_ret, const String &p_name);
+ MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1);
+ MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2);
+ MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3);
+ 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);
+ 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);
};
// old cast_to
@@ -214,7 +221,7 @@ struct MethodInfo {
//return NULL;
/*
- the following is an uncomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
+ the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
*/
#define REVERSE_GET_PROPERTY_LIST \
@@ -561,12 +568,6 @@ public:
template <class T>
static T *cast_to(Object *p_object) {
-#ifdef DEBUG_ENABLED
- // TODO there are some legitimate reasons to pass NULL as p_object.
- // we need to figure out how to deal with that in debug mode.
- // This code will return NULL for a NULL input in release mode also.
- ERR_FAIL_COND_V(p_object == NULL, NULL);
-#endif
#ifndef NO_SAFE_CAST
return dynamic_cast<T *>(p_object);
#else
@@ -581,12 +582,6 @@ public:
template <class T>
static const T *cast_to(const Object *p_object) {
-#ifdef DEBUG_ENABLED
- // TODO there are some legitimate reasons to pass NULL as p_object.
- // we need to figure out how to deal with that in debug mode.
- // This code will return NULL for a NULL input in release mode also.
- ERR_FAIL_COND_V(p_object == NULL, NULL);
-#endif
#ifndef NO_SAFE_CAST
return dynamic_cast<const T *>(p_object);
#else
diff --git a/core/ordered_hash_map.h b/core/ordered_hash_map.h
new file mode 100644
index 0000000000..9e95f963e1
--- /dev/null
+++ b/core/ordered_hash_map.h
@@ -0,0 +1,315 @@
+/*************************************************************************/
+/* ordered_hash_map.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.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 ORDERED_HASH_MAP_H
+#define ORDERED_HASH_MAP_H
+
+#include "hash_map.h"
+#include "list.h"
+#include "pair.h"
+
+/**
+ * A hash map which allows to iterate elements in insertion order.
+ * Insertion, lookup, deletion have O(1) complexity.
+ * The API aims to be consistent with Map rather than HashMap, because the
+ * former is more frequently used and is more coherent with the rest of the
+ * codebase.
+ * Deletion during iteration is safe and will preserve the order.
+ */
+template <class K, class V, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<K>, uint8_t MIN_HASH_TABLE_POWER = 3, uint8_t RELATIONSHIP = 8>
+class OrderedHashMap {
+ typedef List<Pair<const K *, V> > InternalList;
+ typedef HashMap<K, typename InternalList::Element *, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP> InternalMap;
+
+ InternalList list;
+ InternalMap map;
+
+public:
+ class Element {
+ friend class OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>;
+
+ typename InternalList::Element *list_element;
+ typename InternalList::Element *prev_element;
+ typename InternalList::Element *next_element;
+
+ Element(typename InternalList::Element *p_element) {
+ list_element = p_element;
+
+ if (list_element) {
+ next_element = list_element->next();
+ prev_element = list_element->prev();
+ }
+ }
+
+ public:
+ _FORCE_INLINE_ Element()
+ : list_element(NULL), prev_element(NULL), next_element(NULL) {
+ }
+
+ Element next() const {
+ return Element(next_element);
+ }
+
+ Element prev() const {
+ return Element(prev_element);
+ }
+
+ Element(const Element &other)
+ : list_element(other.list_element),
+ prev_element(other.prev_element),
+ next_element(other.next_element) {
+ }
+
+ Element &operator=(const Element &other) {
+ list_element = other.list_element;
+ next_element = other.next_element;
+ prev_element = other.prev_element;
+ return *this;
+ }
+
+ friend bool operator==(const Element &, const Element &);
+ friend bool operator!=(const Element &, const Element &);
+
+ operator bool() const {
+ return (list_element != NULL);
+ }
+
+ const K &key() const {
+ CRASH_COND(!list_element);
+ return *(list_element->get().first);
+ };
+
+ V &value() {
+ CRASH_COND(!list_element);
+ return list_element->get().second;
+ };
+
+ const V &value() const {
+ CRASH_COND(!list_element);
+ return list_element->get().second;
+ };
+
+ V &get() {
+ CRASH_COND(!list_element);
+ return list_element->get().second;
+ };
+
+ const V &get() const {
+ CRASH_COND(!list_element);
+ return list_element->get().second;
+ };
+ };
+
+ class ConstElement {
+ friend class OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>;
+
+ const typename InternalList::Element *list_element;
+
+ ConstElement(const typename InternalList::Element *p_element)
+ : list_element(p_element) {
+ }
+
+ public:
+ _FORCE_INLINE_ ConstElement()
+ : list_element(NULL) {
+ }
+
+ ConstElement(const ConstElement &other)
+ : list_element(other.list_element) {
+ }
+
+ ConstElement &operator=(const ConstElement &other) {
+ list_element = other.list_element;
+ return *this;
+ }
+
+ ConstElement next() const {
+ return ConstElement(list_element ? list_element->next() : NULL);
+ }
+
+ ConstElement prev() const {
+ return ConstElement(list_element ? list_element->prev() : NULL);
+ }
+
+ friend bool operator==(const ConstElement &, const ConstElement &);
+ friend bool operator!=(const ConstElement &, const ConstElement &);
+
+ operator bool() const {
+ return (list_element != NULL);
+ }
+
+ const K &key() const {
+ CRASH_COND(!list_element);
+ return *(list_element->get().first);
+ };
+
+ const V &value() const {
+ CRASH_COND(!list_element);
+ return list_element->get().second;
+ };
+
+ const V &get() const {
+ CRASH_COND(!list_element);
+ return list_element->get().second;
+ };
+ };
+
+ ConstElement find(const K &p_key) const {
+ typename InternalList::Element **list_element = map.getptr(p_key);
+ if (list_element) {
+ return ConstElement(*list_element);
+ }
+ return ConstElement(NULL);
+ }
+
+ Element find(const K &p_key) {
+ typename InternalList::Element **list_element = map.getptr(p_key);
+ if (list_element) {
+ return Element(*list_element);
+ }
+ return Element(NULL);
+ }
+
+ Element insert(const K &p_key, const V &p_value) {
+ typename InternalList::Element **list_element = map.getptr(p_key);
+ if (list_element) {
+ (*list_element)->get().second = p_value;
+ return Element(*list_element);
+ }
+ typename InternalList::Element *new_element = list.push_back(Pair<const K *, V>(NULL, p_value));
+ typename InternalMap::Element *e = map.set(p_key, new_element);
+ new_element->get().first = &e->key();
+
+ return Element(new_element);
+ }
+
+ void erase(Element &p_element) {
+ map.erase(p_element.key());
+ list.erase(p_element.list_element);
+ p_element.list_element = NULL;
+ }
+
+ bool erase(const K &p_key) {
+ typename InternalList::Element **list_element = map.getptr(p_key);
+ if (list_element) {
+ list.erase(*list_element);
+ map.erase(p_key);
+ return true;
+ }
+ return false;
+ }
+
+ inline bool has(const K &p_key) const {
+ return map.has(p_key);
+ }
+
+ const V &operator[](const K &p_key) const {
+ ConstElement e = find(p_key);
+ CRASH_COND(!e);
+ return e.value();
+ }
+
+ V &operator[](const K &p_key) {
+ Element e = find(p_key);
+ if (!e) {
+ // consistent with Map behaviour
+ e = insert(p_key, V());
+ }
+ return e.value();
+ }
+
+ inline Element front() {
+ return Element(list.front());
+ }
+
+ inline Element back() {
+ return Element(list.back());
+ }
+
+ inline ConstElement front() const {
+ return ConstElement(list.front());
+ }
+
+ inline ConstElement back() const {
+ return ConstElement(list.back());
+ }
+
+ inline bool empty() const { return list.empty(); }
+ inline int size() const { return list.size(); }
+
+ void clear() {
+ map.clear();
+ list.clear();
+ }
+
+private:
+ void _copy_from(const OrderedHashMap &p_map) {
+ for (ConstElement E = p_map.front(); E; E = E.next()) {
+ insert(E.key(), E.value());
+ }
+ }
+
+public:
+ void operator=(const OrderedHashMap &p_map) {
+ _copy_from(p_map);
+ }
+
+ OrderedHashMap(const OrderedHashMap &p_map) {
+ _copy_from(p_map);
+ }
+
+ _FORCE_INLINE_ OrderedHashMap() {
+ }
+};
+
+template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
+bool operator==(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &first,
+ const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &second) {
+ return (first.list_element == second.list_element);
+}
+
+template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
+bool operator!=(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &first,
+ const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::Element &second) {
+ return (first.list_element != second.list_element);
+}
+
+template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
+bool operator==(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &first,
+ const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &second) {
+ return (first.list_element == second.list_element);
+}
+
+template <class K, class V, class Hasher, class Comparator, uint8_t MIN_HASH_TABLE_POWER, uint8_t RELATIONSHIP>
+bool operator!=(const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &first,
+ const typename OrderedHashMap<K, V, Hasher, Comparator, MIN_HASH_TABLE_POWER, RELATIONSHIP>::ConstElement &second) {
+ return (first.list_element != second.list_element);
+}
+
+#endif // ORDERED_HASH_MAP_H
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index f24d6d16ca..0875f78478 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;
@@ -312,7 +312,7 @@ Error DirAccess::copy(String p_from, String p_to) {
}
fsrc->seek_end(0);
- int size = fsrc->get_pos();
+ int size = fsrc->get_position();
fsrc->seek(0);
err = OK;
while (size--) {
@@ -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.cpp b/core/os/file_access.cpp
index b969b58bfb..fcb3b58fed 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -55,7 +55,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
bool FileAccess::exists(const String &p_name) {
- if (PackedData::get_singleton()->has_path(p_name))
+ if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name))
return true;
FileAccess *f = open(p_name, READ);
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 8393f0530b..455dd1ea99 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -90,7 +90,7 @@ public:
virtual void seek(size_t p_position) = 0; ///< seek to a given position
virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file
- virtual size_t get_pos() const = 0; ///< get position in the file
+ virtual size_t get_position() const = 0; ///< get position in the file
virtual size_t get_len() const = 0; ///< get size of the file
virtual bool eof_reached() const = 0; ///< reading passed EOF
@@ -119,6 +119,7 @@ public:
virtual Error get_error() const = 0; ///< get last error
+ virtual void flush() = 0;
virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
@@ -140,6 +141,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 +177,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/input.cpp b/core/os/input.cpp
index 65752662d7..848b003d5e 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -58,6 +58,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released);
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping);
+ ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed);
ClassDB::bind_method(D_METHOD("is_joy_known", "device"), &Input::is_joy_known);
ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &Input::get_joy_axis);
ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &Input::get_joy_name);
@@ -80,7 +81,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &Input::get_mouse_button_mask);
ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode);
ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode);
- ClassDB::bind_method(D_METHOD("warp_mouse_pos", "to"), &Input::warp_mouse_pos);
+ ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position);
ClassDB::bind_method(D_METHOD("action_press", "action"), &Input::action_press);
ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release);
ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(Vector2()));
diff --git a/core/os/input.h b/core/os/input.h
index f98b97e647..97d3bef4f9 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -81,7 +81,7 @@ public:
virtual Point2 get_last_mouse_speed() const = 0;
virtual int get_mouse_button_mask() const = 0;
- virtual void warp_mouse_pos(const Vector2 &p_to) = 0;
+ virtual void warp_mouse_position(const Vector2 &p_to) = 0;
virtual Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) = 0;
virtual Vector3 get_gravity() const = 0;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 88037859aa..6b43f2c63b 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -637,7 +637,7 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event) const
if (jm.is_null())
return false;
- return (axis == jm->axis && (axis_value < 0) == (jm->axis_value < 0));
+ return (axis == jm->axis && ((axis_value < 0) == (jm->axis_value < 0) || jm->axis_value == 0));
}
String InputEventJoypadMotion::as_text() const {
@@ -781,7 +781,7 @@ void InputEventScreenTouch::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenTouch::set_index);
ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenTouch::get_index);
- ClassDB::bind_method(D_METHOD("set_position", "pos"), &InputEventScreenTouch::set_position);
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventScreenTouch::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &InputEventScreenTouch::get_position);
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventScreenTouch::set_pressed);
diff --git a/core/os/input_event.h b/core/os/input_event.h
index 5dc0f91d5f..f2c8cc802d 100644
--- a/core/os/input_event.h
+++ b/core/os/input_event.h
@@ -44,7 +44,7 @@
* The events are pretty obvious.
*/
-enum {
+enum ButtonList {
BUTTON_LEFT = 1,
BUTTON_RIGHT = 2,
BUTTON_MIDDLE = 3,
@@ -58,7 +58,7 @@ enum {
};
-enum {
+enum JoystickList {
JOY_BUTTON_0 = 0,
JOY_BUTTON_1 = 1,
diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp
index 30e7d5e791..edf4f3e2f9 100644
--- a/core/os/keyboard.cpp
+++ b/core/os/keyboard.cpp
@@ -505,6 +505,27 @@ static const _KeyCodeReplace _keycode_replace_neo[] = {
{ 0, 0 }
};
+static const _KeyCodeReplace _keycode_replace_colemak[] = {
+ { KEY_E, KEY_F },
+ { KEY_R, KEY_P },
+ { KEY_T, KEY_G },
+ { KEY_Y, KEY_J },
+ { KEY_U, KEY_L },
+ { KEY_I, KEY_U },
+ { KEY_O, KEY_Y },
+ { KEY_P, KEY_SEMICOLON },
+ { KEY_S, KEY_R },
+ { KEY_D, KEY_S },
+ { KEY_F, KEY_T },
+ { KEY_G, KEY_D },
+ { KEY_J, KEY_N },
+ { KEY_K, KEY_E },
+ { KEY_L, KEY_I },
+ { KEY_SEMICOLON, KEY_O },
+ { KEY_N, KEY_K },
+ { 0, 0 }
+};
+
int keycode_get_count() {
const _KeyCodeText *kct = &_keycodes[0];
@@ -537,6 +558,7 @@ int latin_keyboard_keycode_convert(int p_keycode) {
case OS::LATIN_KEYBOARD_QZERTY: kcr = _keycode_replace_qzerty; break;
case OS::LATIN_KEYBOARD_DVORAK: kcr = _keycode_replace_dvorak; break;
case OS::LATIN_KEYBOARD_NEO: kcr = _keycode_replace_neo; break;
+ case OS::LATIN_KEYBOARD_COLEMAK: kcr = _keycode_replace_colemak; break;
default: return p_keycode;
}
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index b146d370f1..8b4449586b 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -52,6 +52,7 @@ void MainLoop::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST);
BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 1292b7eeed..eb5d5be33d 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -62,19 +62,20 @@ void OS::debug_break(){
// something
};
-void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
- const char *err_type;
- switch (p_type) {
- case ERR_ERROR: err_type = "**ERROR**"; break;
- case ERR_WARNING: err_type = "**WARNING**"; break;
- case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
- case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
+void OS::_set_logger(Logger *p_logger) {
+ if (_logger) {
+ memdelete(_logger);
}
+ _logger = p_logger;
+}
+
+void OS::initialize_logger() {
+ _set_logger(memnew(StdLogger));
+}
+
+void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
- if (p_rationale && *p_rationale)
- print("%s: %s\n ", err_type, p_rationale);
- print("%s: At: %s:%i:%s() - %s\n", err_type, p_file, p_line, p_function, p_code);
+ _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
}
void OS::print(const char *p_format, ...) {
@@ -82,17 +83,16 @@ void OS::print(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
- vprint(p_format, argp);
+ _logger->logv(p_format, argp, false);
va_end(argp);
};
void OS::printerr(const char *p_format, ...) {
-
va_list argp;
va_start(argp, p_format);
- vprint(p_format, argp, true);
+ _logger->logv(p_format, argp, true);
va_end(argp);
};
@@ -193,6 +193,10 @@ void OS::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_scr
void OS::hide_virtual_keyboard() {
}
+int OS::get_virtual_keyboard_height() const {
+ return 0;
+}
+
void OS::print_all_resources(String p_to_file) {
ERR_FAIL_COND(p_to_file != "" && _OSPRF);
@@ -484,7 +488,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() {
@@ -494,7 +498,7 @@ int OS::get_power_percent_left() {
return -1;
}
-bool OS::check_feature_support(const String &p_feature) {
+bool OS::has_feature(const String &p_feature) {
if (p_feature == get_name())
return true;
@@ -506,6 +510,13 @@ bool OS::check_feature_support(const String &p_feature) {
return true;
#endif
+ if (sizeof(void *) == 8 && p_feature == "64") {
+ return true;
+ }
+ if (sizeof(void *) == 4 && p_feature == "32") {
+ return true;
+ }
+
if (_check_internal_feature_support(p_feature))
return true;
@@ -530,11 +541,14 @@ OS::OS() {
_render_thread_mode = RENDER_THREAD_SAFE;
- _allow_hidpi = true;
+ _allow_hidpi = false;
_stack_bottom = (void *)(&stack_bottom);
+
+ _logger = NULL;
+ _set_logger(memnew(StdLogger));
}
OS::~OS() {
-
+ memdelete(_logger);
singleton = NULL;
}
diff --git a/core/os/os.h b/core/os/os.h
index 258708eea2..f5e479ac0b 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -32,9 +32,9 @@
#include "engine.h"
#include "image.h"
+#include "io/logger.h"
#include "list.h"
#include "os/main_loop.h"
-#include "power.h"
#include "ustring.h"
#include "vector.h"
#include <stdarg.h>
@@ -62,9 +62,22 @@ class OS {
void *_stack_bottom;
+ Logger *_logger;
+
+protected:
+ void _set_logger(Logger *p_logger);
+
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,
@@ -101,6 +114,7 @@ protected:
virtual int get_audio_driver_count() const = 0;
virtual const char *get_audio_driver_name(int p_driver) const = 0;
+ virtual void initialize_logger();
virtual void initialize_core() = 0;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
@@ -120,18 +134,10 @@ public:
static OS *get_singleton();
- enum ErrorType {
- ERR_ERROR,
- ERR_WARNING,
- ERR_SCRIPT,
- ERR_SHADER
- };
+ void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
+ void print(const char *p_format, ...);
+ void printerr(const char *p_format, ...);
- virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
-
- virtual void print(const char *p_format, ...);
- virtual void printerr(const char *p_format, ...);
- virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false) = 0;
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0;
virtual String get_stdin_string(bool p_block = true) = 0;
@@ -149,7 +155,7 @@ public:
virtual void set_mouse_mode(MouseMode p_mode);
virtual MouseMode get_mouse_mode() const;
- virtual void warp_mouse_pos(const Point2 &p_to) {}
+ virtual void warp_mouse_position(const Point2 &p_to) {}
virtual Point2 get_mouse_position() const = 0;
virtual int get_mouse_button_state() const = 0;
virtual void set_window_title(const String &p_title) = 0;
@@ -198,7 +204,7 @@ public:
virtual String get_installed_templates_path() const { return ""; }
virtual String get_executable_path() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL) = 0;
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
@@ -277,8 +283,13 @@ public:
virtual bool can_draw() const = 0;
+ virtual bool is_userfs_persistent() const { return true; }
+
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,
@@ -304,6 +315,9 @@ public:
virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2());
virtual void hide_virtual_keyboard();
+ // returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
+ virtual int get_virtual_keyboard_height() const;
+
virtual void set_cursor_shape(CursorShape p_shape) = 0;
virtual bool get_swap_ok_cancel() { return false; }
@@ -325,6 +339,8 @@ public:
virtual String get_data_dir() const;
virtual String get_resource_dir() const;
+ virtual Error move_to_trash(const String &p_path) { return FAILED; }
+
enum SystemDir {
SYSTEM_DIR_DESKTOP,
SYSTEM_DIR_DCIM,
@@ -393,6 +409,7 @@ public:
LATIN_KEYBOARD_QZERTY,
LATIN_KEYBOARD_DVORAK,
LATIN_KEYBOARD_NEO,
+ LATIN_KEYBOARD_COLEMAK,
};
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
@@ -410,11 +427,11 @@ 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();
- bool check_feature_support(const String &p_feature);
+ bool has_feature(const String &p_feature);
/**
* Returns the stack bottom of the main thread of the application.
@@ -428,6 +445,6 @@ public:
virtual ~OS();
};
-VARIANT_ENUM_CAST(PowerState);
+VARIANT_ENUM_CAST(OS::PowerState);
#endif
diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp
index 4040680c6d..ad8438e416 100644
--- a/core/packed_data_container.cpp
+++ b/core/packed_data_container.cpp
@@ -61,7 +61,7 @@ Variant PackedDataContainer::_iter_init_ofs(const Array &p_iter, uint32_t p_offs
Variant PackedDataContainer::_iter_next_ofs(const Array &p_iter, uint32_t p_offset) {
Array ref = p_iter;
- uint32_t size = _size(p_offset);
+ int size = _size(p_offset);
if (ref.size() != 1)
return false;
int pos = ref[0];
@@ -74,7 +74,7 @@ Variant PackedDataContainer::_iter_next_ofs(const Array &p_iter, uint32_t p_offs
Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_offset) {
- uint32_t size = _size(p_offset);
+ int size = _size(p_offset);
int pos = p_iter;
if (pos < 0 || pos >= size)
return Variant();
@@ -164,7 +164,7 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b
if (p_key.is_num()) {
int idx = p_key;
- uint32_t len = decode_uint32(r + 4);
+ int len = decode_uint32(r + 4);
if (idx < 0 || idx >= len) {
err = true;
return Variant();
@@ -183,7 +183,7 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b
uint32_t len = decode_uint32(r + 4);
bool found = false;
- for (int i = 0; i < len; i++) {
+ for (uint32_t i = 0; i < len; i++) {
uint32_t khash = decode_uint32(r + 8 + i * 12 + 0);
if (khash == hash) {
Variant key = _get_at_ofs(decode_uint32(r + 8 + i * 12 + 4), rd.ptr(), err);
diff --git a/core/pair.h b/core/pair.h
index f780c79c81..535c3355b6 100644
--- a/core/pair.h
+++ b/core/pair.h
@@ -44,6 +44,16 @@ struct Pair {
};
template <class F, class S>
+bool operator==(const Pair<F, S> &pair, const Pair<F, S> &other) {
+ return (pair.first == other.first) && (pair.second == other.second);
+}
+
+template <class F, class S>
+bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) {
+ return (pair.first != other.first) || (pair.second != other.second);
+}
+
+template <class F, class S>
struct PairSort {
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index c122d21545..c5f6d0dde0 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -339,9 +339,9 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) {
ERR_FAIL_COND_V(e->lock, ERR_ALREADY_IN_USE);
}
- int alloc_size = aligned(p_new_size);
+ uint32_t alloc_size = aligned(p_new_size);
- if (aligned(e->len) == alloc_size) {
+ if ((uint32_t)aligned(e->len) == alloc_size) {
e->len = p_new_size;
mt_unlock();
@@ -374,7 +374,7 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) {
}
//no need to move stuff around, it fits before the next block
- int next_pos;
+ uint32_t next_pos;
if (entry_indices_pos + 1 == entry_count) {
next_pos = pool_size; // - static_area_size;
} else {
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index ce1d7918db..2e4fc26784 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* globals.cpp */
+/* project_settings.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -114,7 +114,15 @@ String ProjectSettings::globalize_path(const String &p_path) const {
return p_path.replace("res:/", resource_path);
};
return p_path.replace("res://", "");
- };
+ } else if (p_path.begins_with("user://")) {
+
+ String data_dir = OS::get_singleton()->get_data_dir();
+ if (data_dir != "") {
+
+ return p_path.replace("user:/", data_dir);
+ };
+ return p_path.replace("user://", "");
+ }
return p_path;
}
@@ -144,7 +152,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
bool override_valid = false;
for (int i = 1; i < s.size(); i++) {
String feature = s[i].strip_edges();
- if (OS::get_singleton()->check_feature_support(feature) || custom_features.has(feature)) {
+ if (OS::get_singleton()->has_feature(feature) || custom_features.has(feature)) {
override_valid = true;
break;
}
@@ -253,7 +261,7 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack) {
return true;
}
-Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
+Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards) {
//If looking for files in network, just use network!
@@ -286,11 +294,26 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
//Attempt with execname.pck
if (exec_path != "") {
+ bool found = false;
- if (_load_resource_pack(exec_path.get_basename() + ".pck")) {
+ // 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();
+
+ // 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 {
+ datapack_name = filebase_name + ".pck";
+ if (_load_resource_pack(datapack_name)) {
+ found = true;
+ }
+ }
+ // 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"));
}
@@ -339,10 +362,14 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
break;
}
- d->change_dir("..");
- if (d->get_current_dir() == current_dir)
- break; //not doing anything useful
- current_dir = d->get_current_dir();
+ if (p_upwards) {
+ d->change_dir("..");
+ if (d->get_current_dir() == current_dir)
+ break; //not doing anything useful
+ current_dir = d->get_current_dir();
+ } else {
+ break;
+ }
}
resource_path = candidate;
@@ -358,7 +385,7 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
return OK;
}
-bool ProjectSettings::has(String p_var) const {
+bool ProjectSettings::has_setting(String p_var) const {
_THREAD_SAFE_METHOD_
@@ -605,8 +632,8 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
file->store_line("; Engine configuration file.");
file->store_line("; It's best edited using the editor UI and not directly,");
file->store_line("; since the parameters that go here are not all obvious.");
- file->store_line("; ");
- file->store_line("; Format: ");
+ file->store_line(";");
+ file->store_line("; Format:");
file->store_line("; [section] ; section goes between []");
file->store_line("; param=value ; assign values to parameters");
file->store_line("");
@@ -738,7 +765,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default) {
Variant ret;
- if (ProjectSettings::get_singleton()->has(p_var)) {
+ if (ProjectSettings::get_singleton()->has_setting(p_var)) {
ret = ProjectSettings::get_singleton()->get(p_var);
} else {
ProjectSettings::get_singleton()->set(p_var, p_default);
@@ -845,10 +872,20 @@ Variant ProjectSettings::property_get_revert(const String &p_name) {
return props[p_name].initial;
}
+void ProjectSettings::set_setting(const String &p_setting, const Variant &p_value) {
+ set(p_setting, p_value);
+}
+
+Variant ProjectSettings::get_setting(const String &p_setting) const {
+ return get(p_setting);
+}
+
void ProjectSettings::_bind_methods() {
- ClassDB::bind_method(D_METHOD("has", "name"), &ProjectSettings::has);
- ClassDB::bind_method(D_METHOD("set_order", "name", "pos"), &ProjectSettings::set_order);
+ ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
+ ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);
+ ClassDB::bind_method(D_METHOD("get_setting", "name"), &ProjectSettings::get_setting);
+ ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order);
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
ClassDB::bind_method(D_METHOD("add_property_info", "hint"), &ProjectSettings::_add_property_info_bind);
@@ -999,10 +1036,16 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("debug/settings/profiler/max_functions", 16384);
//assigning here, because using GLOBAL_GET on every block for compressing can be slow
+ Compression::zstd_long_distance_matching = GLOBAL_DEF("compression/formats/zstd/long_distance_matching", false);
+ custom_prop_info["compression/formats/zstd/long_distance_matching"] = PropertyInfo(Variant::BOOL, "compression/formats/zstd/long_distance_matching");
Compression::zstd_level = GLOBAL_DEF("compression/formats/zstd/compression_level", 3);
custom_prop_info["compression/formats/zstd/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/zstd/compression_level", PROPERTY_HINT_RANGE, "1,22,1");
+ Compression::zstd_window_log_size = GLOBAL_DEF("compression/formats/zstd/window_log_size", 27);
+ custom_prop_info["compression/formats/zstd/window_log_size"] = PropertyInfo(Variant::INT, "compression/formats/zstd/window_log_size", PROPERTY_HINT_RANGE, "10,30,1");
+
Compression::zlib_level = GLOBAL_DEF("compression/formats/zlib/compression_level", Z_DEFAULT_COMPRESSION);
custom_prop_info["compression/formats/zlib/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/zlib/compression_level", PROPERTY_HINT_RANGE, "-1,9,1");
+
Compression::gzip_level = GLOBAL_DEF("compression/formats/gzip/compression_level", Z_DEFAULT_COMPRESSION);
custom_prop_info["compression/formats/gzip/compression_level"] = PropertyInfo(Variant::INT, "compression/formats/gzip/compression_level", PROPERTY_HINT_RANGE, "-1,9,1");
diff --git a/core/project_settings.h b/core/project_settings.h
index 5c8907c74e..f75cad815f 100644
--- a/core/project_settings.h
+++ b/core/project_settings.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* globals.h */
+/* project_settings.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -119,7 +119,10 @@ protected:
static void _bind_methods();
public:
- bool has(String p_var) const;
+ void set_setting(const String &p_setting, const Variant &p_value);
+ Variant get_setting(const String &p_setting) const;
+
+ bool has_setting(String p_var) const;
String localize_path(const String &p_path) const;
String globalize_path(const String &p_path) const;
@@ -136,7 +139,7 @@ public:
void set_order(const String &p_name, int p_order);
void set_builtin_order(const String &p_name);
- Error setup(const String &p_path, const String &p_main_pack);
+ Error setup(const String &p_path, const String &p_main_pack, bool p_upwards = false);
Error save_custom(const String &p_path = "", const CustomMap &p_custom = CustomMap(), const Vector<String> &p_custom_features = Vector<String>(), bool p_merge_with_current = true);
Error save();
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 5fe8296314..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;
@@ -62,7 +62,7 @@ public:
template <class T>
class Ref {
- T *reference;
+ T *reference = NULL;
void ref(const Ref &p_from) {
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 27c31127a4..c6d7cd44e8 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -40,6 +40,7 @@
#include "io/config_file.h"
#include "io/http_client.h"
#include "io/marshalls.h"
+#include "io/networked_multiplayer_peer.h"
#include "io/packet_peer.h"
#include "io/packet_peer_udp.h"
#include "io/pck_packer.h"
@@ -68,6 +69,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;
@@ -108,6 +110,8 @@ void register_core_types() {
ClassDB::register_class<Object>();
+ ClassDB::register_virtual_class<Script>();
+
ClassDB::register_class<Reference>();
ClassDB::register_class<WeakRef>();
ClassDB::register_class<Resource>();
@@ -135,6 +139,7 @@ void register_core_types() {
ClassDB::register_virtual_class<IP>();
ClassDB::register_virtual_class<PacketPeer>();
ClassDB::register_class<PacketPeerStream>();
+ ClassDB::register_virtual_class<NetworkedMultiplayerPeer>();
ClassDB::register_class<MainLoop>();
//ClassDB::register_type<OptimizedSaver>();
ClassDB::register_class<Translation>();
@@ -162,6 +167,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 +179,7 @@ void register_core_types() {
_engine = memnew(_Engine);
_classdb = memnew(_ClassDB);
_marshalls = memnew(_Marshalls);
+ _json = memnew(_JSON);
}
void register_core_settings() {
@@ -181,6 +189,20 @@ void register_core_settings() {
void register_core_singletons() {
+ ClassDB::register_class<ProjectSettings>();
+ ClassDB::register_virtual_class<IP>();
+ ClassDB::register_class<_Geometry>();
+ ClassDB::register_class<_ResourceLoader>();
+ ClassDB::register_class<_ResourceSaver>();
+ ClassDB::register_class<_OS>();
+ ClassDB::register_class<_Engine>();
+ ClassDB::register_class<_ClassDB>();
+ ClassDB::register_class<_Marshalls>();
+ ClassDB::register_class<TranslationServer>();
+ ClassDB::register_virtual_class<Input>();
+ ClassDB::register_class<InputMap>();
+ ClassDB::register_class<_JSON>();
+
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("ProjectSettings", ProjectSettings::get_singleton()));
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("IP", IP::get_singleton()));
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Geometry", _Geometry::get_singleton()));
@@ -193,6 +215,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 +226,7 @@ void unregister_core_types() {
memdelete(_engine);
memdelete(_classdb);
memdelete(_marshalls);
+ memdelete(_json);
memdelete(_geometry);
diff --git a/core/resource.cpp b/core/resource.cpp
index 37d42226b4..78e20bada4 100644
--- a/core/resource.cpp
+++ b/core/resource.cpp
@@ -69,12 +69,11 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
ResourceCache::resources.get(p_path)->set_name("");
ResourceCache::lock->write_unlock();
} else {
- ERR_EXPLAIN("Another resource is loaded from path: " + p_path);
-
ResourceCache::lock->read_lock();
bool exists = ResourceCache::resources.has(p_path);
ResourceCache::lock->read_unlock();
+ ERR_EXPLAIN("Another resource is loaded from path: " + p_path);
ERR_FAIL_COND(exists);
}
}
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index c330a983a7..c9acdb7970 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -27,122 +27,10 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "safe_refcount.h"
-
-// Atomic functions, these are used for multithread safe reference counters!
-
-#ifdef NO_THREADS
-
-/* Bogus implementation unaware of multiprocessing */
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_conditional_increment_impl(register T *pw) {
-
- if (*pw == 0)
- return 0;
-
- (*pw)++;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_decrement_impl(register T *pw) {
-
- (*pw)--;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_increment_impl(register T *pw) {
-
- (*pw)++;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_sub_impl(register T *pw, register T val) {
-
- (*pw) -= val;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
-
- (*pw) += val;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) {
-
- if (val > *pw)
- *pw = val;
-
- return *pw;
-}
-#elif defined(__GNUC__)
-
-/* Implementation for GCC & Clang */
-
-// GCC guarantees atomic intrinsics for sizes of 1, 2, 4 and 8 bytes.
-// Clang states it supports GCC atomic builtins.
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_conditional_increment_impl(register T *pw) {
-
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp == 0)
- return 0; // if zero, can't add to it anymore
- if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
- return tmp + 1;
- }
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_decrement_impl(register T *pw) {
-
- return __sync_sub_and_fetch(pw, 1);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_increment_impl(register T *pw) {
-
- return __sync_add_and_fetch(pw, 1);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_sub_impl(register T *pw, register T val) {
-
- return __sync_sub_and_fetch(pw, val);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
-
- return __sync_add_and_fetch(pw, val);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) {
-
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp >= val)
- return tmp; // already greater, or equal
- if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
- return val;
- }
-}
+#include "safe_refcount.h"
-#elif defined(_MSC_VER)
+#if defined(_MSC_VER)
/* Implementation for MSVC-Windows */
@@ -169,73 +57,66 @@ static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, regist
return m_val; \
}
-static _ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw) {
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t)
}
-static _ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(register uint32_t *pw) {
return InterlockedDecrement((LONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
return InterlockedIncrement((LONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val;
}
-static _ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
return InterlockedAdd((LONG volatile *)pw, val);
}
-static _ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val) {
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t)
}
-static _ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw) {
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
-static _ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(register uint64_t *pw) {
return InterlockedDecrement64((LONGLONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
return InterlockedIncrement64((LONGLONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val;
}
-static _ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
return InterlockedAdd64((LONGLONG volatile *)pw, val);
}
-static _ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val) {
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
-#else
-
-//no threads supported?
-#error Must provide atomic functions for this platform or compiler!
-
-#endif
-
// The actual advertised functions; they'll call the right implementation
uint32_t atomic_conditional_increment(register uint32_t *counter) {
@@ -285,3 +166,4 @@ uint64_t atomic_add(register uint64_t *pw, register uint64_t val) {
uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val) {
return _atomic_exchange_if_greater_impl(pw, val);
}
+#endif
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 802d84cccc..39967d5ac4 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -36,20 +36,141 @@
#include "platform_config.h"
#include "typedefs.h"
-uint32_t atomic_conditional_increment(register uint32_t *counter);
+// Atomic functions, these are used for multithread safe reference counters!
+
+#ifdef NO_THREADS
+
+/* Bogus implementation unaware of multiprocessing */
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+
+ if (*pw == 0)
+ return 0;
+
+ (*pw)++;
+
+ return *pw;
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+
+ (*pw)--;
+
+ return *pw;
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+
+ (*pw)++;
+
+ return *pw;
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+
+ (*pw) -= val;
+
+ return *pw;
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+
+ (*pw) += val;
+
+ return *pw;
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+
+ if (val > *pw)
+ *pw = val;
+
+ return *pw;
+}
+
+#elif defined(__GNUC__)
+
+/* Implementation for GCC & Clang */
+
+// GCC guarantees atomic intrinsics for sizes of 1, 2, 4 and 8 bytes.
+// Clang states it supports GCC atomic builtins.
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+
+ while (true) {
+ T tmp = static_cast<T const volatile &>(*pw);
+ if (tmp == 0)
+ return 0; // if zero, can't add to it anymore
+ if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
+ return tmp + 1;
+ }
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+
+ return __sync_sub_and_fetch(pw, 1);
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+
+ return __sync_add_and_fetch(pw, 1);
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+
+ return __sync_sub_and_fetch(pw, val);
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+
+ return __sync_add_and_fetch(pw, val);
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+
+ while (true) {
+ T tmp = static_cast<T const volatile &>(*pw);
+ if (tmp >= val)
+ return tmp; // already greater, or equal
+ if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
+ return val;
+ }
+}
+
+#elif defined(_MSC_VER)
+// For MSVC use a separate compilation unit to prevent windows.h from polluting
+// the global namespace.
+uint32_t atomic_conditional_increment(register uint32_t *pw);
uint32_t atomic_decrement(register uint32_t *pw);
uint32_t atomic_increment(register uint32_t *pw);
uint32_t atomic_sub(register uint32_t *pw, register uint32_t val);
uint32_t atomic_add(register uint32_t *pw, register uint32_t val);
uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val);
-uint64_t atomic_conditional_increment(register uint64_t *counter);
+uint64_t atomic_conditional_increment(register uint64_t *pw);
uint64_t atomic_decrement(register uint64_t *pw);
uint64_t atomic_increment(register uint64_t *pw);
uint64_t atomic_sub(register uint64_t *pw, register uint64_t val);
uint64_t atomic_add(register uint64_t *pw, register uint64_t val);
uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val);
+#else
+//no threads supported?
+#error Must provide atomic functions for this platform or compiler!
+#endif
+
struct SafeRefCount {
uint32_t count;
@@ -57,17 +178,17 @@ struct SafeRefCount {
public:
// destroy() is called when weak_count_ drops to zero.
- bool ref() { //true on success
+ _ALWAYS_INLINE_ bool ref() { //true on success
return atomic_conditional_increment(&count) != 0;
}
- uint32_t refval() { //true on success
+ _ALWAYS_INLINE_ uint32_t refval() { //true on success
return atomic_conditional_increment(&count);
}
- bool unref() { // true if must be disposed of
+ _ALWAYS_INLINE_ bool unref() { // true if must be disposed of
if (atomic_decrement(&count) == 0) {
return true;
@@ -76,12 +197,12 @@ public:
return false;
}
- uint32_t get() const { // nothrow
+ _ALWAYS_INLINE_ uint32_t get() const { // nothrow
return count;
}
- void init(uint32_t p_value = 1) {
+ _ALWAYS_INLINE_ void init(uint32_t p_value = 1) {
count = p_value;
}
diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index c2632da38b..8d2600e52d 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -186,12 +186,12 @@ struct _ScriptDebuggerLocalProfileInfoSort {
}
};
-void ScriptDebuggerLocal::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) {
+void ScriptDebuggerLocal::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
frame_time = p_frame_time;
idle_time = p_idle_time;
- fixed_time = p_fixed_time;
- fixed_frame_time = p_fixed_frame_time;
+ physics_time = p_physics_time;
+ physics_frame_time = p_physics_frame_time;
}
void ScriptDebuggerLocal::idle_poll() {
@@ -250,9 +250,9 @@ void ScriptDebuggerLocal::profiling_start() {
profiling = true;
pinfo.resize(32768);
frame_time = 0;
- fixed_time = 0;
+ physics_time = 0;
idle_time = 0;
- fixed_frame_time = 0;
+ physics_frame_time = 0;
}
void ScriptDebuggerLocal::profiling_end() {
diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h
index 097c7c41f3..91f787052c 100644
--- a/core/script_debugger_local.h
+++ b/core/script_debugger_local.h
@@ -35,7 +35,7 @@
class ScriptDebuggerLocal : public ScriptDebugger {
bool profiling;
- float frame_time, idle_time, fixed_time, fixed_frame_time;
+ float frame_time, idle_time, physics_time, physics_frame_time;
uint64_t idle_accum;
Vector<ScriptLanguage::ProfilingInfo> pinfo;
@@ -51,7 +51,7 @@ public:
virtual void profiling_start();
virtual void profiling_end();
- virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time);
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
ScriptDebuggerLocal();
};
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 8875732b8e..2feb068ecb 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 {
@@ -644,8 +647,8 @@ void ScriptDebuggerRemote::_poll_events() {
profiling = true;
frame_time = 0;
idle_time = 0;
- fixed_time = 0;
- fixed_frame_time = 0;
+ physics_time = 0;
+ physics_frame_time = 0;
print_line("PROFILING ALRIGHT!");
@@ -724,8 +727,8 @@ void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) {
packet_peer_stream->put_var(Engine::get_singleton()->get_frames_drawn()); //total frame time
packet_peer_stream->put_var(frame_time); //total frame time
packet_peer_stream->put_var(idle_time); //idle frame time
- packet_peer_stream->put_var(fixed_time); //fixed frame time
- packet_peer_stream->put_var(fixed_frame_time); //fixed frame time
+ packet_peer_stream->put_var(physics_time); //fixed frame time
+ packet_peer_stream->put_var(physics_frame_time); //fixed frame time
packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time
@@ -852,15 +855,19 @@ void ScriptDebuggerRemote::_print_handler(void *p_this, const String &p_string)
}
sdr->char_count += allowed_chars;
-
- if (sdr->char_count >= sdr->max_cps) {
- s += "\n[output overflow, print less text!]\n";
- }
+ bool overflowed = sdr->char_count >= sdr->max_cps;
sdr->mutex->lock();
if (!sdr->locking && sdr->tcp_client->is_connected_to_host()) {
+ if (overflowed)
+ s += "[...]";
+
sdr->output_strings.push_back(s);
+
+ if (overflowed) {
+ sdr->output_strings.push_back("[output overflow, print less text!]");
+ }
}
sdr->mutex->unlock();
}
@@ -914,12 +921,12 @@ void ScriptDebuggerRemote::profiling_end() {
//ignores this, uses it via connnection
}
-void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) {
+void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
frame_time = p_frame_time;
idle_time = p_idle_time;
- fixed_time = p_fixed_time;
- fixed_frame_time = p_fixed_frame_time;
+ physics_time = p_physics_time;
+ physics_frame_time = p_physics_frame_time;
}
ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func = NULL;
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index b1ef88b812..22137d1350 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -54,7 +54,7 @@ class ScriptDebuggerRemote : public ScriptDebugger {
Vector<ScriptLanguage::ProfilingInfo *> profile_info_ptrs;
Map<StringName, int> profiler_function_signature_map;
- float frame_time, idle_time, fixed_time, fixed_frame_time;
+ float frame_time, idle_time, physics_time, physics_frame_time;
bool profiling;
int max_frame_functions;
@@ -161,7 +161,7 @@ public:
virtual void profiling_start();
virtual void profiling_end();
- virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time);
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
ScriptDebuggerRemote();
~ScriptDebuggerRemote();
diff --git a/core/script_language.cpp b/core/script_language.cpp
index f2be15897e..384e41e4bd 100644
--- a/core/script_language.cpp
+++ b/core/script_language.cpp
@@ -55,11 +55,9 @@ void Script::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_source_code", "source"), &Script::set_source_code);
ClassDB::bind_method(D_METHOD("reload", "keep_state"), &Script::reload, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("has_method", "method_name"), &Script::has_method);
ClassDB::bind_method(D_METHOD("has_script_signal", "signal_name"), &Script::has_script_signal);
ClassDB::bind_method(D_METHOD("is_tool"), &Script::is_tool);
- ClassDB::bind_method(D_METHOD("get_node_type"), &Script::get_node_type);
}
void ScriptServer::set_scripting_enabled(bool p_enabled) {
@@ -185,7 +183,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/script_language.h b/core/script_language.h
index 342d8c8072..5da72d0492 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -107,8 +107,6 @@ public:
virtual bool is_tool() const = 0;
- virtual String get_node_type() const = 0;
-
virtual ScriptLanguage *get_language() const = 0;
virtual bool has_script_signal(const StringName &p_signal) const = 0;
@@ -202,10 +200,12 @@ public:
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0;
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
+ virtual bool supports_builtin_mode() const = 0;
virtual bool can_inherit_from_file() { return false; }
virtual int find_function(const String &p_function, const String &p_code) const = 0;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0;
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
+ virtual bool overrides_external_editor() { return false; }
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
@@ -396,7 +396,7 @@ public:
virtual void add_profiling_frame_data(const StringName &p_name, const Array &p_data) = 0;
virtual void profiling_start() = 0;
virtual void profiling_end() = 0;
- virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) = 0;
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) = 0;
ScriptDebugger();
virtual ~ScriptDebugger() { singleton = NULL; }
diff --git a/core/set.h b/core/set.h
index 317e180869..331979d4e3 100644
--- a/core/set.h
+++ b/core/set.h
@@ -100,17 +100,15 @@ private:
Element *_nil;
int size_cache;
- _Data() {
+ _FORCE_INLINE_ _Data() {
#ifdef GLOBALNIL_DISABLED
_nil = memnew_allocator(Element, A);
_nil->parent = _nil->left = _nil->right = _nil;
_nil->color = BLACK;
#else
-
_nil = (Element *)&_GlobalNilClass::_nil;
#endif
_root = NULL;
-
size_cache = 0;
}
@@ -132,10 +130,10 @@ private:
~_Data() {
_free_root();
+
#ifdef GLOBALNIL_DISABLED
memdelete_allocator<Element, A>(_nil);
#endif
- //memdelete_allocator<Element,A>(_root);
}
};
@@ -146,6 +144,7 @@ private:
ERR_FAIL_COND(p_node == _data._nil && p_color == RED);
p_node->color = p_color;
}
+
inline void _rotate_left(Element *p_node) {
Element *r = p_node->right;
@@ -194,8 +193,9 @@ private:
while (node == node->parent->right) {
node = node->parent;
}
+
if (node->parent == _data._root)
- return NULL;
+ return NULL; // No successor, as p_node = last node
return node->parent;
}
}
@@ -213,11 +213,11 @@ private:
} else {
while (node == node->parent->left) {
- if (node->parent == _data._root)
- return NULL;
-
node = node->parent;
}
+
+ if (node == _data._root)
+ return NULL; // No predecessor, as p_node = first node.
return node->parent;
}
}
@@ -228,16 +228,15 @@ private:
C less;
while (node != _data._nil) {
-
if (less(p_value, node->value))
node = node->left;
else if (less(node->value, p_value))
node = node->right;
else
- break; // found
+ return node; // found
}
- return (node != _data._nil) ? node : NULL;
+ return NULL;
}
Element *_lower_bound(const T &p_value) const {
@@ -254,24 +253,68 @@ private:
else if (less(node->value, p_value))
node = node->right;
else
- break; // found
+ return node; // found
}
- if (node == _data._nil) {
- if (prev == NULL)
- return NULL;
- if (less(prev->value, p_value)) {
+ if (prev == NULL)
+ return NULL; // tree empty
- prev = prev->_next;
- }
+ if (less(prev->value, p_value))
+ prev = prev->_next;
- return prev;
+ return prev;
+ }
- } else
- return node;
+ void _insert_rb_fix(Element *p_new_node) {
+
+ Element *node = p_new_node;
+ Element *nparent = node->parent;
+ Element *ngrand_parent;
+
+ while (nparent->color == RED) {
+ ngrand_parent = nparent->parent;
+
+ if (nparent == ngrand_parent->left) {
+ if (ngrand_parent->right->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->right, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->right) {
+ _rotate_left(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_right(ngrand_parent);
+ }
+ } else {
+ if (ngrand_parent->left->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->left, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->left) {
+ _rotate_right(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_left(ngrand_parent);
+ }
+ }
+ }
+
+ _set_color(_data._root->left, BLACK);
}
- Element *_insert(const T &p_value, bool &r_exists) {
+ Element *_insert(const T &p_value) {
Element *new_parent = _data._root;
Element *node = _data._root->left;
@@ -286,27 +329,23 @@ private:
else if (less(node->value, p_value))
node = node->right;
else {
- r_exists = true;
- return node;
+ return node; // Return existing node
}
}
Element *new_node = memnew_allocator(Element, A);
-
new_node->parent = new_parent;
new_node->right = _data._nil;
new_node->left = _data._nil;
new_node->value = p_value;
//new_node->data=_data;
- if (new_parent == _data._root || less(p_value, new_parent->value)) {
+ if (new_parent == _data._root || less(p_value, new_parent->value)) {
new_parent->left = new_node;
} else {
new_parent->right = new_node;
}
- r_exists = false;
-
new_node->_next = _successor(new_node);
new_node->_prev = _predecessor(new_node);
if (new_node->_next)
@@ -314,163 +353,112 @@ private:
if (new_node->_prev)
new_node->_prev->_next = new_node;
- return new_node;
- }
-
- Element *_insert_rb(const T &p_value) {
-
- bool exists = false;
- Element *new_node = _insert(p_value, exists);
- if (exists)
- return new_node;
-
- Element *node = new_node;
_data.size_cache++;
-
- while (node->parent->color == RED) {
-
- if (node->parent == node->parent->parent->left) {
-
- Element *aux = node->parent->parent->right;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->right) {
- node = node->parent;
- _rotate_left(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_right(node->parent->parent);
- }
- } else {
- Element *aux = node->parent->parent->left;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->left) {
- node = node->parent;
- _rotate_right(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_left(node->parent->parent);
- }
- }
- }
- _set_color(_data._root->left, BLACK);
+ _insert_rb_fix(new_node);
return new_node;
}
- void _erase_fix(Element *p_node) {
+ void _erase_fix_rb(Element *p_node) {
Element *root = _data._root->left;
- Element *node = p_node;
-
- while ((node->color == BLACK) && (root != node)) {
- if (node == node->parent->left) {
- Element *aux = node->parent->right;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_left(node->parent);
- aux = node->parent->right;
- }
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ Element *node = _data._nil;
+ Element *sibling = p_node;
+ Element *parent = sibling->parent;
+
+ while (node != root) { // If red node found, will exit at a break
+ if (sibling->color == RED) {
+ _set_color(sibling, BLACK);
+ _set_color(parent, RED);
+ if (sibling == parent->right) {
+ sibling = sibling->left;
+ _rotate_left(parent);
} else {
- if (aux->right->color == BLACK) {
- _set_color(aux->left, BLACK);
- _set_color(aux, RED);
- _rotate_right(aux);
- aux = node->parent->right;
- }
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->right, BLACK);
- _rotate_left(node->parent);
- node = root; /* this is to exit while loop */
+ sibling = sibling->right;
+ _rotate_right(parent);
}
- } else { /* the code below is has left and right switched from above */
- Element *aux = node->parent->left;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_right(node->parent);
- aux = node->parent->left;
+ }
+ if ((sibling->left->color == BLACK) && (sibling->right->color == BLACK)) {
+ _set_color(sibling, RED);
+ if (parent->color == RED) {
+ _set_color(parent, BLACK);
+ break;
+ } else { // loop: haven't found any red nodes yet
+ node = parent;
+ parent = node->parent;
+ sibling = (node == parent->left) ? parent->right : parent->left;
}
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ } else {
+ if (sibling == parent->right) {
+ if (sibling->right->color == BLACK) {
+ _set_color(sibling->left, BLACK);
+ _set_color(sibling, RED);
+ _rotate_right(sibling);
+ sibling = sibling->parent;
+ }
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->right, BLACK);
+ _rotate_left(parent);
+ break;
} else {
- if (aux->left->color == BLACK) {
- _set_color(aux->right, BLACK);
- _set_color(aux, RED);
- _rotate_left(aux);
- aux = node->parent->left;
+ if (sibling->left->color == BLACK) {
+ _set_color(sibling->right, BLACK);
+ _set_color(sibling, RED);
+ _rotate_left(sibling);
+ sibling = sibling->parent;
}
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->left, BLACK);
- _rotate_right(node->parent);
- node = root;
+
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->left, BLACK);
+ _rotate_right(parent);
+ break;
}
}
}
- _set_color(node, BLACK);
-
ERR_FAIL_COND(_data._nil->color != BLACK);
}
void _erase(Element *p_node) {
- Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : _successor(p_node);
- if (!rp)
- rp = _data._nil;
+ Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- if (_data._root == (node->parent = rp->parent)) {
- _data._root->left = node;
+ Element *sibling;
+ if (rp == rp->parent->left) {
+ rp->parent->left = node;
+ sibling = rp->parent->right;
} else {
- if (rp == rp->parent->left) {
- rp->parent->left = node;
- } else {
- rp->parent->right = node;
- }
+ rp->parent->right = node;
+ sibling = rp->parent->left;
+ }
+
+ if (node->color == RED) {
+ node->parent = rp->parent;
+ _set_color(node, BLACK);
+ } else if (rp->color == BLACK && rp->parent != _data._root) {
+ _erase_fix_rb(sibling);
}
if (rp != p_node) {
ERR_FAIL_COND(rp == _data._nil);
- if (rp->color == BLACK)
- _erase_fix(node);
-
rp->left = p_node->left;
rp->right = p_node->right;
rp->parent = p_node->parent;
rp->color = p_node->color;
- p_node->left->parent = rp;
- p_node->right->parent = rp;
+ if (p_node->left != _data._nil)
+ p_node->left->parent = rp;
+ if (p_node->right != _data._nil)
+ p_node->right->parent = rp;
if (p_node == p_node->parent->left) {
p_node->parent->left = rp;
} else {
p_node->parent->right = rp;
}
- } else {
- if (p_node->color == BLACK)
- _erase_fix(node);
}
if (p_node->_next)
@@ -485,11 +473,12 @@ private:
void _calculate_depth(Element *p_element, int &max_d, int d) const {
- if (p_element == _data._nil) {
+ if (p_element == _data._nil)
return;
- }
+
_calculate_depth(p_element->left, max_d, d + 1);
_calculate_depth(p_element->right, max_d, d + 1);
+
if (d > max_d)
max_d = d;
}
@@ -528,14 +517,18 @@ public:
if (!_data._root)
return NULL;
+
Element *res = _find(p_value);
return res;
}
+ Element *lower_bound(const T &p_value) const {
+
+ return _lower_bound(p_value);
+ }
+
bool has(const T &p_value) const {
- if (!_data._root)
- return false;
return find(p_value) != NULL;
}
@@ -543,13 +536,14 @@ public:
if (!_data._root)
_data._create_root();
- return _insert_rb(p_value);
+ return _insert(p_value);
}
void erase(Element *p_element) {
- if (!_data._root)
+ if (!_data._root || !p_element)
return;
+
_erase(p_element);
if (_data.size_cache == 0 && _data._root)
_data._free_root();
@@ -559,9 +553,11 @@ public:
if (!_data._root)
return false;
+
Element *e = find(p_value);
if (!e)
return false;
+
_erase(e);
if (_data.size_cache == 0 && _data._root)
_data._free_root();
@@ -572,6 +568,7 @@ public:
if (!_data._root)
return NULL;
+
Element *e = _data._root->left;
if (e == _data._nil)
return NULL;
@@ -586,6 +583,7 @@ public:
if (!_data._root)
return NULL;
+
Element *e = _data._root->left;
if (e == _data._nil)
return NULL;
@@ -596,16 +594,13 @@ public:
return e;
}
- Element *lower_bound(const T &p_value) const {
-
- return _lower_bound(p_value);
- }
-
inline int size() const { return _data.size_cache; }
+
int calculate_depth() const {
// used for debug mostly
if (!_data._root)
return 0;
+
int max_d = 0;
_calculate_depth(_data._root->left, max_d, 0);
return max_d;
@@ -619,7 +614,6 @@ public:
_cleanup_tree(_data._root->left);
_data._root->left = _data._nil;
_data.size_cache = 0;
- _data._nil->parent = _data._nil;
_data._free_root();
}
@@ -632,6 +626,7 @@ public:
_copy_from(p_set);
}
+
_FORCE_INLINE_ Set() {
}
diff --git a/core/string_buffer.cpp b/core/string_buffer.cpp
new file mode 100644
index 0000000000..195068f887
--- /dev/null
+++ b/core/string_buffer.cpp
@@ -0,0 +1,102 @@
+/*************************************************************************/
+/* string_buffer.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 "string_buffer.h"
+
+#include <string.h>
+
+StringBuffer &StringBuffer::append(CharType p_char) {
+ reserve(string_length + 2);
+ current_buffer_ptr()[string_length++] = p_char;
+ return *this;
+}
+
+StringBuffer &StringBuffer::append(const String &p_string) {
+ return append(p_string.c_str());
+}
+
+StringBuffer &StringBuffer::append(const char *p_str) {
+ int len = strlen(p_str);
+ reserve(string_length + len + 1);
+
+ CharType *buf = current_buffer_ptr();
+ for (const char *c_ptr = p_str; c_ptr; ++c_ptr) {
+ buf[string_length++] = *c_ptr;
+ }
+ return *this;
+}
+
+StringBuffer &StringBuffer::append(const CharType *p_str, int p_clip_to_len) {
+ int len = 0;
+ while ((p_clip_to_len < 0 || len < p_clip_to_len) && p_str[len]) {
+ ++len;
+ }
+ reserve(string_length + len + 1);
+ memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(CharType));
+ string_length += len;
+
+ return *this;
+}
+
+StringBuffer &StringBuffer::reserve(int p_size) {
+ if (p_size < SHORT_BUFFER_SIZE || p_size < buffer.size())
+ return *this;
+
+ bool need_copy = string_length > 0 && buffer.empty();
+ buffer.resize(next_power_of_2(p_size));
+ if (need_copy) {
+ memcpy(buffer.ptr(), short_buffer, string_length * sizeof(CharType));
+ }
+
+ return *this;
+}
+
+int StringBuffer::length() const {
+ return string_length;
+}
+
+String StringBuffer::as_string() {
+ current_buffer_ptr()[string_length] = '\0';
+ if (buffer.empty()) {
+ return String(short_buffer);
+ } else {
+ buffer.resize(string_length + 1);
+ return buffer;
+ }
+}
+
+double StringBuffer::as_double() {
+ current_buffer_ptr()[string_length] = '\0';
+ return String::to_double(current_buffer_ptr());
+}
+
+int64_t StringBuffer::as_int() {
+ current_buffer_ptr()[string_length] = '\0';
+ return String::to_int(current_buffer_ptr());
+}
diff --git a/core/os/power.h b/core/string_buffer.h
index 59a091012e..3f36249148 100644
--- a/core/os/power.h
+++ b/core/string_buffer.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* power.h */
+/* string_buffer.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,16 +27,56 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef STRING_BUFFER_H
+#define STRING_BUFFER_H
-#ifndef CORE_OS_POWER_H_
-#define CORE_OS_POWER_H_
+#include "ustring.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;
+class StringBuffer {
+ static const int SHORT_BUFFER_SIZE = 64;
-#endif /* CORE_OS_POWER_H_ */
+ CharType short_buffer[SHORT_BUFFER_SIZE];
+ String buffer;
+ int string_length = 0;
+
+ _FORCE_INLINE_ CharType *current_buffer_ptr() {
+ return static_cast<Vector<CharType> &>(buffer).empty() ? short_buffer : buffer.ptr();
+ }
+
+public:
+ StringBuffer &append(CharType p_char);
+ StringBuffer &append(const String &p_string);
+ StringBuffer &append(const char *p_str);
+ StringBuffer &append(const CharType *p_str, int p_clip_to_len = -1);
+
+ _FORCE_INLINE_ void operator+=(CharType p_char) {
+ append(p_char);
+ }
+
+ _FORCE_INLINE_ void operator+=(const String &p_string) {
+ append(p_string);
+ }
+
+ _FORCE_INLINE_ void operator+=(const char *p_str) {
+ append(p_str);
+ }
+
+ _FORCE_INLINE_ void operator+=(const CharType *p_str) {
+ append(p_str);
+ }
+
+ StringBuffer &reserve(int p_size);
+
+ int length() const;
+
+ String as_string();
+
+ double as_double();
+ int64_t as_int();
+
+ _FORCE_INLINE_ operator String() {
+ return as_string();
+ }
+};
+
+#endif
diff --git a/core/string_builder.cpp b/core/string_builder.cpp
new file mode 100644
index 0000000000..18c710ed2d
--- /dev/null
+++ b/core/string_builder.cpp
@@ -0,0 +1,94 @@
+/*************************************************************************/
+/* string_builder.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 "string_builder.h"
+
+#include <string.h>
+
+StringBuilder &StringBuilder::append(const String &p_string) {
+
+ strings.push_back(p_string);
+ appended_strings.push_back(-1);
+
+ string_length += p_string.length();
+
+ return *this;
+}
+
+StringBuilder &StringBuilder::append(const char *p_cstring) {
+
+ int32_t len = strlen(p_cstring);
+
+ c_strings.push_back(p_cstring);
+ appended_strings.push_back(len);
+
+ string_length += len;
+
+ return *this;
+}
+
+String StringBuilder::as_string() const {
+
+ CharType *buffer = memnew_arr(CharType, string_length);
+
+ int current_position = 0;
+
+ int godot_string_elem = 0;
+ int c_string_elem = 0;
+
+ for (int i = 0; i < appended_strings.size(); i++) {
+ if (appended_strings[i] == -1) {
+ // Godot string
+ const String &s = strings[godot_string_elem];
+
+ memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(CharType));
+
+ current_position += s.length();
+
+ godot_string_elem++;
+ } else {
+
+ const char *s = c_strings[c_string_elem];
+
+ for (int32_t j = 0; j < appended_strings[i]; j++) {
+ buffer[current_position + j] = s[j];
+ }
+
+ current_position += appended_strings[i];
+
+ c_string_elem++;
+ }
+ }
+
+ String final_string = String(buffer, string_length);
+
+ memdelete_arr(buffer);
+
+ return final_string;
+}
diff --git a/core/event_queue.h b/core/string_builder.h
index af1a760945..7cf2f07872 100644
--- a/core/event_queue.h
+++ b/core/string_builder.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* event_queue.h */
+/* string_builder.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,38 +27,53 @@
/* 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
+#ifndef STRING_BUILDER_H
+#define STRING_BUILDER_H
-#include "object.h"
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class EventQueue {
+#include "core/ustring.h"
- enum {
+#include "core/vector.h"
- DEFAULT_EVENT_QUEUE_SIZE_KB = 256
- };
+class StringBuilder {
- struct Event {
+ uint32_t string_length = 0;
- uint32_t instance_ID;
- StringName method;
- int args;
- };
+ Vector<String> strings;
+ Vector<const char *> c_strings;
- uint8_t *event_buffer;
- uint32_t buffer_end;
- uint32_t buffer_max_used;
- uint32_t buffer_size;
+ // -1 means it's a Godot String
+ // a natural number means C string.
+ Vector<int32_t> appended_strings;
public:
- Error push_call(uint32_t p_instance_ID, const StringName &p_method, VARIANT_ARG_LIST);
- void flush_events();
+ StringBuilder &append(const String &p_string);
+ StringBuilder &append(const char *p_cstring);
- EventQueue(uint32_t p_buffer_size = DEFAULT_EVENT_QUEUE_SIZE_KB * 1024);
- ~EventQueue();
+ _FORCE_INLINE_ StringBuilder &operator+(const String &p_string) {
+ return append(p_string);
+ }
+
+ _FORCE_INLINE_ StringBuilder &operator+(const char *p_cstring) {
+ return append(p_cstring);
+ }
+
+ _FORCE_INLINE_ void operator+=(const String &p_string) {
+ append(p_string);
+ }
+
+ _FORCE_INLINE_ void operator+=(const char *p_cstring) {
+ append(p_cstring);
+ }
+
+ _FORCE_INLINE_ int num_strings_appended() const {
+ return appended_strings.size();
+ }
+
+ String as_string() const;
+
+ _FORCE_INLINE_ operator String() const {
+ return as_string();
+ }
};
-#endif
+#endif // STRING_BUILDER_H
diff --git a/core/string_db.h b/core/string_db.h
index 2bef29fab8..de91e2abd8 100644
--- a/core/string_db.h
+++ b/core/string_db.h
@@ -113,6 +113,9 @@ public:
else
return 0;
}
+ _FORCE_INLINE_ const void *data_unique_pointer() const {
+ return (void *)_data;
+ }
bool operator!=(const StringName &p_name) const;
_FORCE_INLINE_ operator String() const {
diff --git a/core/translation.cpp b/core/translation.cpp
index f1f9c72b85..058db956e5 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -753,65 +753,17 @@ static const char *locale_names[] = {
0
};
-bool TranslationServer::is_locale_valid(const String &p_locale) {
-
- const char **ptr = locale_list;
-
- while (*ptr) {
-
- if (*ptr == p_locale)
- return true;
- ptr++;
- }
-
- return false;
-}
-
-Vector<String> TranslationServer::get_all_locales() {
-
- Vector<String> locales;
-
- const char **ptr = locale_list;
-
- while (*ptr) {
- locales.push_back(*ptr);
- ptr++;
- }
-
- return locales;
-}
-
-Vector<String> TranslationServer::get_all_locale_names() {
-
- Vector<String> locales;
-
- const char **ptr = locale_names;
-
- while (*ptr) {
- locales.push_back(*ptr);
- ptr++;
- }
-
- return locales;
-}
+static const char *locale_renames[][2] = {
+ { "no", "nb" },
+ { NULL, NULL }
+};
static String get_trimmed_locale(const String &p_locale) {
return p_locale.substr(0, 2);
}
-static bool is_valid_locale(const String &p_locale) {
-
- const char **ptr = locale_list;
-
- while (*ptr) {
- if (p_locale == *ptr)
- return true;
- ptr++;
- }
-
- return false;
-}
+///////////////////////////////////////////////
PoolVector<String> Translation::_get_messages() const {
@@ -857,14 +809,13 @@ void Translation::_set_messages(const PoolVector<String> &p_messages) {
void Translation::set_locale(const String &p_locale) {
- // replaces '-' with '_' for macOS Sierra-style locales
- String univ_locale = p_locale.replace("-", "_");
+ String univ_locale = TranslationServer::standardize_locale(p_locale);
- if (!is_valid_locale(univ_locale)) {
+ if (!TranslationServer::is_locale_valid(univ_locale)) {
String trimmed_locale = get_trimmed_locale(univ_locale);
- ERR_EXPLAIN("Invalid Locale: " + trimmed_locale);
- ERR_FAIL_COND(!is_valid_locale(trimmed_locale));
+ ERR_EXPLAIN("Invalid locale: " + trimmed_locale);
+ ERR_FAIL_COND(!TranslationServer::is_locale_valid(trimmed_locale));
locale = trimmed_locale;
} else {
@@ -929,16 +880,47 @@ Translation::Translation()
///////////////////////////////////////////////
-void TranslationServer::set_locale(const String &p_locale) {
+bool TranslationServer::is_locale_valid(const String &p_locale) {
+
+ const char **ptr = locale_list;
+
+ while (*ptr) {
+
+ if (*ptr == p_locale)
+ return true;
+ ptr++;
+ }
- // replaces '-' with '_' for macOS Sierra-style locales
+ return false;
+}
+
+String TranslationServer::standardize_locale(const String &p_locale) {
+
+ // Replaces '-' with '_' for macOS Sierra-style locales
String univ_locale = p_locale.replace("-", "_");
- if (!is_valid_locale(univ_locale)) {
+ // Handles known non-ISO locale names used e.g. on Windows
+ int idx = 0;
+ while (locale_renames[idx][0] != NULL) {
+ if (locale_renames[idx][0] == univ_locale) {
+ univ_locale = locale_renames[idx][1];
+ break;
+ }
+ idx++;
+ }
+
+ return univ_locale;
+}
+
+void TranslationServer::set_locale(const String &p_locale) {
+
+ String univ_locale = standardize_locale(p_locale);
+
+ if (!is_locale_valid(univ_locale)) {
String trimmed_locale = get_trimmed_locale(univ_locale);
- ERR_EXPLAIN("Invalid Locale: " + trimmed_locale);
- ERR_FAIL_COND(!is_valid_locale(trimmed_locale));
+ ERR_EXPLAIN("Invalid locale: " + trimmed_locale);
+ ERR_FAIL_COND(!is_locale_valid(trimmed_locale));
locale = trimmed_locale;
} else {
@@ -957,6 +939,40 @@ String TranslationServer::get_locale() const {
return locale;
}
+String TranslationServer::get_locale_name(const String &p_locale) const {
+
+ if (!locale_name_map.has(p_locale)) return String();
+ return locale_name_map[p_locale];
+}
+
+Vector<String> TranslationServer::get_all_locales() {
+
+ Vector<String> locales;
+
+ const char **ptr = locale_list;
+
+ while (*ptr) {
+ locales.push_back(*ptr);
+ ptr++;
+ }
+
+ return locales;
+}
+
+Vector<String> TranslationServer::get_all_locale_names() {
+
+ Vector<String> locales;
+
+ const char **ptr = locale_names;
+
+ while (*ptr) {
+ locales.push_back(*ptr);
+ ptr++;
+ }
+
+ return locales;
+}
+
void TranslationServer::add_translation(const Ref<Translation> &p_translation) {
translations.insert(p_translation);
@@ -1052,7 +1068,7 @@ TranslationServer *TranslationServer::singleton = NULL;
bool TranslationServer::_load_translations(const String &p_from) {
- if (ProjectSettings::get_singleton()->has(p_from)) {
+ if (ProjectSettings::get_singleton()->has_setting(p_from)) {
PoolVector<String> translations = ProjectSettings::get_singleton()->get(p_from);
int tcount = translations.size();
@@ -1122,6 +1138,8 @@ void TranslationServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_locale", "locale"), &TranslationServer::set_locale);
ClassDB::bind_method(D_METHOD("get_locale"), &TranslationServer::get_locale);
+ ClassDB::bind_method(D_METHOD("get_locale_name", "locale"), &TranslationServer::get_locale_name);
+
ClassDB::bind_method(D_METHOD("translate", "message"), &TranslationServer::translate);
ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationServer::add_translation);
@@ -1147,4 +1165,9 @@ TranslationServer::TranslationServer()
: locale("en"),
enabled(true) {
singleton = this;
+
+ for (int i = 0; locale_list[i]; ++i) {
+
+ locale_name_map.insert(locale_list[i], locale_names[i]);
+ }
}
diff --git a/core/translation.h b/core/translation.h
index cf59583ad6..0cdab3b0bc 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -73,6 +73,8 @@ class TranslationServer : public Object {
Set<Ref<Translation> > translations;
Ref<Translation> tool_translation;
+ Map<String, String> locale_name_map;
+
bool enabled;
static TranslationServer *singleton;
@@ -83,14 +85,14 @@ class TranslationServer : public Object {
public:
_FORCE_INLINE_ static TranslationServer *get_singleton() { return singleton; }
- //yes, portuguese is supported!
-
void set_enabled(bool p_enabled) { enabled = p_enabled; }
_FORCE_INLINE_ bool is_enabled() const { return enabled; }
void set_locale(const String &p_locale);
String get_locale() const;
+ String get_locale_name(const String &p_locale) const;
+
void add_translation(const Ref<Translation> &p_translation);
void remove_translation(const Ref<Translation> &p_translation);
@@ -99,6 +101,7 @@ public:
static Vector<String> get_all_locales();
static Vector<String> get_all_locale_names();
static bool is_locale_valid(const String &p_locale);
+ static String standardize_locale(const String &p_locale);
void set_tool_translation(const Ref<Translation> &p_translation);
StringName tool_translate(const StringName &p_message) const;
diff --git a/core/type_info.h b/core/type_info.h
index a7d3fa20c8..9fb80af0eb 100644
--- a/core/type_info.h
+++ b/core/type_info.h
@@ -39,28 +39,27 @@ struct TypeInherits {
template <class T, typename = void>
struct GetTypeInfo {
- enum { VARIANT_TYPE = Variant::NIL };
-
+ static const Variant::Type VARIANT_TYPE = Variant::NIL;
static inline PropertyInfo get_class_info() {
ERR_PRINT("GetTypeInfo fallback. Bug!");
return PropertyInfo(); // Not "Nil", this is an error
}
};
-#define MAKE_TYPE_INFO(m_type, m_var_type) \
- template <> \
- struct GetTypeInfo<m_type> { \
- enum { VARIANT_TYPE = m_var_type }; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \
- } \
- }; \
- template <> \
- struct GetTypeInfo<const m_type &> { \
- enum { VARIANT_TYPE = m_var_type }; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \
- } \
+#define MAKE_TYPE_INFO(m_type, m_var_type) \
+ template <> \
+ struct GetTypeInfo<m_type> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
+ }; \
+ template <> \
+ struct GetTypeInfo<const m_type &> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
};
MAKE_TYPE_INFO(bool, Variant::BOOL)
@@ -108,52 +107,50 @@ MAKE_TYPE_INFO(BSP_Tree, Variant::DICTIONARY)
//for RefPtr
template <>
struct GetTypeInfo<RefPtr> {
- enum { VARIANT_TYPE = Variant::OBJECT };
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::OBJECT,String(),PROPERTY_HINT_RESOURCE_TYPE,"Reference");
+ return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
}
};
template <>
struct GetTypeInfo<const RefPtr &> {
- enum { VARIANT_TYPE = Variant::OBJECT };
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::OBJECT,String(),PROPERTY_HINT_RESOURCE_TYPE,"Reference");
+ return PropertyInfo(Variant::OBJECT, String(), PROPERTY_HINT_RESOURCE_TYPE, "Reference");
}
};
-
//for variant
-template<>
+template <>
struct GetTypeInfo<Variant> {
- enum { VARIANT_TYPE = Variant::NIL };
+ static const Variant::Type VARIANT_TYPE = Variant::NIL;
static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::NIL,String(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_NIL_IS_VARIANT);
+ return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
};
-template<>
-struct GetTypeInfo<const Variant&> {
- enum { VARIANT_TYPE = Variant::NIL };
+template <>
+struct GetTypeInfo<const Variant &> {
+ static const Variant::Type VARIANT_TYPE = Variant::NIL;
static inline PropertyInfo get_class_info() {
- return PropertyInfo(Variant::NIL,String(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_NIL_IS_VARIANT);
+ return PropertyInfo(Variant::NIL, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT);
}
};
-
-#define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \
- template <> \
- struct GetTypeInfo<m_template<m_type> > { \
- enum { VARIANT_TYPE = m_var_type }; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \
- } \
- }; \
- template <> \
- struct GetTypeInfo<const m_template<m_type> &> { \
- enum { VARIANT_TYPE = m_var_type }; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo((Variant::Type)VARIANT_TYPE,String()); \
- } \
+#define MAKE_TEMPLATE_TYPE_INFO(m_template, m_type, m_var_type) \
+ template <> \
+ struct GetTypeInfo<m_template<m_type> > { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
+ }; \
+ template <> \
+ struct GetTypeInfo<const m_template<m_type> &> { \
+ static const Variant::Type VARIANT_TYPE = m_var_type; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(VARIANT_TYPE, String()); \
+ } \
};
MAKE_TEMPLATE_TYPE_INFO(Vector, uint8_t, Variant::POOL_BYTE_ARRAY)
@@ -173,30 +170,27 @@ MAKE_TEMPLATE_TYPE_INFO(PoolVector, Face3, Variant::POOL_VECTOR3_ARRAY)
template <typename T>
struct GetTypeInfo<T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
- enum { VARIANT_TYPE = Variant::OBJECT };
-
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static inline PropertyInfo get_class_info() {
return PropertyInfo(StringName(T::get_class_static()));
}
-
};
template <typename T>
struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>::type> {
- enum { VARIANT_TYPE = Variant::OBJECT };
-
+ static const Variant::Type VARIANT_TYPE = Variant::OBJECT;
static inline PropertyInfo get_class_info() {
return PropertyInfo(StringName(T::get_class_static()));
}
};
-#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
- template <> \
- struct GetTypeInfo<m_impl> { \
- enum { VARIANT_TYPE = Variant::INT }; \
- static inline PropertyInfo get_class_info() { \
- return PropertyInfo(Variant::INT,String(),PROPERTY_HINT_NONE,String(),PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_CLASS_IS_ENUM,String(#m_enum).replace("::",".")); \
- } \
+#define TEMPL_MAKE_ENUM_TYPE_INFO(m_enum, m_impl) \
+ template <> \
+ struct GetTypeInfo<m_impl> { \
+ static const Variant::Type VARIANT_TYPE = Variant::INT; \
+ static inline PropertyInfo get_class_info() { \
+ return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_CLASS_IS_ENUM, String(#m_enum).replace("::", ".")); \
+ } \
};
#define MAKE_ENUM_TYPE_INFO(m_enum) \
@@ -212,9 +206,15 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) {
return GetTypeInfo<T>::get_class_info().class_name;
}
+#define CLASS_INFO(m_type) \
+ (GetTypeInfo<m_type *>::VARIANT_TYPE != Variant::NIL ? \
+ GetTypeInfo<m_type *>::get_class_info() : \
+ GetTypeInfo<m_type>::get_class_info())
+
#else
#define MAKE_ENUM_TYPE_INFO(m_enum)
+#define CLASS_INFO(m_type)
#endif // DEBUG_METHODS_ENABLED
diff --git a/core/typedefs.h b/core/typedefs.h
index 565e28020b..c509edf9fe 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -98,11 +98,11 @@ T *_nullptr() {
#undef OK
#endif
+#include "int_types.h"
+
#include "error_list.h"
#include "error_macros.h"
-#include "int_types.h"
-
/** Generic ABS function, for math uses please use Math::abs */
#ifndef ABS
@@ -290,4 +290,12 @@ struct _GlobalLock {
#define __STRX(m_index) #m_index
#define __STR(m_index) __STRX(m_index)
+#ifdef __GNUC__
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
+
#endif /* typedefs.h */
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/ustring.cpp b/core/ustring.cpp
index ee07c7b11b..80881f1adb 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -588,7 +588,7 @@ String String::camelcase_to_underscore(bool lowercase) const {
const char a = 'a', z = 'z';
int start_index = 0;
- for (size_t i = 1; i < this->size(); i++) {
+ for (int i = 1; i < this->size(); i++) {
bool is_upper = cstr[i] >= A && cstr[i] <= Z;
bool is_number = cstr[i] >= '0' && cstr[i] <= '9';
bool are_next_2_lower = false;
@@ -1755,7 +1755,7 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
register int c;
int exp = 0; /* Exponent read from "EX" field. */
int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
+ * part. Under normal circumstances, it is
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
@@ -2332,12 +2332,12 @@ int String::findn(String p_str, int p_from) const {
int String::rfind(String p_str, int p_from) const {
- //stabilish a limit
+ // establish a limit
int limit = length() - p_str.length();
if (limit < 0)
return -1;
- //stabilish a starting point
+ // establish a starting point
if (p_from < 0)
p_from = limit;
else if (p_from > limit)
@@ -2347,7 +2347,7 @@ int String::rfind(String p_str, int p_from) const {
int len = length();
if (src_len == 0 || len == 0)
- return -1; //wont find anything!
+ return -1; // won't find anything!
const CharType *src = c_str();
@@ -2378,12 +2378,12 @@ int String::rfind(String p_str, int p_from) const {
}
int String::rfindn(String p_str, int p_from) const {
- //stabilish a limit
+ // establish a limit
int limit = length() - p_str.length();
if (limit < 0)
return -1;
- //stabilish a starting point
+ // establish a starting point
if (p_from < 0)
p_from = limit;
else if (p_from > limit)
@@ -2476,6 +2476,11 @@ bool String::begins_with(const char *p_string) const {
return *p_string == 0;
}
+bool String::is_enclosed_in(const String &p_string) const {
+
+ return begins_with(p_string) && ends_with(p_string);
+}
+
bool String::is_subsequence_of(const String &p_string) const {
return _base_is_subsequence_of(p_string, false);
@@ -2486,6 +2491,11 @@ bool String::is_subsequence_ofi(const String &p_string) const {
return _base_is_subsequence_of(p_string, true);
}
+bool String::is_quoted() const {
+
+ return is_enclosed_in("\"") || is_enclosed_in("'");
+}
+
bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const {
int len = length();
@@ -3655,12 +3665,12 @@ String String::sprintf(const Array &values, bool *error) const {
CharType *self = (CharType *)c_str();
bool in_format = false;
int value_index = 0;
- int min_chars;
- int min_decimals;
- bool in_decimals;
- bool pad_with_zeroes;
- bool left_justified;
- bool show_sign;
+ int min_chars = 0;
+ int min_decimals = 0;
+ bool in_decimals = false;
+ bool pad_with_zeroes = false;
+ bool left_justified = false;
+ bool show_sign = false;
*error = true;
@@ -3687,12 +3697,12 @@ String String::sprintf(const Array &values, bool *error) const {
}
int64_t value = values[value_index];
- int base;
+ int base = 16;
bool capitalize = false;
switch (c) {
case 'd': base = 10; break;
case 'o': base = 8; break;
- case 'x': base = 16; break;
+ case 'x': break;
case 'X':
base = 16;
capitalize = true;
@@ -3842,7 +3852,7 @@ String String::sprintf(const Array &values, bool *error) const {
}
break;
}
- case '.': { // Float separtor.
+ case '.': { // Float separator.
if (in_decimals) {
return "too many decimal points in format";
}
@@ -3851,7 +3861,7 @@ String String::sprintf(const Array &values, bool *error) const {
break;
}
- case '*': { // Dyanmic width, based on value.
+ case '*': { // Dynamic width, based on value.
if (value_index >= values.size()) {
return "not enough arguments for format string";
}
@@ -3906,6 +3916,18 @@ String String::sprintf(const Array &values, bool *error) const {
return formatted;
}
+String String::quote(String quotechar) const {
+ return quotechar + *this + quotechar;
+}
+
+String String::unquote() const {
+ if (!is_quoted()) {
+ return *this;
+ }
+
+ return substr(1, length() - 2);
+}
+
#include "translation.h"
#ifdef TOOLS_ENABLED
diff --git a/core/ustring.h b/core/ustring.h
index ab4e325f2c..aa4a5c910d 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -118,8 +118,10 @@ public:
bool begins_with(const String &p_string) const;
bool begins_with(const char *p_string) const;
bool ends_with(const String &p_string) const;
+ bool is_enclosed_in(const String &p_string) const;
bool is_subsequence_of(const String &p_string) const;
bool is_subsequence_ofi(const String &p_string) const;
+ bool is_quoted() const;
Vector<String> bigrams() const;
float similarity(const String &p_string) const;
String format(const Variant &values, String placeholder = "{_}") const;
@@ -132,6 +134,8 @@ public:
String lpad(int min_length, const String &character = " ") const;
String rpad(int min_length, const String &character = " ") const;
String sprintf(const Array &values, bool *error) const;
+ String quote(String quotechar = "\"") const;
+ String unquote() const;
static String num(double p_num, int p_decimals = -1);
static String num_scientific(double p_num);
static String num_real(double p_num);
diff --git a/core/variant.cpp b/core/variant.cpp
index 74f6b6a711..f70e4a5218 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 (unlikely(this == &p_variant))
+ return;
+
+ if (unlikely(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..45066af401 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,
@@ -99,15 +99,15 @@ public:
_RID,
OBJECT,
DICTIONARY,
- ARRAY, // 20
+ ARRAY,
// arrays
- POOL_BYTE_ARRAY,
+ POOL_BYTE_ARRAY, // 20
POOL_INT_ARRAY,
POOL_REAL_ARRAY,
POOL_STRING_ARRAY,
- POOL_VECTOR2_ARRAY, // 25
- POOL_VECTOR3_ARRAY,
+ POOL_VECTOR2_ARRAY,
+ POOL_VECTOR3_ARRAY, // 25
POOL_COLOR_ARRAY,
VARIANT_MAX
@@ -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,
@@ -367,6 +368,7 @@ public:
static Vector<Variant> get_method_default_arguments(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return = NULL);
static Vector<StringName> get_method_argument_names(Variant::Type p_type, const StringName &p_method);
+ static bool is_method_const(Variant::Type p_type, const StringName &p_method);
void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = NULL);
Variant get_named(const StringName &p_index, bool *r_valid = NULL) const;
@@ -389,7 +391,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 77372d1e60..cdf1ea46a3 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -53,9 +53,9 @@ struct _VariantCall {
Vector<StringName> arg_names;
Variant::Type return_type;
-#ifdef DEBUG_ENABLED
+ bool _const;
bool returns;
-#endif
+
VariantFunc func;
_FORCE_INLINE_ bool verify_arguments(const Variant **p_args, Variant::CallError &r_error) {
@@ -145,14 +145,15 @@ struct _VariantCall {
#endif
}
- static void addfunc(Variant::Type p_type, Variant::Type p_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) {
+ static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, bool p_has_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) {
FuncData funcdata;
funcdata.func = p_func;
funcdata.default_args = p_defaultarg;
+ funcdata._const = p_const;
#ifdef DEBUG_ENABLED
funcdata.return_type = p_return;
- funcdata.returns = p_return != Variant::NIL;
+ funcdata.returns = p_has_return;
#endif
if (p_argtype1.name) {
@@ -428,8 +429,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);
@@ -481,6 +482,7 @@ struct _VariantCall {
VCALL_LOCALMEM1(Array, erase);
VCALL_LOCALMEM0(Array, sort);
VCALL_LOCALMEM2(Array, sort_custom);
+ VCALL_LOCALMEM0R(Array, duplicate);
VCALL_LOCALMEM0(Array, invert);
static void _call_PoolByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) {
@@ -729,9 +731,6 @@ struct _VariantCall {
VCALL_PTR1R(Basis, scaled);
VCALL_PTR0R(Basis, get_scale);
VCALL_PTR0R(Basis, get_euler);
- VCALL_PTR1(Basis, set_scale);
- VCALL_PTR1(Basis, set_rotation_euler);
- VCALL_PTR2(Basis, set_rotation_axis_angle);
VCALL_PTR1R(Basis, tdotx);
VCALL_PTR1R(Basis, tdoty);
VCALL_PTR1R(Basis, tdotz);
@@ -1051,7 +1050,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i
return String();
// math types
-
case VECTOR2:
return Vector2(); // 5
case RECT2: return Rect2();
@@ -1203,6 +1201,17 @@ Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, c
return E->get().arg_types;
}
+bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) {
+
+ const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type];
+
+ const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method);
+ if (!E)
+ return false;
+
+ return E->get()._const;
+}
+
Vector<StringName> Variant::get_method_argument_names(Variant::Type p_type, const StringName &p_method) {
const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type];
@@ -1223,7 +1232,7 @@ Variant::Type Variant::get_method_return_type(Variant::Type p_type, const String
return Variant::NIL;
if (r_has_return)
- *r_has_return = E->get().return_type;
+ *r_has_return = E->get().returns;
return E->get().return_type;
}
@@ -1250,6 +1259,10 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
MethodInfo mi;
mi.name = E->key();
+ if (fd._const) {
+ mi.flags |= METHOD_FLAG_CONST;
+ }
+
for (int i = 0; i < fd.arg_types.size(); i++) {
PropertyInfo pi;
@@ -1361,381 +1374,407 @@ void register_variant_methods() {
_VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX);
_VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX);
+#define ADDFUNC0R(m_vtype, m_ret, m_class, m_method, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+#define ADDFUNC1R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+#define ADDFUNC2R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+#define ADDFUNC3R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+#define ADDFUNC4R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+
+#define ADDFUNC0RNC(m_vtype, m_ret, m_class, m_method, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+#define ADDFUNC1RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+#define ADDFUNC2RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+#define ADDFUNC3RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+#define ADDFUNC4RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+
#define ADDFUNC0(m_vtype, m_ret, m_class, m_method, m_defarg) \
- _VariantCall::addfunc(Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
#define ADDFUNC1(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
- _VariantCall::addfunc(Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
#define ADDFUNC2(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
- _VariantCall::addfunc(Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
#define ADDFUNC3(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
- _VariantCall::addfunc(Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
#define ADDFUNC4(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
- _VariantCall::addfunc(Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+ _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
+
+#define ADDFUNC0NC(m_vtype, m_ret, m_class, m_method, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+#define ADDFUNC1NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+#define ADDFUNC2NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)));
+#define ADDFUNC3NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)));
+#define ADDFUNC4NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4)));
/* STRING */
- ADDFUNC1(STRING, INT, String, casecmp_to, STRING, "to", varray());
- ADDFUNC1(STRING, INT, String, nocasecmp_to, STRING, "to", varray());
- ADDFUNC0(STRING, INT, String, length, varray());
- ADDFUNC2(STRING, STRING, String, substr, INT, "from", INT, "len", varray());
-
- ADDFUNC2(STRING, INT, String, find, STRING, "what", INT, "from", varray(0));
-
- ADDFUNC1(STRING, INT, String, find_last, STRING, "what", varray());
- ADDFUNC2(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
- ADDFUNC2(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
- ADDFUNC2(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1));
- ADDFUNC1(STRING, BOOL, String, match, STRING, "expr", varray());
- ADDFUNC1(STRING, BOOL, String, matchn, STRING, "expr", varray());
- ADDFUNC1(STRING, BOOL, String, begins_with, STRING, "text", varray());
- ADDFUNC1(STRING, BOOL, String, ends_with, STRING, "text", varray());
- ADDFUNC1(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray());
- ADDFUNC1(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray());
- ADDFUNC0(STRING, POOL_STRING_ARRAY, String, bigrams, varray());
- ADDFUNC1(STRING, REAL, String, similarity, STRING, "text", varray());
-
- ADDFUNC2(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}"));
- ADDFUNC2(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray());
- ADDFUNC2(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray());
- ADDFUNC2(STRING, STRING, String, insert, INT, "pos", STRING, "what", varray());
- ADDFUNC0(STRING, STRING, String, capitalize, varray());
- ADDFUNC2(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true));
- ADDFUNC2(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
-
- ADDFUNC0(STRING, STRING, String, to_upper, varray());
- ADDFUNC0(STRING, STRING, String, to_lower, varray());
-
- ADDFUNC1(STRING, STRING, String, left, INT, "pos", varray());
- ADDFUNC1(STRING, STRING, String, right, INT, "pos", varray());
- ADDFUNC2(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true));
- ADDFUNC0(STRING, STRING, String, get_extension, varray());
- ADDFUNC0(STRING, STRING, String, get_basename, varray());
- ADDFUNC1(STRING, STRING, String, plus_file, STRING, "file", varray());
- ADDFUNC1(STRING, INT, String, ord_at, INT, "at", varray());
- ADDFUNC2(STRING, NIL, String, erase, INT, "pos", INT, "chars", varray());
- ADDFUNC0(STRING, INT, String, hash, varray());
- ADDFUNC0(STRING, STRING, String, md5_text, varray());
- ADDFUNC0(STRING, STRING, String, sha256_text, varray());
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray());
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray());
- ADDFUNC0(STRING, BOOL, String, empty, varray());
- ADDFUNC0(STRING, BOOL, String, is_abs_path, varray());
- ADDFUNC0(STRING, BOOL, String, is_rel_path, varray());
- ADDFUNC0(STRING, STRING, String, get_base_dir, varray());
- ADDFUNC0(STRING, STRING, String, get_file, varray());
- ADDFUNC0(STRING, STRING, String, xml_escape, varray());
- ADDFUNC0(STRING, STRING, String, xml_unescape, varray());
- ADDFUNC0(STRING, STRING, String, c_escape, varray());
- ADDFUNC0(STRING, STRING, String, c_unescape, varray());
- ADDFUNC0(STRING, STRING, String, json_escape, varray());
- ADDFUNC0(STRING, STRING, String, percent_encode, varray());
- ADDFUNC0(STRING, STRING, String, percent_decode, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_identifier, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_integer, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_float, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_html_color, varray());
- ADDFUNC0(STRING, BOOL, String, is_valid_ip_address, varray());
- ADDFUNC0(STRING, INT, String, to_int, varray());
- ADDFUNC0(STRING, REAL, String, to_float, varray());
- ADDFUNC0(STRING, INT, String, hex_to_int, varray());
- ADDFUNC1(STRING, STRING, String, pad_decimals, INT, "digits", varray());
- ADDFUNC1(STRING, STRING, String, pad_zeros, INT, "digits", varray());
-
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray());
- ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray());
-
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, normalized, varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, length, varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, angle, varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, length_squared, varray());
- ADDFUNC0(VECTOR2, BOOL, Vector2, is_normalized, varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray());
- ADDFUNC2(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray());
- ADDFUNC4(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray());
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, tangent, varray());
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, floor, varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray());
- ADDFUNC0(VECTOR2, REAL, Vector2, aspect, varray());
- ADDFUNC1(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray());
- //ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
- ADDFUNC0(VECTOR2, VECTOR2, Vector2, abs, varray());
- ADDFUNC1(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
-
- ADDFUNC0(RECT2, REAL, Rect2, get_area, varray());
- ADDFUNC1(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray());
- ADDFUNC1(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray());
- ADDFUNC0(RECT2, BOOL, Rect2, has_no_area, varray());
- ADDFUNC1(RECT2, RECT2, Rect2, clip, RECT2, "b", varray());
- ADDFUNC1(RECT2, RECT2, Rect2, merge, RECT2, "b", varray());
- ADDFUNC1(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
- ADDFUNC1(RECT2, RECT2, Rect2, grow, REAL, "by", varray());
- ADDFUNC2(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray());
- ADDFUNC4(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
- ADDFUNC1(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
-
- ADDFUNC0(VECTOR3, INT, Vector3, min_axis, varray());
- ADDFUNC0(VECTOR3, INT, Vector3, max_axis, varray());
- ADDFUNC0(VECTOR3, REAL, Vector3, length, varray());
- ADDFUNC0(VECTOR3, REAL, Vector3, length_squared, varray());
- ADDFUNC0(VECTOR3, BOOL, Vector3, is_normalized, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, normalized, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, inverse, varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray());
- ADDFUNC2(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", REAL, "phi", varray());
- ADDFUNC2(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", REAL, "t", varray());
- ADDFUNC4(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray());
- ADDFUNC0(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, abs, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, floor, varray());
- ADDFUNC0(VECTOR3, VECTOR3, Vector3, ceil, varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray());
- ADDFUNC1(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray());
- ADDFUNC1(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
-
- ADDFUNC0(PLANE, PLANE, Plane, normalized, varray());
- ADDFUNC0(PLANE, VECTOR3, Plane, center, varray());
- ADDFUNC0(PLANE, VECTOR3, Plane, get_any_point, varray());
- ADDFUNC1(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray());
- ADDFUNC1(PLANE, REAL, Plane, distance_to, VECTOR3, "point", varray());
- ADDFUNC2(PLANE, BOOL, Plane, has_point, VECTOR3, "point", REAL, "epsilon", varray(CMP_EPSILON));
- ADDFUNC1(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray());
- ADDFUNC2(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray());
- ADDFUNC2(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray());
- ADDFUNC2(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray());
-
- ADDFUNC0(QUAT, REAL, Quat, length, varray());
- ADDFUNC0(QUAT, REAL, Quat, length_squared, varray());
- ADDFUNC0(QUAT, QUAT, Quat, normalized, varray());
- ADDFUNC0(QUAT, BOOL, Quat, is_normalized, varray());
- ADDFUNC0(QUAT, QUAT, Quat, inverse, varray());
- ADDFUNC1(QUAT, REAL, Quat, dot, QUAT, "b", varray());
- ADDFUNC1(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray());
- ADDFUNC2(QUAT, QUAT, Quat, slerp, QUAT, "b", REAL, "t", varray());
- 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, REAL, Color, gray, varray());
- ADDFUNC0(COLOR, COLOR, Color, inverted, varray());
- ADDFUNC0(COLOR, COLOR, Color, contrasted, varray());
- ADDFUNC2(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray());
- ADDFUNC1(COLOR, COLOR, Color, blend, COLOR, "over", varray());
- ADDFUNC1(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true));
-
- ADDFUNC0(_RID, INT, RID, get_id, varray());
-
- ADDFUNC0(NODE_PATH, BOOL, NodePath, is_absolute, varray());
- ADDFUNC0(NODE_PATH, INT, NodePath, get_name_count, varray());
- ADDFUNC1(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
- ADDFUNC0(NODE_PATH, INT, NodePath, get_subname_count, varray());
- ADDFUNC1(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
- ADDFUNC0(NODE_PATH, STRING, NodePath, get_property, varray());
- ADDFUNC0(NODE_PATH, BOOL, NodePath, is_empty, varray());
-
- ADDFUNC0(DICTIONARY, INT, Dictionary, size, varray());
- ADDFUNC0(DICTIONARY, BOOL, Dictionary, empty, varray());
- ADDFUNC0(DICTIONARY, NIL, Dictionary, clear, varray());
- ADDFUNC1(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray());
- ADDFUNC1(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray());
+ ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray());
+ ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray());
+ ADDFUNC0R(STRING, INT, String, length, varray());
+ ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray());
+
+ ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0));
+
+ ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray());
+ ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0));
+ ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1));
+ ADDFUNC2R(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1));
+ ADDFUNC1R(STRING, BOOL, String, match, STRING, "expr", varray());
+ ADDFUNC1R(STRING, BOOL, String, matchn, STRING, "expr", varray());
+ ADDFUNC1R(STRING, BOOL, String, begins_with, STRING, "text", varray());
+ ADDFUNC1R(STRING, BOOL, String, ends_with, STRING, "text", varray());
+ ADDFUNC1R(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray());
+ ADDFUNC1R(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray());
+ ADDFUNC0R(STRING, POOL_STRING_ARRAY, String, bigrams, varray());
+ ADDFUNC1R(STRING, REAL, String, similarity, STRING, "text", varray());
+
+ ADDFUNC2R(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}"));
+ ADDFUNC2R(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray());
+ ADDFUNC2R(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray());
+ ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray());
+ ADDFUNC0R(STRING, STRING, String, capitalize, varray());
+ ADDFUNC2R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true));
+ ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
+
+ ADDFUNC0R(STRING, STRING, String, to_upper, varray());
+ ADDFUNC0R(STRING, STRING, String, to_lower, varray());
+
+ ADDFUNC1R(STRING, STRING, String, left, INT, "position", varray());
+ ADDFUNC1R(STRING, STRING, String, right, INT, "position", varray());
+ ADDFUNC2R(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true));
+ ADDFUNC0R(STRING, STRING, String, get_extension, varray());
+ ADDFUNC0R(STRING, STRING, String, get_basename, varray());
+ ADDFUNC1R(STRING, STRING, String, plus_file, STRING, "file", varray());
+ ADDFUNC1R(STRING, INT, String, ord_at, INT, "at", varray());
+ ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray());
+ ADDFUNC0R(STRING, INT, String, hash, varray());
+ ADDFUNC0R(STRING, STRING, String, md5_text, varray());
+ ADDFUNC0R(STRING, STRING, String, sha256_text, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray());
+ ADDFUNC0R(STRING, BOOL, String, empty, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_rel_path, varray());
+ ADDFUNC0R(STRING, STRING, String, get_base_dir, varray());
+ ADDFUNC0R(STRING, STRING, String, get_file, varray());
+ ADDFUNC0R(STRING, STRING, String, xml_escape, varray());
+ ADDFUNC0R(STRING, STRING, String, xml_unescape, varray());
+ ADDFUNC0R(STRING, STRING, String, c_escape, varray());
+ ADDFUNC0R(STRING, STRING, String, c_unescape, varray());
+ ADDFUNC0R(STRING, STRING, String, json_escape, varray());
+ ADDFUNC0R(STRING, STRING, String, percent_encode, varray());
+ ADDFUNC0R(STRING, STRING, String, percent_decode, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_identifier, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_integer, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_float, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_html_color, varray());
+ ADDFUNC0R(STRING, BOOL, String, is_valid_ip_address, varray());
+ ADDFUNC0R(STRING, INT, String, to_int, varray());
+ ADDFUNC0R(STRING, REAL, String, to_float, varray());
+ ADDFUNC0R(STRING, INT, String, hex_to_int, varray());
+ ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray());
+ ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray());
+
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray());
+ ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray());
+
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, normalized, varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, length, varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, angle, varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, length_squared, varray());
+ ADDFUNC0R(VECTOR2, BOOL, Vector2, is_normalized, varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray());
+ ADDFUNC2R(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray());
+ ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray());
+ ADDFUNC0R(VECTOR2, REAL, Vector2, aspect, varray());
+ ADDFUNC1R(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray());
+ //ADDFUNC1R(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
+ ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray());
+ ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray());
+
+ ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray());
+ ADDFUNC1R(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray());
+ ADDFUNC1R(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray());
+ ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, clip, RECT2, "b", varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, merge, RECT2, "b", varray());
+ ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, grow, REAL, "by", varray());
+ ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray());
+ ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray());
+ ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray());
+
+ ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray());
+ ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray());
+ ADDFUNC0R(VECTOR3, REAL, Vector3, length, varray());
+ ADDFUNC0R(VECTOR3, REAL, Vector3, length_squared, varray());
+ ADDFUNC0R(VECTOR3, BOOL, Vector3, is_normalized, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, normalized, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, inverse, varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray());
+ ADDFUNC2R(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", REAL, "phi", varray());
+ ADDFUNC2R(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", REAL, "t", varray());
+ ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray());
+ ADDFUNC0R(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, abs, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, floor, varray());
+ ADDFUNC0R(VECTOR3, VECTOR3, Vector3, ceil, varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray());
+ ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray());
+ ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray());
+
+ ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray());
+ ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray());
+ ADDFUNC0R(PLANE, VECTOR3, Plane, get_any_point, varray());
+ ADDFUNC1R(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray());
+ ADDFUNC1R(PLANE, REAL, Plane, distance_to, VECTOR3, "point", varray());
+ ADDFUNC2R(PLANE, BOOL, Plane, has_point, VECTOR3, "point", REAL, "epsilon", varray(CMP_EPSILON));
+ ADDFUNC1R(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray());
+ ADDFUNC2R(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray());
+ ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray());
+ ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray());
+
+ ADDFUNC0R(QUAT, REAL, Quat, length, varray());
+ ADDFUNC0R(QUAT, REAL, Quat, length_squared, varray());
+ ADDFUNC0R(QUAT, QUAT, Quat, normalized, varray());
+ ADDFUNC0R(QUAT, BOOL, Quat, is_normalized, varray());
+ ADDFUNC0R(QUAT, QUAT, Quat, inverse, varray());
+ ADDFUNC1R(QUAT, REAL, Quat, dot, QUAT, "b", varray());
+ ADDFUNC1R(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray());
+ ADDFUNC2R(QUAT, QUAT, Quat, slerp, QUAT, "b", REAL, "t", varray());
+ ADDFUNC2R(QUAT, QUAT, Quat, slerpni, QUAT, "b", REAL, "t", varray());
+ ADDFUNC4R(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", REAL, "t", varray());
+
+ ADDFUNC0R(COLOR, INT, Color, to_rgba32, varray());
+ ADDFUNC0R(COLOR, INT, Color, to_argb32, varray());
+ ADDFUNC0R(COLOR, REAL, Color, gray, varray());
+ ADDFUNC0R(COLOR, COLOR, Color, inverted, varray());
+ ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray());
+ ADDFUNC2R(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray());
+ ADDFUNC1R(COLOR, COLOR, Color, blend, COLOR, "over", varray());
+ ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true));
+
+ ADDFUNC0R(_RID, INT, RID, get_id, varray());
+
+ ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_absolute, varray());
+ ADDFUNC0R(NODE_PATH, INT, NodePath, get_name_count, varray());
+ ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray());
+ ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray());
+ ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray());
+ ADDFUNC0R(NODE_PATH, STRING, NodePath, get_property, varray());
+ ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray());
+
+ ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray());
+ ADDFUNC0R(DICTIONARY, BOOL, Dictionary, empty, varray());
+ ADDFUNC0NC(DICTIONARY, NIL, Dictionary, clear, varray());
+ ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray());
+ ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray());
ADDFUNC1(DICTIONARY, NIL, Dictionary, erase, NIL, "key", varray());
- ADDFUNC0(DICTIONARY, INT, Dictionary, hash, varray());
- ADDFUNC0(DICTIONARY, ARRAY, Dictionary, keys, varray());
- ADDFUNC0(DICTIONARY, ARRAY, Dictionary, values, varray());
-
- ADDFUNC0(ARRAY, INT, Array, size, varray());
- ADDFUNC0(ARRAY, BOOL, Array, empty, varray());
- ADDFUNC0(ARRAY, NIL, Array, clear, varray());
- ADDFUNC0(ARRAY, INT, Array, hash, varray());
- ADDFUNC1(ARRAY, NIL, Array, push_back, NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, push_front, NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, append, NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, resize, INT, "pos", varray());
- ADDFUNC2(ARRAY, NIL, Array, insert, INT, "pos", NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, remove, INT, "pos", varray());
- ADDFUNC1(ARRAY, NIL, Array, erase, NIL, "value", varray());
- ADDFUNC0(ARRAY, NIL, Array, front, varray());
- ADDFUNC0(ARRAY, NIL, Array, back, varray());
- ADDFUNC2(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0));
- ADDFUNC2(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1));
- ADDFUNC1(ARRAY, INT, Array, find_last, NIL, "value", varray());
- ADDFUNC1(ARRAY, INT, Array, count, NIL, "value", varray());
- ADDFUNC1(ARRAY, BOOL, Array, has, NIL, "value", varray());
- ADDFUNC0(ARRAY, NIL, Array, pop_back, varray());
- ADDFUNC0(ARRAY, NIL, Array, pop_front, varray());
- ADDFUNC0(ARRAY, NIL, Array, sort, varray());
- ADDFUNC2(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
- ADDFUNC0(ARRAY, NIL, Array, invert, varray());
-
- ADDFUNC0(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
+ ADDFUNC0R(DICTIONARY, INT, Dictionary, hash, varray());
+ ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray());
+ ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray());
+
+ ADDFUNC0R(ARRAY, INT, Array, size, varray());
+ ADDFUNC0R(ARRAY, BOOL, Array, empty, varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, clear, varray());
+ ADDFUNC0R(ARRAY, INT, Array, hash, varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, push_back, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, push_front, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, append, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, resize, INT, "size", varray());
+ ADDFUNC2NC(ARRAY, NIL, Array, insert, INT, "position", NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, remove, INT, "position", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, erase, NIL, "value", varray());
+ ADDFUNC0R(ARRAY, NIL, Array, front, varray());
+ ADDFUNC0R(ARRAY, NIL, Array, back, varray());
+ ADDFUNC2R(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0));
+ ADDFUNC2R(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1));
+ ADDFUNC1R(ARRAY, INT, Array, find_last, NIL, "value", varray());
+ ADDFUNC1R(ARRAY, INT, Array, count, NIL, "value", varray());
+ ADDFUNC1R(ARRAY, BOOL, Array, has, NIL, "value", varray());
+ ADDFUNC0RNC(ARRAY, NIL, Array, pop_back, varray());
+ ADDFUNC0RNC(ARRAY, NIL, Array, pop_front, varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, sort, varray());
+ ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, invert, varray());
+ ADDFUNC0RNC(ARRAY, ARRAY, Array, duplicate, varray());
+
+ ADDFUNC0R(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, push_back, INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append, INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append_array, POOL_BYTE_ARRAY, "array", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray());
+ ADDFUNC2R(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray());
ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_BYTE_ARRAY, NIL, PoolByteArray, invert, varray());
- ADDFUNC2(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray());
+ ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray());
- ADDFUNC0(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
- ADDFUNC0(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
- ADDFUNC1(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
- ADDFUNC2(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
+ ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
+ ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
- ADDFUNC0(POOL_INT_ARRAY, INT, PoolIntArray, size, varray());
+ ADDFUNC0R(POOL_INT_ARRAY, INT, PoolIntArray, size, varray());
ADDFUNC2(POOL_INT_ARRAY, NIL, PoolIntArray, set, INT, "idx", INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, push_back, INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append, INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append_array, POOL_INT_ARRAY, "array", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray());
+ ADDFUNC2R(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray());
ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_INT_ARRAY, NIL, PoolIntArray, invert, varray());
- ADDFUNC0(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray());
+ ADDFUNC0R(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray());
ADDFUNC2(POOL_REAL_ARRAY, NIL, PoolRealArray, set, INT, "idx", REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, push_back, REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append, REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append_array, POOL_REAL_ARRAY, "array", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray());
+ ADDFUNC2R(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray());
ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_REAL_ARRAY, NIL, PoolRealArray, invert, varray());
- ADDFUNC0(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray());
+ ADDFUNC0R(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray());
ADDFUNC2(POOL_STRING_ARRAY, NIL, PoolStringArray, set, INT, "idx", STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, push_back, STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append, STRING, "string", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append_array, POOL_STRING_ARRAY, "array", varray());
ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray());
+ ADDFUNC2R(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());
+ ADDFUNC0R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray());
ADDFUNC2(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, set, INT, "idx", VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, push_back, VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append, VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append_array, POOL_VECTOR2_ARRAY, "array", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, remove, INT, "idx", varray());
- ADDFUNC2(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray());
+ ADDFUNC2R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray());
ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, resize, INT, "idx", varray());
ADDFUNC0(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, invert, varray());
- ADDFUNC0(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray());
+ ADDFUNC0R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray());
ADDFUNC2(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, set, INT, "idx", VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, push_back, VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append, VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append_array, POOL_VECTOR3_ARRAY, "array", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, remove, INT, "idx", varray());
- ADDFUNC2(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray());
+ ADDFUNC2R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray());
ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, resize, INT, "idx", varray());
ADDFUNC0(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, invert, varray());
- ADDFUNC0(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray());
+ ADDFUNC0R(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray());
ADDFUNC2(POOL_COLOR_ARRAY, NIL, PoolColorArray, set, INT, "idx", COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, push_back, COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append, COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append_array, POOL_COLOR_ARRAY, "array", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, remove, INT, "idx", varray());
- ADDFUNC2(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray());
+ ADDFUNC2R(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray());
ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, resize, INT, "idx", varray());
ADDFUNC0(POOL_COLOR_ARRAY, NIL, PoolColorArray, invert, varray());
//pointerbased
- ADDFUNC0(RECT3, REAL, Rect3, get_area, varray());
- ADDFUNC0(RECT3, BOOL, Rect3, has_no_area, varray());
- ADDFUNC0(RECT3, BOOL, Rect3, has_no_surface, varray());
- ADDFUNC1(RECT3, BOOL, Rect3, intersects, RECT3, "with", varray());
- ADDFUNC1(RECT3, BOOL, Rect3, encloses, RECT3, "with", varray());
- ADDFUNC1(RECT3, RECT3, Rect3, merge, RECT3, "with", varray());
- ADDFUNC1(RECT3, RECT3, Rect3, intersection, RECT3, "with", varray());
- ADDFUNC1(RECT3, BOOL, Rect3, intersects_plane, PLANE, "plane", varray());
- ADDFUNC2(RECT3, BOOL, Rect3, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray());
- ADDFUNC1(RECT3, BOOL, Rect3, has_point, VECTOR3, "point", varray());
- ADDFUNC1(RECT3, VECTOR3, Rect3, get_support, VECTOR3, "dir", varray());
- ADDFUNC0(RECT3, VECTOR3, Rect3, get_longest_axis, varray());
- ADDFUNC0(RECT3, INT, Rect3, get_longest_axis_index, varray());
- ADDFUNC0(RECT3, REAL, Rect3, get_longest_axis_size, varray());
- ADDFUNC0(RECT3, VECTOR3, Rect3, get_shortest_axis, varray());
- ADDFUNC0(RECT3, INT, Rect3, get_shortest_axis_index, varray());
- ADDFUNC0(RECT3, REAL, Rect3, get_shortest_axis_size, varray());
- ADDFUNC1(RECT3, RECT3, Rect3, expand, VECTOR3, "to_point", varray());
- ADDFUNC1(RECT3, RECT3, Rect3, grow, REAL, "by", varray());
- ADDFUNC1(RECT3, VECTOR3, Rect3, get_endpoint, INT, "idx", varray());
-
- ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray());
- ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray());
- ADDFUNC0(TRANSFORM2D, REAL, Transform2D, get_rotation, varray());
- ADDFUNC0(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray());
- ADDFUNC0(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray());
- ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray());
- ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray());
- ADDFUNC2(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray());
-
- ADDFUNC0(BASIS, BASIS, Basis, inverse, varray());
- ADDFUNC0(BASIS, BASIS, Basis, transposed, varray());
- ADDFUNC0(BASIS, BASIS, Basis, orthonormalized, varray());
- ADDFUNC0(BASIS, REAL, Basis, determinant, varray());
- ADDFUNC2(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray());
- ADDFUNC1(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray());
- ADDFUNC1(BASIS, NIL, Basis, set_scale, VECTOR3, "scale", varray());
- ADDFUNC1(BASIS, NIL, Basis, set_rotation_euler, VECTOR3, "euler", varray());
- ADDFUNC2(BASIS, NIL, Basis, set_rotation_axis_angle, VECTOR3, "axis", REAL, "angle", varray());
- ADDFUNC0(BASIS, VECTOR3, Basis, get_scale, varray());
- ADDFUNC0(BASIS, VECTOR3, Basis, get_euler, varray());
- ADDFUNC1(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray());
- ADDFUNC1(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray());
- ADDFUNC1(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray());
- ADDFUNC1(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray());
- ADDFUNC1(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray());
- ADDFUNC0(BASIS, INT, Basis, get_orthogonal_index, varray());
-
- ADDFUNC0(TRANSFORM, TRANSFORM, Transform, inverse, varray());
- ADDFUNC0(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray());
- ADDFUNC0(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray());
- ADDFUNC2(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", REAL, "phi", varray());
- ADDFUNC1(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray());
- ADDFUNC1(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "ofs", varray());
- ADDFUNC2(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray());
- ADDFUNC2(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", REAL, "weight", varray());
- ADDFUNC1(TRANSFORM, NIL, Transform, xform, NIL, "v", varray());
- ADDFUNC1(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray());
-
-#ifdef DEBUG_ENABLED
- _VariantCall::type_funcs[Variant::TRANSFORM].functions["xform"].returns = true;
- _VariantCall::type_funcs[Variant::TRANSFORM].functions["xform_inv"].returns = true;
-#endif
+ ADDFUNC0R(RECT3, REAL, Rect3, get_area, varray());
+ ADDFUNC0R(RECT3, BOOL, Rect3, has_no_area, varray());
+ ADDFUNC0R(RECT3, BOOL, Rect3, has_no_surface, varray());
+ ADDFUNC1R(RECT3, BOOL, Rect3, intersects, RECT3, "with", varray());
+ ADDFUNC1R(RECT3, BOOL, Rect3, encloses, RECT3, "with", varray());
+ ADDFUNC1R(RECT3, RECT3, Rect3, merge, RECT3, "with", varray());
+ ADDFUNC1R(RECT3, RECT3, Rect3, intersection, RECT3, "with", varray());
+ ADDFUNC1R(RECT3, BOOL, Rect3, intersects_plane, PLANE, "plane", varray());
+ ADDFUNC2R(RECT3, BOOL, Rect3, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray());
+ ADDFUNC1R(RECT3, BOOL, Rect3, has_point, VECTOR3, "point", varray());
+ ADDFUNC1R(RECT3, VECTOR3, Rect3, get_support, VECTOR3, "dir", varray());
+ ADDFUNC0R(RECT3, VECTOR3, Rect3, get_longest_axis, varray());
+ ADDFUNC0R(RECT3, INT, Rect3, get_longest_axis_index, varray());
+ ADDFUNC0R(RECT3, REAL, Rect3, get_longest_axis_size, varray());
+ ADDFUNC0R(RECT3, VECTOR3, Rect3, get_shortest_axis, varray());
+ ADDFUNC0R(RECT3, INT, Rect3, get_shortest_axis_index, varray());
+ ADDFUNC0R(RECT3, REAL, Rect3, get_shortest_axis_size, varray());
+ ADDFUNC1R(RECT3, RECT3, Rect3, expand, VECTOR3, "to_point", varray());
+ ADDFUNC1R(RECT3, RECT3, Rect3, grow, REAL, "by", varray());
+ ADDFUNC1R(RECT3, VECTOR3, Rect3, get_endpoint, INT, "idx", varray());
+
+ ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray());
+ ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray());
+ ADDFUNC0R(TRANSFORM2D, REAL, Transform2D, get_rotation, varray());
+ ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray());
+ ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray());
+ ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray());
+ ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray());
+
+ ADDFUNC0R(BASIS, BASIS, Basis, inverse, varray());
+ ADDFUNC0R(BASIS, BASIS, Basis, transposed, varray());
+ ADDFUNC0R(BASIS, BASIS, Basis, orthonormalized, varray());
+ ADDFUNC0R(BASIS, REAL, Basis, determinant, varray());
+ ADDFUNC2R(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray());
+ ADDFUNC1R(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray());
+ ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale, varray());
+ ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler, varray());
+ ADDFUNC1R(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray());
+ ADDFUNC1R(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray());
+ ADDFUNC1R(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray());
+ ADDFUNC1R(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray());
+ ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray());
+ ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray());
+
+ ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray());
+ ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray());
+ ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray());
+ ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", REAL, "phi", varray());
+ ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray());
+ ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "ofs", varray());
+ ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray());
+ ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", REAL, "weight", varray());
+ ADDFUNC1R(TRANSFORM, NIL, Transform, xform, NIL, "v", varray());
+ ADDFUNC1R(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray());
/* REGISTER CONSTRUCTORS */
_VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::REAL, "y", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "pos", Variant::VECTOR2, "size", Variant::VECTOR2);
+ _VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::REAL, "y", Variant::REAL, "width", Variant::REAL, "height", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rot", Variant::REAL, "pos", Variant::VECTOR2);
+ _VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::REAL, "position", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::REAL, "y", Variant::REAL, "z", Variant::REAL);
@@ -1750,7 +1789,7 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::REAL, "g", Variant::REAL, "b", Variant::REAL, "a", Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::REAL, "g", Variant::REAL, "b", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Rect3_init1, Variant::RECT3, "pos", Variant::VECTOR3, "size", Variant::VECTOR3);
+ _VariantCall::add_constructor(_VariantCall::Rect3_init1, Variant::RECT3, "position", Variant::VECTOR3, "size", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::REAL);
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index b6e114b853..6362090902 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 const 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,146 +158,228 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
}
-#define DEFAULT_OP_NUM(m_op, m_name, m_type) \
- case 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: {} \
- } \
- r_valid = false; \
- return; \
+#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) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_NUM_NEG(m_name, m_type) \
- case m_name: { \
- \
- _RETURN(-p_a._data.m_type); \
+#define DEFAULT_OP_NUM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_NUM_POS(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) { \
+ if (p_b.type == INT) { \
+ if (p_b._data._int == 0) { \
+ r_valid = false; \
+ _RETURN("Division By Zero"); \
+ } \
+ _RETURN(p_a._data.m_type / p_b._data._int); \
+ } \
+ if (p_b.type == REAL) { \
+ if (p_b._data._real == 0) { \
+ r_valid = false; \
+ _RETURN("Division By Zero"); \
+ } \
+ _RETURN(p_a._data.m_type / p_b._data._real); \
+ } \
+ \
+ _RETURN_FAIL \
+ };
+#else
+#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type / p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type / p_b._data._real); \
+ \
+ _RETURN_FAIL \
};
+#endif
-#define DEFAULT_OP_NUM_VEC(m_op, m_name, m_type) \
- case 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)); \
- case VECTOR3: _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#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_STR(m_op, m_name, m_type) \
- case 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)); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#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_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_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
+ if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#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) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
+ if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
+ };
-#define DEFAULT_OP_LOCALMEM_NEG(m_name, m_type) \
- case m_name: { \
+#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)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#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)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_LOCALMEM_NULL(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)); \
+ if (p_b.type == NIL) \
+ _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
+ };
+
+#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: { \
- 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: {} \
- } \
- r_valid = false; \
- return; \
+#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) { \
+ 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)); \
+ if (p_b.type == INT) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._real); \
+ \
+ _RETURN_FAIL \
}
-#define DEFAULT_OP_PTR(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_PTR(m_op, m_name, 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); \
+ \
+ _RETURN_FAIL \
}
-#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); \
+ \
+ _RETURN_FAIL \
}
-#define DEFAULT_OP_ARRAY_EQ(m_name, m_type) \
- DEFAULT_OP_ARRAY_OP(m_name, m_type, !=, !=, true, false, false)
+#define DEFAULT_OP_PTRREF_NULL(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); \
+ if (p_b.type == NIL) \
+ _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
+ }
-#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_EQ(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == NIL) \
+ _RETURN(false) \
+ DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, !=, !=, true, false, false) \
+ }
-#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_NEQ(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == NIL) \
+ _RETURN(true) \
+ DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, !=, ==, true, true, 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) { \
+ DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
+ }
+
+#define DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
+ if (p_a.type != p_b.type) \
+ _RETURN_FAIL \
+ \
+ 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: { \
- if (p_a.type != p_b.type) { \
- r_valid = false; \
- _RETURN(NIL); \
- } \
+#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) \
+ _RETURN_FAIL; \
+ \
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); \
PoolVector<m_type> sum = array_a; \
@@ -231,595 +387,670 @@ 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);
- case OP_EQUAL: {
+ _RETURN(false);
+ }
- 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) {
- _RETURN(p_a._get_obj().obj == NULL);
- } else if (p_b.type == Variant::OBJECT) {
- _RETURN(p_b._get_obj().obj == NULL);
+ CASE_TYPE(math, OP_EQUAL, BOOL) {
+ if (p_b.type != BOOL) {
+ if (p_b.type == NIL)
+ _RETURN(false);
+ _RETURN_FAIL;
}
- //otherwise, always false
- _RETURN(false);
+
+ _RETURN(p_a._data._bool == p_b._data._bool);
}
- switch (p_a.type) {
+ 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);
- case NIL: {
+ _RETURN_FAIL;
+ }
- _RETURN(p_b.type == NIL || (p_b.type == Variant::OBJECT && !p_b._get_obj().obj));
- } break;
+ CASE_TYPE(math, OP_EQUAL, DICTIONARY) {
+ if (p_b.type != DICTIONARY) {
+ if (p_b.type == NIL)
+ _RETURN(false);
+ _RETURN_FAIL;
+ }
- 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);
+ const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
+ const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
- DEFAULT_OP_LOCALMEM(==, COLOR, Color);
- DEFAULT_OP_STR(==, NODE_PATH, NodePath);
- DEFAULT_OP_LOCALMEM(==, _RID, RID);
- case OBJECT: {
+ _RETURN(*arr_a == *arr_b);
+ }
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj == p_b._get_obj().obj));
+ CASE_TYPE(math, OP_EQUAL, ARRAY) {
+ if (p_b.type != ARRAY) {
if (p_b.type == NIL)
- _RETURN(!p_a._get_obj().obj);
- } break;
-
- case DICTIONARY: {
+ _RETURN(false);
+ _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);
- if (p_b.type != DICTIONARY)
+ 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);
+ }
+ }
- 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(true);
+ }
+
+ DEFAULT_OP_NUM_NULL(math, OP_EQUAL, INT, ==, _int);
+ DEFAULT_OP_NUM_NULL(math, OP_EQUAL, REAL, ==, _real);
+ DEFAULT_OP_STR_NULL(math, OP_EQUAL, STRING, ==, String);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2, ==, Vector2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2, ==, Rect2);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3, ==, Vector3);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, PLANE, ==, Plane);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, QUAT, ==, Quat);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, RECT3, ==, _rect3);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, BASIS, ==, _basis);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM, ==, _transform);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, COLOR, ==, Color);
+ DEFAULT_OP_STR_NULL(math, OP_EQUAL, NODE_PATH, ==, NodePath);
+ DEFAULT_OP_LOCALMEM_NULL(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);
+ }
- _RETURN(*arr_a == *arr_b);
+ 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);
- } break;
- case ARRAY: {
+ _RETURN(true);
+ }
- if (p_b.type != ARRAY)
- _RETURN(false);
+ CASE_TYPE(math, OP_NOT_EQUAL, BOOL) {
+ if (p_b.type != BOOL) {
+ if (p_b.type == NIL)
+ _RETURN(true);
- 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_FAIL;
+ }
- 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._bool != p_b._data._bool);
+ }
- _RETURN(true);
+ 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);
- } break;
+ _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);
+ CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) {
+ if (p_b.type != DICTIONARY) {
+ if (p_b.type == NIL)
+ _RETURN(true);
+ _RETURN_FAIL;
+ }
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ 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;
+ _RETURN((*arr_a == *arr_b) == false);
}
- } 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);
+ CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) {
+ if (p_b.type != ARRAY) {
+ if (p_b.type == NIL)
+ _RETURN(true);
+
+ _RETURN_FAIL;
+ }
- int l = arr_a->size();
- if (arr_b->size() < l)
+ 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(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(true);
- }
}
+ }
- _RETURN(false);
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, INT, !=, _int);
+ DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, REAL, !=, _real);
+ DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, STRING, !=, String);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2, !=, Rect2);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, PLANE, !=, Plane);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, QUAT, !=, Quat);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, RECT3, !=, _rect3);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, BASIS, !=, _basis);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, COLOR, !=, Color);
+ DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, _RID, !=, RID);
+
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_VECTOR2_ARRAY, Vector2);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_COLOR_ARRAY, Color);
+ }
- } 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;
+ SWITCH_OP(math, OP_LESS, p_a.type) {
+ CASE_TYPE(math, OP_LESS, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
- } 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;
+ if (p_a._data._bool == p_b._data._bool)
+ _RETURN(false);
+
+ if (p_a._data._bool && !p_b._data._bool)
+ _RETURN(false);
- } break;
+ _RETURN(true);
}
- } break;
- case OP_GREATER: {
+ CASE_TYPE(math, OP_LESS, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
+ }
- Variant res;
- evaluate(OP_LESS, p_b, p_a, res, r_valid);
- if (!r_valid)
- return;
- _RETURN(res);
+ CASE_TYPE(math, OP_LESS, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- } break;
- case OP_GREATER_EQUAL: {
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- 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;
+ 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);
}
- 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;
-
- } 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;
+ }
- } break;
+ _RETURN(false);
}
- } 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: {
+ 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;
+ }
- 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: {
+ 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;
+ }
- switch (p_b.type) {
- case VECTOR3: {
+ SWITCH_OP(math, OP_GREATER, p_a.type) {
+ CASE_TYPE(math, OP_GREATER, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
- _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem));
- };
- case BASIS: {
+ if (p_a._data._bool == p_b._data._bool)
+ _RETURN(false);
- _RETURN(*p_a._data._basis * *p_b._data._basis);
- };
- default: {}
- };
- r_valid = false;
- return;
- } break;
- case TRANSFORM: {
+ if (!p_a._data._bool && p_b._data._bool)
+ _RETURN(false);
- switch (p_b.type) {
- case VECTOR3: {
+ _RETURN(true);
+ }
- _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
- };
- case TRANSFORM: {
+ CASE_TYPE(math, OP_GREATER, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj > p_b._get_obj().obj));
+ }
- _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;
+ CASE_TYPE(math, OP_GREATER, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- } break;
- }
- } break;
- case OP_DIVIDE: {
- switch (p_a.type) {
+ 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_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) {
+ 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(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;
+ }
- r_valid = false;
- _RETURN("Division By False");
- }
- _RETURN(p_a._data._int / b);
+ 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;
+ }
- } break;
- case INT: {
- int64_t b = p_b._data._int;
- if (b == 0) {
+ 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;
+ }
- r_valid = false;
- _RETURN("Division By Zero");
- }
- _RETURN(p_a._data._int / b);
+ 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;
- case REAL: _RETURN(p_a._data._int / p_b._data._real);
- default: {}
+ 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);
}
- 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 VECTOR2: {
+ _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem));
}
- _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;
+ 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;
+ }
+ }
- } 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: {
- r_valid = false;
- return;
+ 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_TYPE(math, OP_MULTIPLY, TRANSFORM) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
+ }
+ case TRANSFORM: {
+ _RETURN(*p_a._data._transform * *p_b._data._transform);
+ }
+ default: _RETURN_FAIL;
+ }
}
- } break;
- case OP_MODULE: {
- if (p_a.type == INT && p_b.type == INT) {
+
+ 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;
+ }
+
+ 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("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;
+ }
+
+ 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 +1058,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,171 +1079,627 @@ 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;
+ }
+
+ 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);
+ }
+ }
+
+ SWITCH_OP(math, OP_OR, p_a.type) {
+ CASE_TYPE_ALL(math, OP_OR) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
+
+ _RETURN(l || r);
+ }
+ }
+
+ SWITCH_OP(math, OP_XOR, p_a.type) {
+ CASE_TYPE_ALL(math, OP_XOR) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
+
+ _RETURN((l || r) && !(l && r));
+ }
+ }
+
+ 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));
+ }
+ }
+}
+
+void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) {
+
+ bool valid = false;
+ switch (type) {
+ case VECTOR2: {
+ if (p_value.type == Variant::INT) {
+ Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ }
+ }
} 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;
+ case RECT2: {
- _RETURN(l && r);
+ if (p_value.type == Variant::VECTOR2) {
+ Rect2 *v = reinterpret_cast<Rect2 *>(_data._mem);
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ v->position = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ v->size = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ v->size = *reinterpret_cast<const Vector2 *>(p_value._data._mem) - v->position;
+ valid = true;
+ }
+ }
} 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;
+ case TRANSFORM2D: {
- _RETURN(l || r);
+ if (p_value.type == Variant::VECTOR2) {
+ Transform2D *v = _data._transform2d;
+ if (p_index == CoreStringNames::singleton->x) {
+ v->elements[0] = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->elements[1] = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->origin) {
+ v->elements[2] = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ }
+ }
} 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;
+ case VECTOR3: {
+
+ if (p_value.type == Variant::INT) {
+ Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._real;
+ valid = true;
+ }
+ }
- _RETURN((l || r) && !(l && r));
} break;
- case OP_NOT: {
+ case PLANE: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- _RETURN(!l);
+ if (p_value.type == Variant::INT) {
+ Plane *v = reinterpret_cast<Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->normal.x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->normal.y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->normal.z = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->d) {
+ v->d = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Plane *v = reinterpret_cast<Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->normal.x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->normal.y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->normal.z = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->d) {
+ v->d = p_value._data._real;
+ valid = true;
+ }
+
+ } else if (p_value.type == Variant::VECTOR3) {
+ Plane *v = reinterpret_cast<Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->normal) {
+ v->normal = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ }
+ }
} break;
- case OP_IN: {
+ case QUAT: {
- _RETURN(p_b.in(p_a, &r_valid));
+ if (p_value.type == Variant::INT) {
+ Quat *v = reinterpret_cast<Quat *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->w) {
+ v->w = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Quat *v = reinterpret_cast<Quat *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->w) {
+ v->w = p_value._data._real;
+ valid = true;
+ }
+ }
+
+ } break; // 10
+ case RECT3: {
+ if (p_value.type == Variant::VECTOR3) {
+ Rect3 *v = _data._rect3;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ v->position = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ v->size = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ v->size = *reinterpret_cast<const Vector3 *>(p_value._data._mem) - v->position;
+ valid = true;
+ }
+ }
} break;
- case OP_MAX: {
+ case BASIS: {
- r_valid = false;
- ERR_FAIL();
- }
- }
+ if (p_value.type == Variant::VECTOR3) {
+ Basis *v = _data._basis;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->x) {
+ v->set_axis(0, *reinterpret_cast<const Vector3 *>(p_value._data._mem));
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->set_axis(1, *reinterpret_cast<const Vector3 *>(p_value._data._mem));
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->set_axis(2, *reinterpret_cast<const Vector3 *>(p_value._data._mem));
+ valid = true;
+ }
+ }
+ } break;
+ case TRANSFORM: {
- r_valid = false;
-}
+ if (p_value.type == Variant::BASIS && p_index == CoreStringNames::singleton->basis) {
+ _data._transform->basis = *p_value._data._basis;
+ valid = true;
+ } else if (p_value.type == Variant::VECTOR3 && p_index == CoreStringNames::singleton->origin) {
+ _data._transform->origin = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ }
-void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) {
+ } break;
+ case COLOR: {
- if (type == OBJECT) {
+ if (p_value.type == Variant::INT) {
+ Color *v = reinterpret_cast<Color *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->r) {
+ v->r = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g) {
+ v->g = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b) {
+ v->b = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a) {
+ v->a = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->r8) {
+ v->r = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g8) {
+ v->g = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b8) {
+ v->b = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a8) {
+ v->a = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->h) {
+ v->set_hsv(p_value._data._int, v->get_s(), v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->s) {
+ v->set_hsv(v->get_h(), p_value._data._int, v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->v) {
+ v->set_hsv(v->get_h(), v->get_v(), p_value._data._int);
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Color *v = reinterpret_cast<Color *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->r) {
+ v->r = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g) {
+ v->g = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b) {
+ v->b = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a) {
+ v->a = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->r8) {
+ v->r = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g8) {
+ v->g = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b8) {
+ v->b = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a8) {
+ v->a = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->h) {
+ v->set_hsv(p_value._data._real, v->get_s(), v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->s) {
+ v->set_hsv(v->get_h(), p_value._data._real, v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->v) {
+ v->set_hsv(v->get_h(), v->get_v(), p_value._data._real);
+ valid = true;
+ }
+ }
+ } break;
+ case OBJECT: {
#ifdef DEBUG_ENABLED
- if (!_get_obj().obj) {
- if (r_valid)
- *r_valid = false;
- return;
- } else {
-
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
- if (r_valid)
- *r_valid = false;
- return;
+ if (!_get_obj().obj) {
+ break;
+ } else if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ break;
}
- }
#endif
- _get_obj().obj->set(p_index, p_value, r_valid);
- return;
+ _get_obj().obj->set(p_index, p_value, &valid);
+
+ } break;
+ default: {
+ set(p_index.operator String(), p_value, &valid);
+ } break;
}
- set(p_index.operator String(), p_value, r_valid);
+ if (r_valid) {
+ *r_valid = valid;
+ }
}
Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
- if (type == OBJECT) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ switch (type) {
+ case VECTOR2: {
+ const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ }
-#ifdef DEBUG_ENABLED
- if (!_get_obj().obj) {
- if (r_valid)
- *r_valid = false;
- return "Instance base is null.";
- } else {
+ } break;
+ case RECT2: {
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ const Rect2 *v = reinterpret_cast<const Rect2 *>(_data._mem);
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ return v->position;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ return v->size;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ return v->size + v->position;
+ }
+ } break;
+ case TRANSFORM2D: {
+
+ const Transform2D *v = _data._transform2d;
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->elements[0];
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->elements[1];
+ } else if (p_index == CoreStringNames::singleton->origin) {
+ return v->elements[2];
+ }
+
+ } break;
+ case VECTOR3: {
+
+ const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->z;
+ }
+
+ } break;
+ case PLANE: {
+
+ const Plane *v = reinterpret_cast<const Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->normal.x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->normal.y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->normal.z;
+ } else if (p_index == CoreStringNames::singleton->d) {
+ return v->d;
+ } else if (p_index == CoreStringNames::singleton->normal) {
+ return v->normal;
+ }
+
+ } break;
+ case QUAT: {
+
+ const Quat *v = reinterpret_cast<const Quat *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->z;
+ } else if (p_index == CoreStringNames::singleton->w) {
+ return v->w;
+ }
+
+ } break; // 10
+ case RECT3: {
+
+ const Rect3 *v = _data._rect3;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ return v->position;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ return v->size;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ return v->size + v->position;
+ }
+ } break;
+ case BASIS: {
+
+ const Basis *v = _data._basis;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->get_axis(0);
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->get_axis(1);
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->get_axis(2);
+ }
+
+ } break;
+ case TRANSFORM: {
+
+ if (p_index == CoreStringNames::singleton->basis) {
+ return _data._transform->basis;
+ } else if (p_index == CoreStringNames::singleton->origin) {
+ return _data._transform->origin;
+ }
+
+ } break;
+ case COLOR: {
+
+ const Color *v = reinterpret_cast<const Color *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->r) {
+ return v->r;
+ } else if (p_index == CoreStringNames::singleton->g) {
+ return v->g;
+ } else if (p_index == CoreStringNames::singleton->b) {
+ return v->b;
+ } else if (p_index == CoreStringNames::singleton->a) {
+ return v->a;
+ } else if (p_index == CoreStringNames::singleton->r8) {
+ return int(v->r * 255.0);
+ } else if (p_index == CoreStringNames::singleton->g8) {
+ return int(v->g * 255.0);
+ } else if (p_index == CoreStringNames::singleton->b8) {
+ return int(v->b * 255.0);
+ } else if (p_index == CoreStringNames::singleton->a8) {
+ return int(v->a * 255.0);
+ } else if (p_index == CoreStringNames::singleton->h) {
+ return v->get_h();
+ } else if (p_index == CoreStringNames::singleton->s) {
+ return v->get_s();
+ } else if (p_index == CoreStringNames::singleton->v) {
+ return v->get_v();
+ }
+ } break;
+ case OBJECT: {
+
+#ifdef DEBUG_ENABLED
+ if (!_get_obj().obj) {
if (r_valid)
*r_valid = false;
- return "Attempted use of stray pointer object.";
+ return "Instance base is null.";
+ } else {
+
+ if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ if (r_valid)
+ *r_valid = false;
+ return "Attempted use of stray pointer object.";
+ }
}
- }
#endif
- return _get_obj().obj->get(p_index, r_valid);
+ return _get_obj().obj->get(p_index, r_valid);
+
+ } break;
+ default: {
+ return get(p_index.operator String(), r_valid);
+ }
}
- return get(p_index.operator String(), r_valid);
+ if (r_valid) {
+ *r_valid = false;
+ }
+ return Variant();
}
#define DEFAULT_OP_ARRAY_CMD(m_name, m_type, skip_test, cmd) \
@@ -1512,7 +2200,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 +2574,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 +3064,8 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
return true;
} break;
- default: {}
+ default: {
+ }
}
valid = false;
@@ -2401,7 +3092,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 +3484,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;
}
}
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 65c7b7cfec..d60d10cd3a 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "variant_parser.h"
+#include "core/string_buffer.h"
#include "io/resource_loader.h"
#include "os/input_event.h"
#include "os/keyboard.h"
@@ -176,14 +177,15 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
};
case '#': {
- String color_str = "#";
+ StringBuffer color_str;
+ color_str += '#';
while (true) {
CharType ch = p_stream->get_char();
if (p_stream->is_eof()) {
r_token.type = TK_EOF;
return OK;
} else if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
- color_str += String::chr(ch);
+ color_str += ch;
} else {
p_stream->saved = ch;
@@ -191,7 +193,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
}
}
- r_token.value = Color::html(color_str);
+ r_token.value = Color::html(color_str.as_string());
r_token.type = TK_COLOR;
return OK;
};
@@ -296,7 +298,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
if (cchar == '-' || (cchar >= '0' && cchar <= '9')) {
//a number
- String num;
+ StringBuffer num;
#define READING_SIGN 0
#define READING_INT 1
#define READING_DEC 2
@@ -359,7 +361,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
if (reading == READING_DONE)
break;
- num += String::chr(c);
+ num += c;
c = p_stream->get_char();
}
@@ -368,19 +370,19 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
r_token.type = TK_NUMBER;
if (is_float)
- r_token.value = num.to_double();
+ r_token.value = num.as_double();
else
- r_token.value = num.to_int();
+ r_token.value = num.as_int();
return OK;
} else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') {
- String id;
+ StringBuffer id;
bool first = true;
while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) {
- id += String::chr(cchar);
+ id += cchar;
cchar = p_stream->get_char();
first = false;
}
@@ -388,7 +390,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri
p_stream->saved = cchar;
r_token.type = TK_IDENTIFIER;
- r_token.value = id;
+ r_token.value = id.as_string();
return OK;
} else {
r_err_str = "Unexpected character.";
diff --git a/core/vmap.h b/core/vmap.h
index f0977341ec..8165a919b6 100644
--- a/core/vmap.h
+++ b/core/vmap.h
@@ -60,9 +60,13 @@ class VMap {
int low = 0;
int high = _data.size() - 1;
- int middle;
const _Pair *a = &_data[0];
+ int middle = 0;
+#if DEBUG_ENABLED
+ if (low > high)
+ ERR_PRINT("low > high, this may be a bug");
+#endif
while (low <= high) {
middle = (low + high) / 2;
diff --git a/core/vset.h b/core/vset.h
index 7b12ae0b25..67af6c1a4c 100644
--- a/core/vset.h
+++ b/core/vset.h
@@ -46,8 +46,13 @@ class VSet {
int low = 0;
int high = _data.size() - 1;
- int middle;
const T *a = &_data[0];
+ int middle = 0;
+
+#if DEBUG_ENABLED
+ if (low > high)
+ ERR_PRINT("low > high, this may be a bug");
+#endif
while (low <= high) {
middle = (low + high) / 2;