diff options
Diffstat (limited to 'core')
274 files changed, 11202 insertions, 13139 deletions
diff --git a/core/SCsub b/core/SCsub index 0ab4f11d87..80a5f6b623 100644 --- a/core/SCsub +++ b/core/SCsub @@ -49,9 +49,9 @@ thirdparty_misc_dir = "#thirdparty/misc/" thirdparty_misc_sources = [ # C sources "fastlz.c", + "r128.c", "smaz.c", # C++ sources - "hq2x.cpp", "pcg.cpp", "triangulator.cpp", "clipper.cpp", diff --git a/core/array.cpp b/core/array.cpp index d65bddae61..d1c0688e63 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -30,8 +30,10 @@ #include "array.h" +#include "container_type_validate.h" #include "core/hashfuncs.h" #include "core/object.h" +#include "core/script_language.h" #include "core/variant.h" #include "core/vector.h" @@ -39,16 +41,18 @@ class ArrayPrivate { public: SafeRefCount refcount; Vector<Variant> array; + + ContainerTypeValidate typed; }; void Array::_ref(const Array &p_from) const { - ArrayPrivate *_fp = p_from._p; ERR_FAIL_COND(!_fp); // should NOT happen. - if (_fp == _p) + if (_fp == _p) { return; // whatever it is, nothing to do here move along + } bool success = _fp->refcount.ref(); @@ -60,9 +64,9 @@ void Array::_ref(const Array &p_from) const { } void Array::_unref() const { - - if (!_p) + if (!_p) { return; + } if (_p->refcount.unref()) { memdelete(_p); @@ -71,64 +75,103 @@ void Array::_unref() const { } Variant &Array::operator[](int p_idx) { - return _p->array.write[p_idx]; } const Variant &Array::operator[](int p_idx) const { - return _p->array[p_idx]; } int Array::size() const { - return _p->array.size(); } -bool Array::empty() const { +bool Array::empty() const { return _p->array.empty(); } -void Array::clear() { +void Array::clear() { _p->array.clear(); } bool Array::operator==(const Array &p_array) const { - return _p == p_array._p; } uint32_t Array::hash() const { - uint32_t h = hash_djb2_one_32(0); for (int i = 0; i < _p->array.size(); i++) { - h = hash_djb2_one_32(_p->array[i].hash(), h); } return h; } -void Array::operator=(const Array &p_array) { - _ref(p_array); +void Array::_assign(const Array &p_array) { + if (_p->typed.type != Variant::OBJECT && _p->typed.type == p_array._p->typed.type) { + //same type or untyped, just reference, shuold be fine + _ref(p_array); + } else if (_p->typed.type == Variant::NIL) { //from typed to untyped, must copy, but this is cheap anyway + _p->array = p_array._p->array; + } else if (p_array._p->typed.type == Variant::NIL) { //from untyped to typed, must try to check if they are all valid + if (_p->typed.type == Variant::OBJECT) { + //for objects, it needs full validation, either can be converted or fail + for (int i = 0; i < p_array._p->array.size(); i++) { + if (!_p->typed.validate(p_array._p->array[i], "assign")) { + return; + } + } + _p->array = p_array._p->array; //then just copy, which is cheap anyway + + } else { + //for non objects, we need to check if there is a valid conversion, which needs to happen one by one, so this is the worst case. + Vector<Variant> new_array; + new_array.resize(p_array._p->array.size()); + for (int i = 0; i < p_array._p->array.size(); i++) { + Variant src_val = p_array._p->array[i]; + if (src_val.get_type() == _p->typed.type) { + new_array.write[i] = src_val; + } else if (Variant::can_convert_strict(src_val.get_type(), _p->typed.type)) { + Variant *ptr = &src_val; + Callable::CallError ce; + new_array.write[i] = Variant::construct(_p->typed.type, (const Variant **)&ptr, 1, ce, true); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); + } + } else { + ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); + } + } + + _p->array = new_array; + } + } else if (_p->typed.can_reference(p_array._p->typed)) { //same type or compatible + _ref(p_array); + } else { + ERR_FAIL_MSG("Assignment of arrays of incompatible types."); + } +} + +void Array::operator=(const Array &p_array) { + _assign(p_array); } -void Array::push_back(const Variant &p_value) { +void Array::push_back(const Variant &p_value) { + ERR_FAIL_COND(!_p->typed.validate(p_value, "push_back")); _p->array.push_back(p_value); } Error Array::resize(int p_new_size) { - return _p->array.resize(p_new_size); } void Array::insert(int p_pos, const Variant &p_value) { - + ERR_FAIL_COND(!_p->typed.validate(p_value, "insert")); _p->array.insert(p_pos, p_value); } void Array::erase(const Variant &p_value) { - + ERR_FAIL_COND(!_p->typed.validate(p_value, "erase")); _p->array.erase(p_value); } @@ -143,14 +186,15 @@ Variant Array::back() const { } int Array::find(const Variant &p_value, int p_from) const { - + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "find"), -1); return _p->array.find(p_value, p_from); } int Array::rfind(const Variant &p_value, int p_from) const { - - if (_p->array.size() == 0) + if (_p->array.size() == 0) { return -1; + } + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "rfind"), -1); if (p_from < 0) { // Relative offset from the end @@ -162,7 +206,6 @@ int Array::rfind(const Variant &p_value, int p_from) const { } for (int i = p_from; i >= 0; i--) { - if (_p->array[i] == p_value) { return i; } @@ -172,18 +215,18 @@ int Array::rfind(const Variant &p_value, int p_from) const { } int Array::find_last(const Variant &p_value) const { - + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "find_last"), -1); return rfind(p_value); } int Array::count(const Variant &p_value) const { - - if (_p->array.size() == 0) + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "count"), 0); + if (_p->array.size() == 0) { return 0; + } int amount = 0; for (int i = 0; i < _p->array.size(); i++) { - if (_p->array[i] == p_value) { amount++; } @@ -193,29 +236,30 @@ int Array::count(const Variant &p_value) const { } bool Array::has(const Variant &p_value) const { + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "use 'has'"), false); + return _p->array.find(p_value, 0) != -1; } void Array::remove(int p_pos) { - _p->array.remove(p_pos); } void Array::set(int p_idx, const Variant &p_value) { + ERR_FAIL_COND(!_p->typed.validate(p_value, "set")); operator[](p_idx) = p_value; } const Variant &Array::get(int p_idx) const { - return operator[](p_idx); } Array Array::duplicate(bool p_deep) const { - Array new_arr; int element_count = size(); new_arr.resize(element_count); + new_arr._p->typed = _p->typed; for (int i = 0; i < element_count; i++) { new_arr[i] = p_deep ? get(i).duplicate(p_deep) : get(i); } @@ -223,59 +267,51 @@ Array Array::duplicate(bool p_deep) const { return new_arr; } -int Array::_fix_slice_index(int p_index, int p_arr_len, int p_top_mod) { - p_index = CLAMP(p_index, -p_arr_len, p_arr_len + p_top_mod); - if (p_index < 0) { - p_index = (p_index % p_arr_len + p_arr_len) % p_arr_len; // positive modulo +int Array::_clamp_slice_index(int p_index) const { + int arr_size = size(); + int fixed_index = CLAMP(p_index, -arr_size, arr_size - 1); + if (fixed_index < 0) { + fixed_index = arr_size + fixed_index; } - return p_index; -} - -int Array::_clamp_index(int p_index) const { - return CLAMP(p_index, -size() + 1, size() - 1); + return fixed_index; } -#define ARRAY_GET_DEEP(idx, is_deep) is_deep ? get(idx).duplicate(is_deep) : get(idx) - Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // like python, but inclusive on upper bound - Array new_arr; - if (empty()) // Don't try to slice empty arrays. - return new_arr; - - p_begin = Array::_fix_slice_index(p_begin, size(), -1); // can't start out of range - p_end = Array::_fix_slice_index(p_end, size(), 0); + Array new_arr; - int x = p_begin; - int new_arr_i = 0; + ERR_FAIL_COND_V_MSG(p_step == 0, new_arr, "Array slice step size cannot be zero."); - ERR_FAIL_COND_V(p_step == 0, new_arr); - if (Array::_clamp_index(p_begin) == Array::_clamp_index(p_end)) { // don't include element twice - new_arr.resize(1); - // new_arr[0] = 1; - new_arr[0] = ARRAY_GET_DEEP(Array::_clamp_index(p_begin), p_deep); + if (empty()) { // Don't try to slice empty arrays. return new_arr; - } else { - int element_count = ceil((int)MAX(0, (p_end - p_begin) / p_step)) + 1; - if (element_count == 1) { // delta going in wrong direction to reach end - new_arr.resize(0); + } + if (p_step > 0) { + if (p_begin >= size() || p_end < -size()) { + return new_arr; + } + } else { // p_step < 0 + if (p_begin < -size() || p_end >= size()) { return new_arr; } - new_arr.resize(element_count); } - // if going backwards, have to have a different terminating condition - if (p_step < 0) { - while (x >= p_end) { - new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep); - x += p_step; - new_arr_i += 1; + int begin = _clamp_slice_index(p_begin); + int end = _clamp_slice_index(p_end); + + int new_arr_size = MAX(((end - begin + p_step) / p_step), 0); + new_arr.resize(new_arr_size); + + if (p_step > 0) { + int dest_idx = 0; + for (int idx = begin; idx <= end; idx += p_step) { + ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()"); + new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx); } - } else if (p_step > 0) { - while (x <= p_end) { - new_arr[new_arr_i] = ARRAY_GET_DEEP(Array::_clamp_index(x), p_deep); - x += p_step; - new_arr_i += 1; + } else { // p_step < 0 + int dest_idx = 0; + for (int idx = begin; idx >= end; idx += p_step) { + ERR_FAIL_COND_V_MSG(dest_idx < 0 || dest_idx >= new_arr_size, Array(), "Bug in Array slice()"); + new_arr[dest_idx++] = p_deep ? get(idx).duplicate(p_deep) : get(idx); } } @@ -283,40 +319,37 @@ Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // l } struct _ArrayVariantSort { - _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { bool valid = false; Variant res; Variant::evaluate(Variant::OP_LESS, p_l, p_r, res, valid); - if (!valid) + if (!valid) { res = false; + } return res; } }; Array &Array::sort() { - _p->array.sort_custom<_ArrayVariantSort>(); return *this; } struct _ArrayVariantSortCustom { - Object *obj; StringName func; _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { - const Variant *args[2] = { &p_l, &p_r }; Callable::CallError err; bool res = obj->call(func, args, 2, err); - if (err.error != Callable::CallError::CALL_OK) + if (err.error != Callable::CallError::CALL_OK) { res = false; + } return res; } }; Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { - ERR_FAIL_NULL_V(p_obj, *this); SortArray<Variant, _ArrayVariantSortCustom, true> avs; @@ -327,10 +360,10 @@ Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { } void Array::shuffle() { - const int n = _p->array.size(); - if (n < 2) + if (n < 2) { return; + } Variant *data = _p->array.ptrw(); for (int i = n - 1; i >= 1; i--) { const int j = Math::rand() % (i + 1); @@ -342,7 +375,6 @@ void Array::shuffle() { template <typename Less> _FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value, bool p_before, const Less &p_less) { - int lo = 0; int hi = p_array.size(); if (p_before) { @@ -368,12 +400,12 @@ _FORCE_INLINE_ int bisect(const Vector<Variant> &p_array, const Variant &p_value } int Array::bsearch(const Variant &p_value, bool p_before) { - + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "binary search"), -1); return bisect(_p->array, p_value, p_before, _ArrayVariantSort()); } int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before) { - + ERR_FAIL_COND_V(!_p->typed.validate(p_value, "custom binary search"), -1); ERR_FAIL_NULL_V(p_obj, 0); _ArrayVariantSortCustom less; @@ -384,18 +416,16 @@ int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringNam } Array &Array::invert() { - _p->array.invert(); return *this; } void Array::push_front(const Variant &p_value) { - + ERR_FAIL_COND(!_p->typed.validate(p_value, "push_front")); _p->array.insert(0, p_value); } Variant Array::pop_back() { - if (!_p->array.empty()) { int n = _p->array.size() - 1; Variant ret = _p->array.get(n); @@ -406,7 +436,6 @@ Variant Array::pop_back() { } Variant Array::pop_front() { - if (!_p->array.empty()) { Variant ret = _p->array.get(0); _p->array.remove(0); @@ -416,7 +445,6 @@ Variant Array::pop_front() { } Variant Array::min() const { - Variant minval; for (int i = 0; i < size(); i++) { if (i == 0) { @@ -439,7 +467,6 @@ Variant Array::min() const { } Variant Array::max() const { - Variant maxval; for (int i = 0; i < size(); i++) { if (i == 0) { @@ -465,18 +492,37 @@ const void *Array::id() const { return _p->array.ptr(); } -Array::Array(const Array &p_from) { +Array::Array(const Array &p_from, uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { + _p = memnew(ArrayPrivate); + _p->refcount.init(); + set_typed(p_type, p_class_name, p_script); + _assign(p_from); +} + +void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script) { + ERR_FAIL_COND_MSG(_p->array.size() > 0, "Type can only be set when array is empty."); + ERR_FAIL_COND_MSG(_p->refcount.get() > 1, "Type can only be set when array has no more than one user."); + ERR_FAIL_COND_MSG(_p->typed.type != Variant::NIL, "Type can only be set once."); + ERR_FAIL_COND_MSG(p_class_name != StringName() && p_type != Variant::OBJECT, "Class names can only be set for type OBJECT"); + Ref<Script> script = p_script; + ERR_FAIL_COND_MSG(script.is_valid() && p_class_name == StringName(), "Script class can only be set together with base class name"); + + _p->typed.type = Variant::Type(p_type); + _p->typed.class_name = p_class_name; + _p->typed.script = script; + _p->typed.where = "TypedArray"; +} +Array::Array(const Array &p_from) { _p = nullptr; _ref(p_from); } Array::Array() { - _p = memnew(ArrayPrivate); _p->refcount.init(); } -Array::~Array() { +Array::~Array() { _unref(); } diff --git a/core/array.h b/core/array.h index 3b14bdb9fe..d2e0537ad5 100644 --- a/core/array.h +++ b/core/array.h @@ -39,13 +39,15 @@ class Object; class StringName; class Array { - mutable ArrayPrivate *_p; void _ref(const Array &p_from) const; void _unref() const; - int _clamp_index(int p_index) const; - static int _fix_slice_index(int p_index, int p_arr_len, int p_top_mod); + inline int _clamp_slice_index(int p_index) const; + +protected: + Array(const Array &p_base, uint32_t p_type, const StringName &p_class_name, const Variant &p_script); + void _assign(const Array &p_array); public: Variant &operator[](int p_idx); @@ -101,6 +103,7 @@ public: const void *id() const; + void set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script); Array(const Array &p_from); Array(); ~Array(); diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index e8955c05df..267391c4d6 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -35,7 +35,8 @@ #include "core/io/file_access_encrypted.h" #include "core/io/json.h" #include "core/io/marshalls.h" -#include "core/math/geometry.h" +#include "core/math/geometry_2d.h" +#include "core/math/geometry_3d.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/project_settings.h" @@ -62,12 +63,14 @@ static const unsigned int MONTH_DAYS_TABLE[2][12] = { { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; +////// _ResourceLoader ////// + _ResourceLoader *_ResourceLoader::singleton = nullptr; Error _ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads) { - return ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads); } + _ResourceLoader::ThreadLoadStatus _ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) { float progress = 0; ResourceLoader::ThreadLoadStatus tls = ResourceLoader::load_threaded_get_status(p_path, &progress); @@ -75,6 +78,7 @@ _ResourceLoader::ThreadLoadStatus _ResourceLoader::load_threaded_get_status(cons r_progress[0] = progress; return (ThreadLoadStatus)tls; } + RES _ResourceLoader::load_threaded_get(const String &p_path) { Error error; RES res = ResourceLoader::load_threaded_get(p_path, &error); @@ -82,7 +86,6 @@ RES _ResourceLoader::load_threaded_get(const String &p_path) { } RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache) { - Error err = OK; RES ret = ResourceLoader::load(p_path, p_type_hint, p_no_cache, &err); @@ -91,12 +94,10 @@ RES _ResourceLoader::load(const String &p_path, const String &p_type_hint, bool } Vector<String> _ResourceLoader::get_recognized_extensions_for_type(const String &p_type) { - List<String> exts; ResourceLoader::get_recognized_extensions_for_type(p_type, &exts); Vector<String> ret; for (List<String>::Element *E = exts.front(); E; E = E->next()) { - ret.push_back(E->get()); } @@ -104,12 +105,10 @@ Vector<String> _ResourceLoader::get_recognized_extensions_for_type(const String } void _ResourceLoader::set_abort_on_missing_resources(bool p_abort) { - ResourceLoader::set_abort_on_missing_resources(p_abort); } PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) { - List<String> deps; ResourceLoader::get_dependencies(p_path, &deps); @@ -119,10 +118,9 @@ PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) { } return ret; -}; +} bool _ResourceLoader::has_cached(const String &p_path) { - String local_path = ProjectSettings::get_singleton()->localize_path(p_path); return ResourceCache::has(local_path); } @@ -132,7 +130,6 @@ bool _ResourceLoader::exists(const String &p_path, const String &p_type_hint) { } void _ResourceLoader::_bind_methods() { - ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads"), &_ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false)); ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &_ResourceLoader::load_threaded_get_status, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &_ResourceLoader::load_threaded_get); @@ -150,10 +147,7 @@ void _ResourceLoader::_bind_methods() { BIND_ENUM_CONSTANT(THREAD_LOAD_LOADED); } -_ResourceLoader::_ResourceLoader() { - - singleton = this; -} +////// _ResourceSaver ////// Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFlags p_flags) { ERR_FAIL_COND_V_MSG(p_resource.is_null(), ERR_INVALID_PARAMETER, "Can't save empty resource to path '" + String(p_path) + "'."); @@ -161,13 +155,11 @@ Error _ResourceSaver::save(const String &p_path, const RES &p_resource, SaverFla } Vector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource) { - ERR_FAIL_COND_V_MSG(p_resource.is_null(), Vector<String>(), "It's not a reference to a valid Resource object."); List<String> exts; ResourceSaver::get_recognized_extensions(p_resource, &exts); Vector<String> ret; for (List<String>::Element *E = exts.front(); E; E = E->next()) { - ret.push_back(E->get()); } return ret; @@ -176,7 +168,6 @@ Vector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource) _ResourceSaver *_ResourceSaver::singleton = nullptr; void _ResourceSaver::_bind_methods() { - ClassDB::bind_method(D_METHOD("save", "path", "resource", "flags"), &_ResourceSaver::save, DEFVAL(0)); ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &_ResourceSaver::get_recognized_extensions); @@ -189,10 +180,7 @@ void _ResourceSaver::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_REPLACE_SUBRESOURCE_PATHS); } -_ResourceSaver::_ResourceSaver() { - - singleton = this; -} +////// _OS ////// PackedStringArray _OS::get_connected_midi_inputs() { return OS::get_singleton()->get_connected_midi_inputs(); @@ -207,87 +195,82 @@ void _OS::close_midi_inputs() { } void _OS::set_use_file_access_save_and_swap(bool p_enable) { - FileAccess::set_backup_save(p_enable); } void _OS::set_low_processor_usage_mode(bool p_enabled) { - OS::get_singleton()->set_low_processor_usage_mode(p_enabled); } -bool _OS::is_in_low_processor_usage_mode() const { +bool _OS::is_in_low_processor_usage_mode() const { return OS::get_singleton()->is_in_low_processor_usage_mode(); } void _OS::set_low_processor_usage_mode_sleep_usec(int p_usec) { - OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(p_usec); } int _OS::get_low_processor_usage_mode_sleep_usec() const { - return OS::get_singleton()->get_low_processor_usage_mode_sleep_usec(); } String _OS::get_executable_path() const { - return OS::get_singleton()->get_executable_path(); } Error _OS::shell_open(String p_uri) { - + if (p_uri.begins_with("res://")) { + WARN_PRINT("Attempting to open an URL with the \"res://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`."); + } else if (p_uri.begins_with("user://")) { + WARN_PRINT("Attempting to open an URL with the \"user://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_open()`."); + } return OS::get_singleton()->shell_open(p_uri); -}; +} int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr) { - OS::ProcessID pid = -2; int exitcode = 0; List<String> args; - for (int i = 0; i < p_arguments.size(); i++) + for (int i = 0; i < p_arguments.size(); i++) { args.push_back(p_arguments[i]); + } String pipe; Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, &exitcode, p_read_stderr); p_output.clear(); p_output.push_back(pipe); - if (err != OK) + if (err != OK) { return -1; - else if (p_blocking) + } else if (p_blocking) { return exitcode; - else + } else { return pid; + } } Error _OS::kill(int p_pid) { - return OS::get_singleton()->kill(p_pid); } int _OS::get_process_id() const { - return OS::get_singleton()->get_process_id(); -}; +} bool _OS::has_environment(const String &p_var) const { - return OS::get_singleton()->has_environment(p_var); } -String _OS::get_environment(const String &p_var) const { +String _OS::get_environment(const String &p_var) const { return OS::get_singleton()->get_environment(p_var); } String _OS::get_name() const { - return OS::get_singleton()->get_name(); } -Vector<String> _OS::get_cmdline_args() { +Vector<String> _OS::get_cmdline_args() { List<String> cmdline = OS::get_singleton()->get_cmdline_args(); Vector<String> cmdlinev; for (List<String>::Element *E = cmdline.front(); E; E = E->next()) { - cmdlinev.push_back(E->get()); } @@ -295,86 +278,34 @@ Vector<String> _OS::get_cmdline_args() { } String _OS::get_locale() const { - return OS::get_singleton()->get_locale(); } String _OS::get_model_name() const { - return OS::get_singleton()->get_model_name(); } Error _OS::set_thread_name(const String &p_name) { - return Thread::set_name(p_name); -}; +} bool _OS::has_feature(const String &p_feature) const { - return OS::get_singleton()->has_feature(p_feature); } -/* -enum Weekday { - DAY_SUNDAY, - DAY_MONDAY, - DAY_TUESDAY, - DAY_WEDNESDAY, - DAY_THURSDAY, - DAY_FRIDAY, - DAY_SATURDAY -}; - -enum Month { - MONTH_JANUARY, - MONTH_FEBRUARY, - MONTH_MARCH, - MONTH_APRIL, - MONTH_MAY, - MONTH_JUNE, - MONTH_JULY, - MONTH_AUGUST, - MONTH_SEPTEMBER, - MONTH_OCTOBER, - MONTH_NOVEMBER, - MONTH_DECEMBER -}; -*/ -/* -struct Date { - - int year; - Month month; - int day; - Weekday weekday; - bool dst; -}; - -struct Time { - - int hour; - int min; - int sec; -}; -*/ - uint64_t _OS::get_static_memory_usage() const { - return OS::get_singleton()->get_static_memory_usage(); } uint64_t _OS::get_static_memory_peak_usage() const { - return OS::get_singleton()->get_static_memory_peak_usage(); } int _OS::get_exit_code() const { - return OS::get_singleton()->get_exit_code(); } void _OS::set_exit_code(int p_code) { - if (p_code < 0 || p_code > 125) { WARN_PRINT("For portability reasons, the exit code should be set between 0 and 125 (inclusive)."); } @@ -387,7 +318,6 @@ void _OS::set_exit_code(int p_code) { * dst */ Dictionary _OS::get_datetime(bool utc) const { - Dictionary dated = get_date(utc); Dictionary timed = get_time(utc); @@ -402,7 +332,6 @@ Dictionary _OS::get_datetime(bool utc) const { } Dictionary _OS::get_date(bool utc) const { - OS::Date date = OS::get_singleton()->get_date(utc); Dictionary dated; dated[YEAR_KEY] = date.year; @@ -414,7 +343,6 @@ Dictionary _OS::get_date(bool utc) const { } Dictionary _OS::get_time(bool utc) const { - OS::Time time = OS::get_singleton()->get_time(utc); Dictionary timed; timed[HOUR_KEY] = time.hour; @@ -436,7 +364,6 @@ Dictionary _OS::get_time(bool utc) const { * @return epoch calculated */ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { - // Bunch of conversion constants static const unsigned int SECONDS_PER_MINUTE = 60; static const unsigned int MINUTES_PER_HOUR = 60; @@ -509,7 +436,6 @@ int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const { * @return dictionary of date and time values */ Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const { - OS::Date date; OS::Time time; @@ -572,71 +498,51 @@ Dictionary _OS::get_time_zone_info() const { return infod; } -uint64_t _OS::get_unix_time() const { - +double _OS::get_unix_time() const { return OS::get_singleton()->get_unix_time(); } -uint64_t _OS::get_system_time_secs() const { - return OS::get_singleton()->get_system_time_secs(); -} - -uint64_t _OS::get_system_time_msecs() const { - return OS::get_singleton()->get_system_time_msecs(); -} - void _OS::delay_usec(uint32_t p_usec) const { - OS::get_singleton()->delay_usec(p_usec); } void _OS::delay_msec(uint32_t p_msec) const { - OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000); } uint32_t _OS::get_ticks_msec() const { - return OS::get_singleton()->get_ticks_msec(); } uint64_t _OS::get_ticks_usec() const { - return OS::get_singleton()->get_ticks_usec(); } uint32_t _OS::get_splash_tick_msec() const { - return OS::get_singleton()->get_splash_tick_msec(); } bool _OS::can_use_threads() const { - return OS::get_singleton()->can_use_threads(); } 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(); } bool _OS::is_stdout_verbose() const { - return OS::get_singleton()->is_stdout_verbose(); } void _OS::dump_memory_to_file(const String &p_file) { - OS::get_singleton()->dump_memory_to_file(p_file.utf8().get_data()); } struct _OSCoreBindImg { - String path; Size2 size; int fmt; @@ -646,7 +552,6 @@ struct _OSCoreBindImg { }; void _OS::print_all_textures_by_size() { - List<_OSCoreBindImg> imgs; int total = 0; { @@ -654,9 +559,9 @@ void _OS::print_all_textures_by_size() { ResourceCache::get_cached_resources(&rsrc); for (List<Ref<Resource>>::Element *E = rsrc.front(); E; E = E->next()) { - - if (!E->get()->is_class("ImageTexture")) + if (!E->get()->is_class("ImageTexture")) { continue; + } Size2 size = E->get()->call("get_size"); int fmt = E->get()->call("get_format"); @@ -675,13 +580,11 @@ void _OS::print_all_textures_by_size() { imgs.sort(); for (List<_OSCoreBindImg>::Element *E = imgs.front(); E; E = E->next()) { - total -= E->get().vram; } } void _OS::print_resources_by_type(const Vector<String> &p_types) { - Map<String, int> type_count; List<Ref<Resource>> resources; @@ -691,17 +594,18 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) { ResourceCache::get_cached_resources(&rsrc); for (List<Ref<Resource>>::Element *E = rsrc.front(); E; E = E->next()) { - Ref<Resource> r = E->get(); bool found = false; for (int i = 0; i < p_types.size(); i++) { - if (r->is_class(p_types[i])) + if (r->is_class(p_types[i])) { found = true; + } } - if (!found) + if (!found) { continue; + } if (!type_count.has(r->get_class())) { type_count[r->get_class()] = 0; @@ -709,30 +613,25 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) { type_count[r->get_class()]++; } -}; +} void _OS::print_all_resources(const String &p_to_file) { - OS::get_singleton()->print_all_resources(p_to_file); } void _OS::print_resources_in_use(bool p_short) { - OS::get_singleton()->print_resources_in_use(p_short); } void _OS::dump_resources_to_file(const String &p_file) { - OS::get_singleton()->dump_resources_to_file(p_file.utf8().get_data()); } String _OS::get_user_data_dir() const { - return OS::get_singleton()->get_user_data_dir(); -}; +} bool _OS::is_debug_build() const { - #ifdef DEBUG_ENABLED return true; #else @@ -741,47 +640,56 @@ bool _OS::is_debug_build() const { } String _OS::get_system_dir(SystemDir p_dir) const { - return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir)); } String _OS::get_keycode_string(uint32_t p_code) const { - return keycode_get_string(p_code); } bool _OS::is_keycode_unicode(uint32_t p_unicode) const { - return keycode_has_unicode(p_unicode); } int _OS::find_keycode_from_string(const String &p_code) const { - return find_keycode(p_code); } bool _OS::request_permission(const String &p_name) { - return OS::get_singleton()->request_permission(p_name); } bool _OS::request_permissions() { - return OS::get_singleton()->request_permissions(); } Vector<String> _OS::get_granted_permissions() const { - return OS::get_singleton()->get_granted_permissions(); } String _OS::get_unique_id() const { return OS::get_singleton()->get_unique_id(); } + +int _OS::get_tablet_driver_count() const { + return OS::get_singleton()->get_tablet_driver_count(); +} + +String _OS::get_tablet_driver_name(int p_driver) const { + return OS::get_singleton()->get_tablet_driver_name(p_driver); +} + +String _OS::get_current_tablet_driver() const { + return OS::get_singleton()->get_current_tablet_driver(); +} + +void _OS::set_current_tablet_driver(const String &p_driver) { + OS::get_singleton()->set_current_tablet_driver(p_driver); +} + _OS *_OS::singleton = nullptr; void _OS::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs); ClassDB::bind_method(D_METHOD("open_midi_inputs"), &_OS::open_midi_inputs); ClassDB::bind_method(D_METHOD("close_midi_inputs"), &_OS::close_midi_inputs); @@ -813,8 +721,6 @@ void _OS::_bind_methods() { 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_system_time_secs"), &_OS::get_system_time_secs); - ClassDB::bind_method(D_METHOD("get_system_time_msecs"), &_OS::get_system_time_msecs); ClassDB::bind_method(D_METHOD("get_exit_code"), &_OS::get_exit_code); ClassDB::bind_method(D_METHOD("set_exit_code", "code"), &_OS::set_exit_code); @@ -834,8 +740,6 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("is_debug_build"), &_OS::is_debug_build); - //ClassDB::bind_method(D_METHOD("get_mouse_button_state"),&_OS::get_mouse_button_state); - ClassDB::bind_method(D_METHOD("dump_memory_to_file", "file"), &_OS::dump_memory_to_file); ClassDB::bind_method(D_METHOD("dump_resources_to_file", "file"), &_OS::dump_resources_to_file); ClassDB::bind_method(D_METHOD("print_resources_in_use", "short"), &_OS::print_resources_in_use, DEFVAL(false)); @@ -865,9 +769,15 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("request_permissions"), &_OS::request_permissions); ClassDB::bind_method(D_METHOD("get_granted_permissions"), &_OS::get_granted_permissions); + ClassDB::bind_method(D_METHOD("get_tablet_driver_count"), &_OS::get_tablet_driver_count); + ClassDB::bind_method(D_METHOD("get_tablet_driver_name", "idx"), &_OS::get_tablet_driver_name); + ClassDB::bind_method(D_METHOD("get_current_tablet_driver"), &_OS::get_current_tablet_driver); + ClassDB::bind_method(D_METHOD("set_current_tablet_driver", "name"), &_OS::set_current_tablet_driver); + ADD_PROPERTY(PropertyInfo(Variant::INT, "exit_code"), "set_exit_code", "get_exit_code"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "tablet_driver"), "set_current_tablet_driver", "get_current_tablet_driver"); // Those default values need to be specified for the docs generator, // to avoid using values from the documentation writer's own OS instance. @@ -909,69 +819,43 @@ void _OS::_bind_methods() { BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES); } -_OS::_OS() { - - singleton = this; -} - -///////////////////// GEOMETRY - -_Geometry *_Geometry::singleton = nullptr; +////// _Geometry2D ////// -_Geometry *_Geometry::get_singleton() { +_Geometry2D *_Geometry2D::singleton = nullptr; +_Geometry2D *_Geometry2D::get_singleton() { return singleton; } -Vector<Plane> _Geometry::build_box_planes(const Vector3 &p_extents) { - - return Geometry::build_box_planes(p_extents); -} - -Vector<Plane> _Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { - - return Geometry::build_cylinder_planes(p_radius, p_height, p_sides, p_axis); +bool _Geometry2D::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) { + return Geometry2D::is_point_in_circle(p_point, p_circle_pos, p_circle_radius); } -Vector<Plane> _Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { - return Geometry::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis); +real_t _Geometry2D::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) { + return Geometry2D::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius); } -bool _Geometry::is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) { - - return Geometry::is_point_in_circle(p_point, p_circle_pos, p_circle_radius); -} - -real_t _Geometry::segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) { - - return Geometry::segment_intersects_circle(p_from, p_to, p_circle_pos, p_circle_radius); -} - -Variant _Geometry::segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) { - +Variant _Geometry2D::segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b) { Vector2 result; - if (Geometry::segment_intersects_segment_2d(p_from_a, p_to_a, p_from_b, p_to_b, &result)) { - + if (Geometry2D::segment_intersects_segment(p_from_a, p_to_a, p_from_b, p_to_b, &result)) { return result; } else { return Variant(); - }; -}; - -Variant _Geometry::line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) { + } +} +Variant _Geometry2D::line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b) { Vector2 result; - if (Geometry::line_intersects_line_2d(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) { + if (Geometry2D::line_intersects_line(p_from_a, p_dir_a, p_from_b, p_dir_b, result)) { return result; } else { return Variant(); } } -Vector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) { - +Vector<Vector2> _Geometry2D::get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2) { Vector2 r1, r2; - Geometry::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2); + Geometry2D::get_closest_points_between_segments(p1, q1, p2, q2, r1, r2); Vector<Vector2> r; r.resize(2); r.set(0, r1); @@ -979,128 +863,42 @@ Vector<Vector2> _Geometry::get_closest_points_between_segments_2d(const Vector2 return r; } -Vector<Vector3> _Geometry::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) { - - Vector3 r1, r2; - Geometry::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2); - Vector<Vector3> r; - r.resize(2); - r.set(0, r1); - r.set(1, r2); - return r; -} -Vector2 _Geometry::get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) { - +Vector2 _Geometry2D::get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) { Vector2 s[2] = { p_a, p_b }; - return Geometry::get_closest_point_to_segment_2d(p_point, s); + return Geometry2D::get_closest_point_to_segment(p_point, s); } -Vector3 _Geometry::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) { - - Vector3 s[2] = { p_a, p_b }; - return Geometry::get_closest_point_to_segment(p_point, s); -} -Vector2 _Geometry::get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) { +Vector2 _Geometry2D::get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b) { Vector2 s[2] = { p_a, p_b }; - return Geometry::get_closest_point_to_segment_uncapped_2d(p_point, s); -} -Vector3 _Geometry::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) { - - Vector3 s[2] = { p_a, p_b }; - return Geometry::get_closest_point_to_segment_uncapped(p_point, s); -} -Variant _Geometry::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { - - Vector3 res; - if (Geometry::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) - return res; - else - return Variant(); -} -Variant _Geometry::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { - - Vector3 res; - if (Geometry::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) - return res; - else - return Variant(); -} - -bool _Geometry::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const { - - return Geometry::is_point_in_triangle(s, a, b, c); -} - -Vector<Vector3> _Geometry::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) { - - Vector<Vector3> r; - Vector3 res, norm; - if (!Geometry::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) - return r; - - r.resize(2); - r.set(0, res); - r.set(1, norm); - return r; -} -Vector<Vector3> _Geometry::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) { - - Vector<Vector3> r; - Vector3 res, norm; - if (!Geometry::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) - return r; - - r.resize(2); - r.set(0, res); - r.set(1, norm); - return r; -} -Vector<Vector3> _Geometry::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) { - - Vector<Vector3> r; - Vector3 res, norm; - if (!Geometry::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) - return r; - - r.resize(2); - r.set(0, res); - r.set(1, norm); - return r; + return Geometry2D::get_closest_point_to_segment_uncapped(p_point, s); } -bool _Geometry::is_polygon_clockwise(const Vector<Vector2> &p_polygon) { - - return Geometry::is_polygon_clockwise(p_polygon); +bool _Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const { + return Geometry2D::is_point_in_triangle(s, a, b, c); } -bool _Geometry::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) { - - return Geometry::is_point_in_polygon(p_point, p_polygon); +bool _Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) { + return Geometry2D::is_polygon_clockwise(p_polygon); } -Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2> &p_polygon) { - - return Geometry::triangulate_polygon(p_polygon); +bool _Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) { + return Geometry2D::is_point_in_polygon(p_point, p_polygon); } -Vector<int> _Geometry::triangulate_delaunay_2d(const Vector<Vector2> &p_points) { - - return Geometry::triangulate_delaunay_2d(p_points); +Vector<int> _Geometry2D::triangulate_polygon(const Vector<Vector2> &p_polygon) { + return Geometry2D::triangulate_polygon(p_polygon); } -Vector<Point2> _Geometry::convex_hull_2d(const Vector<Point2> &p_points) { - - return Geometry::convex_hull_2d(p_points); +Vector<int> _Geometry2D::triangulate_delaunay(const Vector<Vector2> &p_points) { + return Geometry2D::triangulate_delaunay(p_points); } -Vector<Vector3> _Geometry::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) { - - return Geometry::clip_polygon(p_points, p_plane); +Vector<Point2> _Geometry2D::convex_hull(const Vector<Point2> &p_points) { + return Geometry2D::convex_hull(p_points); } -Array _Geometry::merge_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { - - Vector<Vector<Point2>> polys = Geometry::merge_polygons_2d(p_polygon_a, p_polygon_b); +Array _Geometry2D::merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { + Vector<Vector<Point2>> polys = Geometry2D::merge_polygons(p_polygon_a, p_polygon_b); Array ret; @@ -1110,9 +908,8 @@ Array _Geometry::merge_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vec return ret; } -Array _Geometry::clip_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { - - Vector<Vector<Point2>> polys = Geometry::clip_polygons_2d(p_polygon_a, p_polygon_b); +Array _Geometry2D::clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { + Vector<Vector<Point2>> polys = Geometry2D::clip_polygons(p_polygon_a, p_polygon_b); Array ret; @@ -1122,9 +919,8 @@ Array _Geometry::clip_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vect return ret; } -Array _Geometry::intersect_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { - - Vector<Vector<Point2>> polys = Geometry::intersect_polygons_2d(p_polygon_a, p_polygon_b); +Array _Geometry2D::intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { + Vector<Vector<Point2>> polys = Geometry2D::intersect_polygons(p_polygon_a, p_polygon_b); Array ret; @@ -1134,9 +930,8 @@ Array _Geometry::intersect_polygons_2d(const Vector<Vector2> &p_polygon_a, const return ret; } -Array _Geometry::exclude_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { - - Vector<Vector<Point2>> polys = Geometry::exclude_polygons_2d(p_polygon_a, p_polygon_b); +Array _Geometry2D::exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b) { + Vector<Vector<Point2>> polys = Geometry2D::exclude_polygons(p_polygon_a, p_polygon_b); Array ret; @@ -1146,9 +941,8 @@ Array _Geometry::exclude_polygons_2d(const Vector<Vector2> &p_polygon_a, const V return ret; } -Array _Geometry::clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { - - Vector<Vector<Point2>> polys = Geometry::clip_polyline_with_polygon_2d(p_polyline, p_polygon); +Array _Geometry2D::clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { + Vector<Vector<Point2>> polys = Geometry2D::clip_polyline_with_polygon(p_polyline, p_polygon); Array ret; @@ -1158,9 +952,8 @@ Array _Geometry::clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline return ret; } -Array _Geometry::intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { - - Vector<Vector<Point2>> polys = Geometry::intersect_polyline_with_polygon_2d(p_polyline, p_polygon); +Array _Geometry2D::intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { + Vector<Vector<Point2>> polys = Geometry2D::intersect_polyline_with_polygon(p_polyline, p_polygon); Array ret; @@ -1170,9 +963,8 @@ Array _Geometry::intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_pol return ret; } -Array _Geometry::offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { - - Vector<Vector<Point2>> polys = Geometry::offset_polygon_2d(p_polygon, p_delta, Geometry::PolyJoinType(p_join_type)); +Array _Geometry2D::offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { + Vector<Vector<Point2>> polys = Geometry2D::offset_polygon(p_polygon, p_delta, Geometry2D::PolyJoinType(p_join_type)); Array ret; @@ -1182,9 +974,8 @@ Array _Geometry::offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_de return ret; } -Array _Geometry::offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { - - Vector<Vector<Point2>> polys = Geometry::offset_polyline_2d(p_polygon, p_delta, Geometry::PolyJoinType(p_join_type), Geometry::PolyEndType(p_end_type)); +Array _Geometry2D::offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { + Vector<Vector<Point2>> polys = Geometry2D::offset_polyline(p_polygon, p_delta, Geometry2D::PolyJoinType(p_join_type), Geometry2D::PolyEndType(p_end_type)); Array ret; @@ -1194,86 +985,62 @@ Array _Geometry::offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_d return ret; } -Dictionary _Geometry::make_atlas(const Vector<Size2> &p_rects) { - +Dictionary _Geometry2D::make_atlas(const Vector<Size2> &p_rects) { Dictionary ret; Vector<Size2i> rects; for (int i = 0; i < p_rects.size(); i++) { - rects.push_back(p_rects[i]); - }; + } Vector<Point2i> result; Size2i size; - Geometry::make_atlas(rects, result, size); + Geometry2D::make_atlas(rects, result, size); Size2 r_size = size; Vector<Point2> r_result; for (int i = 0; i < result.size(); i++) { - r_result.push_back(result[i]); - }; + } ret["points"] = r_result; ret["size"] = r_size; return ret; -}; - -int _Geometry::get_uv84_normal_bit(const Vector3 &p_vector) { - - return Geometry::get_uv84_normal_bit(p_vector); } -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("is_point_in_circle", "point", "circle_position", "circle_radius"), &_Geometry::is_point_in_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("line_intersects_line_2d", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry::line_intersects_line_2d); +void _Geometry2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &_Geometry2D::is_point_in_circle); + ClassDB::bind_method(D_METHOD("segment_intersects_segment", "from_a", "to_a", "from_b", "to_b"), &_Geometry2D::segment_intersects_segment); + ClassDB::bind_method(D_METHOD("line_intersects_line", "from_a", "dir_a", "from_b", "dir_b"), &_Geometry2D::line_intersects_line); - ClassDB::bind_method(D_METHOD("get_closest_points_between_segments_2d", "p1", "q1", "p2", "q2"), &_Geometry::get_closest_points_between_segments_2d); - ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry::get_closest_points_between_segments); + ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "q1", "p2", "q2"), &_Geometry2D::get_closest_points_between_segments); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_2d", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment_2d); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment); + ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped_2d", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment_uncapped_2d); - ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry::get_closest_point_to_segment_uncapped); + ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry2D::get_closest_point_to_segment_uncapped); - ClassDB::bind_method(D_METHOD("get_uv84_normal_bit", "normal"), &_Geometry::get_uv84_normal_bit); + ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &_Geometry2D::point_is_inside_triangle); - 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", "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); + ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &_Geometry2D::is_polygon_clockwise); + ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &_Geometry2D::is_point_in_polygon); + ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry2D::triangulate_polygon); + ClassDB::bind_method(D_METHOD("triangulate_delaunay", "points"), &_Geometry2D::triangulate_delaunay); + ClassDB::bind_method(D_METHOD("convex_hull", "points"), &_Geometry2D::convex_hull); - ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &_Geometry::is_polygon_clockwise); - ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &_Geometry::is_point_in_polygon); - ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &_Geometry::triangulate_polygon); - ClassDB::bind_method(D_METHOD("triangulate_delaunay_2d", "points"), &_Geometry::triangulate_delaunay_2d); - ClassDB::bind_method(D_METHOD("convex_hull_2d", "points"), &_Geometry::convex_hull_2d); - ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry::clip_polygon); + ClassDB::bind_method(D_METHOD("merge_polygons", "polygon_a", "polygon_b"), &_Geometry2D::merge_polygons); + ClassDB::bind_method(D_METHOD("clip_polygons", "polygon_a", "polygon_b"), &_Geometry2D::clip_polygons); + ClassDB::bind_method(D_METHOD("intersect_polygons", "polygon_a", "polygon_b"), &_Geometry2D::intersect_polygons); + ClassDB::bind_method(D_METHOD("exclude_polygons", "polygon_a", "polygon_b"), &_Geometry2D::exclude_polygons); - ClassDB::bind_method(D_METHOD("merge_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::merge_polygons_2d); - ClassDB::bind_method(D_METHOD("clip_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::clip_polygons_2d); - ClassDB::bind_method(D_METHOD("intersect_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::intersect_polygons_2d); - ClassDB::bind_method(D_METHOD("exclude_polygons_2d", "polygon_a", "polygon_b"), &_Geometry::exclude_polygons_2d); + ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon", "polyline", "polygon"), &_Geometry2D::clip_polyline_with_polygon); + ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon", "polyline", "polygon"), &_Geometry2D::intersect_polyline_with_polygon); - ClassDB::bind_method(D_METHOD("clip_polyline_with_polygon_2d", "polyline", "polygon"), &_Geometry::clip_polyline_with_polygon_2d); - ClassDB::bind_method(D_METHOD("intersect_polyline_with_polygon_2d", "polyline", "polygon"), &_Geometry::intersect_polyline_with_polygon_2d); + ClassDB::bind_method(D_METHOD("offset_polygon", "polygon", "delta", "join_type"), &_Geometry2D::offset_polygon, DEFVAL(JOIN_SQUARE)); + ClassDB::bind_method(D_METHOD("offset_polyline", "polyline", "delta", "join_type", "end_type"), &_Geometry2D::offset_polyline, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE)); - ClassDB::bind_method(D_METHOD("offset_polygon_2d", "polygon", "delta", "join_type"), &_Geometry::offset_polygon_2d, DEFVAL(JOIN_SQUARE)); - ClassDB::bind_method(D_METHOD("offset_polyline_2d", "polyline", "delta", "join_type", "end_type"), &_Geometry::offset_polyline_2d, DEFVAL(JOIN_SQUARE), DEFVAL(END_SQUARE)); - - ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry::make_atlas); + ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry2D::make_atlas); BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE); @@ -1291,17 +1058,140 @@ void _Geometry::_bind_methods() { BIND_ENUM_CONSTANT(END_ROUND); } -_Geometry::_Geometry() { - singleton = this; +////// _Geometry3D ////// + +_Geometry3D *_Geometry3D::singleton = nullptr; + +_Geometry3D *_Geometry3D::get_singleton() { + return singleton; } -///////////////////////// FILE +Vector<Plane> _Geometry3D::build_box_planes(const Vector3 &p_extents) { + return Geometry3D::build_box_planes(p_extents); +} -Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { +Vector<Plane> _Geometry3D::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { + return Geometry3D::build_cylinder_planes(p_radius, p_height, p_sides, p_axis); +} + +Vector<Plane> _Geometry3D::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { + return Geometry3D::build_capsule_planes(p_radius, p_height, p_sides, p_lats, p_axis); +} + +Vector<Vector3> _Geometry3D::get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2) { + Vector3 r1, r2; + Geometry3D::get_closest_points_between_segments(p1, p2, q1, q2, r1, r2); + Vector<Vector3> r; + r.resize(2); + r.set(0, r1); + r.set(1, r2); + return r; +} + +Vector3 _Geometry3D::get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) { + Vector3 s[2] = { p_a, p_b }; + return Geometry3D::get_closest_point_to_segment(p_point, s); +} + +Vector3 _Geometry3D::get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b) { + Vector3 s[2] = { p_a, p_b }; + return Geometry3D::get_closest_point_to_segment_uncapped(p_point, s); +} + +Variant _Geometry3D::ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { + Vector3 res; + if (Geometry3D::ray_intersects_triangle(p_from, p_dir, p_v0, p_v1, p_v2, &res)) { + return res; + } else { + return Variant(); + } +} + +Variant _Geometry3D::segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2) { + Vector3 res; + if (Geometry3D::segment_intersects_triangle(p_from, p_to, p_v0, p_v1, p_v2, &res)) { + return res; + } else { + return Variant(); + } +} + +Vector<Vector3> _Geometry3D::segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius) { + Vector<Vector3> r; + Vector3 res, norm; + if (!Geometry3D::segment_intersects_sphere(p_from, p_to, p_sphere_pos, p_sphere_radius, &res, &norm)) { + return r; + } + + r.resize(2); + r.set(0, res); + r.set(1, norm); + return r; +} + +Vector<Vector3> _Geometry3D::segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius) { + Vector<Vector3> r; + Vector3 res, norm; + if (!Geometry3D::segment_intersects_cylinder(p_from, p_to, p_height, p_radius, &res, &norm)) { + return r; + } + + r.resize(2); + r.set(0, res); + r.set(1, norm); + return r; +} + +Vector<Vector3> _Geometry3D::segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes) { + Vector<Vector3> r; + Vector3 res, norm; + if (!Geometry3D::segment_intersects_convex(p_from, p_to, p_planes.ptr(), p_planes.size(), &res, &norm)) { + return r; + } + + r.resize(2); + r.set(0, res); + r.set(1, norm); + return r; +} + +Vector<Vector3> _Geometry3D::clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane) { + return Geometry3D::clip_polygon(p_points, p_plane); +} + +int _Geometry3D::get_uv84_normal_bit(const Vector3 &p_vector) { + return Geometry3D::get_uv84_normal_bit(p_vector); +} + +void _Geometry3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &_Geometry3D::build_box_planes); + ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &_Geometry3D::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z)); + ClassDB::bind_method(D_METHOD("build_capsule_planes", "radius", "height", "sides", "lats", "axis"), &_Geometry3D::build_capsule_planes, DEFVAL(Vector3::AXIS_Z)); + + ClassDB::bind_method(D_METHOD("get_closest_points_between_segments", "p1", "p2", "q1", "q2"), &_Geometry3D::get_closest_points_between_segments); + ClassDB::bind_method(D_METHOD("get_closest_point_to_segment", "point", "s1", "s2"), &_Geometry3D::get_closest_point_to_segment); + + ClassDB::bind_method(D_METHOD("get_closest_point_to_segment_uncapped", "point", "s1", "s2"), &_Geometry3D::get_closest_point_to_segment_uncapped); + + ClassDB::bind_method(D_METHOD("get_uv84_normal_bit", "normal"), &_Geometry3D::get_uv84_normal_bit); + + ClassDB::bind_method(D_METHOD("ray_intersects_triangle", "from", "dir", "a", "b", "c"), &_Geometry3D::ray_intersects_triangle); + ClassDB::bind_method(D_METHOD("segment_intersects_triangle", "from", "to", "a", "b", "c"), &_Geometry3D::segment_intersects_triangle); + ClassDB::bind_method(D_METHOD("segment_intersects_sphere", "from", "to", "sphere_position", "sphere_radius"), &_Geometry3D::segment_intersects_sphere); + ClassDB::bind_method(D_METHOD("segment_intersects_cylinder", "from", "to", "height", "radius"), &_Geometry3D::segment_intersects_cylinder); + ClassDB::bind_method(D_METHOD("segment_intersects_convex", "from", "to", "planes"), &_Geometry3D::segment_intersects_convex); + + ClassDB::bind_method(D_METHOD("clip_polygon", "points", "plane"), &_Geometry3D::clip_polygon); +} + +////// _File ////// + +Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { Error err = open(p_path, p_mode_flags); - if (err) + if (err) { return err; + } FileAccessEncrypted *fae = memnew(FileAccessEncrypted); err = fae->open_and_parse(f, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ); @@ -1315,10 +1205,10 @@ Error _File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const } Error _File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass) { - Error err = open(p_path, p_mode_flags); - if (err) + if (err) { return err; + } FileAccessEncrypted *fae = memnew(FileAccessEncrypted); err = fae->open_and_parse_password(f, p_pass, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ); @@ -1333,7 +1223,6 @@ Error _File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, c } Error _File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) { - FileAccessCompressed *fac = memnew(FileAccessCompressed); fac->configure("GCPF", (Compression::Mode)p_compress_mode); @@ -1350,110 +1239,104 @@ Error _File::open_compressed(const String &p_path, ModeFlags p_mode_flags, Compr } Error _File::open(const String &p_path, ModeFlags p_mode_flags) { - close(); Error err; f = FileAccess::open(p_path, p_mode_flags, &err); - if (f) + if (f) { f->set_endian_swap(eswap); + } return err; } void _File::close() { - - if (f) + if (f) { memdelete(f); + } f = nullptr; } -bool _File::is_open() const { +bool _File::is_open() const { return f != nullptr; } -String _File::get_path() const { +String _File::get_path() const { ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use."); return f->get_path(); } String _File::get_path_absolute() const { - ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use."); return f->get_path_absolute(); } void _File::seek(int64_t p_position) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->seek(p_position); } -void _File::seek_end(int64_t p_position) { +void _File::seek_end(int64_t p_position) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->seek_end(p_position); } -int64_t _File::get_position() const { +int64_t _File::get_position() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_position(); } int64_t _File::get_len() const { - ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_len(); } bool _File::eof_reached() const { - ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use."); return f->eof_reached(); } uint8_t _File::get_8() const { - ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_8(); } -uint16_t _File::get_16() const { +uint16_t _File::get_16() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_16(); } -uint32_t _File::get_32() const { +uint32_t _File::get_32() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_32(); } -uint64_t _File::get_64() const { +uint64_t _File::get_64() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_64(); } float _File::get_float() const { - ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_float(); } -double _File::get_double() const { +double _File::get_double() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_double(); } -real_t _File::get_real() const { +real_t _File::get_real() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); return f->get_real(); } Vector<uint8_t> _File::get_buffer(int p_length) const { - Vector<uint8_t> data; ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use."); ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0."); - if (p_length == 0) + if (p_length == 0) { return data; + } Error err = data.resize(p_length); ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements."); @@ -1462,14 +1345,14 @@ Vector<uint8_t> _File::get_buffer(int p_length) const { int len = f->get_buffer(&w[0], p_length); ERR_FAIL_COND_V(len < 0, Vector<uint8_t>()); - if (len < p_length) + if (len < p_length) { data.resize(p_length); + } return data; } String _File::get_as_text() const { - ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use."); String text; @@ -1489,17 +1372,14 @@ String _File::get_as_text() const { } String _File::get_md5(const String &p_path) const { - return FileAccess::get_md5(p_path); } String _File::get_sha256(const String &p_path) const { - return FileAccess::get_sha256(p_path); } String _File::get_line() const { - ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use."); return f->get_line(); } @@ -1515,90 +1395,84 @@ Vector<String> _File::get_csv_line(const String &p_delim) const { */ void _File::set_endian_swap(bool p_swap) { - eswap = p_swap; - if (f) + if (f) { f->set_endian_swap(p_swap); + } } -bool _File::get_endian_swap() { +bool _File::get_endian_swap() { return eswap; } Error _File::get_error() const { - - if (!f) + if (!f) { return ERR_UNCONFIGURED; + } return f->get_error(); } void _File::store_8(uint8_t p_dest) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_8(p_dest); } -void _File::store_16(uint16_t p_dest) { +void _File::store_16(uint16_t p_dest) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_16(p_dest); } -void _File::store_32(uint32_t p_dest) { +void _File::store_32(uint32_t p_dest) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_32(p_dest); } -void _File::store_64(uint64_t p_dest) { +void _File::store_64(uint64_t p_dest) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_64(p_dest); } void _File::store_float(float p_dest) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_float(p_dest); } -void _File::store_double(double p_dest) { +void _File::store_double(double p_dest) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_double(p_dest); } -void _File::store_real(real_t p_real) { +void _File::store_real(real_t p_real) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_real(p_real); } void _File::store_string(const String &p_string) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_string(p_string); } void _File::store_pascal_string(const String &p_string) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_pascal_string(p_string); -}; +} String _File::get_pascal_string() { - ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use."); return f->get_pascal_string(); -}; +} void _File::store_line(const String &p_string) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); f->store_line(p_string); } @@ -1609,12 +1483,12 @@ void _File::store_csv_line(const Vector<String> &p_values, const String &p_delim } void _File::store_buffer(const Vector<uint8_t> &p_buffer) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); int len = p_buffer.size(); - if (len == 0) + if (len == 0) { return; + } const uint8_t *r = p_buffer.ptr(); @@ -1622,12 +1496,10 @@ void _File::store_buffer(const Vector<uint8_t> &p_buffer) { } bool _File::file_exists(const String &p_name) const { - return FileAccess::exists(p_name); } void _File::store_var(const Variant &p_var, bool p_full_objects) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); int len; Error err = encode_variant(p_var, nullptr, len, p_full_objects); @@ -1645,7 +1517,6 @@ void _File::store_var(const Variant &p_var, bool p_full_objects) { } Variant _File::get_var(bool p_allow_objects) const { - ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use."); uint32_t len = get_32(); Vector<uint8_t> buff = get_buffer(len); @@ -1661,12 +1532,10 @@ Variant _File::get_var(bool p_allow_objects) const { } uint64_t _File::get_modified_time(const String &p_file) const { - return FileAccess::get_modified_time(p_file); } void _File::_bind_methods() { - ClassDB::bind_method(D_METHOD("open_encrypted", "path", "mode_flags", "key"), &_File::open_encrypted); ClassDB::bind_method(D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &_File::open_encrypted_pass); ClassDB::bind_method(D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &_File::open_compressed, DEFVAL(0)); @@ -1731,35 +1600,30 @@ void _File::_bind_methods() { BIND_ENUM_CONSTANT(COMPRESSION_GZIP); } -_File::_File() { - - f = nullptr; - eswap = false; -} - _File::~_File() { - - if (f) + if (f) { memdelete(f); + } } -/////////////////////////////////////////////////////// +////// _Directory ////// Error _Directory::open(const String &p_path) { Error err; DirAccess *alt = DirAccess::open(p_path, &err); - if (!alt) + if (!alt) { return err; - if (d) + } + if (d) { memdelete(d); + } d = alt; return OK; } Error _Directory::list_dir_begin(bool p_skip_navigational, bool p_skip_hidden) { - ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); _list_skip_navigational = p_skip_navigational; @@ -1769,55 +1633,51 @@ Error _Directory::list_dir_begin(bool p_skip_navigational, bool p_skip_hidden) { } String _Directory::get_next() { - ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use."); String next = d->get_next(); while (next != "" && ((_list_skip_navigational && (next == "." || next == "..")) || (_list_skip_hidden && d->current_is_hidden()))) { - next = d->get_next(); } return next; } -bool _Directory::current_is_dir() const { +bool _Directory::current_is_dir() const { ERR_FAIL_COND_V_MSG(!d, false, "Directory must be opened before use."); return d->current_is_dir(); } void _Directory::list_dir_end() { - ERR_FAIL_COND_MSG(!d, "Directory must be opened before use."); d->list_dir_end(); } int _Directory::get_drive_count() { - ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use."); return d->get_drive_count(); } -String _Directory::get_drive(int p_drive) { +String _Directory::get_drive(int p_drive) { ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use."); return d->get_drive(p_drive); } + int _Directory::get_current_drive() { ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use."); return d->get_current_drive(); } Error _Directory::change_dir(String p_dir) { - ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); return d->change_dir(p_dir); } -String _Directory::get_current_dir() { +String _Directory::get_current_dir() { ERR_FAIL_COND_V_MSG(!d, "", "Directory must be opened before use."); return d->get_current_dir(); } -Error _Directory::make_dir(String p_dir) { +Error _Directory::make_dir(String p_dir) { ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); if (!p_dir.is_rel_path()) { DirAccess *d = DirAccess::create_for_path(p_dir); @@ -1827,8 +1687,8 @@ Error _Directory::make_dir(String p_dir) { } return d->make_dir(p_dir); } -Error _Directory::make_dir_recursive(String p_dir) { +Error _Directory::make_dir_recursive(String p_dir) { ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); if (!p_dir.is_rel_path()) { DirAccess *d = DirAccess::create_for_path(p_dir); @@ -1840,7 +1700,6 @@ Error _Directory::make_dir_recursive(String p_dir) { } bool _Directory::file_exists(String p_file) { - ERR_FAIL_COND_V_MSG(!d, false, "Directory must be opened before use."); if (!p_file.is_rel_path()) { @@ -1853,7 +1712,6 @@ bool _Directory::file_exists(String p_file) { bool _Directory::dir_exists(String p_dir) { ERR_FAIL_COND_V_MSG(!d, false, "Directory must be opened before use."); if (!p_dir.is_rel_path()) { - DirAccess *d = DirAccess::create_for_path(p_dir); bool exists = d->dir_exists(p_dir); memdelete(d); @@ -1865,18 +1723,16 @@ bool _Directory::dir_exists(String p_dir) { } int _Directory::get_space_left() { - ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use."); return d->get_space_left() / 1024 * 1024; //return value in megabytes, given binding is int } Error _Directory::copy(String p_from, String p_to) { - ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); return d->copy(p_from, p_to); } -Error _Directory::rename(String p_from, String p_to) { +Error _Directory::rename(String p_from, String p_to) { ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); if (!p_from.is_rel_path()) { DirAccess *d = DirAccess::create_for_path(p_from); @@ -1887,8 +1743,8 @@ Error _Directory::rename(String p_from, String p_to) { return d->rename(p_from, p_to); } -Error _Directory::remove(String p_name) { +Error _Directory::remove(String p_name) { ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory must be opened before use."); if (!p_name.is_rel_path()) { DirAccess *d = DirAccess::create_for_path(p_name); @@ -1901,7 +1757,6 @@ Error _Directory::remove(String p_name) { } void _Directory::_bind_methods() { - ClassDB::bind_method(D_METHOD("open", "path"), &_Directory::open); ClassDB::bind_method(D_METHOD("list_dir_begin", "skip_navigational", "skip_hidden"), &_Directory::list_dir_begin, DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_next"), &_Directory::get_next); @@ -1924,16 +1779,17 @@ void _Directory::_bind_methods() { } _Directory::_Directory() { - d = DirAccess::create(DirAccess::ACCESS_RESOURCES); } _Directory::~_Directory() { - - if (d) + if (d) { memdelete(d); + } } +////// _Marshalls ////// + _Marshalls *_Marshalls::singleton = nullptr; _Marshalls *_Marshalls::get_singleton() { @@ -1941,7 +1797,6 @@ _Marshalls *_Marshalls::get_singleton() { } String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) { - int len; Error err = encode_variant(p_var, nullptr, len, p_full_objects); ERR_FAIL_COND_V_MSG(err != OK, "", "Error when trying to encode Variant."); @@ -1957,10 +1812,9 @@ String _Marshalls::variant_to_base64(const Variant &p_var, bool p_full_objects) ERR_FAIL_COND_V(ret == "", ret); return ret; -}; +} Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) { - int strlen = p_str.length(); CharString cstr = p_str.ascii(); @@ -1976,17 +1830,15 @@ Variant _Marshalls::base64_to_variant(const String &p_str, bool p_allow_objects) ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant."); return v; -}; +} String _Marshalls::raw_to_base64(const Vector<uint8_t> &p_arr) { - String ret = CryptoCore::b64_encode_str(p_arr.ptr(), p_arr.size()); ERR_FAIL_COND_V(ret == "", ret); return ret; -}; +} Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) { - int strlen = p_str.length(); CharString cstr = p_str.ascii(); @@ -2001,18 +1853,16 @@ Vector<uint8_t> _Marshalls::base64_to_raw(const String &p_str) { buf.resize(arr_len); return buf; -}; +} String _Marshalls::utf8_to_base64(const String &p_str) { - CharString cstr = p_str.utf8(); String ret = CryptoCore::b64_encode_str((unsigned char *)cstr.get_data(), cstr.length()); ERR_FAIL_COND_V(ret == "", ret); return ret; -}; +} String _Marshalls::base64_to_utf8(const String &p_str) { - int strlen = p_str.length(); CharString cstr = p_str.ascii(); @@ -2027,10 +1877,9 @@ String _Marshalls::base64_to_utf8(const String &p_str) { String ret = String::utf8((char *)&w[0]); return ret; -}; +} void _Marshalls::_bind_methods() { - ClassDB::bind_method(D_METHOD("variant_to_base64", "variant", "full_objects"), &_Marshalls::variant_to_base64, DEFVAL(false)); ClassDB::bind_method(D_METHOD("base64_to_variant", "base64_str", "allow_objects"), &_Marshalls::base64_to_variant, DEFVAL(false)); @@ -2039,60 +1888,51 @@ void _Marshalls::_bind_methods() { ClassDB::bind_method(D_METHOD("utf8_to_base64", "utf8_str"), &_Marshalls::utf8_to_base64); ClassDB::bind_method(D_METHOD("base64_to_utf8", "base64_str"), &_Marshalls::base64_to_utf8); -}; +} -//////////////// +////// _Semaphore ////// void _Semaphore::wait() { - semaphore.wait(); } Error _Semaphore::try_wait() { - return semaphore.try_wait() ? OK : ERR_BUSY; } void _Semaphore::post() { - semaphore.post(); } void _Semaphore::_bind_methods() { - ClassDB::bind_method(D_METHOD("wait"), &_Semaphore::wait); ClassDB::bind_method(D_METHOD("try_wait"), &_Semaphore::try_wait); ClassDB::bind_method(D_METHOD("post"), &_Semaphore::post); } -/////////////// +////// _Mutex ////// void _Mutex::lock() { - mutex.lock(); } Error _Mutex::try_lock() { - return mutex.try_lock(); } void _Mutex::unlock() { - mutex.unlock(); } void _Mutex::_bind_methods() { - ClassDB::bind_method(D_METHOD("lock"), &_Mutex::lock); ClassDB::bind_method(D_METHOD("try_lock"), &_Mutex::try_lock); ClassDB::bind_method(D_METHOD("unlock"), &_Mutex::unlock); } -/////////////// +////// _Thread ////// void _Thread::_start_func(void *ud) { - Ref<_Thread> *tud = (Ref<_Thread> *)ud; Ref<_Thread> t = *tud; memdelete(tud); @@ -2103,23 +1943,18 @@ void _Thread::_start_func(void *ud) { t->ret = t->target_instance->call(t->target_method, arg, 1, ce); if (ce.error != Callable::CallError::CALL_OK) { - String reason; switch (ce.error) { case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { - reason = "Invalid Argument #" + itos(ce.argument); } break; case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { - reason = "Too Many Arguments"; } break; case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: { - reason = "Too Few Arguments"; } break; case Callable::CallError::CALL_ERROR_INVALID_METHOD: { - reason = "Method Not Found"; } break; default: { @@ -2131,7 +1966,6 @@ void _Thread::_start_func(void *ud) { } Error _Thread::start(Object *p_instance, const StringName &p_method, const Variant &p_userdata, Priority p_priority) { - ERR_FAIL_COND_V_MSG(active, ERR_ALREADY_IN_USE, "Thread already started."); ERR_FAIL_COND_V(!p_instance, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_method == StringName(), ERR_INVALID_PARAMETER); @@ -2160,19 +1994,18 @@ Error _Thread::start(Object *p_instance, const StringName &p_method, const Varia } String _Thread::get_id() const { - - if (!thread) + if (!thread) { return String(); + } return itos(thread->get_id()); } bool _Thread::is_active() const { - return active; } -Variant _Thread::wait_to_finish() { +Variant _Thread::wait_to_finish() { ERR_FAIL_COND_V_MSG(!thread, Variant(), "Thread must exist to wait for its completion."); ERR_FAIL_COND_V_MSG(!active, Variant(), "Thread must be active to wait for its completion."); Thread::wait_to_finish(thread); @@ -2181,15 +2014,15 @@ Variant _Thread::wait_to_finish() { target_method = StringName(); target_instance = nullptr; userdata = Variant(); - if (thread) + if (thread) { memdelete(thread); + } thread = nullptr; return r; } void _Thread::_bind_methods() { - ClassDB::bind_method(D_METHOD("start", "instance", "method", "userdata", "priority"), &_Thread::start, DEFVAL(Variant()), DEFVAL(PRIORITY_NORMAL)); ClassDB::bind_method(D_METHOD("get_id"), &_Thread::get_id); ClassDB::bind_method(D_METHOD("is_active"), &_Thread::is_active); @@ -2199,22 +2032,14 @@ void _Thread::_bind_methods() { BIND_ENUM_CONSTANT(PRIORITY_NORMAL); BIND_ENUM_CONSTANT(PRIORITY_HIGH); } -_Thread::_Thread() { - - active = false; - thread = nullptr; - target_instance = nullptr; -} _Thread::~_Thread() { - ERR_FAIL_COND_MSG(active, "Reference to a Thread object was lost while the thread is still running..."); } -///////////////////////////////////// +////// _ClassDB ////// PackedStringArray _ClassDB::get_class_list() const { - List<StringName> classes; ClassDB::get_class_list(&classes); @@ -2227,8 +2052,8 @@ PackedStringArray _ClassDB::get_class_list() const { return ret; } -PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class) const { +PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class) const { List<StringName> classes; ClassDB::get_inheriters_from_class(p_class, &classes); @@ -2241,27 +2066,28 @@ PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class) return ret; } -StringName _ClassDB::get_parent_class(const StringName &p_class) const { +StringName _ClassDB::get_parent_class(const StringName &p_class) const { return ClassDB::get_parent_class(p_class); } -bool _ClassDB::class_exists(const StringName &p_class) const { +bool _ClassDB::class_exists(const StringName &p_class) const { return ClassDB::class_exists(p_class); } -bool _ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) const { +bool _ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) const { return ClassDB::is_parent_class(p_class, p_inherits); } -bool _ClassDB::can_instance(const StringName &p_class) const { +bool _ClassDB::can_instance(const StringName &p_class) const { return ClassDB::can_instance(p_class); } -Variant _ClassDB::instance(const StringName &p_class) const { +Variant _ClassDB::instance(const StringName &p_class) const { Object *obj = ClassDB::instance(p_class); - if (!obj) + if (!obj) { return Variant(); + } Reference *r = Object::cast_to<Reference>(obj); if (r) { @@ -2272,11 +2098,10 @@ Variant _ClassDB::instance(const StringName &p_class) const { } bool _ClassDB::has_signal(StringName p_class, StringName p_signal) const { - return ClassDB::has_signal(p_class, p_signal); } -Dictionary _ClassDB::get_signal(StringName p_class, StringName p_signal) const { +Dictionary _ClassDB::get_signal(StringName p_class, StringName p_signal) const { MethodInfo signal; if (ClassDB::get_signal(p_class, p_signal, &signal)) { return signal.operator Dictionary(); @@ -2284,8 +2109,8 @@ Dictionary _ClassDB::get_signal(StringName p_class, StringName p_signal) const { return Dictionary(); } } -Array _ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const { +Array _ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const { List<MethodInfo> signals; ClassDB::get_signal_list(p_class, &signals, p_no_inheritance); Array ret; @@ -2298,7 +2123,6 @@ Array _ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const } Array _ClassDB::get_property_list(StringName p_class, bool p_no_inheritance) const { - List<PropertyInfo> plist; ClassDB::get_property_list(p_class, &plist, p_no_inheritance); Array ret; @@ -2327,12 +2151,10 @@ Error _ClassDB::set_property(Object *p_object, const StringName &p_property, con } bool _ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inheritance) const { - return ClassDB::has_method(p_class, p_method, p_no_inheritance); } Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const { - List<MethodInfo> methods; ClassDB::get_method_list(p_class, &methods, p_no_inheritance); Array ret; @@ -2351,7 +2173,6 @@ Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const } PackedStringArray _ClassDB::get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const { - List<String> constants; ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance); @@ -2366,31 +2187,27 @@ PackedStringArray _ClassDB::get_integer_constant_list(const StringName &p_class, } bool _ClassDB::has_integer_constant(const StringName &p_class, const StringName &p_name) const { - bool success; ClassDB::get_integer_constant(p_class, p_name, &success); return success; } int _ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name) const { - bool found; int c = ClassDB::get_integer_constant(p_class, p_name, &found); ERR_FAIL_COND_V(!found, 0); return c; } -StringName _ClassDB::get_category(const StringName &p_node) const { +StringName _ClassDB::get_category(const StringName &p_node) const { return ClassDB::get_category(p_node); } bool _ClassDB::is_class_enabled(StringName p_class) const { - return ClassDB::is_class_enabled(p_class); } void _ClassDB::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_class_list"), &_ClassDB::get_class_list); ClassDB::bind_method(D_METHOD("get_inheriters_from_class", "class"), &_ClassDB::get_inheriters_from_class); ClassDB::bind_method(D_METHOD("get_parent_class", "class"), &_ClassDB::get_parent_class); @@ -2420,18 +2237,13 @@ void _ClassDB::_bind_methods() { ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &_ClassDB::is_class_enabled); } -_ClassDB::_ClassDB() { -} -_ClassDB::~_ClassDB() { -} -/////////////////////////////// +////// _Engine ////// void _Engine::set_iterations_per_second(int p_ips) { - Engine::get_singleton()->set_iterations_per_second(p_ips); } -int _Engine::get_iterations_per_second() const { +int _Engine::get_iterations_per_second() const { return Engine::get_singleton()->get_iterations_per_second(); } @@ -2456,17 +2268,14 @@ int _Engine::get_target_fps() const { } float _Engine::get_frames_per_second() const { - return Engine::get_singleton()->get_frames_per_second(); } uint64_t _Engine::get_physics_frames() const { - return Engine::get_singleton()->get_physics_frames(); } uint64_t _Engine::get_idle_frames() const { - return Engine::get_singleton()->get_idle_frames(); } @@ -2475,23 +2284,19 @@ void _Engine::set_time_scale(float p_scale) { } float _Engine::get_time_scale() { - return Engine::get_singleton()->get_time_scale(); } int _Engine::get_frames_drawn() { - return Engine::get_singleton()->get_frames_drawn(); } MainLoop *_Engine::get_main_loop() const { - //needs to remain in OS, since it's actually OS that interacts with it, but it's better exposed here return OS::get_singleton()->get_main_loop(); } Dictionary _Engine::get_version_info() const { - return Engine::get_singleton()->get_version_info(); } @@ -2520,27 +2325,22 @@ bool _Engine::is_in_physics_frame() const { } bool _Engine::has_singleton(const String &p_name) const { - return Engine::get_singleton()->has_singleton(p_name); } Object *_Engine::get_singleton_object(const String &p_name) const { - return Engine::get_singleton()->get_singleton_object(p_name); } void _Engine::set_editor_hint(bool p_enabled) { - Engine::get_singleton()->set_editor_hint(p_enabled); } bool _Engine::is_editor_hint() const { - return Engine::get_singleton()->is_editor_hint(); } void _Engine::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_iterations_per_second", "iterations_per_second"), &_Engine::set_iterations_per_second); ClassDB::bind_method(D_METHOD("get_iterations_per_second"), &_Engine::get_iterations_per_second); ClassDB::bind_method(D_METHOD("set_physics_jitter_fix", "physics_jitter_fix"), &_Engine::set_physics_jitter_fix); @@ -2583,9 +2383,7 @@ void _Engine::_bind_methods() { _Engine *_Engine::singleton = nullptr; -_Engine::_Engine() { - singleton = this; -} +////// _JSON ////// void JSONParseResult::_bind_methods() { ClassDB::bind_method(D_METHOD("get_error"), &JSONParseResult::get_error); @@ -2658,7 +2456,3 @@ Ref<JSONParseResult> _JSON::parse(const String &p_json) { } _JSON *_JSON::singleton = nullptr; - -_JSON::_JSON() { - singleton = this; -} diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index d5f44cdc44..f9f5a4e7d7 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -69,7 +69,7 @@ public: bool has_cached(const String &p_path); bool exists(const String &p_path, const String &p_type_hint = ""); - _ResourceLoader(); + _ResourceLoader() { singleton = this; } }; VARIANT_ENUM_CAST(_ResourceLoader::ThreadLoadStatus); @@ -98,7 +98,7 @@ public: Error save(const String &p_path, const RES &p_resource, SaverFlags p_flags); Vector<String> get_recognized_extensions(const RES &p_resource); - _ResourceSaver(); + _ResourceSaver() { singleton = this; } }; VARIANT_ENUM_CAST(_ResourceSaver::SaverFlags); @@ -199,9 +199,7 @@ public: Dictionary get_datetime_from_unix_time(int64_t unix_time_val) const; int64_t get_unix_time_from_datetime(Dictionary datetime) const; Dictionary get_time_zone_info() const; - uint64_t get_unix_time() const; - uint64_t get_system_time_secs() const; - uint64_t get_system_time_msecs() const; + double get_unix_time() const; uint64_t get_static_memory_usage() const; uint64_t get_static_memory_peak_usage() const; @@ -243,9 +241,14 @@ public: bool request_permissions(); Vector<String> get_granted_permissions() const; + int get_tablet_driver_count() const; + String get_tablet_driver_name(int p_driver) const; + String get_current_tablet_driver() const; + void set_current_tablet_driver(const String &p_driver); + static _OS *get_singleton() { return singleton; } - _OS(); + _OS() { singleton = this; } }; VARIANT_ENUM_CAST(_OS::VideoDriver); @@ -253,45 +256,31 @@ VARIANT_ENUM_CAST(_OS::Weekday); VARIANT_ENUM_CAST(_OS::Month); VARIANT_ENUM_CAST(_OS::SystemDir); -class _Geometry : public Object { - - GDCLASS(_Geometry, Object); +class _Geometry2D : public Object { + GDCLASS(_Geometry2D, Object); - static _Geometry *singleton; + static _Geometry2D *singleton; protected: static void _bind_methods(); public: - static _Geometry *get_singleton(); - Vector<Plane> build_box_planes(const Vector3 &p_extents); - Vector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); - Vector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); - Variant segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b); - Variant line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b); - Vector<Vector2> get_closest_points_between_segments_2d(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2); - Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2); - Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b); - Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); - Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b); - Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); - Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); - Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); + static _Geometry2D *get_singleton(); + Variant segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b); + Variant line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b); + Vector<Vector2> get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2); + Vector2 get_closest_point_to_segment(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b); + Vector2 get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 &p_a, const Vector2 &p_b); bool point_is_inside_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) const; - Vector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius); - Vector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius); - Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes); bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius); real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius); - int get_uv84_normal_bit(const Vector3 &p_vector); bool is_polygon_clockwise(const Vector<Vector2> &p_polygon); bool is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon); Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon); - Vector<int> triangulate_delaunay_2d(const Vector<Vector2> &p_points); - Vector<Point2> convex_hull_2d(const Vector<Point2> &p_points); - Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane); + Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points); + Vector<Point2> convex_hull(const Vector<Point2> &p_points); enum PolyBooleanOperation { OPERATION_UNION, @@ -300,14 +289,14 @@ public: OPERATION_XOR }; // 2D polygon boolean operations. - Array merge_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Union (add). - Array clip_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Difference (subtract). - Array intersect_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Common area (multiply). - Array exclude_polygons_2d(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // All but common area (xor). + Array merge_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Union (add). + Array clip_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Difference (subtract). + Array intersect_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // Common area (multiply). + Array exclude_polygons(const Vector<Vector2> &p_polygon_a, const Vector<Vector2> &p_polygon_b); // All but common area (xor). // 2D polyline vs polygon operations. - Array clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Cut. - Array intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Chop. + Array clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Cut. + Array intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon); // Chop. // 2D offset polygons/polylines. enum PolyJoinType { @@ -322,23 +311,52 @@ public: END_SQUARE, END_ROUND }; - Array offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE); - Array offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE, PolyEndType p_end_type = END_SQUARE); + Array offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE); + Array offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type = JOIN_SQUARE, PolyEndType p_end_type = END_SQUARE); Dictionary make_atlas(const Vector<Size2> &p_rects); - _Geometry(); + _Geometry2D() { singleton = this; } }; -VARIANT_ENUM_CAST(_Geometry::PolyBooleanOperation); -VARIANT_ENUM_CAST(_Geometry::PolyJoinType); -VARIANT_ENUM_CAST(_Geometry::PolyEndType); +VARIANT_ENUM_CAST(_Geometry2D::PolyBooleanOperation); +VARIANT_ENUM_CAST(_Geometry2D::PolyJoinType); +VARIANT_ENUM_CAST(_Geometry2D::PolyEndType); -class _File : public Reference { +class _Geometry3D : public Object { + GDCLASS(_Geometry3D, Object); + + static _Geometry3D *singleton; + +protected: + static void _bind_methods(); +public: + static _Geometry3D *get_singleton(); + Vector<Plane> build_box_planes(const Vector3 &p_extents); + Vector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); + Vector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); + Vector<Vector3> get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2); + Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); + Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 &p_a, const Vector3 &p_b); + Variant ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); + Variant segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2); + + Vector<Vector3> segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius); + Vector<Vector3> segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, float p_height, float p_radius); + Vector<Vector3> segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Vector<Plane> &p_planes); + int get_uv84_normal_bit(const Vector3 &p_vector); + + Vector<Vector3> clip_polygon(const Vector<Vector3> &p_points, const Plane &p_plane); + + _Geometry3D() { singleton = this; } +}; + +class _File : public Reference { GDCLASS(_File, Reference); - FileAccess *f; - bool eswap; + + FileAccess *f = nullptr; + bool eswap = false; protected: static void _bind_methods(); @@ -429,7 +447,7 @@ public: uint64_t get_modified_time(const String &p_file) const; - _File(); + _File() {} virtual ~_File(); }; @@ -437,7 +455,6 @@ VARIANT_ENUM_CAST(_File::ModeFlags); VARIANT_ENUM_CAST(_File::CompressionMode); class _Directory : public Reference { - GDCLASS(_Directory, Reference); DirAccess *d; @@ -481,7 +498,6 @@ private: }; class _Marshalls : public Object { - GDCLASS(_Marshalls, Object); static _Marshalls *singleton; @@ -506,7 +522,6 @@ public: }; class _Mutex : public Reference { - GDCLASS(_Mutex, Reference); Mutex mutex; @@ -519,7 +534,6 @@ public: }; class _Semaphore : public Reference { - GDCLASS(_Semaphore, Reference); Semaphore semaphore; @@ -532,16 +546,15 @@ public: }; class _Thread : public Reference { - GDCLASS(_Thread, Reference); protected: Variant ret; Variant userdata; - volatile bool active; - Object *target_instance; + volatile bool active = false; + Object *target_instance = nullptr; StringName target_method; - Thread *thread; + Thread *thread = nullptr; static void _bind_methods(); static void _start_func(void *ud); @@ -559,14 +572,13 @@ public: bool is_active() const; Variant wait_to_finish(); - _Thread(); + _Thread() {} ~_Thread(); }; VARIANT_ENUM_CAST(_Thread::Priority); class _ClassDB : public Object { - GDCLASS(_ClassDB, Object); protected: @@ -600,8 +612,8 @@ public: bool is_class_enabled(StringName p_class) const; - _ClassDB(); - ~_ClassDB(); + _ClassDB() {} + ~_ClassDB() {} }; class _Engine : public Object { @@ -649,7 +661,7 @@ public: void set_editor_hint(bool p_enabled); bool is_editor_hint() const; - _Engine(); + _Engine() { singleton = this; } }; class _JSON; @@ -661,7 +673,7 @@ class JSONParseResult : public Reference { Error error; String error_string; - int error_line; + int error_line = -1; Variant result; @@ -681,8 +693,7 @@ public: void set_result(const Variant &p_result); Variant get_result() const; - JSONParseResult() : - error_line(-1) {} + JSONParseResult() {} }; class _JSON : public Object { @@ -698,7 +709,7 @@ public: String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false); Ref<JSONParseResult> parse(const String &p_json); - _JSON(); + _JSON() { singleton = this; } }; #endif // CORE_BIND_H diff --git a/core/callable.cpp b/core/callable.cpp index 6a5dc151e5..b7bdc715f8 100644 --- a/core/callable.cpp +++ b/core/callable.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "callable.h" + #include "core/script_language.h" #include "message_queue.h" #include "object.h" @@ -39,7 +40,6 @@ void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const } void Callable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const { - if (is_null()) { r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; r_call_error.argument = 0; @@ -72,6 +72,7 @@ ObjectID Callable::get_object_id() const { return ObjectID(object); } } + StringName Callable::get_method() const { ERR_FAIL_COND_V_MSG(is_custom(), StringName(), vformat("Can't get method on CallableCustom \"%s\".", operator String())); @@ -117,9 +118,11 @@ bool Callable::operator==(const Callable &p_callable) const { return false; } } + bool Callable::operator!=(const Callable &p_callable) const { return !(*this == p_callable); } + bool Callable::operator<(const Callable &p_callable) const { bool custom_a = is_custom(); bool custom_b = p_callable.is_custom(); @@ -178,7 +181,6 @@ void Callable::operator=(const Callable &p_callable) { } Callable::operator String() const { - if (is_custom()) { return custom->get_as_text(); } else { @@ -191,7 +193,6 @@ Callable::operator String() const { String class_name = base->get_class(); Ref<Script> script = base->get_script(); if (script.is_valid() && script->get_path().is_resource_file()) { - class_name += "(" + script->get_path().get_file() + ")"; } return class_name + "::" + String(method); @@ -224,6 +225,7 @@ Callable::Callable(ObjectID p_object, const StringName &p_method) { object = p_object; method = p_method; } + Callable::Callable(CallableCustom *p_custom) { if (p_custom->referenced) { object = 0; @@ -233,6 +235,7 @@ Callable::Callable(CallableCustom *p_custom) { object = 0; //ensure object is all zero, since pointer may be 32 bits custom = p_custom; } + Callable::Callable(const Callable &p_callable) { if (p_callable.is_custom()) { if (!p_callable.custom->ref_count.ref()) { @@ -255,12 +258,7 @@ Callable::~Callable() { } } -Callable::Callable() { - object = 0; -} - CallableCustom::CallableCustom() { - referenced = false; ref_count.init(); } @@ -269,9 +267,11 @@ CallableCustom::CallableCustom() { Object *Signal::get_object() const { return ObjectDB::get_instance(object); } + ObjectID Signal::get_object_id() const { return object; } + StringName Signal::get_name() const { return name; } @@ -298,7 +298,6 @@ Signal::operator String() const { String class_name = base->get_class(); Ref<Script> script = base->get_script(); if (script.is_valid() && script->get_path().is_resource_file()) { - class_name += "(" + script->get_path().get_file() + ")"; } return class_name + "::[signal]" + String(name); @@ -315,18 +314,20 @@ Error Signal::emit(const Variant **p_arguments, int p_argcount) const { return obj->emit_signal(name, p_arguments, p_argcount); } -Error Signal::connect(const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) { +Error Signal::connect(const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) { Object *object = get_object(); ERR_FAIL_COND_V(!object, ERR_UNCONFIGURED); return object->connect(name, p_callable, p_binds, p_flags); } + void Signal::disconnect(const Callable &p_callable) { Object *object = get_object(); ERR_FAIL_COND(!object); object->disconnect(name, p_callable); } + bool Signal::is_connected(const Callable &p_callable) const { Object *object = get_object(); ERR_FAIL_COND_V(!object, false); @@ -349,17 +350,15 @@ Array Signal::get_connections() const { } return arr; } -Signal::Signal(const Object *p_object, const StringName &p_name) { +Signal::Signal(const Object *p_object, const StringName &p_name) { ERR_FAIL_COND_MSG(p_object == nullptr, "Object argument to Signal constructor must be non-null"); object = p_object->get_instance_id(); name = p_name; } -Signal::Signal(ObjectID p_object, const StringName &p_name) { +Signal::Signal(ObjectID p_object, const StringName &p_name) { object = p_object; name = p_name; } -Signal::Signal() { -} diff --git a/core/callable.h b/core/callable.h index 7fa024dccd..7fd6b54cf7 100644 --- a/core/callable.h +++ b/core/callable.h @@ -45,11 +45,10 @@ class CallableCustom; // but can be optimized or customized. class Callable { - //needs to be max 16 bytes in 64 bits StringName method; union { - uint64_t object; + uint64_t object = 0; CallableCustom *custom; }; @@ -75,7 +74,7 @@ public: return method == StringName() && object == 0; } _FORCE_INLINE_ bool is_custom() const { - return method == StringName() && custom != 0; + return method == StringName() && custom != nullptr; } _FORCE_INLINE_ bool is_standard() const { return method != StringName(); @@ -100,14 +99,14 @@ public: Callable(ObjectID p_object, const StringName &p_method); Callable(CallableCustom *p_custom); Callable(const Callable &p_callable); - Callable(); + Callable() {} ~Callable(); }; class CallableCustom { friend class Callable; SafeRefCount ref_count; - bool referenced; + bool referenced = false; public: typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b); @@ -156,7 +155,7 @@ public: Array get_connections() const; Signal(const Object *p_object, const StringName &p_name); Signal(ObjectID p_object, const StringName &p_name); - Signal(); + Signal() {} }; #endif // CALLABLE_H diff --git a/core/callable_method_pointer.cpp b/core/callable_method_pointer.cpp index 8774af6add..21a917cbd7 100644 --- a/core/callable_method_pointer.cpp +++ b/core/callable_method_pointer.cpp @@ -48,7 +48,6 @@ bool CallableCustomMethodPointerBase::compare_equal(const CallableCustom *p_a, c } bool CallableCustomMethodPointerBase::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) { - const CallableCustomMethodPointerBase *a = static_cast<const CallableCustomMethodPointerBase *>(p_a); const CallableCustomMethodPointerBase *b = static_cast<const CallableCustomMethodPointerBase *>(p_b); diff --git a/core/callable_method_pointer.h b/core/callable_method_pointer.h index fb809c2b44..22db7d1c82 100644 --- a/core/callable_method_pointer.h +++ b/core/callable_method_pointer.h @@ -38,7 +38,6 @@ #include "core/simple_type.h" class CallableCustomMethodPointerBase : public CallableCustom { - uint32_t *comp_ptr; uint32_t comp_size; uint32_t h; @@ -74,7 +73,6 @@ public: template <class T> struct VariantCasterAndValidate { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { @@ -89,7 +87,6 @@ struct VariantCasterAndValidate { template <class T> struct VariantCasterAndValidate<T &> { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { @@ -104,7 +101,6 @@ struct VariantCasterAndValidate<T &> { template <class T> struct VariantCasterAndValidate<const T &> { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { @@ -163,23 +159,37 @@ void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Vari template <class T, class... P> class CallableCustomMethodPointer : public CallableCustomMethodPointerBase { - struct Data { T *instance; +#ifdef DEBUG_ENABLED + uint64_t object_id; +#endif void (T::*method)(P...); } data; public: - virtual ObjectID get_object() const { return data.instance->get_instance_id(); } + virtual ObjectID get_object() const { +#ifdef DEBUG_ENABLED + if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) { + return ObjectID(); + } +#endif + return data.instance->get_instance_id(); + } virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { - +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); +#endif call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error); } CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) { zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes. data.instance = p_instance; +#ifdef DEBUG_ENABLED + data.object_id = p_instance->get_instance_id(); +#endif data.method = p_method; _setup((uint32_t *)&data, sizeof(Data)); } @@ -246,24 +256,38 @@ void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Var template <class T, class R, class... P> class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { - struct Data { T *instance; +#ifdef DEBUG_ENABLED + uint64_t object_id; +#endif R(T::*method) (P...); } data; public: - virtual ObjectID get_object() const { return data.instance->get_instance_id(); } + virtual ObjectID get_object() const { +#ifdef DEBUG_ENABLED + if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) { + return ObjectID(); + } +#endif + return data.instance->get_instance_id(); + } virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { - +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); +#endif call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); } CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) { zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes. data.instance = p_instance; +#ifdef DEBUG_ENABLED + data.object_id = p_instance->get_instance_id(); +#endif data.method = p_method; _setup((uint32_t *)&data, sizeof(Data)); } diff --git a/core/class_db.cpp b/core/class_db.cpp index 5e49688e9b..05c9850c39 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -40,14 +40,12 @@ #ifdef DEBUG_METHODS_ENABLED MethodDefinition D_METHOD(const char *p_name) { - MethodDefinition md; md.name = StaticCString::create(p_name); return md; } MethodDefinition D_METHOD(const char *p_name, const char *p_arg1) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.push_back(StaticCString::create(p_arg1)); @@ -55,7 +53,6 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1) { } MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_arg2) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(2); @@ -65,7 +62,6 @@ 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) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(3); @@ -76,7 +72,6 @@ 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) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(4); @@ -88,7 +83,6 @@ 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) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(5); @@ -101,7 +95,6 @@ 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) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(6); @@ -115,7 +108,6 @@ 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) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(7); @@ -130,7 +122,6 @@ 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 md; md.name = StaticCString::create(p_name); md.args.resize(8); @@ -146,7 +137,6 @@ 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, const char *p_arg9) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(9); @@ -163,7 +153,6 @@ 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, const char *p_arg9, const char *p_arg10) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(10); @@ -181,7 +170,6 @@ 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, const char *p_arg9, const char *p_arg10, const char *p_arg11) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(11); @@ -200,7 +188,6 @@ 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, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(12); @@ -220,7 +207,6 @@ 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, const char *p_arg9, const char *p_arg10, const char *p_arg11, const char *p_arg12, const char *p_arg13) { - MethodDefinition md; md.name = StaticCString::create(p_name); md.args.resize(13); @@ -245,12 +231,10 @@ MethodDefinition D_METHOD(const char *p_name, const char *p_arg1, const char *p_ ClassDB::APIType ClassDB::current_api = API_CORE; void ClassDB::set_current_api(APIType p_api) { - current_api = p_api; } ClassDB::APIType ClassDB::get_current_api() { - return current_api; } @@ -258,42 +242,27 @@ HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes; HashMap<StringName, StringName> ClassDB::resource_base_extensions; HashMap<StringName, StringName> ClassDB::compat_classes; -ClassDB::ClassInfo::ClassInfo() { - - api = API_NONE; - class_ptr = nullptr; - creation_func = nullptr; - inherits_ptr = nullptr; - disabled = false; - exposed = false; -} - -ClassDB::ClassInfo::~ClassInfo() { -} - bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { - OBJTYPE_RLOCK; StringName inherits = p_class; while (inherits.operator String().length()) { - - if (inherits == p_inherits) + if (inherits == p_inherits) { return true; + } inherits = get_parent_class(inherits); } return false; } -void ClassDB::get_class_list(List<StringName> *p_classes) { +void ClassDB::get_class_list(List<StringName> *p_classes) { OBJTYPE_RLOCK; const StringName *k = nullptr; while ((k = classes.next(k))) { - p_classes->push_back(*k); } @@ -301,43 +270,40 @@ void ClassDB::get_class_list(List<StringName> *p_classes) { } void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) { - OBJTYPE_RLOCK; const StringName *k = nullptr; while ((k = classes.next(k))) { - - if (*k != p_class && is_parent_class(*k, p_class)) + if (*k != p_class && is_parent_class(*k, p_class)) { p_classes->push_back(*k); + } } } void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<StringName> *p_classes) { - OBJTYPE_RLOCK; const StringName *k = nullptr; while ((k = classes.next(k))) { - - if (*k != p_class && get_parent_class(*k) == p_class) + if (*k != p_class && get_parent_class(*k) == p_class) { p_classes->push_back(*k); + } } } StringName ClassDB::get_parent_class_nocheck(const StringName &p_class) { - OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); - if (!ti) + if (!ti) { return StringName(); + } return ti->inherits; } StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) { - if (classes.has(p_class)) { return p_class; } @@ -350,7 +316,6 @@ StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) } StringName ClassDB::get_parent_class(const StringName &p_class) { - OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); @@ -359,7 +324,6 @@ StringName ClassDB::get_parent_class(const StringName &p_class) { } ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { - OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); @@ -369,7 +333,6 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { } uint64_t ClassDB::get_api_hash(APIType p_api) { - OBJTYPE_RLOCK; #ifdef DEBUG_METHODS_ENABLED @@ -380,18 +343,17 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { const StringName *k = nullptr; while ((k = classes.next(k))) { - names.push_back(*k); } //must be alphabetically sorted for hash to compute names.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - ClassInfo *t = classes.getptr(E->get()); ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E->get()) + "'."); - if (t->api != p_api || !t->exposed) + if (t->api != p_api || !t->exposed) { continue; + } hash = hash_djb2_one_64(t->name.hash(), hash); hash = hash_djb2_one_64(t->inherits.hash(), hash); @@ -402,13 +364,13 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { k = nullptr; while ((k = t->method_map.next(k))) { - String name = k->operator String(); ERR_CONTINUE(name.empty()); - if (name[0] == '_') + if (name[0] == '_') { continue; // Ignore non-virtual methods that start with an underscore + } snames.push_back(*k); } @@ -416,7 +378,6 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { - MethodBind *mb = t->method_map[F->get()]; hash = hash_djb2_one_64(mb->get_name().hash(), hash); hash = hash_djb2_one_64(mb->get_argument_count(), hash); @@ -449,14 +410,12 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { k = nullptr; while ((k = t->constant_map.next(k))) { - snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { - hash = hash_djb2_one_64(F->get().hash(), hash); hash = hash_djb2_one_64(t->constant_map[F->get()], hash); } @@ -469,14 +428,12 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { k = nullptr; while ((k = t->signal_map.next(k))) { - snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { - MethodInfo &mi = t->signal_map[F->get()]; hash = hash_djb2_one_64(F->get().hash(), hash); for (int i = 0; i < mi.arguments.size(); i++) { @@ -492,14 +449,12 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { k = nullptr; while ((k = t->property_setget.next(k))) { - snames.push_back(*k); } snames.sort_custom<StringName::AlphCompare>(); for (List<StringName>::Element *F = snames.front(); F; F = F->next()) { - PropertySetGet *psg = t->property_setget.getptr(F->get()); ERR_FAIL_COND_V(!psg, 0); @@ -511,7 +466,6 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { //property list for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) { - hash = hash_djb2_one_64(F->get().name.hash(), hash); hash = hash_djb2_one_64(F->get().type, hash); hash = hash_djb2_one_64(F->get().hint, hash); @@ -527,19 +481,16 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { } bool ClassDB::class_exists(const StringName &p_class) { - OBJTYPE_RLOCK; return classes.has(p_class); } void ClassDB::add_compatibility_class(const StringName &p_class, const StringName &p_fallback) { - OBJTYPE_WLOCK; compat_classes[p_class] = p_fallback; } Object *ClassDB::instance(const StringName &p_class) { - ClassInfo *ti; { OBJTYPE_RLOCK; @@ -561,8 +512,8 @@ Object *ClassDB::instance(const StringName &p_class) { #endif return ti->creation_func(); } -bool ClassDB::can_instance(const StringName &p_class) { +bool ClassDB::can_instance(const StringName &p_class) { OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); @@ -576,7 +527,6 @@ bool ClassDB::can_instance(const StringName &p_class) { } void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) { - OBJTYPE_WLOCK; const StringName &name = p_class; @@ -590,7 +540,6 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit ti.api = current_api; if (ti.inherits) { - ERR_FAIL_COND(!classes.has(ti.inherits)); //it MUST be registered. ti.inherits_ptr = &classes[ti.inherits]; @@ -600,17 +549,15 @@ void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherit } void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, bool p_no_inheritance, bool p_exclude_from_properties) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - if (type->disabled) { - - if (p_no_inheritance) + if (p_no_inheritance) { break; + } type = type->inherits_ptr; continue; @@ -619,22 +566,20 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b #ifdef DEBUG_METHODS_ENABLED for (List<MethodInfo>::Element *E = type->virtual_methods.front(); E; E = E->next()) { - p_methods->push_back(E->get()); } for (List<StringName>::Element *E = type->method_order.front(); E; E = E->next()) { - MethodBind *method = type->method_map.get(E->get()); MethodInfo minfo; minfo.name = E->get(); minfo.id = method->get_method_id(); - if (p_exclude_from_properties && type->methods_in_properties.has(minfo.name)) + if (p_exclude_from_properties && type->methods_in_properties.has(minfo.name)) { continue; + } for (int i = 0; i < method->get_argument_count(); i++) { - //Variant::Type t=method->get_argument_type(i); minfo.arguments.push_back(method->get_argument_info(i)); @@ -644,8 +589,9 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b minfo.flags = method->get_hint_flags(); for (int i = 0; i < method->get_argument_count(); i++) { - if (method->has_default_argument(i)) + if (method->has_default_argument(i)) { minfo.default_arguments.push_back(method->get_default_argument(i)); + } } p_methods->push_back(minfo); @@ -656,7 +602,6 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b const StringName *K = nullptr; while ((K = type->method_map.next(K))) { - MethodBind *m = type->method_map[*K]; MethodInfo mi; mi.name = m->get_name(); @@ -665,31 +610,30 @@ void ClassDB::get_method_list(StringName p_class, List<MethodInfo> *p_methods, b #endif - if (p_no_inheritance) + if (p_no_inheritance) { break; + } type = type->inherits_ptr; } } MethodBind *ClassDB::get_method(StringName p_class, StringName p_name) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - MethodBind **method = type->method_map.getptr(p_name); - if (method && *method) + if (method && *method) { return *method; + } type = type->inherits_ptr; } return nullptr; } void ClassDB::bind_integer_constant(const StringName &p_class, const StringName &p_enum, const StringName &p_name, int p_constant) { - OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); @@ -697,7 +641,6 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName ERR_FAIL_COND(!type); if (type->constant_map.has(p_name)) { - ERR_FAIL(); } @@ -726,16 +669,15 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName } void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> *p_constants, bool p_no_inheritance) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - #ifdef DEBUG_METHODS_ENABLED - for (List<StringName>::Element *E = type->constant_order.front(); E; E = E->next()) + for (List<StringName>::Element *E = type->constant_order.front(); E; E = E->next()) { p_constants->push_back(E->get()); + } #else const StringName *K = nullptr; @@ -744,57 +686,56 @@ void ClassDB::get_integer_constant_list(const StringName &p_class, List<String> } #endif - if (p_no_inheritance) + if (p_no_inheritance) { break; + } type = type->inherits_ptr; } } int ClassDB::get_integer_constant(const StringName &p_class, const StringName &p_name, bool *p_success) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - int *constant = type->constant_map.getptr(p_name); if (constant) { - - if (p_success) + if (p_success) { *p_success = true; + } return *constant; } type = type->inherits_ptr; } - if (p_success) + if (p_success) { *p_success = false; + } return 0; } StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const StringName &p_name, bool p_no_inheritance) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - const StringName *k = nullptr; while ((k = type->enum_map.next(k))) { - List<StringName> &constants_list = type->enum_map.get(*k); const List<StringName>::Element *found = constants_list.find(p_name); - if (found) + if (found) { return *k; + } } - if (p_no_inheritance) + if (p_no_inheritance) { break; + } type = type->inherits_ptr; } @@ -803,33 +744,30 @@ StringName ClassDB::get_integer_constant_enum(const StringName &p_class, const S } void ClassDB::get_enum_list(const StringName &p_class, List<StringName> *p_enums, bool p_no_inheritance) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - const StringName *k = nullptr; while ((k = type->enum_map.next(k))) { p_enums->push_back(*k); } - if (p_no_inheritance) + if (p_no_inheritance) { break; + } type = type->inherits_ptr; } } void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_enum, List<StringName> *p_constants, bool p_no_inheritance) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); while (type) { - const List<StringName> *constants = type->enum_map.getptr(p_enum); if (constants) { @@ -838,15 +776,15 @@ void ClassDB::get_enum_constants(const StringName &p_class, const StringName &p_ } } - if (p_no_inheritance) + if (p_no_inheritance) { break; + } type = type->inherits_ptr; } } void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) { - OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); @@ -866,7 +804,6 @@ void ClassDB::add_signal(StringName p_class, const MethodInfo &p_signal) { } void ClassDB::get_signal_list(StringName p_class, List<MethodInfo> *p_signals, bool p_no_inheritance) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); @@ -875,28 +812,27 @@ void ClassDB::get_signal_list(StringName p_class, List<MethodInfo> *p_signals, b ClassInfo *check = type; while (check) { - const StringName *S = nullptr; while ((S = check->signal_map.next(S))) { - p_signals->push_back(check->signal_map[*S]); } - if (p_no_inheritance) + if (p_no_inheritance) { return; + } check = check->inherits_ptr; } } bool ClassDB::has_signal(StringName p_class, StringName p_signal) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { - if (check->signal_map.has(p_signal)) + if (check->signal_map.has(p_signal)) { return true; + } check = check->inherits_ptr; } @@ -904,7 +840,6 @@ bool ClassDB::has_signal(StringName p_class, StringName p_signal) { } bool ClassDB::get_signal(StringName p_class, StringName p_signal, MethodInfo *r_signal) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; @@ -922,7 +857,6 @@ bool ClassDB::get_signal(StringName p_class, StringName p_signal, MethodInfo *r_ } void ClassDB::add_property_group(StringName p_class, const String &p_name, const String &p_prefix) { - OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); ERR_FAIL_COND(!type); @@ -931,7 +865,6 @@ void ClassDB::add_property_group(StringName p_class, const String &p_name, const } void ClassDB::add_property_subgroup(StringName p_class, const String &p_name, const String &p_prefix) { - OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); ERR_FAIL_COND(!type); @@ -940,7 +873,6 @@ void ClassDB::add_property_subgroup(StringName p_class, const String &p_name, co } void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) { - lock->read_lock(); ClassInfo *type = classes.getptr(p_class); lock->read_unlock(); @@ -961,7 +893,6 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons MethodBind *mb_get = nullptr; if (p_getter) { - mb_get = get_method(p_class, p_getter); #ifdef DEBUG_METHODS_ENABLED @@ -1006,15 +937,12 @@ void ClassDB::set_property_default_value(StringName p_class, const StringName &p } void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list, bool p_no_inheritance, const Object *p_validator) { - OBJTYPE_RLOCK; ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { - for (List<PropertyInfo>::Element *E = check->property_list.front(); E; E = E->next()) { - if (p_validator) { PropertyInfo pi = E->get(); p_validator->_validate_property(pi); @@ -1024,22 +952,23 @@ void ClassDB::get_property_list(StringName p_class, List<PropertyInfo> *p_list, } } - if (p_no_inheritance) + if (p_no_inheritance) { return; + } check = check->inherits_ptr; } } -bool ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid) { +bool ClassDB::set_property(Object *p_object, const StringName &p_property, const Variant &p_value, bool *r_valid) { ClassInfo *type = classes.getptr(p_object->get_class_name()); ClassInfo *check = type; while (check) { const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - if (!psg->setter) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return true; //return true but do nothing } @@ -1064,8 +993,9 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const } } - if (r_valid) + if (r_valid) { *r_valid = ce.error == Callable::CallError::CALL_OK; + } return true; } @@ -1075,15 +1005,16 @@ bool ClassDB::set_property(Object *p_object, const StringName &p_property, const return false; } -bool ClassDB::get_property(Object *p_object, const StringName &p_property, Variant &r_value) { +bool ClassDB::get_property(Object *p_object, const StringName &p_property, Variant &r_value) { ClassInfo *type = classes.getptr(p_object->get_class_name()); ClassInfo *check = type; while (check) { const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - if (!psg->getter) + if (!psg->getter) { return true; //return true but do nothing + } if (psg->index >= 0) { Variant index = psg->index; @@ -1092,10 +1023,8 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia r_value = p_object->call(psg->getter, arg, 1, ce); } else { - Callable::CallError ce; if (psg->_getptr) { - r_value = psg->_getptr->call(p_object, nullptr, 0, ce); } else { r_value = p_object->call(psg->getter, nullptr, 0, ce); @@ -1106,7 +1035,6 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia const int *c = check->constant_map.getptr(p_property); //constants count if (c) { - r_value = *c; return true; } @@ -1128,57 +1056,55 @@ bool ClassDB::get_property(Object *p_object, const StringName &p_property, Varia } int ClassDB::get_property_index(const StringName &p_class, const StringName &p_property, bool *r_is_valid) { - ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - - if (r_is_valid) + if (r_is_valid) { *r_is_valid = true; + } return psg->index; } check = check->inherits_ptr; } - if (r_is_valid) + if (r_is_valid) { *r_is_valid = false; + } return -1; } Variant::Type ClassDB::get_property_type(const StringName &p_class, const StringName &p_property, bool *r_is_valid) { - ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - - if (r_is_valid) + if (r_is_valid) { *r_is_valid = true; + } return psg->type; } check = check->inherits_ptr; } - if (r_is_valid) + if (r_is_valid) { *r_is_valid = false; + } return Variant::NIL; } StringName ClassDB::get_property_setter(StringName p_class, const StringName &p_property) { - ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - return psg->setter; } @@ -1189,13 +1115,11 @@ StringName ClassDB::get_property_setter(StringName p_class, const StringName &p_ } StringName ClassDB::get_property_getter(StringName p_class, const StringName &p_property) { - ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { const PropertySetGet *psg = check->property_setget.getptr(p_property); if (psg) { - return psg->getter; } @@ -1206,15 +1130,16 @@ StringName ClassDB::get_property_getter(StringName p_class, const StringName &p_ } bool ClassDB::has_property(const StringName &p_class, const StringName &p_property, bool p_no_inheritance) { - ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { - if (check->property_setget.has(p_property)) + if (check->property_setget.has(p_property)) { return true; + } - if (p_no_inheritance) + if (p_no_inheritance) { break; + } check = check->inherits_ptr; } @@ -1222,7 +1147,6 @@ bool ClassDB::has_property(const StringName &p_class, const StringName &p_proper } void ClassDB::set_method_flags(StringName p_class, StringName p_method, int p_flags) { - OBJTYPE_WLOCK; ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; @@ -1232,14 +1156,15 @@ void ClassDB::set_method_flags(StringName p_class, StringName p_method, int p_fl } bool ClassDB::has_method(StringName p_class, StringName p_method, bool p_no_inheritance) { - ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { - if (check->method_map.has(p_method)) + if (check->method_map.has(p_method)) { return true; - if (p_no_inheritance) + } + if (p_no_inheritance) { return false; + } check = check->inherits_ptr; } @@ -1295,7 +1220,6 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c defvals.resize(p_defcount); for (int i = 0; i < p_defcount; i++) { - defvals.write[i] = *p_defs[p_defcount - i - 1]; } @@ -1311,15 +1235,15 @@ void ClassDB::add_virtual_method(const StringName &p_class, const MethodInfo &p_ #ifdef DEBUG_METHODS_ENABLED MethodInfo mi = p_method; - if (p_virtual) + if (p_virtual) { mi.flags |= METHOD_FLAG_VIRTUAL; + } classes[p_class].virtual_methods.push_back(mi); #endif } void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p_methods, bool p_no_inheritance) { - ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'."); #ifdef DEBUG_METHODS_ENABLED @@ -1327,13 +1251,13 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p ClassInfo *type = classes.getptr(p_class); ClassInfo *check = type; while (check) { - for (List<MethodInfo>::Element *E = check->virtual_methods.front(); E; E = E->next()) { p_methods->push_back(E->get()); } - if (p_no_inheritance) + if (p_no_inheritance) { return; + } check = check->inherits_ptr; } @@ -1341,7 +1265,6 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p } void ClassDB::set_class_enabled(StringName p_class, bool p_enable) { - OBJTYPE_WLOCK; ERR_FAIL_COND_MSG(!classes.has(p_class), "Request for nonexistent class '" + p_class + "'."); @@ -1349,7 +1272,6 @@ void ClassDB::set_class_enabled(StringName p_class, bool p_enable) { } bool ClassDB::is_class_enabled(StringName p_class) { - OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); @@ -1364,7 +1286,6 @@ bool ClassDB::is_class_enabled(StringName p_class) { } bool ClassDB::is_class_exposed(StringName p_class) { - OBJTYPE_RLOCK; ClassInfo *ti = classes.getptr(p_class); @@ -1373,7 +1294,6 @@ bool ClassDB::is_class_exposed(StringName p_class) { } StringName ClassDB::get_category(const StringName &p_node) { - ERR_FAIL_COND_V(!classes.has(p_node), StringName()); #ifdef DEBUG_ENABLED return classes[p_node].category; @@ -1383,31 +1303,29 @@ StringName ClassDB::get_category(const StringName &p_node) { } void ClassDB::add_resource_base_extension(const StringName &p_extension, const StringName &p_class) { - - if (resource_base_extensions.has(p_extension)) + if (resource_base_extensions.has(p_extension)) { return; + } resource_base_extensions[p_extension] = p_class; } void ClassDB::get_resource_base_extensions(List<String> *p_extensions) { - const StringName *K = nullptr; while ((K = resource_base_extensions.next(K))) { - p_extensions->push_back(*K); } } void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) { - const StringName *K = nullptr; while ((K = resource_base_extensions.next(K))) { StringName cmp = resource_base_extensions[*K]; - if (is_parent_class(p_class, cmp) || is_parent_class(cmp, p_class)) + if (is_parent_class(p_class, cmp) || is_parent_class(cmp, p_class)) { p_extensions->push_back(*K); + } } } @@ -1415,9 +1333,7 @@ HashMap<StringName, HashMap<StringName, Variant>> ClassDB::default_values; Set<StringName> ClassDB::default_values_cached; Variant ClassDB::class_get_default_property_value(const StringName &p_class, const StringName &p_property, bool *r_valid) { - if (!default_values_cached.has(p_class)) { - if (!default_values.has(p_class)) { default_values[p_class] = HashMap<StringName, Variant>(); } @@ -1434,12 +1350,10 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con } if (c) { - List<PropertyInfo> plist; c->get_property_list(&plist); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) { - if (!default_values[p_class].has(E->get().name)) { Variant v = c->get(E->get().name); default_values[p_class][E->get().name] = v; @@ -1456,45 +1370,62 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con } if (!default_values.has(p_class)) { - if (r_valid != nullptr) *r_valid = false; + if (r_valid != nullptr) { + *r_valid = false; + } return Variant(); } if (!default_values[p_class].has(p_property)) { - if (r_valid != nullptr) *r_valid = false; + if (r_valid != nullptr) { + *r_valid = false; + } return Variant(); } - if (r_valid != nullptr) *r_valid = true; - return default_values[p_class][p_property]; + if (r_valid != nullptr) { + *r_valid = true; + } + + Variant var = default_values[p_class][p_property]; + +#ifdef DEBUG_ENABLED + // Some properties may have an instantiated Object as default value, + // (like Path2D's `curve` used to have), but that's not a good practice. + // Instead, those properties should use PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT + // to be auto-instantiated when created in the editor. + if (var.get_type() == Variant::OBJECT) { + Object *obj = var.get_validated_object(); + if (obj) { + WARN_PRINT(vformat("Instantiated %s used as default value for %s's \"%s\" property.", obj->get_class(), p_class, p_property)); + } + } +#endif + + return var; } RWLock *ClassDB::lock = nullptr; void ClassDB::init() { - lock = RWLock::create(); } void ClassDB::cleanup_defaults() { - default_values.clear(); default_values_cached.clear(); } void ClassDB::cleanup() { - //OBJTYPE_LOCK; hah not here const StringName *k = nullptr; while ((k = classes.next(k))) { - ClassInfo &ti = classes[*k]; const StringName *m = nullptr; while ((m = ti.method_map.next(m))) { - memdelete(ti.method_map[*m]); } } diff --git a/core/class_db.h b/core/class_db.h index f760aa1738..eae2a9afd4 100644 --- a/core/class_db.h +++ b/core/class_db.h @@ -48,7 +48,6 @@ #ifdef DEBUG_METHODS_ENABLED struct MethodDefinition { - StringName name; Vector<StringName> args; MethodDefinition() {} @@ -103,7 +102,6 @@ public: public: struct PropertySetGet { - int index; StringName setter; StringName getter; @@ -113,10 +111,10 @@ public: }; struct ClassInfo { + APIType api = API_NONE; + ClassInfo *inherits_ptr = nullptr; + void *class_ptr = nullptr; - APIType api; - ClassInfo *inherits_ptr; - void *class_ptr; HashMap<StringName, MethodBind *> method_map; HashMap<StringName, int> constant_map; HashMap<StringName, List<StringName>> enum_map; @@ -133,11 +131,12 @@ public: StringName inherits; StringName name; - bool disabled; - bool exposed; - Object *(*creation_func)(); - ClassInfo(); - ~ClassInfo(); + bool disabled = false; + bool exposed = false; + Object *(*creation_func)() = nullptr; + + ClassInfo() {} + ~ClassInfo() {} }; template <class T> @@ -167,13 +166,11 @@ public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! template <class T> static void _add_class() { - _add_class2(T::get_class_static(), T::get_parent_class_static()); } template <class T> static void register_class() { - GLOBAL_LOCK_FUNCTION; T::initialize_class(); ClassInfo *t = classes.getptr(T::get_class_static()); @@ -186,7 +183,6 @@ public: template <class T> static void register_virtual_class() { - GLOBAL_LOCK_FUNCTION; T::initialize_class(); ClassInfo *t = classes.getptr(T::get_class_static()); @@ -198,13 +194,11 @@ public: template <class T> static Object *_create_ptr_func() { - return T::create(); } template <class T> static void register_custom_instance_class() { - GLOBAL_LOCK_FUNCTION; T::initialize_class(); ClassInfo *t = classes.getptr(T::get_class_static()); @@ -231,7 +225,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method) { - MethodBind *bind = create_method_bind(p_method); return bind_methodfi(METHOD_FLAGS_DEFAULT, bind, p_method_name, nullptr, 0); //use static function, much smaller binary usage @@ -239,7 +232,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[1] = { &p_def1 }; @@ -248,7 +240,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[2] = { &p_def1, &p_def2 }; @@ -257,7 +248,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[3] = { &p_def1, &p_def2, &p_def3 }; @@ -266,7 +256,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[4] = { &p_def1, &p_def2, &p_def3, &p_def4 }; @@ -275,7 +264,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[5] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5 }; @@ -284,7 +272,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[6] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6 }; @@ -293,7 +280,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[7] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7 }; @@ -302,7 +288,6 @@ public: template <class N, class M> static MethodBind *bind_method(N p_method_name, M p_method, const Variant &p_def1, const Variant &p_def2, const Variant &p_def3, const Variant &p_def4, const Variant &p_def5, const Variant &p_def6, const Variant &p_def7, const Variant &p_def8) { - MethodBind *bind = create_method_bind(p_method); const Variant *ptr[8] = { &p_def1, &p_def2, &p_def3, &p_def4, &p_def5, &p_def6, &p_def7, &p_def8 }; @@ -311,7 +296,6 @@ public: template <class M> static MethodBind *bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info = MethodInfo(), const Vector<Variant> &p_default_args = Vector<Variant>(), bool p_return_nil_is_variant = true) { - GLOBAL_LOCK_FUNCTION; MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant); diff --git a/core/color.cpp b/core/color.cpp index 03aeb2085b..27a2d0af5c 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -36,7 +36,6 @@ #include "core/print_string.h" uint32_t Color::to_argb32() const { - uint32_t c = (uint8_t)Math::round(a * 255); c <<= 8; c |= (uint8_t)Math::round(r * 255); @@ -49,7 +48,6 @@ uint32_t Color::to_argb32() const { } uint32_t Color::to_abgr32() const { - uint32_t c = (uint8_t)Math::round(a * 255); c <<= 8; c |= (uint8_t)Math::round(b * 255); @@ -62,7 +60,6 @@ uint32_t Color::to_abgr32() const { } uint32_t Color::to_rgba32() const { - uint32_t c = (uint8_t)Math::round(r * 255); c <<= 8; c |= (uint8_t)Math::round(g * 255); @@ -75,7 +72,6 @@ uint32_t Color::to_rgba32() const { } uint64_t Color::to_abgr64() const { - uint64_t c = (uint16_t)Math::round(a * 65535); c <<= 16; c |= (uint16_t)Math::round(b * 65535); @@ -88,7 +84,6 @@ uint64_t Color::to_abgr64() const { } uint64_t Color::to_argb64() const { - uint64_t c = (uint16_t)Math::round(a * 65535); c <<= 16; c |= (uint16_t)Math::round(r * 65535); @@ -101,7 +96,6 @@ uint64_t Color::to_argb64() const { } uint64_t Color::to_rgba64() const { - uint64_t c = (uint16_t)Math::round(r * 65535); c <<= 16; c |= (uint16_t)Math::round(g * 65535); @@ -114,7 +108,6 @@ uint64_t Color::to_rgba64() const { } float Color::get_h() const { - float min = MIN(r, g); min = MIN(min, b); float max = MAX(r, g); @@ -122,26 +115,28 @@ float Color::get_h() const { float delta = max - min; - if (delta == 0) + if (delta == 0) { return 0; + } float h; - if (r == max) + if (r == max) { h = (g - b) / delta; // between yellow & magenta - else if (g == max) + } else if (g == max) { h = 2 + (b - r) / delta; // between cyan & yellow - else + } else { h = 4 + (r - g) / delta; // between magenta & cyan + } h /= 6.0; - if (h < 0) + if (h < 0) { h += 1.0; + } return h; } float Color::get_s() const { - float min = MIN(r, g); min = MIN(min, b); float max = MAX(r, g); @@ -153,14 +148,12 @@ float Color::get_s() const { } float Color::get_v() const { - float max = MAX(r, g); max = MAX(max, b); return max; } void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { - int i; float f, p, q, t; a = p_alpha; @@ -215,25 +208,22 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { } bool Color::is_equal_approx(const Color &p_color) const { - return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a); } void Color::invert() { - r = 1.0 - r; g = 1.0 - g; b = 1.0 - b; } -void Color::contrast() { +void Color::contrast() { r = Math::fmod(r + 0.5, 1.0); g = Math::fmod(g + 0.5, 1.0); b = Math::fmod(b + 0.5, 1.0); } Color Color::hex(uint32_t p_hex) { - float a = (p_hex & 0xFF) / 255.0; p_hex >>= 8; float b = (p_hex & 0xFF) / 255.0; @@ -246,7 +236,6 @@ Color Color::hex(uint32_t p_hex) { } Color Color::hex64(uint64_t p_hex) { - float a = (p_hex & 0xFFFF) / 65535.0; p_hex >>= 16; float b = (p_hex & 0xFFFF) / 65535.0; @@ -259,7 +248,6 @@ Color Color::hex64(uint64_t p_hex) { } Color Color::from_rgbe9995(uint32_t p_rgbe) { - float r = p_rgbe & 0x1ff; float g = (p_rgbe >> 9) & 0x1ff; float b = (p_rgbe >> 18) & 0x1ff; @@ -274,11 +262,9 @@ Color Color::from_rgbe9995(uint32_t p_rgbe) { } static float _parse_col(const String &p_str, int p_ofs) { - int ig = 0; for (int i = 0; i < 2; i++) { - int c = p_str[i + p_ofs]; int v = 0; @@ -294,36 +280,36 @@ static float _parse_col(const String &p_str, int p_ofs) { return -1; } - if (i == 0) + if (i == 0) { ig += v * 16; - else + } else { ig += v; + } } return ig; } Color Color::inverted() const { - Color c = *this; c.invert(); return c; } Color Color::contrasted() const { - Color c = *this; c.contrast(); return c; } Color Color::html(const String &p_color) { - String color = p_color; - if (color.length() == 0) + if (color.length() == 0) { return Color(); - if (color[0] == '#') + } + 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++) { @@ -362,13 +348,14 @@ Color Color::html(const String &p_color) { } bool Color::html_is_valid(const String &p_color) { - String color = p_color; - if (color.length() == 0) + if (color.length() == 0) { return false; - if (color[0] == '#') + } + if (color[0] == '#') { color = color.substr(1, color.length() - 1); + } bool alpha = false; @@ -406,7 +393,9 @@ bool Color::html_is_valid(const String &p_color) { } Color Color::named(const String &p_name) { - if (_named_colors.empty()) _populate_named_colors(); // from color_names.inc + if (_named_colors.empty()) { + _populate_named_colors(); // from color_names.inc + } String name = p_name; // Normalize name name = name.replace(" ", ""); @@ -422,19 +411,18 @@ Color Color::named(const String &p_name) { } String _to_hex(float p_val) { - int v = Math::round(p_val * 255); v = CLAMP(v, 0, 255); String ret; for (int i = 0; i < 2; i++) { - CharType c[2] = { 0, 0 }; int lv = v & 0xF; - if (lv < 10) + if (lv < 10) { c[0] = '0' + lv; - else + } else { c[0] = 'a' + lv - 10; + } v >>= 4; String cs = (const CharType *)c; @@ -445,21 +433,21 @@ String _to_hex(float p_val) { } String Color::to_html(bool p_alpha) const { - String txt; txt += _to_hex(r); txt += _to_hex(g); txt += _to_hex(b); - if (p_alpha) + if (p_alpha) { txt = _to_hex(a) + txt; + } return txt; } Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const { - p_h = Math::fmod(p_h * 360.0f, 360.0f); - if (p_h < 0.0) + if (p_h < 0.0) { p_h += 360.0f; + } const float h_ = p_h / 60.0f; const float c = p_v * p_s; @@ -509,12 +497,10 @@ Color Color::from_hsv(float p_h, float p_s, float p_v, float p_a) const { } Color::operator String() const { - return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a); } Color Color::operator+(const Color &p_color) const { - return Color( r + p_color.r, g + p_color.g, @@ -523,7 +509,6 @@ Color Color::operator+(const Color &p_color) const { } Color Color::operator-(const Color &p_color) const { - return Color( r - p_color.r, g - p_color.g, @@ -532,7 +517,6 @@ Color Color::operator-(const Color &p_color) const { } void Color::operator-=(const Color &p_color) { - r = r - p_color.r; g = g - p_color.g; b = b - p_color.b; @@ -540,7 +524,6 @@ void Color::operator-=(const Color &p_color) { } Color Color::operator*(const Color &p_color) const { - return Color( r * p_color.r, g * p_color.g, @@ -549,7 +532,6 @@ Color Color::operator*(const Color &p_color) const { } Color Color::operator*(const real_t &rvalue) const { - return Color( r * rvalue, g * rvalue, @@ -558,7 +540,6 @@ Color Color::operator*(const real_t &rvalue) const { } void Color::operator*=(const Color &p_color) { - r = r * p_color.r; g = g * p_color.g; b = b * p_color.b; @@ -566,7 +547,6 @@ void Color::operator*=(const Color &p_color) { } void Color::operator*=(const real_t &rvalue) { - r = r * rvalue; g = g * rvalue; b = b * rvalue; @@ -574,7 +554,6 @@ void Color::operator*=(const real_t &rvalue) { } Color Color::operator/(const Color &p_color) const { - return Color( r / p_color.r, g / p_color.g, @@ -583,7 +562,6 @@ Color Color::operator/(const Color &p_color) const { } Color Color::operator/(const real_t &rvalue) const { - return Color( r / rvalue, g / rvalue, @@ -592,7 +570,6 @@ Color Color::operator/(const real_t &rvalue) const { } void Color::operator/=(const Color &p_color) { - r = r / p_color.r; g = g / p_color.g; b = b / p_color.b; @@ -600,7 +577,6 @@ void Color::operator/=(const Color &p_color) { } void Color::operator/=(const real_t &rvalue) { - if (rvalue == 0) { r = 1.0; g = 1.0; @@ -612,10 +588,9 @@ void Color::operator/=(const real_t &rvalue) { b = b / rvalue; a = a / rvalue; } -}; +} Color Color::operator-() const { - return Color( 1.0 - r, 1.0 - g, diff --git a/core/color.h b/core/color.h index 16dc721072..258965fd16 100644 --- a/core/color.h +++ b/core/color.h @@ -35,16 +35,14 @@ #include "core/ustring.h" struct Color { - union { - struct { float r; float g; float b; float a; }; - float components[4]; + float components[4] = { 0, 0, 0, 1.0 }; }; bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); } @@ -97,8 +95,7 @@ struct Color { Color inverted() const; Color contrasted() const; - _FORCE_INLINE_ Color linear_interpolate(const Color &p_b, float p_t) const { - + _FORCE_INLINE_ Color lerp(const Color &p_b, float p_t) const { Color res = *this; res.r += (p_t * (p_b.r - r)); @@ -110,7 +107,6 @@ struct Color { } _FORCE_INLINE_ Color darkened(float p_amount) const { - Color res = *this; res.r = res.r * (1.0f - p_amount); res.g = res.g * (1.0f - p_amount); @@ -119,7 +115,6 @@ struct Color { } _FORCE_INLINE_ Color lightened(float p_amount) const { - Color res = *this; res.r = res.r + (1.0f - res.r) * p_amount; res.g = res.g + (1.0f - res.g) * p_amount; @@ -128,7 +123,6 @@ struct Color { } _FORCE_INLINE_ uint32_t to_rgbe9995() const { - const float pow2to9 = 512.0f; const float B = 15.0f; //const float Emax = 31.0f; @@ -162,7 +156,6 @@ struct Color { } _FORCE_INLINE_ Color blend(const Color &p_over) const { - Color res; float sa = 1.0 - p_over.a; res.a = a * sa + p_over.a; @@ -177,7 +170,6 @@ struct Color { } _FORCE_INLINE_ Color to_linear() const { - return Color( r < 0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4), g < 0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4), @@ -185,7 +177,6 @@ struct Color { a); } _FORCE_INLINE_ Color to_srgb() const { - return Color( r < 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055, g < 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055, @@ -204,15 +195,7 @@ struct Color { _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys operator String() const; - /** - * No construct parameters, r=0, g=0, b=0. a=255 - */ - _FORCE_INLINE_ Color() { - r = 0; - g = 0; - b = 0; - a = 1.0; - } + _FORCE_INLINE_ Color() {} /** * RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0 @@ -223,20 +206,32 @@ struct Color { b = p_b; a = p_a; } + + /** + * Construct a Color from another Color, but with the specified alpha value. + */ + _FORCE_INLINE_ Color(const Color &p_c, float p_a) { + r = p_c.r; + g = p_c.g; + b = p_c.b; + a = p_a; + } }; bool Color::operator<(const Color &p_color) const { - if (r == p_color.r) { if (g == p_color.g) { if (b == p_color.b) { return (a < p_color.a); - } else + } else { return (b < p_color.b); - } else + } + } else { return g < p_color.g; - } else + } + } else { return r < p_color.r; + } } #endif // COLOR_H diff --git a/core/color_names.inc b/core/color_names.inc index 428a8473fe..2b50d88b02 100644 --- a/core/color_names.inc +++ b/core/color_names.inc @@ -3,7 +3,9 @@ static Map<String, Color> _named_colors; static void _populate_named_colors() { - if (!_named_colors.empty()) return; + if (!_named_colors.empty()) { + return; + } _named_colors.insert("aliceblue", Color(0.94, 0.97, 1.00)); _named_colors.insert("antiquewhite", Color(0.98, 0.92, 0.84)); _named_colors.insert("aqua", Color(0.00, 1.00, 1.00)); diff --git a/core/command_queue_mt.cpp b/core/command_queue_mt.cpp index 3ce769c72c..ace210ca2c 100644 --- a/core/command_queue_mt.cpp +++ b/core/command_queue_mt.cpp @@ -33,30 +33,24 @@ #include "core/os/os.h" void CommandQueueMT::lock() { - mutex.lock(); } void CommandQueueMT::unlock() { - mutex.unlock(); } void CommandQueueMT::wait_for_flush() { - // wait one millisecond for a flush to happen OS::get_singleton()->delay_usec(1000); } CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() { - int idx = -1; while (true) { - lock(); for (int i = 0; i < SYNC_SEMAPHORES; i++) { - if (!sync_sems[i].in_use) { sync_sems[i].in_use = true; idx = i; @@ -100,25 +94,14 @@ tryagain: } CommandQueueMT::CommandQueueMT(bool p_sync) { - - read_ptr = 0; - write_ptr = 0; - dealloc_ptr = 0; - command_mem = (uint8_t *)memalloc(COMMAND_MEM_SIZE); - - for (int i = 0; i < SYNC_SEMAPHORES; i++) { - - sync_sems[i].in_use = false; - } - if (p_sync) + if (p_sync) { sync = memnew(Semaphore); - else - sync = nullptr; + } } CommandQueueMT::~CommandQueueMT() { - - if (sync) + if (sync) { memdelete(sync); + } memfree(command_mem); } diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h index 558453bdf5..d7a6a5bc43 100644 --- a/core/command_queue_mt.h +++ b/core/command_queue_mt.h @@ -253,7 +253,8 @@ cmd->method = p_method; \ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \ unlock(); \ - if (sync) sync->post(); \ + if (sync) \ + sync->post(); \ } #define CMD_RET_TYPE(N) CommandRet##N<T, M, COMMA_SEP_LIST(TYPE_ARG, N) COMMA(N) R> @@ -269,7 +270,8 @@ cmd->ret = r_ret; \ cmd->sync_sem = ss; \ unlock(); \ - if (sync) sync->post(); \ + if (sync) \ + sync->post(); \ ss->sem.wait(); \ ss->in_use = false; \ } @@ -286,7 +288,8 @@ SEMIC_SEP_LIST(CMD_ASSIGN_PARAM, N); \ cmd->sync_sem = ss; \ unlock(); \ - if (sync) sync->post(); \ + if (sync) \ + sync->post(); \ ss->sem.wait(); \ ss->in_use = false; \ } @@ -294,22 +297,18 @@ #define MAX_CMD_PARAMS 15 class CommandQueueMT { - struct SyncSemaphore { - Semaphore sem; - bool in_use; + bool in_use = false; }; struct CommandBase { - virtual void call() = 0; - virtual void post(){}; - virtual ~CommandBase(){}; + virtual void post() {} + virtual ~CommandBase() {} }; struct SyncCommand : public CommandBase { - SyncSemaphore *sync_sem; virtual void post() { @@ -336,17 +335,16 @@ class CommandQueueMT { SYNC_SEMAPHORES = 8 }; - uint8_t *command_mem; - uint32_t read_ptr; - uint32_t write_ptr; - uint32_t dealloc_ptr; + uint8_t *command_mem = (uint8_t *)memalloc(COMMAND_MEM_SIZE); + uint32_t read_ptr = 0; + uint32_t write_ptr = 0; + uint32_t dealloc_ptr = 0; SyncSemaphore sync_sems[SYNC_SEMAPHORES]; Mutex mutex; - Semaphore *sync; + Semaphore *sync = nullptr; template <class T> T *allocate() { - // alloc size is size+T+safeguard uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1)) + 8; @@ -355,7 +353,6 @@ class CommandQueueMT { if (write_ptr < dealloc_ptr) { // behind dealloc_ptr, check that there is room if ((dealloc_ptr - write_ptr) <= alloc_size) { - // There is no more room, try to deallocate something if (dealloc_one()) { goto tryagain; @@ -402,12 +399,10 @@ class CommandQueueMT { template <class T> T *allocate_and_lock() { - lock(); T *ret; while ((ret = allocate<T>()) == nullptr) { - unlock(); // sleep a little until fetch happened and some room is made wait_for_flush(); @@ -418,12 +413,16 @@ class CommandQueueMT { } bool flush_one(bool p_lock = true) { - if (p_lock) lock(); + if (p_lock) { + lock(); + } tryagain: // tried to read an empty queue if (read_ptr == write_ptr) { - if (p_lock) unlock(); + if (p_lock) { + unlock(); + } return false; } @@ -442,15 +441,21 @@ class CommandQueueMT { read_ptr += size; - if (p_lock) unlock(); + if (p_lock) { + unlock(); + } cmd->call(); - if (p_lock) lock(); + if (p_lock) { + lock(); + } cmd->post(); cmd->~CommandBase(); *(uint32_t *)&command_mem[size_ptr] &= ~1; - if (p_lock) unlock(); + if (p_lock) { + unlock(); + } return true; } @@ -480,11 +485,10 @@ public: } void flush_all() { - //ERR_FAIL_COND(sync); lock(); - while (flush_one(false)) - ; + while (flush_one(false)) { + } unlock(); } diff --git a/core/compressed_translation.cpp b/core/compressed_translation.cpp index 0225524bc8..a66997aa52 100644 --- a/core/compressed_translation.cpp +++ b/core/compressed_translation.cpp @@ -37,7 +37,6 @@ extern "C" { } struct _PHashTranslationCmp { - int orig_len; CharString compressed; int offset; @@ -65,7 +64,6 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { int total_string_size = 0; for (List<StringName>::Element *E = keys.front(); E; E = E->next()) { - //hash string CharString cs = E->get().operator String().utf8(); uint32_t h = hash(0, cs.get_data()); @@ -108,21 +106,19 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { int bucket_table_size = 0; for (int i = 0; i < size; i++) { - const Vector<Pair<int, CharString>> &b = buckets[i]; Map<uint32_t, int> &t = table.write[i]; - if (b.size() == 0) + if (b.size() == 0) { continue; + } int d = 1; int item = 0; while (item < b.size()) { - uint32_t slot = hash(d, b[item].second.get_data()); if (t.has(slot)) { - item = 0; d++; t.clear(); @@ -151,7 +147,6 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { int collisions = 0; for (int i = 0; i < size; i++) { - const Map<uint32_t, int> &t = table[i]; if (t.size() == 0) { htw[i] = 0xFFFFFFFF; //nothing @@ -165,7 +160,6 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { btw[btindex++] = hfunc_table[i]; for (Map<uint32_t, int>::Element *E = t.front(); E; E = E->next()) { - btw[btindex++] = E->key(); btw[btindex++] = compressed[E->get()].offset; btw[btindex++] = compressed[E->get()].compressed.size(); @@ -187,7 +181,6 @@ void PHashTranslation::generate(const Ref<Translation> &p_from) { } bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) { - String name = p_name.operator String(); if (name == "hash_table") { hash_table = p_value; @@ -197,33 +190,34 @@ bool PHashTranslation::_set(const StringName &p_name, const Variant &p_value) { strings = p_value; } else if (name == "load_from") { generate(p_value); - } else + } else { return false; + } return true; } bool PHashTranslation::_get(const StringName &p_name, Variant &r_ret) const { - String name = p_name.operator String(); - if (name == "hash_table") + if (name == "hash_table") { r_ret = hash_table; - else if (name == "bucket_table") + } else if (name == "bucket_table") { r_ret = bucket_table; - else if (name == "strings") + } else if (name == "strings") { r_ret = strings; - else + } else { return false; + } return true; } StringName PHashTranslation::get_message(const StringName &p_src_text) const { - int htsize = hash_table.size(); - if (htsize == 0) + if (htsize == 0) { return StringName(); + } CharString str = p_src_text.operator String().utf8(); uint32_t h = hash(0, str.get_data()); @@ -248,9 +242,7 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const { int idx = -1; for (int i = 0; i < bucket.size; i++) { - if (bucket.elem[i].key == h) { - idx = i; break; } @@ -261,13 +253,11 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const { } if (bucket.elem[idx].comp_size == bucket.elem[idx].uncomp_size) { - String rstr; rstr.parse_utf8(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].uncomp_size); return rstr; } else { - CharString uncomp; uncomp.resize(bucket.elem[idx].uncomp_size + 1); smaz_decompress(&sptr[bucket.elem[idx].str_offset], bucket.elem[idx].comp_size, uncomp.ptrw(), bucket.elem[idx].uncomp_size); @@ -278,16 +268,12 @@ StringName PHashTranslation::get_message(const StringName &p_src_text) const { } void PHashTranslation::_get_property_list(List<PropertyInfo> *p_list) const { - p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "hash_table")); p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, "bucket_table")); p_list->push_back(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "strings")); p_list->push_back(PropertyInfo(Variant::OBJECT, "load_from", PROPERTY_HINT_RESOURCE_TYPE, "Translation", PROPERTY_USAGE_EDITOR)); } -void PHashTranslation::_bind_methods() { +void PHashTranslation::_bind_methods() { ClassDB::bind_method(D_METHOD("generate", "from"), &PHashTranslation::generate); } - -PHashTranslation::PHashTranslation() { -} diff --git a/core/compressed_translation.h b/core/compressed_translation.h index d599240dfe..3c029bdf58 100644 --- a/core/compressed_translation.h +++ b/core/compressed_translation.h @@ -34,7 +34,6 @@ #include "core/translation.h" class PHashTranslation : public Translation { - GDCLASS(PHashTranslation, Translation); //this translation uses a sort of modified perfect hash algorithm @@ -48,12 +47,10 @@ class PHashTranslation : public Translation { Vector<uint8_t> strings; struct Bucket { - int size; uint32_t func; struct Elem { - uint32_t key; uint32_t str_offset; uint32_t comp_size; @@ -64,11 +61,10 @@ class PHashTranslation : public Translation { }; _FORCE_INLINE_ uint32_t hash(uint32_t d, const char *p_str) const { - - if (d == 0) + if (d == 0) { d = 0x1000193; + } while (*p_str) { - d = (d * 0x1000193) ^ uint32_t(*p_str); p_str++; } @@ -86,7 +82,7 @@ public: virtual StringName get_message(const StringName &p_src_text) const; //overridable for other implementations void generate(const Ref<Translation> &p_from); - PHashTranslation(); + PHashTranslation() {} }; #endif // COMPRESSED_TRANSLATION_H diff --git a/core/container_type_validate.h b/core/container_type_validate.h new file mode 100644 index 0000000000..f2724e884d --- /dev/null +++ b/core/container_type_validate.h @@ -0,0 +1,126 @@ +/*************************************************************************/ +/* container_type_validate.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONTAINER_TYPE_VALIDATE_H +#define CONTAINER_TYPE_VALIDATE_H + +#include "core/script_language.h" +#include "core/variant.h" + +struct ContainerTypeValidate { + Variant::Type type = Variant::NIL; + StringName class_name; + Ref<Script> script; + const char *where = "conatiner"; + + _FORCE_INLINE_ bool can_reference(const ContainerTypeValidate &p_type) const { + if (type == p_type.type) { + if (type != Variant::OBJECT) { + return true; //nothing else to check + } + } else { + return false; + } + + //both are object + + if ((class_name != StringName()) != (p_type.class_name != StringName())) { + return false; //both need to have class or none + } + + if (class_name != p_type.class_name) { + if (!ClassDB::is_parent_class(p_type.class_name, class_name)) { + return false; + } + } + + if (script.is_null() != p_type.script.is_null()) { + return false; + } + + if (script != p_type.script) { + if (!p_type.script->inherits_script(script)) { + return false; + } + } + + return true; + } + + _FORCE_INLINE_ bool validate(const Variant &p_variant, const char *p_operation = "use") { + if (type == Variant::NIL) { + return true; + } + + ERR_FAIL_COND_V_MSG(type != p_variant.get_type(), false, "Attempted to " + String(p_operation) + " a variable of type '" + Variant::get_type_name(p_variant.get_type()) + "' into a " + where + " of type '" + Variant::get_type_name(type) + "'."); + if (type != p_variant.get_type()) { + return false; + } + + if (type != Variant::OBJECT) { + return true; + } +#ifdef DEBUG_ENABLED + ObjectID object_id = p_variant; + if (object_id == ObjectID()) { + return true; //fine its null; + } + Object *object = ObjectDB::get_instance(object_id); + ERR_FAIL_COND_V_MSG(object == nullptr, false, "Attempted to " + String(p_operation) + " an invalid (previously freed?) object instance into a '" + String(where) + "."); +#else + Object *object = p_variant; + if (object == nullptr) { + return true; //fine + } +#endif + if (class_name == StringName()) { + return true; //all good, no class type requested + } + + StringName obj_class = object->get_class_name(); + if (obj_class != class_name) { + ERR_FAIL_COND_V_MSG(!ClassDB::is_parent_class(object->get_class_name(), class_name), false, "Attempted to " + String(p_operation) + " an object of type '" + object->get_class() + "' into a " + where + ", which does not inherit from '" + String(class_name) + "'."); + } + + if (script.is_null()) { + return true; //all good + } + + Ref<Script> other_script = object->get_script(); + + //check base script.. + ERR_FAIL_COND_V_MSG(other_script.is_null(), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'."); + ERR_FAIL_COND_V_MSG(!other_script->inherits_script(script), false, "Attempted to " + String(p_operation) + " an object into a " + String(where) + ", that does not inherit from '" + String(script->get_class_name()) + "'."); + + return true; + } +}; + +#endif // CONTAINER_TYPE_VALIDATE_H diff --git a/core/core_string_names.h b/core/core_string_names.h index 2ade44f4e0..1a18c84572 100644 --- a/core/core_string_names.h +++ b/core/core_string_names.h @@ -34,7 +34,6 @@ #include "core/string_name.h" class CoreStringNames { - friend void register_core_types(); friend void unregister_core_types(); diff --git a/core/cowdata.h b/core/cowdata.h index 975a572906..82daefb5bd 100644 --- a/core/cowdata.h +++ b/core/cowdata.h @@ -54,30 +54,30 @@ class CowData { friend class VMap; private: - mutable T *_ptr; + mutable T *_ptr = nullptr; // internal helpers _FORCE_INLINE_ uint32_t *_get_refcount() const { - - if (!_ptr) + if (!_ptr) { return nullptr; + } return reinterpret_cast<uint32_t *>(_ptr) - 2; } _FORCE_INLINE_ uint32_t *_get_size() const { - - if (!_ptr) + if (!_ptr) { return nullptr; + } return reinterpret_cast<uint32_t *>(_ptr) - 1; } _FORCE_INLINE_ T *_get_data() const { - - if (!_ptr) + if (!_ptr) { return nullptr; + } return reinterpret_cast<T *>(_ptr); } @@ -125,31 +125,29 @@ public: _FORCE_INLINE_ int size() const { uint32_t *size = (uint32_t *)_get_size(); - if (size) + if (size) { return *size; - else + } else { return 0; + } } _FORCE_INLINE_ void clear() { resize(0); } - _FORCE_INLINE_ bool empty() const { return _ptr == 0; } + _FORCE_INLINE_ bool empty() const { return _ptr == nullptr; } _FORCE_INLINE_ void set(int p_index, const T &p_elem) { - CRASH_BAD_INDEX(p_index, size()); _copy_on_write(); _get_data()[p_index] = p_elem; } _FORCE_INLINE_ T &get_m(int p_index) { - CRASH_BAD_INDEX(p_index, size()); _copy_on_write(); return _get_data()[p_index]; } _FORCE_INLINE_ const T &get(int p_index) const { - CRASH_BAD_INDEX(p_index, size()); return _get_data()[p_index]; @@ -158,46 +156,45 @@ public: Error resize(int p_size); _FORCE_INLINE_ void remove(int p_index) { - ERR_FAIL_INDEX(p_index, size()); T *p = ptrw(); int len = size(); for (int i = p_index; i < len - 1; i++) { - p[i] = p[i + 1]; - }; + } resize(len - 1); - }; + } Error insert(int p_pos, const T &p_val) { - ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER); resize(size() + 1); - for (int i = (size() - 1); i > p_pos; i--) + for (int i = (size() - 1); i > p_pos; i--) { set(i, get(i - 1)); + } set(p_pos, p_val); return OK; - }; + } int find(const T &p_val, int p_from = 0) const; - _FORCE_INLINE_ CowData(); + _FORCE_INLINE_ CowData() {} _FORCE_INLINE_ ~CowData(); _FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }; }; template <class T> void CowData<T>::_unref(void *p_data) { - - if (!p_data) + if (!p_data) { return; + } uint32_t *refc = _get_refcount(); - if (atomic_decrement(refc) > 0) + if (atomic_decrement(refc) > 0) { return; // still in use + } // clean up if (!__has_trivial_destructor(T)) { @@ -216,9 +213,9 @@ void CowData<T>::_unref(void *p_data) { template <class T> void CowData<T>::_copy_on_write() { - - if (!_ptr) + if (!_ptr) { return; + } uint32_t *refc = _get_refcount(); @@ -250,13 +247,13 @@ void CowData<T>::_copy_on_write() { template <class T> Error CowData<T>::resize(int p_size) { - ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); int current_size = size(); - if (p_size == current_size) + if (p_size == current_size) { return OK; + } if (p_size == 0) { // wants to clean up @@ -273,7 +270,6 @@ Error CowData<T>::resize(int p_size) { ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); if (p_size > current_size) { - if (alloc_size != current_alloc_size) { if (current_size == 0) { // alloc from scratch @@ -304,7 +300,6 @@ Error CowData<T>::resize(int p_size) { *_get_size() = p_size; } else if (p_size < current_size) { - if (!__has_trivial_destructor(T)) { // deinitialize no longer needed elements for (uint32_t i = p_size; i < *_get_size(); i++) { @@ -351,15 +346,16 @@ void CowData<T>::_ref(const CowData *p_from) { template <class T> void CowData<T>::_ref(const CowData &p_from) { - - if (_ptr == p_from._ptr) + if (_ptr == p_from._ptr) { return; // self assign, do nothing. + } _unref(_ptr); _ptr = nullptr; - if (!p_from._ptr) + if (!p_from._ptr) { return; //nothing to do + } if (atomic_conditional_increment(p_from._get_refcount()) > 0) { // could reference _ptr = p_from._ptr; @@ -367,14 +363,7 @@ void CowData<T>::_ref(const CowData &p_from) { } template <class T> -CowData<T>::CowData() { - - _ptr = nullptr; -} - -template <class T> CowData<T>::~CowData() { - _unref(_ptr); } diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index ab8548e3ba..a9a7cabee9 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -38,8 +38,9 @@ CryptoKey *(*CryptoKey::_create)() = nullptr; CryptoKey *CryptoKey::create() { - if (_create) + if (_create) { return _create(); + } return nullptr; } @@ -50,8 +51,9 @@ void CryptoKey::_bind_methods() { X509Certificate *(*X509Certificate::_create)() = nullptr; X509Certificate *X509Certificate::create() { - if (_create) + if (_create) { return _create(); + } return nullptr; } @@ -65,15 +67,16 @@ void X509Certificate::_bind_methods() { void (*Crypto::_load_default_certificates)(String p_path) = nullptr; Crypto *(*Crypto::_create)() = nullptr; Crypto *Crypto::create() { - if (_create) + if (_create) { return _create(); - return memnew(Crypto); + } + ERR_FAIL_V_MSG(nullptr, "Crypto is not available when the mbedtls module is disabled."); } void Crypto::load_default_certificates(String p_path) { - - if (_load_default_certificates) + if (_load_default_certificates) { _load_default_certificates(p_path); + } } void Crypto::_bind_methods() { @@ -82,63 +85,46 @@ void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000")); } -PackedByteArray Crypto::generate_random_bytes(int p_bytes) { - ERR_FAIL_V_MSG(PackedByteArray(), "generate_random_bytes is not available when mbedtls module is disabled."); -} - -Ref<CryptoKey> Crypto::generate_rsa(int p_bytes) { - ERR_FAIL_V_MSG(nullptr, "generate_rsa is not available when mbedtls module is disabled."); -} - -Ref<X509Certificate> Crypto::generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) { - ERR_FAIL_V_MSG(nullptr, "generate_self_signed_certificate is not available when mbedtls module is disabled."); -} - -Crypto::Crypto() { -} - /// Resource loader/saver -RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { String el = p_path.get_extension().to_lower(); if (el == "crt") { X509Certificate *cert = X509Certificate::create(); - if (cert) + if (cert) { cert->load(p_path); + } return cert; } else if (el == "key") { CryptoKey *key = CryptoKey::create(); - if (key) + if (key) { key->load(p_path); + } return key; } return nullptr; } void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("crt"); p_extensions->push_back("key"); } bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const { - return p_type == "X509Certificate" || p_type == "CryptoKey"; } String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const { - String el = p_path.get_extension().to_lower(); - if (el == "crt") + if (el == "crt") { return "X509Certificate"; - else if (el == "key") + } else if (el == "key") { return "CryptoKey"; + } return ""; } Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Error err; Ref<X509Certificate> cert = p_resource; Ref<CryptoKey> key = p_resource; @@ -154,7 +140,6 @@ Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resourc } void ResourceFormatSaverCrypto::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource); const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource); if (cert) { @@ -164,7 +149,7 @@ void ResourceFormatSaverCrypto::get_recognized_extensions(const RES &p_resource, p_extensions->push_back("key"); } } -bool ResourceFormatSaverCrypto::recognize(const RES &p_resource) const { +bool ResourceFormatSaverCrypto::recognize(const RES &p_resource) const { return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource); } diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index e515367de5..6cc5f46164 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -31,11 +31,10 @@ #ifndef CRYPTO_H #define CRYPTO_H -#include "core/reference.h" -#include "core/resource.h" - #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" +#include "core/reference.h" +#include "core/resource.h" class CryptoKey : public Resource { GDCLASS(CryptoKey, Resource); @@ -76,26 +75,22 @@ public: static Crypto *create(); static void load_default_certificates(String p_path); - virtual PackedByteArray generate_random_bytes(int p_bytes); - virtual Ref<CryptoKey> generate_rsa(int p_bytes); - virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after); + virtual PackedByteArray generate_random_bytes(int p_bytes) = 0; + virtual Ref<CryptoKey> generate_rsa(int p_bytes) = 0; + virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) = 0; - Crypto(); + Crypto() {} }; class ResourceFormatLoaderCrypto : public ResourceFormatLoader { - GDCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader); - public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; }; class ResourceFormatSaverCrypto : public ResourceFormatSaver { - GDCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver); - public: virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h index b3be58e8ee..36d8ace723 100644 --- a/core/crypto/crypto_core.h +++ b/core/crypto/crypto_core.h @@ -34,10 +34,8 @@ #include "core/reference.h" class CryptoCore { - public: class MD5Context { - private: void *ctx; // To include, or not to include... @@ -51,7 +49,6 @@ public: }; class SHA1Context { - private: void *ctx; // To include, or not to include... @@ -65,7 +62,6 @@ public: }; class SHA256Context { - private: void *ctx; // To include, or not to include... @@ -79,7 +75,6 @@ public: }; class AESContext { - private: void *ctx; // To include, or not to include... diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp index af43bc9bad..fb0dadfbab 100644 --- a/core/crypto/hashing_context.cpp +++ b/core/crypto/hashing_context.cpp @@ -104,7 +104,6 @@ void HashingContext::_create_ctx(HashType p_type) { } void HashingContext::_delete_ctx() { - switch (type) { case HASH_MD5: memdelete((CryptoCore::MD5Context *)ctx); @@ -128,11 +127,8 @@ void HashingContext::_bind_methods() { BIND_ENUM_CONSTANT(HASH_SHA256); } -HashingContext::HashingContext() { - ctx = nullptr; -} - HashingContext::~HashingContext() { - if (ctx != nullptr) + if (ctx != nullptr) { _delete_ctx(); + } } diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h index 230ba7ee85..f9454fa891 100644 --- a/core/crypto/hashing_context.h +++ b/core/crypto/hashing_context.h @@ -44,7 +44,7 @@ public: }; private: - void *ctx; + void *ctx = nullptr; HashType type; protected: @@ -57,7 +57,7 @@ public: Error update(PackedByteArray p_chunk); PackedByteArray finish(); - HashingContext(); + HashingContext() {} ~HashingContext(); }; diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index 410c55129d..3f949b0ae1 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -228,8 +228,9 @@ Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) { int len = 0; Error err = encode_variant(var, nullptr, len, true); - if (err != OK) + if (err != OK) { ERR_PRINT("Failed to encode variant."); + } if (len > max_size) { arr.push_back(Variant()); diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h index 04229c0afc..7b7f4ac4b5 100644 --- a/core/debugger/debugger_marshalls.h +++ b/core/debugger/debugger_marshalls.h @@ -35,18 +35,14 @@ #include "servers/rendering_server.h" struct DebuggerMarshalls { - // Memory usage struct ResourceInfo { String path; String format; String type; RID id; - int vram; + int vram = 0; bool operator<(const ResourceInfo &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; } - ResourceInfo() { - vram = 0; - } }; struct ResourceUsage { @@ -119,10 +115,7 @@ struct DebuggerMarshalls { struct ScriptStackVariable { String name; Variant value; - int type; - ScriptStackVariable() { - type = -1; - } + int type = -1; Array serialize(int max_size = 1 << 20); // 1 MiB default. bool deserialize(const Array &p_arr); @@ -137,27 +130,18 @@ struct DebuggerMarshalls { }; struct OutputError { - int hr; - int min; - int sec; - int msec; + int hr = -1; + int min = -1; + int sec = -1; + int msec = -1; String source_file; String source_func; - int source_line; + int source_line = -1; String error; String error_descr; - bool warning; + bool warning = false; Vector<ScriptLanguage::StackInfo> callstack; - OutputError() { - hr = -1; - min = -1; - sec = -1; - msec = -1; - source_line = -1; - warning = false; - } - Array serialize(); bool deserialize(const Array &p_arr); }; diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index bfe38d0f4a..5c9fb67de4 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -32,6 +32,7 @@ #include "core/debugger/local_debugger.h" #include "core/debugger/remote_debugger.h" +#include "core/debugger/remote_debugger_peer.h" #include "core/debugger/script_debugger.h" #include "core/os/os.h" @@ -40,6 +41,7 @@ ScriptDebugger *EngineDebugger::script_debugger = nullptr; Map<StringName, EngineDebugger::Profiler> EngineDebugger::profilers; Map<StringName, EngineDebugger::Capture> EngineDebugger::captures; +Map<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols; void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) { ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name); @@ -66,6 +68,11 @@ void EngineDebugger::unregister_message_capture(const StringName &p_name) { captures.erase(p_name); } +void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) { + ERR_FAIL_COND_MSG(protocols.has(p_protocol), "Protocol handler already registered: " + p_protocol); + protocols.insert(p_protocol, p_func); +} + void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) { ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't change profiler state, no profiler: " + p_name); Profiler &p = profilers[p_name]; @@ -104,8 +111,9 @@ Error EngineDebugger::capture_parse(const StringName &p_name, const String &p_ms void EngineDebugger::line_poll() { // The purpose of this is just processing events every now and then when the script might get too busy otherwise bugs like infinite loops can't be caught - if (poll_every % 2048 == 0) + if (poll_every % 2048 == 0) { poll_events(false); + } poll_every++; } @@ -117,40 +125,49 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, ui // Notify tick to running profilers for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) { Profiler &p = E->get(); - if (!p.active || !p.tick) + if (!p.active || !p.tick) { continue; + } p.tick(p.data, frame_time, idle_time, physics_time, physics_frame_time); } singleton->poll_events(true); } void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints) { - if (p_uri.empty()) + register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more. + if (p_uri.empty()) { return; + } if (p_uri == "local://") { singleton = memnew(LocalDebugger); script_debugger = memnew(ScriptDebugger); // Tell the OS that we want to handle termination signals. OS::get_singleton()->initialize_debugging(); - } else { - singleton = RemoteDebugger::create_for_uri(p_uri); - if (!singleton) + } else if (p_uri.find("://") >= 0) { + const String proto = p_uri.substr(0, p_uri.find("://") + 3); + if (!protocols.has(proto)) { return; + } + RemoteDebuggerPeer *peer = protocols[proto](p_uri); + if (!peer) { + return; + } + singleton = memnew(RemoteDebugger(Ref<RemoteDebuggerPeer>(peer))); script_debugger = memnew(ScriptDebugger); // Notify editor of our pid (to allow focus stealing). Array msg; msg.push_back(OS::get_singleton()->get_process_id()); singleton->send_message("set_pid", msg); } - if (!singleton) + if (!singleton) { return; + } // There is a debugger, parse breakpoints. ScriptDebugger *singleton_script_debugger = singleton->get_script_debugger(); singleton_script_debugger->set_skip_breakpoints(p_skip_breakpoints); for (int i = 0; i < p_breakpoints.size(); i++) { - String bp = p_breakpoints[i]; int sp = bp.find_last(":"); ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format."); @@ -160,27 +177,31 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve } void EngineDebugger::deinitialize() { - if (!singleton) - return; - - // Stop all profilers - for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) { - if (E->get().active) - singleton->profiler_enable(E->key(), false); + if (singleton) { + // Stop all profilers + for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) { + if (E->get().active) { + singleton->profiler_enable(E->key(), false); + } + } + + // Flush any remaining message + singleton->poll_events(false); + + memdelete(singleton); + singleton = nullptr; } - // Flush any remaining message - singleton->poll_events(false); - - memdelete(singleton); - singleton = nullptr; + // Clear profilers/captuers/protocol handlers. profilers.clear(); captures.clear(); + protocols.clear(); } EngineDebugger::~EngineDebugger() { - if (script_debugger) + if (script_debugger) { memdelete(script_debugger); + } script_debugger = nullptr; singleton = nullptr; } diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 7b6b77ca9b..8d5ebb2394 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -38,6 +38,7 @@ #include "core/variant.h" #include "core/vector.h" +class RemoteDebuggerPeer; class ScriptDebugger; class EngineDebugger { @@ -45,8 +46,11 @@ public: typedef void (*ProfilingToggle)(void *p_user, bool p_enable, const Array &p_opts); typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time); typedef void (*ProfilingAdd)(void *p_user, const Array &p_arr); + typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured); + typedef RemoteDebuggerPeer *(*CreatePeerFunc)(const String &p_uri); + class Profiler { friend class EngineDebugger; @@ -94,6 +98,7 @@ protected: static Map<StringName, Profiler> profilers; static Map<StringName, Capture> captures; + static Map<String, CreatePeerFunc> protocols; public: _FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; } @@ -113,6 +118,8 @@ public: static void unregister_message_capture(const StringName &p_name); static bool has_capture(const StringName &p_name); + static void register_uri_handler(const String &p_protocol, CreatePeerFunc p_func); + void iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, uint64_t p_physics_ticks, float p_physics_frame_time); void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array()); Error capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured); diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 6d88ceb2c1..876be79418 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -36,7 +36,6 @@ struct LocalDebugger::ScriptsProfiler { struct ProfileInfoSort { - bool operator()(const ScriptLanguage::ProfilingInfo &A, const ScriptLanguage::ProfilingInfo &B) const { return A.total_time > B.total_time; } @@ -70,17 +69,19 @@ struct LocalDebugger::ScriptsProfiler { void _print_frame_data(bool p_accumulated) { uint64_t diff = OS::get_singleton()->get_ticks_usec() - idle_accum; - if (!p_accumulated && diff < 1000000) //show every one second + if (!p_accumulated && diff < 1000000) { //show every one second return; + } idle_accum = OS::get_singleton()->get_ticks_usec(); int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { - if (p_accumulated) + if (p_accumulated) { ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&pinfo.write[ofs], pinfo.size() - ofs); - else + } else { ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&pinfo.write[ofs], pinfo.size() - ofs); + } } SortArray<ScriptLanguage::ProfilingInfo, ProfileInfoSort> sort; @@ -89,7 +90,6 @@ struct LocalDebugger::ScriptsProfiler { // compute total script frame time uint64_t script_time_us = 0; for (int i = 0; i < ofs; i++) { - script_time_us += pinfo[i].self_time; } float script_time = USEC_TO_SEC(script_time_us); @@ -102,7 +102,6 @@ struct LocalDebugger::ScriptsProfiler { } for (int i = 0; i < ofs; i++) { - print_line(itos(i) + ":" + pinfo[i].signature); float tt = USEC_TO_SEC(pinfo[i].total_time); float st = USEC_TO_SEC(pinfo[i].self_time); @@ -116,7 +115,6 @@ struct LocalDebugger::ScriptsProfiler { }; void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { - ScriptLanguage *script_lang = script_debugger->get_break_language(); if (!target_function.empty()) { @@ -135,7 +133,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { int current_frame = 0; int total_frames = script_lang->debug_get_stack_level_count(); while (true) { - OS::get_singleton()->print("debug> "); String line = OS::get_singleton()->get_stdin_string().strip_edges(); @@ -146,18 +143,15 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { print_line("\nDebugger Break, Reason: '" + script_lang->debug_get_error() + "'"); print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'"); print_line("Enter \"help\" for assistance."); - } else if (line == "c" || line == "continue") + } else if (line == "c" || line == "continue") { break; - else if (line == "bt" || line == "breakpoint") { - + } else if (line == "bt" || line == "breakpoint") { for (int i = 0; i < total_frames; i++) { - String cfi = (current_frame == i) ? "*" : " "; //current frame indicator print_line(cfi + "Frame " + itos(i) + " - " + script_lang->debug_get_stack_level_source(i) + ":" + itos(script_lang->debug_get_stack_level_line(i)) + " in function '" + script_lang->debug_get_stack_level_function(i) + "'"); } } else if (line.begins_with("fr") || line.begins_with("frame")) { - if (line.get_slice_count(" ") == 1) { print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'"); } else { @@ -171,9 +165,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line.begins_with("set")) { - if (line.get_slice_count(" ") == 1) { - for (Map<String, String>::Element *E = options.front(); E; E = E->next()) { print_line("\t" + E->key() + "=" + E->value()); } @@ -185,13 +177,11 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { if (value_pos < 0) { print_line("Error: Invalid set format. Use: set key=value"); } else { - String key = key_value.left(value_pos); if (!options.has(key)) { print_line("Error: Unknown option " + key); } else { - // Allow explicit tab character String value = key_value.right(value_pos + 1).replace("\\t", "\t"); @@ -201,49 +191,41 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line == "lv" || line == "locals") { - List<String> locals; List<Variant> values; script_lang->debug_get_stack_level_locals(current_frame, &locals, &values); print_variables(locals, values, variable_prefix); } else if (line == "gv" || line == "globals") { - List<String> globals; List<Variant> values; script_lang->debug_get_globals(&globals, &values); print_variables(globals, values, variable_prefix); } else if (line == "mv" || line == "members") { - List<String> members; List<Variant> values; script_lang->debug_get_stack_level_members(current_frame, &members, &values); print_variables(members, values, variable_prefix); } else if (line.begins_with("p") || line.begins_with("print")) { - if (line.get_slice_count(" ") <= 1) { print_line("Usage: print <expre>"); } else { - String expr = line.get_slicec(' ', 2); String res = script_lang->debug_parse_stack_level_expression(current_frame, expr); print_line(res); } } else if (line == "s" || line == "step") { - script_debugger->set_depth(-1); script_debugger->set_lines_left(1); break; } else if (line == "n" || line == "next") { - script_debugger->set_depth(0); script_debugger->set_lines_left(1); break; } else if (line == "fin" || line == "finish") { - String current_function = script_lang->debug_get_stack_level_function(0); for (int i = 0; i < total_frames; i++) { @@ -259,9 +241,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { target_function = ""; } else if (line.begins_with("br") || line.begins_with("break")) { - if (line.get_slice_count(" ") <= 1) { - const Map<int, Set<StringName>> &breakpoints = script_debugger->get_breakpoints(); if (breakpoints.size() == 0) { print_line("No Breakpoints."); @@ -274,14 +254,14 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else { - Pair<String, int> breakpoint = to_breakpoint(line); String source = breakpoint.first; int linenr = breakpoint.second; - if (source.empty()) + if (source.empty()) { continue; + } script_debugger->insert_breakpoint(linenr, source); @@ -289,7 +269,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line == "q" || line == "quit") { - // Do not stop again on quit script_debugger->clear_breakpoints(); script_debugger->set_depth(-1); @@ -298,18 +277,17 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { SceneTree::get_singleton()->quit(); break; } else if (line.begins_with("delete")) { - if (line.get_slice_count(" ") <= 1) { script_debugger->clear_breakpoints(); } else { - Pair<String, int> breakpoint = to_breakpoint(line); String source = breakpoint.first; int linenr = breakpoint.second; - if (source.empty()) + if (source.empty()) { continue; + } script_debugger->remove_breakpoint(linenr, source); @@ -317,7 +295,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line == "h" || line == "help") { - print_line("Built-In Debugger command list:\n"); print_line("\tc,continue\t\t Continue execution."); print_line("\tbt,backtrace\t\t Show stack trace (frames)."); @@ -340,18 +317,15 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } void LocalDebugger::print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix) { - String value; Vector<String> value_lines; const List<Variant>::Element *V = values.front(); for (const List<String>::Element *E = names.front(); E; E = E->next()) { - value = String(V->get()); if (variable_prefix.empty()) { print_line(E->get() + ": " + String(V->get())); } else { - print_line(E->get() + ":"); value_lines = value.split("\n"); for (int i = 0; i < value_lines.size(); ++i) { @@ -364,7 +338,6 @@ void LocalDebugger::print_variables(const List<String> &names, const List<Varian } Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) { - String breakpoint_part = p_line.get_slicec(' ', 1); Pair<String, int> breakpoint; @@ -381,18 +354,15 @@ Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) { } void LocalDebugger::send_message(const String &p_message, const Array &p_args) { - // This needs to be cleaned up entirely. // print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args))); } void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { - print_line("ERROR: '" + (p_descr.empty() ? p_err : p_descr) + "'"); } LocalDebugger::LocalDebugger() { - options["variable_prefix"] = ""; // Bind scripts profiler. @@ -411,6 +381,7 @@ LocalDebugger::LocalDebugger() { LocalDebugger::~LocalDebugger() { unregister_profiler("scripts"); - if (scripts_profiler) + if (scripts_profiler) { memdelete(scripts_profiler); + } } diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h index 2c4302f4da..d342da6d44 100644 --- a/core/debugger/local_debugger.h +++ b/core/debugger/local_debugger.h @@ -36,7 +36,6 @@ #include "core/script_language.h" class LocalDebugger : public EngineDebugger { - private: struct ScriptsProfiler; diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index e6bcc5f77e..62f600c5e5 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -33,7 +33,7 @@ #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" -#include "core/input/input_filter.h" +#include "core/input/input.h" #include "core/os/os.h" #include "core/project_settings.h" #include "core/script_language.h" @@ -57,7 +57,6 @@ void RemoteDebugger::_bind_profiler(const String &p_name, T *p_prof) { } struct RemoteDebugger::NetworkProfiler { - public: typedef DebuggerMarshalls::MultiplayerNodeInfo NodeInfo; struct BandwidthFrame { @@ -97,8 +96,9 @@ public: } void init_node(const ObjectID p_node) { - if (multiplayer_node_data.has(p_node)) + if (multiplayer_node_data.has(p_node)) { return; + } multiplayer_node_data.insert(p_node, DebuggerMarshalls::MultiplayerNodeInfo()); multiplayer_node_data[p_node].node = p_node; multiplayer_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path(); @@ -191,7 +191,6 @@ struct RemoteDebugger::ScriptsProfiler { typedef DebuggerMarshalls::ScriptFunctionSignature FunctionSignature; typedef DebuggerMarshalls::ScriptFunctionInfo FunctionInfo; struct ProfileInfoSort { - bool operator()(ScriptLanguage::ProfilingInfo *A, ScriptLanguage::ProfilingInfo *B) const { return A->total_time < B->total_time; } @@ -220,10 +219,11 @@ struct RemoteDebugger::ScriptsProfiler { void write_frame_data(Vector<FunctionInfo> &r_funcs, uint64_t &r_total, bool p_accumulated) { int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { - if (p_accumulated) + if (p_accumulated) { ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&info.write[ofs], info.size() - ofs); - else + } else { ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&info.write[ofs], info.size() - ofs); + } } for (int i = 0; i < ofs; i++) { @@ -270,7 +270,6 @@ struct RemoteDebugger::ScriptsProfiler { }; struct RemoteDebugger::ServersProfiler { - bool skip_profile_frame = false; typedef DebuggerMarshalls::ServerInfo ServerInfo; typedef DebuggerMarshalls::ServerFunctionInfo ServerFunctionInfo; @@ -347,7 +346,6 @@ struct RemoteDebugger::ServersProfiler { }; struct RemoteDebugger::VisualProfiler { - typedef DebuggerMarshalls::ServerInfo ServerInfo; typedef DebuggerMarshalls::ServerFunctionInfo ServerFunctionInfo; @@ -362,8 +360,9 @@ struct RemoteDebugger::VisualProfiler { void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) { Vector<RS::FrameProfileArea> profile_areas = RS::get_singleton()->get_frame_profile(); DebuggerMarshalls::VisualProfilerFrame frame; - if (!profile_areas.size()) + if (!profile_areas.size()) { return; + } frame.frame_number = RS::get_singleton()->get_frame_profile_frame(); frame.areas.append_array(profile_areas); @@ -372,19 +371,20 @@ struct RemoteDebugger::VisualProfiler { }; struct RemoteDebugger::PerformanceProfiler { - Object *performance = nullptr; int last_perf_time = 0; void toggle(bool p_enable, const Array &p_opts) {} void add(const Array &p_data) {} void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) { - if (!performance) + if (!performance) { return; + } uint64_t pt = OS::get_singleton()->get_ticks_msec(); - if (pt - last_perf_time < 1000) + if (pt - last_perf_time < 1000) { return; + } last_perf_time = pt; int max = performance->get("MONITOR_MAX"); Array arr; @@ -401,14 +401,12 @@ struct RemoteDebugger::PerformanceProfiler { }; void RemoteDebugger::_send_resource_usage() { - DebuggerMarshalls::ResourceUsage usage; List<RS::TextureInfo> tinfo; RS::get_singleton()->texture_debug_usage(&tinfo); for (List<RS::TextureInfo>::Element *E = tinfo.front(); E; E = E->next()) { - DebuggerMarshalls::ResourceInfo info; info.path = E->get().path; info.vram = E->get().bytes; @@ -430,26 +428,29 @@ Error RemoteDebugger::_put_msg(String p_message, Array p_data) { msg.push_back(p_message); msg.push_back(p_data); Error err = peer->put_message(msg); - if (err != OK) + if (err != OK) { n_messages_dropped++; + } return err; } void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) { - - if (p_type == ERR_HANDLER_SCRIPT) + if (p_type == ERR_HANDLER_SCRIPT) { return; //ignore script errors, those go through debugger + } RemoteDebugger *rd = (RemoteDebugger *)p_this; - if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) // Can't handle recursive errors during flush. + if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive errors during flush. return; + } Vector<ScriptLanguage::StackInfo> si; for (int i = 0; i < ScriptServer::get_language_count(); i++) { si = ScriptServer::get_language(i)->debug_get_current_stack_info(); - if (si.size()) + if (si.size()) { break; + } } // send_error will lock internally. @@ -457,17 +458,18 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char * } void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) { - RemoteDebugger *rd = (RemoteDebugger *)p_this; - if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) // Can't handle recursive prints during flush. + if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive prints during flush. return; + } String s = p_string; int allowed_chars = MIN(MAX(rd->max_chars_per_second - rd->char_count, 0), s.length()); - if (allowed_chars == 0) + if (allowed_chars == 0 && s.length() > 0) { return; + } if (allowed_chars < s.length()) { s = s.substr(0, allowed_chars); @@ -478,12 +480,19 @@ void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p rd->char_count += allowed_chars; bool overflowed = rd->char_count >= rd->max_chars_per_second; if (rd->is_peer_connected()) { - if (overflowed) + if (overflowed) { s += "[...]"; - rd->output_strings.push_back(s); + } + + OutputString output_string; + output_string.message = s; + output_string.type = p_error ? MESSAGE_TYPE_ERROR : MESSAGE_TYPE_LOG; + rd->output_strings.push_back(output_string); if (overflowed) { - rd->output_strings.push_back("[output overflow, print less text!]"); + output_string.message = "[output overflow, print less text!]"; + output_string.type = MESSAGE_TYPE_ERROR; + rd->output_strings.push_back(output_string); } } } @@ -505,27 +514,45 @@ void RemoteDebugger::flush_output() { flush_thread = Thread::get_caller_id(); flushing = true; MutexLock lock(mutex); - if (!is_peer_connected()) + if (!is_peer_connected()) { return; + } if (n_messages_dropped > 0) { ErrorMessage err_msg = _create_overflow_error("TOO_MANY_MESSAGES", "Too many messages! " + String::num_int64(n_messages_dropped) + " messages were dropped. Profiling might misbheave, try raising 'network/limits/debugger/max_queued_messages' in project setting."); - if (_put_msg("error", err_msg.serialize()) == OK) + if (_put_msg("error", err_msg.serialize()) == OK) { n_messages_dropped = 0; + } } if (output_strings.size()) { - // Join output strings so we generate less messages. + Vector<String> joined_log_strings; Vector<String> strings; - strings.resize(output_strings.size()); - String *w = strings.ptrw(); + Vector<int> types; for (int i = 0; i < output_strings.size(); i++) { - w[i] = output_strings[i]; + const OutputString &output_string = output_strings[i]; + if (output_string.type == MESSAGE_TYPE_ERROR) { + if (!joined_log_strings.empty()) { + strings.push_back(String("\n").join(joined_log_strings)); + types.push_back(MESSAGE_TYPE_LOG); + joined_log_strings.clear(); + } + strings.push_back(output_string.message); + types.push_back(MESSAGE_TYPE_ERROR); + } else { + joined_log_strings.push_back(output_string.message); + } + } + + if (!joined_log_strings.empty()) { + strings.push_back(String("\n").join(joined_log_strings)); + types.push_back(MESSAGE_TYPE_LOG); } Array arr; arr.push_back(strings); + arr.push_back(types); _put_msg("output", arr); output_strings.clear(); } @@ -551,7 +578,6 @@ void RemoteDebugger::flush_output() { } void RemoteDebugger::send_message(const String &p_message, const Array &p_args) { - MutexLock lock(mutex); if (is_peer_connected()) { _put_msg(p_message, p_args); @@ -559,7 +585,6 @@ void RemoteDebugger::send_message(const String &p_message, const Array &p_args) } void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { - ErrorMessage oe; oe.error = p_err; oe.error_descr = p_descr; @@ -574,8 +599,9 @@ void RemoteDebugger::send_error(const String &p_func, const String &p_file, int oe.msec = time % 1000; oe.callstack.append_array(script_debugger->get_error_stack_info()); - if (flushing && Thread::get_caller_id() == flush_thread) // Can't handle recursive errors during flush. + if (flushing && Thread::get_caller_id() == flush_thread) { // Can't handle recursive errors during flush. return; + } MutexLock lock(mutex); @@ -586,7 +612,6 @@ void RemoteDebugger::send_error(const String &p_func, const String &p_file, int } if (is_peer_connected()) { - if (oe.warning) { if (warn_count > max_warnings_per_second) { n_warnings_dropped++; @@ -634,22 +659,27 @@ Error RemoteDebugger::_try_capture(const String &p_msg, const Array &p_data, boo return OK; } const String cap = p_msg.substr(0, idx); - if (!has_capture(cap)) + if (!has_capture(cap)) { return ERR_UNAVAILABLE; // Unknown message... + } const String msg = p_msg.substr(idx + 1); return capture_parse(cap, msg, p_data, r_captured); } void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { - //this function is called when there is a debugger break (bug on script) //or when execution is paused from editor - if (script_debugger->is_skipping_breakpoints() && !p_is_error_breakpoint) + if (script_debugger->is_skipping_breakpoints() && !p_is_error_breakpoint) { return; + } ERR_FAIL_COND_MSG(!is_peer_connected(), "Script Debugger failed to connect, but being used anyway."); + if (!peer->can_block()) { + return; // Peer does not support blocking IO. We could at least send the error though. + } + ScriptLanguage *script_lang = script_debugger->get_break_language(); const String error_str = script_lang ? script_lang->debug_get_error() : ""; Array msg; @@ -659,9 +689,10 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { servers_profiler->skip_profile_frame = true; // Avoid frame time spike in debug. - InputFilter::MouseMode mouse_mode = InputFilter::get_singleton()->get_mouse_mode(); - if (mouse_mode != InputFilter::MOUSE_MODE_VISIBLE) - InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE); + Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode(); + if (mouse_mode != Input::MOUSE_MODE_VISIBLE) { + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + } uint64_t loop_begin_usec = 0; uint64_t loop_time_sec = 0; @@ -672,7 +703,6 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { peer->poll(); if (peer->has_message()) { - Array cmd = peer->get_message(); ERR_CONTINUE(cmd.size() != 2); @@ -750,10 +780,11 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else if (command == "breakpoint") { ERR_FAIL_COND(data.size() < 3); bool set = data[2]; - if (set) + if (set) { script_debugger->insert_breakpoint(data[1], data[0]); - else + } else { script_debugger->remove_breakpoint(data[1], data[0]); + } } else if (command == "set_skip_breakpoints") { ERR_FAIL_COND(data.size() < 1); @@ -761,8 +792,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else { bool captured = false; ERR_CONTINUE(_try_capture(command, data, captured) != OK); - if (!captured) + if (!captured) { WARN_PRINT("Unknown message received from debugger: " + command); + } } } else { OS::get_singleton()->delay_usec(10000); @@ -779,18 +811,19 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { send_message("debug_exit", Array()); - if (mouse_mode != InputFilter::MOUSE_MODE_VISIBLE) - InputFilter::get_singleton()->set_mouse_mode(mouse_mode); + if (mouse_mode != Input::MOUSE_MODE_VISIBLE) { + Input::get_singleton()->set_mouse_mode(mouse_mode); + } } void RemoteDebugger::poll_events(bool p_is_idle) { - if (peer.is_null()) + if (peer.is_null()) { return; + } flush_output(); peer->poll(); while (peer->has_message()) { - Array arr = peer->get_message(); ERR_CONTINUE(arr.size() != 2); @@ -806,8 +839,9 @@ void RemoteDebugger::poll_events(bool p_is_idle) { } const String cap = cmd.substr(0, idx); - if (!has_capture(cap)) + if (!has_capture(cap)) { continue; // Unknown message... + } const String msg = cmd.substr(idx + 1); capture_parse(cap, msg, arr[1], parsed); @@ -830,10 +864,11 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo } else if (p_cmd == "breakpoint") { ERR_FAIL_COND_V(p_data.size() < 3, ERR_INVALID_DATA); bool set = p_data[2]; - if (set) + if (set) { script_debugger->insert_breakpoint(p_data[1], p_data[0]); - else + } else { script_debugger->remove_breakpoint(p_data[1], p_data[0]); + } } else if (p_cmd == "set_skip_breakpoints") { ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA); @@ -863,13 +898,6 @@ Error RemoteDebugger::_profiler_capture(const String &p_cmd, const Array &p_data return OK; } -RemoteDebugger *RemoteDebugger::create_for_uri(const String &p_uri) { - Ref<RemoteDebuggerPeer> peer = RemoteDebuggerPeer::create_from_uri(p_uri); - if (peer.is_valid()) - return memnew(RemoteDebugger(peer)); - return nullptr; -} - RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) { peer = p_peer; max_chars_per_second = GLOBAL_GET("network/limits/debugger/max_chars_per_second"); @@ -931,6 +959,7 @@ RemoteDebugger::~RemoteDebugger() { memdelete(servers_profiler); memdelete(network_profiler); memdelete(visual_profiler); - if (performance_profiler) + if (performance_profiler) { memdelete(performance_profiler); + } } diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index f805eec631..dc7e4436e1 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -40,6 +40,11 @@ #include "core/ustring.h" class RemoteDebugger : public EngineDebugger { +public: + enum MessageType { + MESSAGE_TYPE_LOG, + MESSAGE_TYPE_ERROR, + }; private: typedef DebuggerMarshalls::OutputError ErrorMessage; @@ -57,7 +62,11 @@ private: Ref<RemoteDebuggerPeer> peer; - List<String> output_strings; + struct OutputString { + String message; + MessageType type; + }; + List<OutputString> output_strings; List<ErrorMessage> errors; int n_messages_dropped = 0; @@ -99,8 +108,6 @@ private: Error _try_capture(const String &p_name, const Array &p_data, bool &r_captured); public: - static RemoteDebugger *create_for_uri(const String &p_uri); - // Overrides void poll_events(bool p_is_idle); void send_message(const String &p_message, const Array &p_args); diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index ed04431177..faa3a75fda 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -52,8 +52,9 @@ Array RemoteDebuggerPeerTCP::get_message() { Error RemoteDebuggerPeerTCP::put_message(const Array &p_arr) { MutexLock lock(mutex); - if (out_queue.size() >= max_queued_messages) + if (out_queue.size() >= max_queued_messages) { return ERR_OUT_OF_MEMORY; + } out_queue.push_back(p_arr); return OK; @@ -99,8 +100,9 @@ void RemoteDebuggerPeerTCP::_write_out() { while (tcp_client->poll(NetSocket::POLL_TYPE_OUT) == OK) { uint8_t *buf = out_buf.ptrw(); if (out_left <= 0) { - if (out_queue.size() == 0) + if (out_queue.size() == 0) { break; // Nothing left to send + } mutex.lock(); Variant var = out_queue[0]; out_queue.pop_front(); @@ -154,12 +156,12 @@ void RemoteDebuggerPeerTCP::_read_in() { } Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) { - IP_Address ip; - if (p_host.is_valid_ip_address()) + if (p_host.is_valid_ip_address()) { ip = p_host; - else + } else { ip = IP::get_singleton()->resolve_hostname(p_host); + } int port = p_port; @@ -169,23 +171,20 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po tcp_client->connect_to_host(ip, port); for (int i = 0; i < tries; i++) { - if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) { print_verbose("Remote Debugger: Connected!"); break; } else { - const int ms = waits[i]; OS::get_singleton()->delay_usec(ms * 1000); print_verbose("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec."); - }; - }; + } + } if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) { - ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + "."); return FAILED; - }; + } connected = true; #ifndef NO_THREADS running = true; @@ -198,8 +197,9 @@ void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) { RemoteDebuggerPeerTCP *peer = (RemoteDebuggerPeerTCP *)p_ud; while (peer->running && peer->is_peer_connected()) { peer->_poll(); - if (!peer->is_peer_connected()) + if (!peer->is_peer_connected()) { break; + } peer->tcp_client->poll(NetSocket::POLL_TYPE_IN_OUT, 1); } } @@ -218,9 +218,8 @@ void RemoteDebuggerPeerTCP::_poll() { } } -Ref<RemoteDebuggerPeer> RemoteDebuggerPeer::create_from_uri(const String p_uri) { - if (!p_uri.begins_with("tcp://")) - return Ref<RemoteDebuggerPeer>(); // Only TCP supported for now, more to come. +RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) { + ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr); String debug_host = p_uri.replace("tcp://", ""); uint16_t debug_port = 6007; @@ -230,10 +229,13 @@ Ref<RemoteDebuggerPeer> RemoteDebuggerPeer::create_from_uri(const String p_uri) debug_port = debug_host.substr(sep_pos + 1).to_int(); debug_host = debug_host.substr(0, sep_pos); } - Ref<RemoteDebuggerPeerTCP> peer = Ref<RemoteDebuggerPeer>(memnew(RemoteDebuggerPeerTCP)); + + RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP); Error err = peer->connect_to_host(debug_host, debug_port); - if (err != OK) - return Ref<RemoteDebuggerPeer>(); + if (err != OK) { + memdelete(peer); + return nullptr; + } return peer; } diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h index e4b838f145..3a75a2a02b 100644 --- a/core/debugger/remote_debugger_peer.h +++ b/core/debugger/remote_debugger_peer.h @@ -42,7 +42,6 @@ protected: int max_queued_messages = 4096; public: - static Ref<RemoteDebuggerPeer> create_from_uri(const String p_uri); virtual bool is_peer_connected() = 0; virtual bool has_message() = 0; virtual Error put_message(const Array &p_arr) = 0; @@ -50,6 +49,7 @@ public: virtual void close() = 0; virtual void poll() = 0; virtual int get_max_message_size() const = 0; + virtual bool can_block() const { return true; } // If blocking io is allowed on main thread (debug). RemoteDebuggerPeer(); }; @@ -77,6 +77,8 @@ private: void _read_in(); public: + static RemoteDebuggerPeer *create(const String &p_uri); + Error connect_to_host(const String &p_host, uint16_t p_port); void poll(); diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index 935ad01d80..0cd3238efb 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -33,69 +33,63 @@ #include "core/debugger/engine_debugger.h" void ScriptDebugger::set_lines_left(int p_left) { - lines_left = p_left; } int ScriptDebugger::get_lines_left() const { - return lines_left; } void ScriptDebugger::set_depth(int p_depth) { - depth = p_depth; } int ScriptDebugger::get_depth() const { - return depth; } void ScriptDebugger::insert_breakpoint(int p_line, const StringName &p_source) { - - if (!breakpoints.has(p_line)) + if (!breakpoints.has(p_line)) { breakpoints[p_line] = Set<StringName>(); + } breakpoints[p_line].insert(p_source); } void ScriptDebugger::remove_breakpoint(int p_line, const StringName &p_source) { - - if (!breakpoints.has(p_line)) + if (!breakpoints.has(p_line)) { return; + } breakpoints[p_line].erase(p_source); - if (breakpoints[p_line].size() == 0) + if (breakpoints[p_line].size() == 0) { breakpoints.erase(p_line); + } } -bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const { - if (!breakpoints.has(p_line)) +bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const { + if (!breakpoints.has(p_line)) { return false; + } return breakpoints[p_line].has(p_source); } -bool ScriptDebugger::is_breakpoint_line(int p_line) const { +bool ScriptDebugger::is_breakpoint_line(int p_line) const { return breakpoints.has(p_line); } String ScriptDebugger::breakpoint_find_source(const String &p_source) const { - return p_source; } void ScriptDebugger::clear_breakpoints() { - breakpoints.clear(); } void ScriptDebugger::set_skip_breakpoints(bool p_skip_breakpoints) { - skip_breakpoints = p_skip_breakpoints; } bool ScriptDebugger::is_skipping_breakpoints() { - return skip_breakpoints; } @@ -118,6 +112,5 @@ Vector<ScriptLanguage::StackInfo> ScriptDebugger::get_error_stack_info() const { } ScriptLanguage *ScriptDebugger::get_break_language() const { - return break_lang; } diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index e5066273d2..0068691825 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -38,7 +38,6 @@ #include "core/vector.h" class ScriptDebugger { - typedef ScriptLanguage::StackInfo StackInfo; int lines_left = -1; diff --git a/core/dictionary.cpp b/core/dictionary.cpp index bc3b792bd5..052e1bdae1 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -35,15 +35,14 @@ #include "core/variant.h" struct DictionaryPrivate { - SafeRefCount refcount; OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> variant_map; }; void Dictionary::get_key_list(List<Variant> *p_keys) const { - - if (_p->variant_map.empty()) + if (_p->variant_map.empty()) { return; + } for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { p_keys->push_back(E.key()); @@ -51,7 +50,6 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const { } Variant Dictionary::get_key_at_index(int p_index) const { - int index = 0; for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { if (index == p_index) { @@ -64,7 +62,6 @@ Variant Dictionary::get_key_at_index(int p_index) const { } Variant Dictionary::get_value_at_index(int p_index) const { - int index = 0; for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { if (index == p_index) { @@ -77,38 +74,37 @@ Variant Dictionary::get_value_at_index(int p_index) const { } Variant &Dictionary::operator[](const Variant &p_key) { - return _p->variant_map[p_key]; } const Variant &Dictionary::operator[](const Variant &p_key) const { - return _p->variant_map[p_key]; } -const Variant *Dictionary::getptr(const Variant &p_key) const { +const Variant *Dictionary::getptr(const Variant &p_key) const { OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); - if (!E) + if (!E) { return nullptr; + } return &E.get(); } Variant *Dictionary::getptr(const Variant &p_key) { - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(p_key); - if (!E) + if (!E) { return nullptr; + } return &E.get(); } Variant Dictionary::get_valid(const Variant &p_key) const { - OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::ConstElement E = ((const OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator> *)&_p->variant_map)->find(p_key); - if (!E) + if (!E) { return Variant(); + } return E.get(); } @@ -122,16 +118,14 @@ Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const { } int Dictionary::size() const { - return _p->variant_map.size(); } -bool Dictionary::empty() const { +bool Dictionary::empty() const { return !_p->variant_map.size(); } bool Dictionary::has(const Variant &p_key) const { - return _p->variant_map.has(p_key); } @@ -145,51 +139,47 @@ bool Dictionary::has_all(const Array &p_keys) const { } bool Dictionary::erase(const Variant &p_key) { - return _p->variant_map.erase(p_key); } bool Dictionary::operator==(const Dictionary &p_dictionary) const { - return _p == p_dictionary._p; } bool Dictionary::operator!=(const Dictionary &p_dictionary) const { - return _p != p_dictionary._p; } void Dictionary::_ref(const Dictionary &p_from) const { - //make a copy first (thread safe) - if (!p_from._p->refcount.ref()) + if (!p_from._p->refcount.ref()) { return; // couldn't copy + } //if this is the same, unreference the other one if (p_from._p == _p) { _p->refcount.unref(); return; } - if (_p) + if (_p) { _unref(); + } _p = p_from._p; } void Dictionary::clear() { - _p->variant_map.clear(); } void Dictionary::_unref() const { - ERR_FAIL_COND(!_p); if (_p->refcount.unref()) { memdelete(_p); } _p = nullptr; } -uint32_t Dictionary::hash() const { +uint32_t Dictionary::hash() const { uint32_t h = hash_djb2_one_32(Variant::DICTIONARY); for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { @@ -201,10 +191,10 @@ uint32_t Dictionary::hash() const { } Array Dictionary::keys() const { - Array varr; - if (_p->variant_map.empty()) + if (_p->variant_map.empty()) { return varr; + } varr.resize(size()); @@ -218,10 +208,10 @@ Array Dictionary::keys() const { } Array Dictionary::values() const { - Array varr; - if (_p->variant_map.empty()) + if (_p->variant_map.empty()) { return varr; + } varr.resize(size()); @@ -235,22 +225,22 @@ Array Dictionary::values() const { } const Variant *Dictionary::next(const Variant *p_key) const { - if (p_key == nullptr) { // caller wants to get the first element - if (_p->variant_map.front()) + if (_p->variant_map.front()) { return &_p->variant_map.front().key(); + } return nullptr; } OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.find(*p_key); - if (E && E.next()) + if (E && E.next()) { return &E.next().key(); + } return nullptr; } Dictionary Dictionary::duplicate(bool p_deep) const { - Dictionary n; for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { @@ -261,7 +251,6 @@ Dictionary Dictionary::duplicate(bool p_deep) const { } void Dictionary::operator=(const Dictionary &p_dictionary) { - _ref(p_dictionary); } @@ -275,11 +264,10 @@ Dictionary::Dictionary(const Dictionary &p_from) { } Dictionary::Dictionary() { - _p = memnew(DictionaryPrivate); _p->refcount.init(); } -Dictionary::~Dictionary() { +Dictionary::~Dictionary() { _unref(); } diff --git a/core/dictionary.h b/core/dictionary.h index c6cbacc144..a01d96ba01 100644 --- a/core/dictionary.h +++ b/core/dictionary.h @@ -40,7 +40,6 @@ class Variant; struct DictionaryPrivate; class Dictionary { - mutable DictionaryPrivate *_p; void _ref(const Dictionary &p_from) const; diff --git a/core/engine.cpp b/core/engine.cpp index 5361e09a8a..c8bfffd020 100644 --- a/core/engine.cpp +++ b/core/engine.cpp @@ -37,18 +37,18 @@ #include "core/version_hash.gen.h" void Engine::set_iterations_per_second(int p_ips) { - ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0."); ips = p_ips; } -int Engine::get_iterations_per_second() const { +int Engine::get_iterations_per_second() const { return ips; } void Engine::set_physics_jitter_fix(float p_threshold) { - if (p_threshold < 0) + if (p_threshold < 0) { p_threshold = 0; + } physics_jitter_fix = p_threshold; } @@ -65,32 +65,26 @@ int Engine::get_target_fps() const { } uint64_t Engine::get_frames_drawn() { - return frames_drawn; } void Engine::set_frame_delay(uint32_t p_msec) { - _frame_delay = p_msec; } uint32_t Engine::get_frame_delay() const { - return _frame_delay; } void Engine::set_time_scale(float p_scale) { - _time_scale = p_scale; } float Engine::get_time_scale() const { - return _time_scale; } Dictionary Engine::get_version_info() const { - Dictionary dict; dict["major"] = VERSION_MAJOR; dict["minor"] = VERSION_MINOR; @@ -104,8 +98,9 @@ Dictionary Engine::get_version_info() const { dict["hash"] = hash.length() == 0 ? String("unknown") : hash; String stringver = String(dict["major"]) + "." + String(dict["minor"]); - if ((int)dict["patch"] != 0) + if ((int)dict["patch"] != 0) { stringver += "." + String(dict["patch"]); + } stringver += "-" + String(dict["status"]) + " (" + String(dict["build"]) + ")"; dict["string"] = stringver; @@ -185,27 +180,24 @@ String Engine::get_license_text() const { } void Engine::add_singleton(const Singleton &p_singleton) { - singletons.push_back(p_singleton); singleton_ptrs[p_singleton.name] = p_singleton.ptr; } Object *Engine::get_singleton_object(const String &p_name) const { - const Map<StringName, Object *>::Element *E = singleton_ptrs.find(p_name); ERR_FAIL_COND_V_MSG(!E, nullptr, "Failed to retrieve non-existent singleton '" + p_name + "'."); return E->get(); -}; +} bool Engine::has_singleton(const String &p_name) const { - return singleton_ptrs.has(p_name); -}; +} void Engine::get_singletons(List<Singleton> *p_singletons) { - - for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) + for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) { p_singletons->push_back(E->get()); + } } Engine *Engine::singleton = nullptr; @@ -217,23 +209,7 @@ Engine *Engine::get_singleton() { bool Engine::is_abort_on_gpu_errors_enabled() const { return abort_on_gpu_errors; } -Engine::Engine() { +Engine::Engine() { singleton = this; - frames_drawn = 0; - ips = 60; - physics_jitter_fix = 0.5; - _physics_interpolation_fraction = 0.0f; - _frame_delay = 0; - _fps = 1; - _target_fps = 0; - _time_scale = 1.0; - _pixel_snap = false; - _physics_frames = 0; - _idle_frames = 0; - _in_physics = false; - _frame_ticks = 0; - _frame_step = 0; - editor_hint = false; - abort_on_gpu_errors = false; } diff --git a/core/engine.h b/core/engine.h index 8512779d4c..fef330c0c1 100644 --- a/core/engine.h +++ b/core/engine.h @@ -37,7 +37,6 @@ #include "core/vector.h" class Engine { - public: struct Singleton { StringName name; @@ -51,28 +50,28 @@ public: private: friend class Main; - uint64_t frames_drawn; - uint32_t _frame_delay; - uint64_t _frame_ticks; - float _frame_step; + uint64_t frames_drawn = 0; + uint32_t _frame_delay = 0; + uint64_t _frame_ticks = 0; + float _frame_step = 0; - int ips; - float physics_jitter_fix; - float _fps; - int _target_fps; - float _time_scale; - bool _pixel_snap; - uint64_t _physics_frames; - float _physics_interpolation_fraction; - bool abort_on_gpu_errors; + int ips = 60; + float physics_jitter_fix = 0.5; + float _fps = 1; + int _target_fps = 0; + float _time_scale = 1.0; + bool _pixel_snap = false; + uint64_t _physics_frames = 0; + float _physics_interpolation_fraction = 0.0f; + bool abort_on_gpu_errors = false; - uint64_t _idle_frames; - bool _in_physics; + uint64_t _idle_frames = 0; + bool _in_physics = false; List<Singleton> singletons; Map<StringName, Object *> singleton_ptrs; - bool editor_hint; + bool editor_hint = false; static Engine *singleton; diff --git a/core/error_macros.cpp b/core/error_macros.cpp index 5de070844a..2fae939965 100644 --- a/core/error_macros.cpp +++ b/core/error_macros.cpp @@ -37,7 +37,6 @@ static ErrorHandlerList *error_handler_list = nullptr; void add_error_handler(ErrorHandlerList *p_handler) { - _global_lock(); p_handler->next = error_handler_list; error_handler_list = p_handler; @@ -45,20 +44,18 @@ void add_error_handler(ErrorHandlerList *p_handler) { } void remove_error_handler(ErrorHandlerList *p_handler) { - _global_lock(); ErrorHandlerList *prev = nullptr; ErrorHandlerList *l = error_handler_list; while (l) { - if (l == p_handler) { - - if (prev) + if (prev) { prev->next = l->next; - else + } else { error_handler_list = l->next; + } break; } prev = l; @@ -77,13 +74,11 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co } void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type) { - OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, (Logger::ErrorType)p_type); _global_lock(); ErrorHandlerList *l = error_handler_list; while (l) { - l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_type); l = l->next; } @@ -104,7 +99,6 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co } 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, const char *p_message, bool fatal) { - String fstr(fatal ? "FATAL: " : ""); String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ")."); _err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message); diff --git a/core/error_macros.h b/core/error_macros.h index 18c46c9e7d..d7366be453 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -47,17 +47,12 @@ enum ErrorHandlerType { typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type); struct ErrorHandlerList { + ErrorHandlerFunc errfunc = nullptr; + void *userdata = nullptr; - ErrorHandlerFunc errfunc; - void *userdata; + ErrorHandlerList *next = nullptr; - ErrorHandlerList *next; - - ErrorHandlerList() { - errfunc = 0; - next = 0; - userdata = 0; - } + ErrorHandlerList() {} }; void add_error_handler(ErrorHandlerList *p_handler); @@ -108,6 +103,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * running application to fail or crash. * Always try to return processable data, so the engine can keep running well. * Use the _MSG versions to print a meaningful message to help with debugging. + * + * The `((void)0)` no-op statement is used as a trick to force us to put a semicolon after + * those macros, making them look like proper statements. + * The if wrappers are used to ensure that the macro replacement does not trigger unexpected + * issues when expanded e.g. after an `if (cond) ERR_FAIL();` without braces. */ // Index out of bounds error macros. @@ -285,7 +285,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, the current function returns. */ #define ERR_FAIL_NULL(m_param) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ return; \ } else \ @@ -296,7 +296,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, prints `m_msg` and the current function returns. */ #define ERR_FAIL_NULL_MSG(m_param, m_msg) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ return; \ } else \ @@ -310,7 +310,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, the current function returns `m_retval`. */ #define ERR_FAIL_NULL_V(m_param, m_retval) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ return m_retval; \ } else \ @@ -321,7 +321,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, prints `m_msg` and the current function returns `m_retval`. */ #define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ return m_retval; \ } else \ @@ -366,11 +366,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Ensures `m_cond` is false. * If `m_cond` is true, the current function returns `m_retval`. */ -#define ERR_FAIL_COND_V(m_cond, m_retval) \ - 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 \ +#define ERR_FAIL_COND_V(m_cond, m_retval) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval)); \ + return m_retval; \ + } else \ ((void)0) /** @@ -380,11 +380,11 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If checking for null use ERR_FAIL_NULL_V_MSG instead. * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead. */ -#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ - if (unlikely(m_cond)) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. returned: " _STR(m_retval), DEBUG_STR(m_msg)); \ - return m_retval; \ - } else \ +#define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \ + return m_retval; \ + } else \ ((void)0) /** @@ -477,7 +477,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li */ #define ERR_FAIL() \ if (1) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed."); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed."); \ return; \ } else \ ((void)0) @@ -490,7 +490,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li */ #define ERR_FAIL_MSG(m_msg) \ if (1) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed.", DEBUG_STR(m_msg)); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", DEBUG_STR(m_msg)); \ return; \ } else \ ((void)0) @@ -504,7 +504,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li */ #define ERR_FAIL_V(m_retval) \ if (1) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " _STR(m_retval)); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval)); \ return m_retval; \ } else \ ((void)0) @@ -517,7 +517,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li */ #define ERR_FAIL_V_MSG(m_retval, m_msg) \ if (1) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/Function Failed, returning: " _STR(m_retval), DEBUG_STR(m_msg)); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), DEBUG_STR(m_msg)); \ return m_retval; \ } else \ ((void)0) @@ -530,19 +530,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * Prints `m_msg`. */ #define ERR_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg) /** * Prints `m_msg` once during the application lifetime. */ -#define ERR_PRINT_ONCE(m_msg) \ - if (1) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg)); \ - first_print = false; \ - } \ - } else \ +#define ERR_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \ + first_print = false; \ + } \ + } else \ ((void)0) // Print warning message macros. @@ -553,21 +553,21 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ #define WARN_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING) /** * Prints `m_msg` once during the application lifetime. * * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINT_ONCE(m_msg) \ - if (1) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, DEBUG_STR(m_msg), ERR_HANDLER_WARNING); \ - first_print = false; \ - } \ - } else \ +#define WARN_PRINT_ONCE(m_msg) \ + if (1) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING); \ + first_print = false; \ + } \ + } else \ ((void)0) // Print deprecated warning message macros. @@ -606,7 +606,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li */ #define CRASH_NOW() \ if (1) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed."); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed."); \ GENERATE_TRAP(); \ } else \ ((void)0) @@ -618,7 +618,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li */ #define CRASH_NOW_MSG(m_msg) \ if (1) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/Function Failed.", DEBUG_STR(m_msg)); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Method/function failed.", DEBUG_STR(m_msg)); \ GENERATE_TRAP(); \ } else \ ((void)0) diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 338c17946b..4427d94d2a 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -31,7 +31,6 @@ #include "func_ref.h" Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (id.is_null()) { r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; return Variant(); @@ -47,7 +46,6 @@ Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Callable::Cal } Variant FuncRef::call_funcv(const Array &p_args) { - ERR_FAIL_COND_V(id.is_null(), Variant()); Object *obj = ObjectDB::get_instance(id); @@ -58,29 +56,28 @@ Variant FuncRef::call_funcv(const Array &p_args) { } void FuncRef::set_instance(Object *p_obj) { - ERR_FAIL_NULL(p_obj); id = p_obj->get_instance_id(); } void FuncRef::set_function(const StringName &p_func) { - function = p_func; } bool FuncRef::is_valid() const { - if (id.is_null()) + if (id.is_null()) { return false; + } Object *obj = ObjectDB::get_instance(id); - if (!obj) + if (!obj) { return false; + } return obj->has_method(function); } void FuncRef::_bind_methods() { - { MethodInfo mi; mi.name = "call_func"; @@ -94,6 +91,3 @@ void FuncRef::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function); ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid); } - -FuncRef::FuncRef() { -} diff --git a/core/func_ref.h b/core/func_ref.h index 8cb3be6e61..6b0b22bab5 100644 --- a/core/func_ref.h +++ b/core/func_ref.h @@ -34,7 +34,6 @@ #include "core/reference.h" class FuncRef : public Reference { - GDCLASS(FuncRef, Reference); ObjectID id; StringName function; @@ -48,7 +47,8 @@ public: void set_instance(Object *p_obj); void set_function(const StringName &p_func); bool is_valid() const; - FuncRef(); + + FuncRef() {} }; #endif // FUNC_REF_H diff --git a/core/global_constants.cpp b/core/global_constants.cpp index 6f6b8c1dd3..6281e56395 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -36,7 +36,6 @@ #include "core/variant.h" struct _GlobalConstant { - #ifdef DEBUG_METHODS_ENABLED StringName enum_name; #endif @@ -88,7 +87,8 @@ static Vector<_GlobalConstant> _global_constants; VARIANT_ENUM_CAST(KeyList); VARIANT_ENUM_CAST(KeyModifierMask); VARIANT_ENUM_CAST(ButtonList); -VARIANT_ENUM_CAST(JoystickList); +VARIANT_ENUM_CAST(JoyButtonList); +VARIANT_ENUM_CAST(JoyAxisList); VARIANT_ENUM_CAST(MidiMessageList); void register_global_constants() { @@ -388,90 +388,70 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_XBUTTON1); BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_XBUTTON2); - //joypads - 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); + // Joypad buttons + BIND_GLOBAL_ENUM_CONSTANT(JOY_INVALID_BUTTON); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_A); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_B); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_BACK); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_GUIDE); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_START); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_LEFT_STICK); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_RIGHT_STICK); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_LEFT_SHOULDER); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_RIGHT_SHOULDER); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_UP); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_DOWN); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_LEFT); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_RIGHT); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SDL_BUTTONS); BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_CROSS); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_CIRCLE); 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_SONY_SELECT); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_START); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_PS); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_L1); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_R1); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_L3); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_R3); BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_A); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_B); BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_X); BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_BACK); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_START); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_HOME); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_LS); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_RS); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_LB); + BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_RB); + BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_MAX); - 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_VR_GRIP); - BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_PAD); - BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_TRIGGER); - - BIND_GLOBAL_ENUM_CONSTANT(JOY_OCULUS_AX); - BIND_GLOBAL_ENUM_CONSTANT(JOY_OCULUS_BY); - BIND_GLOBAL_ENUM_CONSTANT(JOY_OCULUS_MENU); - - BIND_GLOBAL_ENUM_CONSTANT(JOY_OPENVR_MENU); - - 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_8); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_9); + // Joypad axes + BIND_GLOBAL_ENUM_CONSTANT(JOY_INVALID_AXIS); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_LEFT_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_LEFT_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_RIGHT_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_RIGHT_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_TRIGGER_LEFT); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_TRIGGER_RIGHT); + BIND_GLOBAL_ENUM_CONSTANT(JOY_SDL_AXES); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_0_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_0_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_1_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_1_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_2_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_2_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_3_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_3_Y); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_4_X); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_4_Y); 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); - - BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_ANALOG_TRIGGER); - BIND_GLOBAL_ENUM_CONSTANT(JOY_VR_ANALOG_GRIP); - - BIND_GLOBAL_ENUM_CONSTANT(JOY_OPENVR_TOUCHPADX); - BIND_GLOBAL_ENUM_CONSTANT(JOY_OPENVR_TOUCHPADY); - // midi BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF); BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON); @@ -568,6 +548,7 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_GROUP); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY); + BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED); BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE); @@ -656,33 +637,27 @@ void register_global_constants() { } void unregister_global_constants() { - _global_constants.clear(); } int GlobalConstants::get_global_constant_count() { - return _global_constants.size(); } #ifdef DEBUG_METHODS_ENABLED StringName GlobalConstants::get_global_constant_enum(int p_idx) { - return _global_constants[p_idx].enum_name; } #else StringName GlobalConstants::get_global_constant_enum(int p_idx) { - return StringName(); } #endif const char *GlobalConstants::get_global_constant_name(int p_idx) { - return _global_constants[p_idx].name; } int GlobalConstants::get_global_constant_value(int p_idx) { - return _global_constants[p_idx].value; } diff --git a/core/hash_map.h b/core/hash_map.h index f27a86cc02..843430d082 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -59,7 +59,6 @@ template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Co class HashMap { public: struct Pair { - TKey key; TData data; @@ -75,8 +74,8 @@ public: friend class HashMap; uint32_t hash; - Element *next; - Element() { next = 0; } + Element *next = nullptr; + Element() {} Pair pair; public: @@ -94,34 +93,32 @@ public: }; private: - Element **hash_table; - uint8_t hash_table_power; - uint32_t elements; + Element **hash_table = nullptr; + uint8_t hash_table_power = 0; + uint32_t elements = 0; void make_hash_table() { - ERR_FAIL_COND(hash_table); hash_table = memnew_arr(Element *, (1 << MIN_HASH_TABLE_POWER)); hash_table_power = MIN_HASH_TABLE_POWER; elements = 0; - for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) - hash_table[i] = 0; + for (int i = 0; i < (1 << MIN_HASH_TABLE_POWER); i++) { + hash_table[i] = nullptr; + } } void erase_hash_table() { - ERR_FAIL_COND_MSG(elements, "Cannot erase hash table if there are still elements inside."); memdelete_arr(hash_table); - hash_table = 0; + hash_table = nullptr; hash_table_power = 0; elements = 0; } void check_hash_table() { - int new_hash_table_power = -1; if ((int)elements > ((1 << hash_table_power) * RELATIONSHIP)) { @@ -129,40 +126,36 @@ private: new_hash_table_power = hash_table_power + 1; while ((int)elements > ((1 << new_hash_table_power) * RELATIONSHIP)) { - new_hash_table_power++; } } else if ((hash_table_power > (int)MIN_HASH_TABLE_POWER) && ((int)elements < ((1 << (hash_table_power - 1)) * RELATIONSHIP))) { - /* rehash down */ new_hash_table_power = hash_table_power - 1; while ((int)elements < ((1 << (new_hash_table_power - 1)) * RELATIONSHIP)) { - new_hash_table_power--; } - if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) + if (new_hash_table_power < (int)MIN_HASH_TABLE_POWER) { new_hash_table_power = MIN_HASH_TABLE_POWER; + } } - if (new_hash_table_power == -1) + if (new_hash_table_power == -1) { return; + } Element **new_hash_table = memnew_arr(Element *, ((uint64_t)1 << new_hash_table_power)); ERR_FAIL_COND_MSG(!new_hash_table, "Out of memory."); for (int i = 0; i < (1 << new_hash_table_power); i++) { - - new_hash_table[i] = 0; + new_hash_table[i] = nullptr; } if (hash_table) { for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { - Element *se = hash_table[i]; hash_table[i] = se->next; int new_pos = se->hash & ((1 << new_hash_table_power) - 1); @@ -179,17 +172,14 @@ private: /* I want to have only one function.. */ _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); Element *e = hash_table[index]; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) { - /* the pair exists in this hashtable, so just update data */ return e; } @@ -201,7 +191,6 @@ private: } Element *create_element(const TKey &p_key) { - /* if element doesn't exist, create it */ Element *e = memnew(Element); ERR_FAIL_COND_V_MSG(!e, nullptr, "Out of memory."); @@ -219,27 +208,26 @@ private: } void copy_from(const HashMap &p_t) { - - if (&p_t == this) + if (&p_t == this) { return; /* much less bother with that */ + } clear(); - if (!p_t.hash_table || p_t.hash_table_power == 0) + if (!p_t.hash_table || p_t.hash_table_power == 0) { return; /* not copying from empty table */ + } hash_table = memnew_arr(Element *, (uint64_t)1 << p_t.hash_table_power); hash_table_power = p_t.hash_table_power; elements = p_t.elements; for (int i = 0; i < (1 << p_t.hash_table_power); i++) { - hash_table[i] = nullptr; const Element *e = p_t.hash_table[i]; while (e) { - Element *le = memnew(Element); /* local element */ *le = *e; /* copy data */ @@ -259,20 +247,20 @@ public: } Element *set(const Pair &p_pair) { - Element *e = nullptr; - if (!hash_table) + if (!hash_table) { make_hash_table(); // if no table, make one - else + } else { 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_element(p_pair.key); - if (!e) + if (!e) { return nullptr; + } check_hash_table(); // perform mantenience routine } @@ -281,7 +269,6 @@ public: } bool has(const TKey &p_key) const { - return getptr(p_key) != nullptr; } @@ -292,14 +279,12 @@ public: */ const TData &get(const TKey &p_key) const { - const TData *res = getptr(p_key); ERR_FAIL_COND_V(!res, *res); return *res; } TData &get(const TKey &p_key) { - TData *res = getptr(p_key); ERR_FAIL_COND_V(!res, *res); return *res; @@ -311,27 +296,29 @@ public: */ _FORCE_INLINE_ TData *getptr(const TKey &p_key) { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } Element *e = const_cast<Element *>(get_element(p_key)); - if (e) + if (e) { return &e->pair.data; + } return nullptr; } _FORCE_INLINE_ const TData *getptr(const TKey &p_key) const { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } const Element *e = const_cast<Element *>(get_element(p_key)); - if (e) + if (e) { return &e->pair.data; + } return nullptr; } @@ -343,9 +330,9 @@ public: template <class C> _FORCE_INLINE_ TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } uint32_t hash = p_custom_hash; uint32_t index = hash & ((1 << hash_table_power) - 1); @@ -353,10 +340,8 @@ public: Element *e = hash_table[index]; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) { - /* the pair exists in this hashtable, so just update data */ return &e->pair.data; } @@ -369,9 +354,9 @@ public: template <class C> _FORCE_INLINE_ const TData *custom_getptr(C p_custom_key, uint32_t p_custom_hash) const { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } uint32_t hash = p_custom_hash; uint32_t index = hash & ((1 << hash_table_power) - 1); @@ -379,10 +364,8 @@ public: const Element *e = hash_table[index]; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_custom_key)) { - /* the pair exists in this hashtable, so just update data */ return &e->pair.data; } @@ -398,9 +381,9 @@ public: */ bool erase(const TKey &p_key) { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return false; + } uint32_t hash = Hasher::hash(p_key); uint32_t index = hash & ((1 << hash_table_power) - 1); @@ -408,12 +391,9 @@ public: Element *e = hash_table[index]; Element *p = nullptr; while (e) { - /* checking hash first avoids comparing key, which may take longer */ if (e->hash == hash && Comparator::compare(e->pair.key, p_key)) { - if (p) { - p->next = e->next; } else { //begin of list @@ -423,10 +403,11 @@ public: memdelete(e); elements--; - if (elements == 0) + if (elements == 0) { erase_hash_table(); - else + } else { check_hash_table(); + } return true; } @@ -444,14 +425,14 @@ public: inline TData &operator[](const TKey &p_key) { //assignment Element *e = nullptr; - if (!hash_table) + if (!hash_table) { make_hash_table(); // if no table, make one - else + } else { 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_element(p_key); CRASH_COND(!e); check_hash_table(); // perform mantenience routine @@ -476,14 +457,13 @@ public: * */ const TKey *next(const TKey *p_key) const { - - if (unlikely(!hash_table)) + if (unlikely(!hash_table)) { return nullptr; + } if (!p_key) { /* get the first key */ for (int i = 0; i < (1 << hash_table_power); i++) { - if (hash_table[i]) { return &hash_table[i]->pair.key; } @@ -501,7 +481,6 @@ public: uint32_t index = e->hash & ((1 << hash_table_power) - 1); index++; for (int i = index; i < (1 << hash_table_power); i++) { - if (hash_table[i]) { return &hash_table[i]->pair.key; } @@ -515,23 +494,18 @@ public: } inline unsigned int size() const { - return elements; } inline bool empty() const { - return elements == 0; } void clear() { - /* clean up */ if (hash_table) { for (int i = 0; i < (1 << hash_table_power); i++) { - while (hash_table[i]) { - Element *e = hash_table[i]; hash_table[i] = e->next; memdelete(e); @@ -541,60 +515,35 @@ public: memdelete_arr(hash_table); } - hash_table = 0; + hash_table = nullptr; hash_table_power = 0; elements = 0; } void operator=(const HashMap &p_table) { - copy_from(p_table); } - HashMap() { - hash_table = nullptr; - elements = 0; - hash_table_power = 0; - } - - void get_key_value_ptr_array(const Pair **p_pairs) const { - if (unlikely(!hash_table)) + void get_key_list(List<TKey> *r_keys) const { + if (unlikely(!hash_table)) { return; - for (int i = 0; i < (1 << hash_table_power); i++) { - - Element *e = hash_table[i]; - while (e) { - *p_pairs = &e->pair; - p_pairs++; - e = e->next; - } } - } - - void get_key_list(List<TKey> *p_keys) const { - if (unlikely(!hash_table)) - return; for (int i = 0; i < (1 << hash_table_power); i++) { - Element *e = hash_table[i]; while (e) { - p_keys->push_back(e->pair.key); + r_keys->push_back(e->pair.key); e = e->next; } } } - HashMap(const HashMap &p_table) { - - hash_table = nullptr; - elements = 0; - hash_table_power = 0; + HashMap() {} + HashMap(const HashMap &p_table) { copy_from(p_table); } ~HashMap() { - clear(); } }; diff --git a/core/hashfuncs.h b/core/hashfuncs.h index a41a034843..d984f6c524 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -49,29 +49,28 @@ * @return 32-bits hashcode */ static inline uint32_t hash_djb2(const char *p_cstr) { - const unsigned char *chr = (const unsigned char *)p_cstr; uint32_t hash = 5381; uint32_t c; - while ((c = *chr++)) + while ((c = *chr++)) { hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + } return hash; } static inline uint32_t hash_djb2_buffer(const uint8_t *p_buff, int p_len, uint32_t p_prev = 5381) { - uint32_t hash = p_prev; - for (int i = 0; i < p_len; i++) + for (int i = 0; i < p_len; i++) { hash = ((hash << 5) + hash) + p_buff[i]; /* hash * 33 + c */ + } return hash; } static inline uint32_t hash_djb2_one_32(uint32_t p_in, uint32_t p_prev = 5381) { - return ((p_prev << 5) + p_prev) + p_in; } @@ -93,19 +92,19 @@ static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381) } u; // Normalize +/- 0.0 and NaN values so they hash the same. - if (p_in == 0.0f) + if (p_in == 0.0f) { u.d = 0.0; - else if (Math::is_nan(p_in)) + } else if (Math::is_nan(p_in)) { u.d = Math_NAN; - else + } else { u.d = p_in; + } return ((p_prev << 5) + p_prev) + hash_one_uint64(u.i); } template <class T> static inline uint32_t make_uint32_t(T p_in) { - union { T t; uint32_t _u32; @@ -116,13 +115,11 @@ static inline uint32_t make_uint32_t(T p_in) { } static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) { - return ((p_prev << 5) + p_prev) + p_in; } template <class T> static inline uint64_t make_uint64_t(T p_in) { - union { T t; uint64_t _u64; @@ -134,7 +131,6 @@ static inline uint64_t make_uint64_t(T p_in) { } 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); } diff --git a/core/image.cpp b/core/image.cpp index 2097f27b01..0f15574053 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -37,8 +37,6 @@ #include "core/os/copymem.h" #include "core/print_string.h" -#include "thirdparty/misc/hq2x.h" - #include <stdio.h> const char *Image::format_names[Image::FORMAT_MAX] = { @@ -90,7 +88,6 @@ SaveEXRFunc Image::save_exr_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr; void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) { - uint32_t ofs = (p_y * width + p_x) * p_pixelsize; for (uint32_t i = 0; i < p_pixelsize; i++) { @@ -99,7 +96,6 @@ void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, } void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel) { - uint32_t ofs = (p_y * width + p_x) * p_pixelsize; for (uint32_t i = 0; i < p_pixelsize; i++) { @@ -108,29 +104,41 @@ void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p } int Image::get_format_pixel_size(Format p_format) { - switch (p_format) { case FORMAT_L8: return 1; //luminance case FORMAT_LA8: return 2; //luminance-alpha - case FORMAT_R8: return 1; - case FORMAT_RG8: return 2; - case FORMAT_RGB8: return 3; - case FORMAT_RGBA8: return 4; - case FORMAT_RGBA4444: return 2; - case FORMAT_RGB565: return 2; + case FORMAT_R8: + return 1; + case FORMAT_RG8: + return 2; + case FORMAT_RGB8: + return 3; + case FORMAT_RGBA8: + return 4; + case FORMAT_RGBA4444: + return 2; + case FORMAT_RGB565: + return 2; case FORMAT_RF: return 4; //float - case FORMAT_RGF: return 8; - case FORMAT_RGBF: return 12; - case FORMAT_RGBAF: return 16; + case FORMAT_RGF: + return 8; + case FORMAT_RGBF: + return 12; + case FORMAT_RGBAF: + return 16; case FORMAT_RH: return 2; //half float - case FORMAT_RGH: return 4; - case FORMAT_RGBH: return 6; - case FORMAT_RGBAH: return 8; - case FORMAT_RGBE9995: return 4; + case FORMAT_RGH: + return 4; + case FORMAT_RGBH: + return 6; + case FORMAT_RGBAH: + return 8; + case FORMAT_RGBE9995: + return 4; case FORMAT_DXT1: return 1; //s3tc bc1 case FORMAT_DXT3: @@ -149,22 +157,32 @@ int Image::get_format_pixel_size(Format p_format) { return 1; //unsigned float case FORMAT_PVRTC2: return 1; //pvrtc - case FORMAT_PVRTC2A: return 1; - case FORMAT_PVRTC4: return 1; - case FORMAT_PVRTC4A: return 1; + case FORMAT_PVRTC2A: + return 1; + case FORMAT_PVRTC4: + return 1; + case FORMAT_PVRTC4A: + return 1; case FORMAT_ETC: return 1; //etc1 case FORMAT_ETC2_R11: return 1; //etc2 case FORMAT_ETC2_R11S: return 1; //signed: return 1; NOT srgb. - case FORMAT_ETC2_RG11: return 1; - case FORMAT_ETC2_RG11S: return 1; - case FORMAT_ETC2_RGB8: return 1; - case FORMAT_ETC2_RGBA8: return 1; - case FORMAT_ETC2_RGB8A1: return 1; - case FORMAT_ETC2_RA_AS_RG: return 1; - case FORMAT_DXT5_RA_AS_RG: return 1; + case FORMAT_ETC2_RG11: + return 1; + case FORMAT_ETC2_RG11S: + return 1; + case FORMAT_ETC2_RGB8: + return 1; + case FORMAT_ETC2_RGBA8: + return 1; + case FORMAT_ETC2_RGB8A1: + return 1; + case FORMAT_ETC2_RA_AS_RG: + return 1; + case FORMAT_DXT5_RA_AS_RG: + return 1; case FORMAT_MAX: { } } @@ -172,7 +190,6 @@ int Image::get_format_pixel_size(Format p_format) { } void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { - switch (p_format) { case FORMAT_DXT1: //s3tc bc1 case FORMAT_DXT3: //bc2 @@ -185,25 +202,21 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { } break; case FORMAT_PVRTC2: case FORMAT_PVRTC2A: { - r_w = 16; r_h = 8; } break; case FORMAT_PVRTC4A: case FORMAT_PVRTC4: { - r_w = 8; r_h = 8; } break; case FORMAT_ETC: { - r_w = 4; r_h = 4; } break; case FORMAT_BPTC_RGBA: case FORMAT_BPTC_RGBF: case FORMAT_BPTC_RGBFU: { - r_w = 4; r_h = 4; } break; @@ -216,7 +229,6 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { case FORMAT_ETC2_RGB8A1: case FORMAT_ETC2_RA_AS_RG: case FORMAT_DXT5_RA_AS_RG: { - r_w = 4; r_h = 4; @@ -230,17 +242,16 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { } int Image::get_format_pixel_rshift(Format p_format) { - - if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) + if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) { return 1; - else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A) + } else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A) { return 2; - else + } else { return 0; + } } int Image::get_format_block_size(Format p_format) { - switch (p_format) { case FORMAT_DXT1: //s3tc bc1 case FORMAT_DXT3: //bc2 @@ -252,22 +263,18 @@ int Image::get_format_block_size(Format p_format) { } case FORMAT_PVRTC2: case FORMAT_PVRTC2A: { - return 4; } case FORMAT_PVRTC4A: case FORMAT_PVRTC4: { - return 4; } case FORMAT_ETC: { - return 4; } case FORMAT_BPTC_RGBA: case FORMAT_BPTC_RGBF: case FORMAT_BPTC_RGBFU: { - return 4; } case FORMAT_ETC2_R11: //etc2 @@ -281,7 +288,6 @@ int Image::get_format_block_size(Format p_format) { case FORMAT_DXT5_RA_AS_RG: //used to make basis universal happy { - return 4; } default: { @@ -292,7 +298,6 @@ int Image::get_format_block_size(Format p_format) { } void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_width, int &r_height) const { - int w = width; int h = height; int ofs = 0; @@ -322,7 +327,6 @@ void Image::_get_mipmap_offset_and_size(int p_mipmap, int &r_offset, int &r_widt } int Image::get_mipmap_offset(int p_mipmap) const { - ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1); int ofs, w, h; @@ -331,7 +335,6 @@ int Image::get_mipmap_offset(int p_mipmap) const { } int Image::get_mipmap_byte_size(int p_mipmap) const { - ERR_FAIL_INDEX_V(p_mipmap, get_mipmap_count() + 1, -1); int ofs, w, h; @@ -342,7 +345,6 @@ int Image::get_mipmap_byte_size(int p_mipmap) const { } void Image::get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const { - int ofs, w, h; _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); int ofs2; @@ -352,7 +354,6 @@ void Image::get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) co } void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const { - int ofs; _get_mipmap_offset_and_size(p_mipmap, ofs, w, h); int ofs2, w2, h2; @@ -362,42 +363,36 @@ void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int } int Image::get_width() const { - return width; } int Image::get_height() const { - return height; } Vector2 Image::get_size() const { - return Vector2(width, height); } bool Image::has_mipmaps() const { - return mipmaps; } int Image::get_mipmap_count() const { - - if (mipmaps) + if (mipmaps) { return get_image_required_mipmaps(width, height, format); - else + } else { return 0; + } } //using template generates perfectly optimized code due to constant expression reduction and unused variable removal present in all compilers template <uint32_t read_bytes, bool read_alpha, uint32_t write_bytes, bool write_alpha, bool read_gray, bool write_gray> static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p_dst) { - uint32_t max_bytes = MAX(read_bytes, write_bytes); for (int y = 0; y < p_height; y++) { for (int x = 0; x < p_width; x++) { - const uint8_t *rofs = &p_src[((y * p_width) + x) * (read_bytes + (read_alpha ? 1 : 0))]; uint8_t *wofs = &p_dst[((y * p_width) + x) * (write_bytes + (write_alpha ? 1 : 0))]; @@ -408,9 +403,7 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p rgba[1] = rofs[0]; rgba[2] = rofs[0]; } else { - for (uint32_t i = 0; i < max_bytes; i++) { - rgba[i] = (i < read_bytes) ? rofs[i] : 0; } } @@ -424,7 +417,6 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p wofs[0] = uint8_t((uint16_t(rofs[0]) + uint16_t(rofs[1]) + uint16_t(rofs[2])) / 3); } else { for (uint32_t i = 0; i < write_bytes; i++) { - wofs[i] = rgba[i]; } } @@ -437,25 +429,23 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p } void Image::convert(Format p_new_format) { - - if (data.size() == 0) + if (data.size() == 0) { return; + } - if (p_new_format == format) + if (p_new_format == format) { return; + } if (format > FORMAT_RGBE9995 || p_new_format > FORMAT_RGBE9995) { - ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead."); } else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) { - //use put/set pixel which is slower but works with non byte formats - Image new_img(width, height, 0, p_new_format); + Image new_img(width, height, false, p_new_format); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - new_img.set_pixel(i, j, get_pixel(i, j)); } } @@ -469,7 +459,7 @@ void Image::convert(Format p_new_format) { return; } - Image new_img(width, height, 0, p_new_format); + Image new_img(width, height, false, p_new_format); const uint8_t *rptr = data.ptr(); uint8_t *wptr = new_img.data.ptrw(); @@ -477,69 +467,127 @@ void Image::convert(Format p_new_format) { int conversion_type = format | p_new_format << 8; switch (conversion_type) { - - case FORMAT_L8 | (FORMAT_LA8 << 8): _convert<1, false, 1, true, true, true>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_R8 << 8): _convert<1, false, 1, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_RG8 << 8): _convert<1, false, 2, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_RGB8 << 8): _convert<1, false, 3, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_L8 | (FORMAT_RGBA8 << 8): _convert<1, false, 3, true, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_L8 << 8): _convert<1, true, 1, false, true, true>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_R8 << 8): _convert<1, true, 1, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_RG8 << 8): _convert<1, true, 2, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_RGB8 << 8): _convert<1, true, 3, false, true, false>(width, height, rptr, wptr); break; - case FORMAT_LA8 | (FORMAT_RGBA8 << 8): _convert<1, true, 3, true, true, false>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_L8 << 8): _convert<1, false, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_LA8 << 8): _convert<1, false, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_RG8 << 8): _convert<1, false, 2, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_RGB8 << 8): _convert<1, false, 3, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_R8 | (FORMAT_RGBA8 << 8): _convert<1, false, 3, true, false, false>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_L8 << 8): _convert<2, false, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_LA8 << 8): _convert<2, false, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_R8 << 8): _convert<2, false, 1, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_RGB8 << 8): _convert<2, false, 3, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RG8 | (FORMAT_RGBA8 << 8): _convert<2, false, 3, true, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_L8 << 8): _convert<3, false, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_LA8 << 8): _convert<3, false, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_R8 << 8): _convert<3, false, 1, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_RG8 << 8): _convert<3, false, 2, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGB8 | (FORMAT_RGBA8 << 8): _convert<3, false, 3, true, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_L8 << 8): _convert<3, true, 1, false, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_LA8 << 8): _convert<3, true, 1, true, false, true>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_R8 << 8): _convert<3, true, 1, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_RG8 << 8): _convert<3, true, 2, false, false, false>(width, height, rptr, wptr); break; - case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): _convert<3, true, 3, false, false, false>(width, height, rptr, wptr); break; + case FORMAT_L8 | (FORMAT_LA8 << 8): + _convert<1, false, 1, true, true, true>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_R8 << 8): + _convert<1, false, 1, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_RG8 << 8): + _convert<1, false, 2, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_RGB8 << 8): + _convert<1, false, 3, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_L8 | (FORMAT_RGBA8 << 8): + _convert<1, false, 3, true, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_L8 << 8): + _convert<1, true, 1, false, true, true>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_R8 << 8): + _convert<1, true, 1, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_RG8 << 8): + _convert<1, true, 2, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_RGB8 << 8): + _convert<1, true, 3, false, true, false>(width, height, rptr, wptr); + break; + case FORMAT_LA8 | (FORMAT_RGBA8 << 8): + _convert<1, true, 3, true, true, false>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_L8 << 8): + _convert<1, false, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_LA8 << 8): + _convert<1, false, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_RG8 << 8): + _convert<1, false, 2, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_RGB8 << 8): + _convert<1, false, 3, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_R8 | (FORMAT_RGBA8 << 8): + _convert<1, false, 3, true, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_L8 << 8): + _convert<2, false, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_LA8 << 8): + _convert<2, false, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_R8 << 8): + _convert<2, false, 1, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_RGB8 << 8): + _convert<2, false, 3, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RG8 | (FORMAT_RGBA8 << 8): + _convert<2, false, 3, true, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_L8 << 8): + _convert<3, false, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_LA8 << 8): + _convert<3, false, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_R8 << 8): + _convert<3, false, 1, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_RG8 << 8): + _convert<3, false, 2, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGB8 | (FORMAT_RGBA8 << 8): + _convert<3, false, 3, true, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_L8 << 8): + _convert<3, true, 1, false, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_LA8 << 8): + _convert<3, true, 1, true, false, true>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_R8 << 8): + _convert<3, true, 1, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_RG8 << 8): + _convert<3, true, 2, false, false, false>(width, height, rptr, wptr); + break; + case FORMAT_RGBA8 | (FORMAT_RGB8 << 8): + _convert<3, true, 3, false, false, false>(width, height, rptr, wptr); + break; } bool gen_mipmaps = mipmaps; _copy_internals_from(new_img); - if (gen_mipmaps) + if (gen_mipmaps) { generate_mipmaps(); + } } Image::Format Image::get_format() const { - return format; } static double _bicubic_interp_kernel(double x) { - x = ABS(x); double bc = 0; - if (x <= 1) + if (x <= 1) { bc = (1.5 * x - 2.5) * x * x + 1; - else if (x < 2) + } else if (x < 2) { bc = ((-0.5 * x + 2.5) * x - 4) * x + 2; + } return bc; } template <int CC, class T> static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) { - // get source image size int width = p_src_width; int height = p_src_height; @@ -580,20 +628,24 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_ k1 = _bicubic_interp_kernel(dy - (double)n); oy2 = oy1 + n; - if (oy2 < 0) + if (oy2 < 0) { oy2 = 0; - if (oy2 > ymax) + } + if (oy2 > ymax) { oy2 = ymax; + } for (int m = -1; m < 3; m++) { // get X coefficient k2 = k1 * _bicubic_interp_kernel((double)m - dx); ox2 = ox1 + m; - if (ox2 < 0) + if (ox2 < 0) { ox2 = 0; - if (ox2 > xmax) + } + if (ox2 > xmax) { ox2 = xmax; + } // get pixel of original image const T *__restrict p = ((T *)p_src) + (oy2 * p_src_width + ox2) * CC; @@ -623,7 +675,6 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_ template <int CC, class T> static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) { - enum { FRAC_BITS = 8, FRAC_LEN = (1 << FRAC_BITS), @@ -632,14 +683,14 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict }; for (uint32_t i = 0; i < p_dst_height; i++) { - uint32_t src_yofs_up_fp = (i * p_src_height * FRAC_LEN / p_dst_height); uint32_t src_yofs_frac = src_yofs_up_fp & FRAC_MASK; uint32_t src_yofs_up = src_yofs_up_fp >> FRAC_BITS; uint32_t src_yofs_down = (i + 1) * p_src_height / p_dst_height; - if (src_yofs_down >= p_src_height) + if (src_yofs_down >= p_src_height) { src_yofs_down = p_src_height - 1; + } //src_yofs_up*=CC; //src_yofs_down*=CC; @@ -648,19 +699,18 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict uint32_t y_ofs_down = src_yofs_down * p_src_width * CC; for (uint32_t j = 0; j < p_dst_width; j++) { - uint32_t src_xofs_left_fp = (j * p_src_width * FRAC_LEN / p_dst_width); uint32_t src_xofs_frac = src_xofs_left_fp & FRAC_MASK; uint32_t src_xofs_left = src_xofs_left_fp >> FRAC_BITS; uint32_t src_xofs_right = (j + 1) * p_src_width / p_dst_width; - if (src_xofs_right >= p_src_width) + if (src_xofs_right >= p_src_width) { src_xofs_right = p_src_width - 1; + } src_xofs_left *= CC; src_xofs_right *= CC; for (uint32_t l = 0; l < CC; l++) { - if (sizeof(T) == 1) { //uint8 uint32_t p00 = p_src[y_ofs_up + src_xofs_left + l] << FRAC_BITS; uint32_t p10 = p_src[y_ofs_up + src_xofs_right + l] << FRAC_BITS; @@ -714,19 +764,15 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict template <int CC, class T> static void _scale_nearest(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) { - for (uint32_t i = 0; i < p_dst_height; i++) { - uint32_t src_yofs = i * p_src_height / p_dst_height; uint32_t y_ofs = src_yofs * p_src_width * CC; for (uint32_t j = 0; j < p_dst_width; j++) { - uint32_t src_xofs = j * p_src_width / p_dst_width; src_xofs *= CC; for (uint32_t l = 0; l < CC; l++) { - const T *src = ((const T *)p_src); T *dst = ((T *)p_dst); @@ -745,7 +791,6 @@ static float _lanczos(float p_x) { template <int CC, class T> static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) { - int32_t src_width = p_src_width; int32_t src_height = p_src_height; int32_t dst_height = p_dst_height; @@ -764,40 +809,40 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict float *kernel = memnew_arr(float, half_kernel * 2); for (int32_t buffer_x = 0; buffer_x < dst_width; buffer_x++) { - // The corresponding point on the source image float src_x = (buffer_x + 0.5f) * x_scale; // Offset by 0.5 so it uses the pixel's center int32_t start_x = MAX(0, int32_t(src_x) - half_kernel + 1); int32_t end_x = MIN(src_width - 1, int32_t(src_x) + half_kernel); // Create the kernel used by all the pixels of the column - for (int32_t target_x = start_x; target_x <= end_x; target_x++) + for (int32_t target_x = start_x; target_x <= end_x; target_x++) { kernel[target_x - start_x] = _lanczos((target_x + 0.5f - src_x) / scale_factor); + } for (int32_t buffer_y = 0; buffer_y < src_height; buffer_y++) { - float pixel[CC] = { 0 }; float weight = 0; for (int32_t target_x = start_x; target_x <= end_x; target_x++) { - float lanczos_val = kernel[target_x - start_x]; weight += lanczos_val; const T *__restrict src_data = ((const T *)p_src) + (buffer_y * src_width + target_x) * CC; for (uint32_t i = 0; i < CC; i++) { - if (sizeof(T) == 2) //half float + if (sizeof(T) == 2) { //half float pixel[i] += Math::half_to_float(src_data[i]) * lanczos_val; - else + } else { pixel[i] += src_data[i] * lanczos_val; + } } } float *dst_data = ((float *)buffer) + (buffer_y * dst_width + buffer_x) * CC; - for (uint32_t i = 0; i < CC; i++) + for (uint32_t i = 0; i < CC; i++) { dst_data[i] = pixel[i] / weight; // Normalize the sum of all the samples + } } } @@ -814,28 +859,27 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict float *kernel = memnew_arr(float, half_kernel * 2); for (int32_t dst_y = 0; dst_y < dst_height; dst_y++) { - float buffer_y = (dst_y + 0.5f) * y_scale; int32_t start_y = MAX(0, int32_t(buffer_y) - half_kernel + 1); int32_t end_y = MIN(src_height - 1, int32_t(buffer_y) + half_kernel); - for (int32_t target_y = start_y; target_y <= end_y; target_y++) + for (int32_t target_y = start_y; target_y <= end_y; target_y++) { kernel[target_y - start_y] = _lanczos((target_y + 0.5f - buffer_y) / scale_factor); + } for (int32_t dst_x = 0; dst_x < dst_width; dst_x++) { - float pixel[CC] = { 0 }; float weight = 0; for (int32_t target_y = start_y; target_y <= end_y; target_y++) { - float lanczos_val = kernel[target_y - start_y]; weight += lanczos_val; float *buffer_data = ((float *)buffer) + (target_y * dst_width + dst_x) * CC; - for (uint32_t i = 0; i < CC; i++) + for (uint32_t i = 0; i < CC; i++) { pixel[i] += buffer_data[i] * lanczos_val; + } } T *dst_data = ((T *)p_dst) + (dst_y * dst_width + dst_x) * CC; @@ -843,12 +887,13 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict for (uint32_t i = 0; i < CC; i++) { pixel[i] /= weight; - if (sizeof(T) == 1) //byte + if (sizeof(T) == 1) { //byte dst_data[i] = CLAMP(Math::fast_ftoi(pixel[i]), 0, 255); - else if (sizeof(T) == 2) //half float + } else if (sizeof(T) == 2) { //half float dst_data[i] = Math::make_half_float(pixel[i]); - else // float + } else { // float dst_data[i] = pixel[i]; + } } } } @@ -860,11 +905,9 @@ static void _scale_lanczos(const uint8_t *__restrict p_src, uint8_t *__restrict } static void _overlay(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, float p_alpha, uint32_t p_width, uint32_t p_height, uint32_t p_pixel_size) { - uint16_t alpha = MIN((uint16_t)(p_alpha * 256.0f), 256); for (uint32_t i = 0; i < p_width * p_height * p_pixel_size; i++) { - p_dst[i] = (p_dst[i] * (256 - alpha) + p_src[i] * alpha) >> 8; } } @@ -874,23 +917,24 @@ bool Image::is_size_po2() const { } void Image::resize_to_po2(bool p_square) { - ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); int w = next_power_of_2(width); int h = next_power_of_2(height); + if (p_square) { + w = h = MAX(w, h); + } if (w == width && h == height) { - - if (!p_square || w == h) + if (!p_square || w == h) { return; //nothing to do + } } resize(w, h); } void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { - ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first."); ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); @@ -902,10 +946,11 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); - if (p_width == width && p_height == height) + if (p_width == width && p_height == height) { return; + } - Image dst(p_width, p_height, 0, format); + Image dst(p_width, p_height, false, format); // Setup mipmap-aware scaling Image dst2; @@ -925,7 +970,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } bool interpolate_mipmaps = mipmap_aware && mip1 != mip2; if (interpolate_mipmaps) { - dst2.create(p_width, p_height, 0, format); + dst2.create(p_width, p_height, false, format); } bool had_mipmaps = mipmaps; @@ -941,37 +986,58 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { unsigned char *w_ptr = w; switch (p_interpolation) { - case INTERPOLATE_NEAREST: { - if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 2: _scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 3: _scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 1: + _scale_nearest<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 2: + _scale_nearest<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 3: + _scale_nearest<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_nearest<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 12: _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 16: _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: + _scale_nearest<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_nearest<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 12: + _scale_nearest<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 16: + _scale_nearest<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 6: _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: + _scale_nearest<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_nearest<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 6: + _scale_nearest<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_nearest<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } } break; case INTERPOLATE_BILINEAR: case INTERPOLATE_TRILINEAR: { - for (int i = 0; i < 2; ++i) { int src_width; int src_height; @@ -1010,24 +1076,48 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 2: _scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 3: _scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 4: _scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; + case 1: + _scale_bilinear<1, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 2: + _scale_bilinear<2, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 3: + _scale_bilinear<3, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 4: + _scale_bilinear<4, uint8_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 8: _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 12: _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 16: _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; + case 4: + _scale_bilinear<1, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 8: + _scale_bilinear<2, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 12: + _scale_bilinear<3, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 16: + _scale_bilinear<4, float>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 4: _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 6: _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; - case 8: _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); break; + case 2: + _scale_bilinear<1, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 4: + _scale_bilinear<2, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 6: + _scale_bilinear<3, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; + case 8: + _scale_bilinear<4, uint16_t>(src_ptr, w_ptr, src_width, src_height, p_width, p_height); + break; } } } @@ -1040,52 +1130,98 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { } break; case INTERPOLATE_CUBIC: { - if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 2: _scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 3: _scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 1: + _scale_cubic<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 2: + _scale_cubic<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 3: + _scale_cubic<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_cubic<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 12: _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 16: _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: + _scale_cubic<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_cubic<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 12: + _scale_cubic<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 16: + _scale_cubic<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 6: _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: + _scale_cubic<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_cubic<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 6: + _scale_cubic<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_cubic<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } } break; case INTERPOLATE_LANCZOS: { - if (format >= FORMAT_L8 && format <= FORMAT_RGBA8) { switch (get_format_pixel_size(format)) { - case 1: _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 2: _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 3: _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 1: + _scale_lanczos<1, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 2: + _scale_lanczos<2, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 3: + _scale_lanczos<3, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_lanczos<4, uint8_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RF && format <= FORMAT_RGBAF) { switch (get_format_pixel_size(format)) { - case 4: _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 12: _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 16: _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 4: + _scale_lanczos<1, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_lanczos<2, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 12: + _scale_lanczos<3, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 16: + _scale_lanczos<4, float>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } else if (format >= FORMAT_RH && format <= FORMAT_RGBAH) { switch (get_format_pixel_size(format)) { - case 2: _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 4: _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 6: _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; - case 8: _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); break; + case 2: + _scale_lanczos<1, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 4: + _scale_lanczos<2, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 6: + _scale_lanczos<3, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; + case 8: + _scale_lanczos<4, uint16_t>(r_ptr, w_ptr, width, height, p_width, p_height); + break; } } } break; @@ -1095,14 +1231,14 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { dst._copy_internals_from(dst2); } - if (had_mipmaps) + if (had_mipmaps) { dst.generate_mipmaps(); + } _copy_internals_from(dst); } void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { - ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats."); ERR_FAIL_COND_MSG(p_x < 0, "Start x position cannot be smaller than 0."); @@ -1116,13 +1252,14 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { will most likely either not be used much, or in critical areas, for now it won't, because it's a waste of time. */ - if (p_width == width && p_height == height && p_x == 0 && p_y == 0) + if (p_width == width && p_height == height && p_x == 0 && p_y == 0) { return; + } uint8_t pdata[16]; //largest is 16 uint32_t pixel_size = get_format_pixel_size(format); - Image dst(p_width, p_height, 0, format); + Image dst(p_width, p_height, false, format); { const uint8_t *r = data.ptr(); @@ -1131,12 +1268,11 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { int m_h = p_y + p_height; int m_w = p_x + p_width; for (int y = p_y; y < m_h; y++) { - for (int x = p_x; x < m_w; x++) { - if ((x >= width || y >= height)) { - for (uint32_t i = 0; i < pixel_size; i++) + for (uint32_t i = 0; i < pixel_size; i++) { pdata[i] = 0; + } } else { _get_pixelb(x, y, pixel_size, r, pdata); } @@ -1146,18 +1282,17 @@ void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) { } } - if (has_mipmaps()) + if (has_mipmaps()) { dst.generate_mipmaps(); + } _copy_internals_from(dst); } void Image::crop(int p_width, int p_height) { - crop_from_point(0, 0, p_width, p_height); } void Image::flip_y() { - ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats."); bool used_mipmaps = has_mipmaps(); @@ -1172,9 +1307,7 @@ void Image::flip_y() { uint32_t pixel_size = get_format_pixel_size(format); for (int y = 0; y < height / 2; y++) { - for (int x = 0; x < width; x++) { - _get_pixelb(x, y, pixel_size, w, up); _get_pixelb(x, height - y - 1, pixel_size, w, down); @@ -1190,7 +1323,6 @@ void Image::flip_y() { } void Image::flip_x() { - ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in compressed or custom image formats."); bool used_mipmaps = has_mipmaps(); @@ -1205,9 +1337,7 @@ void Image::flip_x() { uint32_t pixel_size = get_format_pixel_size(format); for (int y = 0; y < height; y++) { - for (int x = 0; x < width / 2; x++) { - _get_pixelb(x, y, pixel_size, w, up); _get_pixelb(width - x - 1, y, pixel_size, w, down); @@ -1223,7 +1353,6 @@ void Image::flip_x() { } int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps, int *r_mm_width, int *r_mm_height) { - int size = 0; int w = p_width; int h = p_height; @@ -1238,7 +1367,6 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & int minw = 1, minh = 1; while (true) { - int bw = w % block != 0 ? w + (block - w % block) : w; int bh = h % block != 0 ? h + (block - h % block) : h; @@ -1256,28 +1384,28 @@ int Image::_get_dst_image_size(int p_width, int p_height, Format p_format, int & *r_mm_height = bh; } - if (p_mipmaps >= 0 && mm == p_mipmaps) + if (p_mipmaps >= 0 && mm == p_mipmaps) { break; + } if (p_mipmaps >= 0) { - w = MAX(minw, w >> 1); h = MAX(minh, h >> 1); } else { - if (w == minw && h == minh) + if (w == minw && h == minh) { break; + } w = MAX(minw, w >> 1); h = MAX(minh, h >> 1); } mm++; - }; + } r_mipmaps = mm; return size; } bool Image::_can_modify(Format p_format) const { - return p_format <= FORMAT_RGBE9995; } @@ -1285,7 +1413,6 @@ template <class Component, int CC, bool renormalize, void (*average_func)(Component &, const Component &, const Component &, const Component &, const Component &), void (*renormalize_func)(Component *)> static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint32_t p_width, uint32_t p_height) { - //fast power of 2 mipmap generation uint32_t dst_w = MAX(p_width >> 1, 1); uint32_t dst_h = MAX(p_height >> 1, 1); @@ -1294,7 +1421,6 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3 int down_step = (p_height == 1) ? 0 : (p_width * CC); for (uint32_t i = 0; i < dst_h; i++) { - const Component *rup_ptr = &p_src[i * 2 * down_step]; const Component *rdown_ptr = rup_ptr + down_step; Component *dst_ptr = &p_dst[i * dst_w * CC]; @@ -1317,52 +1443,10 @@ static void _generate_po2_mipmap(const Component *p_src, Component *p_dst, uint3 } } -void Image::expand_x2_hq2x() { - - ERR_FAIL_COND(!_can_modify(format)); - - bool used_mipmaps = has_mipmaps(); - if (used_mipmaps) { - clear_mipmaps(); - } - - Format current = format; - - if (current != FORMAT_RGBA8) - convert(FORMAT_RGBA8); - - Vector<uint8_t> dest; - dest.resize(width * 2 * height * 2 * 4); - - { - const uint8_t *r = data.ptr(); - uint8_t *w = dest.ptrw(); - - ERR_FAIL_COND(!r); - - hq2x_resize((const uint32_t *)r, width, height, (uint32_t *)w); - } - - width *= 2; - height *= 2; - data = dest; - - if (current != FORMAT_RGBA8) - convert(current); - - // FIXME: This is likely meant to use "used_mipmaps" as defined above, but if we do, - // we end up with a regression: GH-22747 - if (mipmaps) { - generate_mipmaps(); - } -} - void Image::shrink_x2() { - ERR_FAIL_COND(data.size() == 0); if (mipmaps) { - //just use the lower mipmap as base and copy all Vector<uint8_t> new_img; @@ -1384,7 +1468,6 @@ void Image::shrink_x2() { data = new_img; } else { - Vector<uint8_t> new_img; ERR_FAIL_COND(!_can_modify(format)); @@ -1398,25 +1481,52 @@ void Image::shrink_x2() { const uint8_t *r = data.ptr(); switch (format) { - case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_LA8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_RGB8: _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - case FORMAT_RGBA8: _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); break; - - case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - case FORMAT_RGF: _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - case FORMAT_RGBF: _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - case FORMAT_RGBAF: _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); break; - - case FORMAT_RH: _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - case FORMAT_RGH: _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - case FORMAT_RGBH: _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - case FORMAT_RGBAH: _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); break; - - case FORMAT_RGBE9995: _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height); break; + case FORMAT_R8: + _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_LA8: + _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_RG8: + _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_RGB8: + _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + case FORMAT_RGBA8: + _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(r, w, width, height); + break; + + case FORMAT_RF: + _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + case FORMAT_RGF: + _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + case FORMAT_RGBF: + _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + case FORMAT_RGBAF: + _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(r), reinterpret_cast<float *>(w), width, height); + break; + + case FORMAT_RH: + _generate_po2_mipmap<uint16_t, 1, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + case FORMAT_RGH: + _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + case FORMAT_RGBH: + _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + case FORMAT_RGBAH: + _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(r), reinterpret_cast<uint16_t *>(w), width, height); + break; + + case FORMAT_RGBE9995: + _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(r), reinterpret_cast<uint32_t *>(w), width, height); + break; default: { } } @@ -1429,16 +1539,13 @@ void Image::shrink_x2() { } void Image::normalize() { - bool used_mipmaps = has_mipmaps(); if (used_mipmaps) { clear_mipmaps(); } for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - Color c = get_pixel(x, y); Vector3 v(c.r * 2.0 - 1.0, c.g * 2.0 - 1.0, c.b * 2.0 - 1.0); v.normalize(); @@ -1455,7 +1562,6 @@ void Image::normalize() { } Error Image::generate_mipmaps(bool p_renormalize) { - ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in compressed or custom image formats."); ERR_FAIL_COND_V_MSG(format == FORMAT_RGBA4444, ERR_UNAVAILABLE, "Cannot generate mipmaps from RGBA4444 format."); @@ -1475,28 +1581,32 @@ Error Image::generate_mipmaps(bool p_renormalize) { int prev_w = width; for (int i = 1; i <= mmcount; i++) { - int ofs, w, h; _get_mipmap_offset_and_size(i, ofs, w, h); switch (format) { - case FORMAT_L8: - case FORMAT_R8: _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_R8: + _generate_po2_mipmap<uint8_t, 1, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + break; case FORMAT_LA8: - case FORMAT_RG8: _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); break; + case FORMAT_RG8: + _generate_po2_mipmap<uint8_t, 2, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + break; case FORMAT_RGB8: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<uint8_t, 3, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); - else + } else { _generate_po2_mipmap<uint8_t, 3, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + } break; case FORMAT_RGBA8: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<uint8_t, 4, true, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); - else + } else { _generate_po2_mipmap<uint8_t, 4, false, Image::average_4_uint8, Image::renormalize_uint8>(&wp[prev_ofs], &wp[ofs], prev_w, prev_h); + } break; case FORMAT_RF: _generate_po2_mipmap<float, 1, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h); @@ -1505,17 +1615,19 @@ Error Image::generate_mipmaps(bool p_renormalize) { _generate_po2_mipmap<float, 2, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h); break; case FORMAT_RGBF: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<float, 3, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h); - else + } else { _generate_po2_mipmap<float, 3, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h); + } break; case FORMAT_RGBAF: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<float, 4, true, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h); - else + } else { _generate_po2_mipmap<float, 4, false, Image::average_4_float, Image::renormalize_float>(reinterpret_cast<const float *>(&wp[prev_ofs]), reinterpret_cast<float *>(&wp[ofs]), prev_w, prev_h); + } break; case FORMAT_RH: @@ -1525,24 +1637,27 @@ Error Image::generate_mipmaps(bool p_renormalize) { _generate_po2_mipmap<uint16_t, 2, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h); break; case FORMAT_RGBH: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<uint16_t, 3, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h); - else + } else { _generate_po2_mipmap<uint16_t, 3, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h); + } break; case FORMAT_RGBAH: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<uint16_t, 4, true, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h); - else + } else { _generate_po2_mipmap<uint16_t, 4, false, Image::average_4_half, Image::renormalize_half>(reinterpret_cast<const uint16_t *>(&wp[prev_ofs]), reinterpret_cast<uint16_t *>(&wp[ofs]), prev_w, prev_h); + } break; case FORMAT_RGBE9995: - if (p_renormalize) + if (p_renormalize) { _generate_po2_mipmap<uint32_t, 1, true, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h); - else + } else { _generate_po2_mipmap<uint32_t, 1, false, Image::average_4_rgbe9995, Image::renormalize_rgbe9995>(reinterpret_cast<const uint32_t *>(&wp[prev_ofs]), reinterpret_cast<uint32_t *>(&wp[ofs]), prev_w, prev_h); + } break; default: { @@ -1560,7 +1675,6 @@ Error Image::generate_mipmaps(bool p_renormalize) { } Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map) { - Vector<double> normal_sat_vec; //summed area table double *normal_sat = nullptr; //summed area table for normalmap int normal_w = 0, normal_h = 0; @@ -1625,7 +1739,6 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con uint8_t *base_ptr = data.ptrw(); for (int i = 1; i <= mmcount; i++) { - int ofs, w, h; _get_mipmap_offset_and_size(i, ofs, w, h); uint8_t *ptr = &base_ptr[ofs]; @@ -1756,12 +1869,13 @@ Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, con } void Image::clear_mipmaps() { - - if (!mipmaps) + if (!mipmaps) { return; + } - if (empty()) + if (empty()) { return; + } int ofs, w, h; _get_mipmap_offset_and_size(1, ofs, w, h); @@ -1771,17 +1885,14 @@ void Image::clear_mipmaps() { } bool Image::empty() const { - return (data.size() == 0); } Vector<uint8_t> Image::get_data() const { - return data; } void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { - ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); @@ -1802,7 +1913,6 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma } void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { - ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); @@ -1821,7 +1931,6 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma } void Image::create(const char **p_xpm) { - int size_width = 0; int size_height = 0; int pixelchars = 0; @@ -1841,16 +1950,13 @@ void Image::create(const char **p_xpm) { HashMap<String, Color> colormap; int colormap_size = 0; uint32_t pixel_size = 0; - uint8_t *w; + uint8_t *data_write = nullptr; while (status != DONE) { - const char *line_ptr = p_xpm[line]; switch (status) { - case READING_HEADER: { - String line_str = line_ptr; line_str.replace("\t", " "); @@ -1865,25 +1971,24 @@ void Image::create(const char **p_xpm) { status = READING_COLORS; } break; case READING_COLORS: { - String colorstring; for (int i = 0; i < pixelchars; i++) { - colorstring += *line_ptr; line_ptr++; } //skip spaces while (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == 0) { - if (*line_ptr == 0) + if (*line_ptr == 0) { break; + } line_ptr++; } if (*line_ptr == 'c') { - line_ptr++; while (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == 0) { - if (*line_ptr == 0) + if (*line_ptr == 0) { break; + } line_ptr++; } @@ -1895,55 +2000,63 @@ void Image::create(const char **p_xpm) { //uint8_t col_a=255; for (int i = 0; i < 6; i++) { - char v = line_ptr[i]; - if (v >= '0' && v <= '9') + if (v >= '0' && v <= '9') { v -= '0'; - else if (v >= 'A' && v <= 'F') + } else if (v >= 'A' && v <= 'F') { v = (v - 'A') + 10; - else if (v >= 'a' && v <= 'f') + } else if (v >= 'a' && v <= 'f') { v = (v - 'a') + 10; - else + } else { break; + } switch (i) { - case 0: col_r = v << 4; break; - case 1: col_r |= v; break; - case 2: col_g = v << 4; break; - case 3: col_g |= v; break; - case 4: col_b = v << 4; break; - case 5: col_b |= v; break; - }; + case 0: + col_r = v << 4; + break; + case 1: + col_r |= v; + break; + case 2: + col_g = v << 4; + break; + case 3: + col_g |= v; + break; + case 4: + col_b = v << 4; + break; + case 5: + col_b |= v; + break; + } } // magenta mask if (col_r == 255 && col_g == 0 && col_b == 255) { - colormap[colorstring] = Color(0, 0, 0, 0); has_alpha = true; } else { - colormap[colorstring] = Color(col_r / 255.0, col_g / 255.0, col_b / 255.0, 1.0); } } } if (line == colormap_size) { - status = READING_PIXELS; - create(size_width, size_height, 0, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8); - w = data.ptrw(); + create(size_width, size_height, false, has_alpha ? FORMAT_RGBA8 : FORMAT_RGB8); + data_write = data.ptrw(); pixel_size = has_alpha ? 4 : 3; } } break; case READING_PIXELS: { - int y = line - colormap_size - 1; for (int x = 0; x < size_width; x++) { - char pixelstr[6] = { 0, 0, 0, 0, 0, 0 }; - for (int i = 0; i < pixelchars; i++) + for (int i = 0; i < pixelchars; i++) { pixelstr[i] = line_ptr[x * pixelchars + i]; + } Color *colorptr = colormap.getptr(pixelstr); ERR_FAIL_COND(!colorptr); @@ -1951,11 +2064,12 @@ void Image::create(const char **p_xpm) { for (uint32_t i = 0; i < pixel_size; i++) { pixel[i] = CLAMP((*colorptr)[i] * 255, 0, 255); } - _put_pixelb(x, y, pixel_size, w, pixel); + _put_pixelb(x, y, pixel_size, data_write, pixel); } - if (y == (size_height - 1)) + if (y == (size_height - 1)) { status = DONE; + } } break; default: { } @@ -1973,7 +2087,6 @@ void Image::create(const char **p_xpm) { if (value < DETECT_ALPHA_MIN_THRESHOLD) \ bit = true; \ else if (value < DETECT_ALPHA_MAX_THRESHOLD) { \ - \ detected = true; \ break; \ } \ @@ -1983,22 +2096,22 @@ void Image::create(const char **p_xpm) { { \ uint8_t value = m_value; \ if (value > 0) { \ - \ detected = true; \ break; \ } \ } bool Image::is_invisible() const { - if (format == FORMAT_L8 || - format == FORMAT_RGB8 || format == FORMAT_RG8) + format == FORMAT_RGB8 || format == FORMAT_RG8) { return false; + } int len = data.size(); - if (len == 0) + if (len == 0) { return true; + } int w, h; _get_mipmap_offset_and_size(1, len, w, h); @@ -2009,16 +2122,13 @@ bool Image::is_invisible() const { bool detected = false; switch (format) { - case FORMAT_LA8: { - for (int i = 0; i < (len >> 1); i++) { DETECT_NON_ALPHA(data_ptr[(i << 1) + 1]); } } break; case FORMAT_RGBA8: { - for (int i = 0; i < (len >> 2); i++) { DETECT_NON_ALPHA(data_ptr[(i << 2) + 3]) } @@ -2039,11 +2149,11 @@ bool Image::is_invisible() const { } Image::AlphaMode Image::detect_alpha() const { - int len = data.size(); - if (len == 0) + if (len == 0) { return ALPHA_NONE; + } int w, h; _get_mipmap_offset_and_size(1, len, w, h); @@ -2055,16 +2165,13 @@ Image::AlphaMode Image::detect_alpha() const { bool detected = false; switch (format) { - case FORMAT_LA8: { - for (int i = 0; i < (len >> 1); i++) { DETECT_ALPHA(data_ptr[(i << 1) + 1]); } } break; case FORMAT_RGBA8: { - for (int i = 0; i < (len >> 2); i++) { DETECT_ALPHA(data_ptr[(i << 2) + 3]) } @@ -2080,12 +2187,13 @@ Image::AlphaMode Image::detect_alpha() const { } } - if (detected) + if (detected) { return ALPHA_BLEND; - else if (bit) + } else if (bit) { return ALPHA_BIT; - else + } else { return ALPHA_NONE; + } } Error Image::load(const String &p_path) { @@ -2098,9 +2206,9 @@ Error Image::load(const String &p_path) { } Error Image::save_png(const String &p_path) const { - - if (save_png_func == nullptr) + if (save_png_func == nullptr) { return ERR_UNAVAILABLE; + } return save_png_func(p_path, Ref<Image>((Image *)this)); } @@ -2114,21 +2222,19 @@ Vector<uint8_t> Image::save_png_to_buffer() const { } Error Image::save_exr(const String &p_path, bool p_grayscale) const { - - if (save_exr_func == nullptr) + if (save_exr_func == nullptr) { return ERR_UNAVAILABLE; + } return save_exr_func(p_path, Ref<Image>((Image *)this), p_grayscale); } int Image::get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps) { - int mm; return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmaps ? -1 : 0); } int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format) { - int mm; _get_dst_image_size(p_width, p_height, p_format, mm, -1); return mm; @@ -2142,7 +2248,6 @@ Size2i Image::get_image_mipmap_size(int p_width, int p_height, Format p_format, } int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) { - if (p_mipmap <= 0) { return 0; } @@ -2151,7 +2256,6 @@ int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, i } int Image::get_image_mipmap_offset_and_dimensions(int p_width, int p_height, Format p_format, int p_mipmap, int &r_w, int &r_h) { - if (p_mipmap <= 0) { r_w = p_width; r_h = p_height; @@ -2166,57 +2270,49 @@ bool Image::is_compressed() const { } Error Image::decompress() { - - if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc) + if (((format >= FORMAT_DXT1 && format <= FORMAT_RGTC_RG) || (format == FORMAT_DXT5_RA_AS_RG)) && _image_decompress_bc) { _image_decompress_bc(this); - else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) + } else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) { _image_decompress_bptc(this); - else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc) + } else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc) { _image_decompress_pvrtc(this); - else if (format == FORMAT_ETC && _image_decompress_etc1) + } else if (format == FORMAT_ETC && _image_decompress_etc1) { _image_decompress_etc1(this); - else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) + } else if (format >= FORMAT_ETC2_R11 && format <= FORMAT_ETC2_RA_AS_RG && _image_decompress_etc2) { _image_decompress_etc2(this); - else + } else { return ERR_UNAVAILABLE; + } return OK; } Error Image::compress(CompressMode p_mode, CompressSource p_source, float p_lossy_quality) { - return compress_from_channels(p_mode, detect_used_channels(p_source), p_lossy_quality); } -Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) { +Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, float p_lossy_quality) { switch (p_mode) { - case COMPRESS_S3TC: { - ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); _image_compress_bc_func(this, p_lossy_quality, p_channels); } break; case COMPRESS_PVRTC2: { - ERR_FAIL_COND_V(!_image_compress_pvrtc2_func, ERR_UNAVAILABLE); _image_compress_pvrtc2_func(this); } break; case COMPRESS_PVRTC4: { - ERR_FAIL_COND_V(!_image_compress_pvrtc4_func, ERR_UNAVAILABLE); _image_compress_pvrtc4_func(this); } break; case COMPRESS_ETC: { - ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE); _image_compress_etc1_func(this, p_lossy_quality); } break; case COMPRESS_ETC2: { - ERR_FAIL_COND_V(!_image_compress_etc2_func, ERR_UNAVAILABLE); _image_compress_etc2_func(this, p_lossy_quality, p_channels); } break; case COMPRESS_BPTC: { - ERR_FAIL_COND_V(!_image_compress_bptc_func, ERR_UNAVAILABLE); _image_compress_bptc_func(this, p_lossy_quality, p_channels); } break; @@ -2226,7 +2322,6 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels } Image::Image(const char **p_xpm) { - width = 0; height = 0; mipmaps = false; @@ -2236,7 +2331,6 @@ Image::Image(const char **p_xpm) { } Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { - width = 0; height = 0; mipmaps = p_use_mipmaps; @@ -2246,7 +2340,6 @@ Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { } Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { - width = 0; height = 0; mipmaps = p_mipmaps; @@ -2256,48 +2349,52 @@ Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const V } Rect2 Image::get_used_rect() const { - - if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) + if (format != FORMAT_LA8 && format != FORMAT_RGBA8 && format != FORMAT_RGBAF && format != FORMAT_RGBAH && format != FORMAT_RGBA4444 && format != FORMAT_RGB565) { return Rect2(Point2(), Size2(width, height)); + } int len = data.size(); - if (len == 0) + if (len == 0) { return Rect2(); + } int minx = 0xFFFFFF, miny = 0xFFFFFFF; int maxx = -1, maxy = -1; for (int j = 0; j < height; j++) { for (int i = 0; i < width; i++) { - - if (!(get_pixel(i, j).a > 0)) + if (!(get_pixel(i, j).a > 0)) { continue; - if (i > maxx) + } + if (i > maxx) { maxx = i; - if (j > maxy) + } + if (j > maxy) { maxy = j; - if (i < minx) + } + if (i < minx) { minx = i; - if (j < miny) + } + if (j < miny) { miny = j; + } } } - if (maxx == -1) + if (maxx == -1) { return Rect2(); - else + } else { return Rect2(minx, miny, maxx - minx + 1, maxy - miny + 1); + } } Ref<Image> Image::get_rect(const Rect2 &p_area) const { - Ref<Image> img = memnew(Image(p_area.size.x, p_area.size.y, mipmaps, format)); img->blit_rect(Ref<Image>((Image *)this), p_area, Point2(0, 0)); return img; } void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { - ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); int srcdsize = p_src->data.size(); @@ -2308,13 +2405,16 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); - if (p_dest.x < 0) + if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); - if (p_dest.y < 0) + } + if (p_dest.y < 0) { clipped_src_rect.position.y = ABS(p_dest.y); + } - if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) + if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) { return; + } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); @@ -2328,9 +2428,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po int pixel_size = get_format_pixel_size(format); for (int i = 0; i < dest_rect.size.y; i++) { - for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; int src_y = clipped_src_rect.position.y + i; @@ -2348,7 +2446,6 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po } void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { - ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); @@ -2363,13 +2460,16 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); - if (p_dest.x < 0) + if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); - if (p_dest.y < 0) + } + if (p_dest.y < 0) { clipped_src_rect.position.y = ABS(p_dest.y); + } - if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) + if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) { return; + } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); @@ -2385,14 +2485,11 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co Ref<Image> msk = p_mask; for (int i = 0; i < dest_rect.size.y; i++) { - for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; int src_y = clipped_src_rect.position.y + i; if (msk->get_pixel(src_x, src_y).a != 0) { - int dst_x = dest_rect.position.x + j; int dst_y = dest_rect.position.y + i; @@ -2408,7 +2505,6 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co } void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) { - ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); int srcdsize = p_src->data.size(); @@ -2418,13 +2514,16 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); - if (p_dest.x < 0) + if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); - if (p_dest.y < 0) + } + if (p_dest.y < 0) { clipped_src_rect.position.y = ABS(p_dest.y); + } - if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) + if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) { return; + } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); @@ -2432,9 +2531,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P Ref<Image> img = p_src; for (int i = 0; i < dest_rect.size.y; i++) { - for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; int src_y = clipped_src_rect.position.y + i; @@ -2442,18 +2539,16 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P int dst_y = dest_rect.position.y + i; Color sc = img->get_pixel(src_x, src_y); - Color dc = get_pixel(dst_x, dst_y); - dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r); - dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); - dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); - dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); - set_pixel(dst_x, dst_y, dc); + if (sc.a != 0) { + Color dc = get_pixel(dst_x, dst_y); + dc = dc.blend(sc); + set_pixel(dst_x, dst_y, dc); + } } } } void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest) { - ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object."); ERR_FAIL_COND_MSG(p_mask.is_null(), "It's not a reference to a valid Image object."); int dsize = data.size(); @@ -2468,13 +2563,16 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); - if (p_dest.x < 0) + if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); - if (p_dest.y < 0) + } + if (p_dest.y < 0) { clipped_src_rect.position.y = ABS(p_dest.y); + } - if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) + if (clipped_src_rect.size.x <= 0 || clipped_src_rect.size.y <= 0) { return; + } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); @@ -2483,9 +2581,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c Ref<Image> msk = p_mask; for (int i = 0; i < dest_rect.size.y; i++) { - for (int j = 0; j < dest_rect.size.x; j++) { - int src_x = clipped_src_rect.position.x + j; int src_y = clipped_src_rect.position.y + i; @@ -2493,17 +2589,15 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c //Color c = msk->get_pixel(src_x, src_y); //if (c.a == 0) continue; if (msk->get_pixel(src_x, src_y).a != 0) { - int dst_x = dest_rect.position.x + j; int dst_y = dest_rect.position.y + i; Color sc = img->get_pixel(src_x, src_y); - Color dc = get_pixel(dst_x, dst_y); - dc.r = (double)(sc.a * sc.r + dc.a * (1.0 - sc.a) * dc.r); - dc.g = (double)(sc.a * sc.g + dc.a * (1.0 - sc.a) * dc.g); - dc.b = (double)(sc.a * sc.b + dc.a * (1.0 - sc.a) * dc.b); - dc.a = (double)(sc.a + dc.a * (1.0 - sc.a)); - set_pixel(dst_x, dst_y, dc); + if (sc.a != 0) { + Color dc = get_pixel(dst_x, dst_y); + dc = dc.blend(sc); + set_pixel(dst_x, dst_y, dc); + } } } } @@ -2521,9 +2615,7 @@ void Image::fill(const Color &c) { set_pixel(0, 0, c); for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size]; for (int k = 0; k < pixel_size; k++) { @@ -2557,7 +2649,6 @@ Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::Used Ref<Image> (*Image::basis_universal_unpacker)(const Vector<uint8_t> &) = nullptr; void Image::_set_data(const Dictionary &p_data) { - ERR_FAIL_COND(!p_data.has("width")); ERR_FAIL_COND(!p_data.has("height")); ERR_FAIL_COND(!p_data.has("format")); @@ -2583,7 +2674,6 @@ void Image::_set_data(const Dictionary &p_data) { } Dictionary Image::_get_data() const { - Dictionary d; d["width"] = width; d["height"] = height; @@ -2598,7 +2688,6 @@ Color Image::get_pixelv(const Point2 &p_src) const { } Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { - switch (format) { case FORMAT_L8: { float l = ptr[ofs] / 255.0; @@ -2610,12 +2699,10 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { return Color(l, l, l, a); } case FORMAT_R8: { - float r = ptr[ofs] / 255.0; return Color(r, 0, 0, 1); } case FORMAT_RG8: { - float r = ptr[ofs * 2 + 0] / 255.0; float g = ptr[ofs * 2 + 1] / 255.0; return Color(r, g, 0, 1); @@ -2642,7 +2729,6 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { return Color(r, g, b, a); } case FORMAT_RGB565: { - uint16_t u = ((uint16_t *)ptr)[ofs]; float r = (u & 0x1F) / 31.0; float g = ((u >> 5) & 0x3F) / 63.0; @@ -2650,25 +2736,21 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { return Color(r, g, b, 1.0); } case FORMAT_RF: { - float r = ((float *)ptr)[ofs]; return Color(r, 0, 0, 1); } case FORMAT_RGF: { - float r = ((float *)ptr)[ofs * 2 + 0]; float g = ((float *)ptr)[ofs * 2 + 1]; return Color(r, g, 0, 1); } case FORMAT_RGBF: { - float r = ((float *)ptr)[ofs * 3 + 0]; float g = ((float *)ptr)[ofs * 3 + 1]; float b = ((float *)ptr)[ofs * 3 + 2]; return Color(r, g, b, 1); } case FORMAT_RGBAF: { - float r = ((float *)ptr)[ofs * 4 + 0]; float g = ((float *)ptr)[ofs * 4 + 1]; float b = ((float *)ptr)[ofs * 4 + 2]; @@ -2676,25 +2758,21 @@ Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { return Color(r, g, b, a); } case FORMAT_RH: { - uint16_t r = ((uint16_t *)ptr)[ofs]; return Color(Math::half_to_float(r), 0, 0, 1); } case FORMAT_RGH: { - uint16_t r = ((uint16_t *)ptr)[ofs * 2 + 0]; uint16_t g = ((uint16_t *)ptr)[ofs * 2 + 1]; return Color(Math::half_to_float(r), Math::half_to_float(g), 0, 1); } case FORMAT_RGBH: { - uint16_t r = ((uint16_t *)ptr)[ofs * 3 + 0]; uint16_t g = ((uint16_t *)ptr)[ofs * 3 + 1]; uint16_t b = ((uint16_t *)ptr)[ofs * 3 + 2]; return Color(Math::half_to_float(r), Math::half_to_float(g), Math::half_to_float(b), 1); } case FORMAT_RGBAH: { - uint16_t r = ((uint16_t *)ptr)[ofs * 4 + 0]; uint16_t g = ((uint16_t *)ptr)[ofs * 4 + 1]; uint16_t b = ((uint16_t *)ptr)[ofs * 4 + 2]; @@ -2720,11 +2798,9 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color) ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.a * 255.0, 0, 255)); } break; case FORMAT_R8: { - ptr[ofs] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255)); } break; case FORMAT_RG8: { - ptr[ofs * 2 + 0] = uint8_t(CLAMP(p_color.r * 255.0, 0, 255)); ptr[ofs * 2 + 1] = uint8_t(CLAMP(p_color.g * 255.0, 0, 255)); } break; @@ -2741,7 +2817,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color) } break; case FORMAT_RGBA4444: { - uint16_t rgba = 0; rgba = uint16_t(CLAMP(p_color.r * 15.0, 0, 15)) << 12; @@ -2753,7 +2828,6 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color) } break; case FORMAT_RGB565: { - uint16_t rgba = 0; rgba = uint16_t(CLAMP(p_color.r * 31.0, 0, 31)); @@ -2764,51 +2838,42 @@ void Image::_set_color_at_ofs(uint8_t *ptr, uint32_t ofs, const Color &p_color) } break; case FORMAT_RF: { - ((float *)ptr)[ofs] = p_color.r; } break; case FORMAT_RGF: { - ((float *)ptr)[ofs * 2 + 0] = p_color.r; ((float *)ptr)[ofs * 2 + 1] = p_color.g; } break; case FORMAT_RGBF: { - ((float *)ptr)[ofs * 3 + 0] = p_color.r; ((float *)ptr)[ofs * 3 + 1] = p_color.g; ((float *)ptr)[ofs * 3 + 2] = p_color.b; } break; case FORMAT_RGBAF: { - ((float *)ptr)[ofs * 4 + 0] = p_color.r; ((float *)ptr)[ofs * 4 + 1] = p_color.g; ((float *)ptr)[ofs * 4 + 2] = p_color.b; ((float *)ptr)[ofs * 4 + 3] = p_color.a; } break; case FORMAT_RH: { - ((uint16_t *)ptr)[ofs] = Math::make_half_float(p_color.r); } break; case FORMAT_RGH: { - ((uint16_t *)ptr)[ofs * 2 + 0] = Math::make_half_float(p_color.r); ((uint16_t *)ptr)[ofs * 2 + 1] = Math::make_half_float(p_color.g); } break; case FORMAT_RGBH: { - ((uint16_t *)ptr)[ofs * 3 + 0] = Math::make_half_float(p_color.r); ((uint16_t *)ptr)[ofs * 3 + 1] = Math::make_half_float(p_color.g); ((uint16_t *)ptr)[ofs * 3 + 2] = Math::make_half_float(p_color.b); } break; case FORMAT_RGBAH: { - ((uint16_t *)ptr)[ofs * 4 + 0] = Math::make_half_float(p_color.r); ((uint16_t *)ptr)[ofs * 4 + 1] = Math::make_half_float(p_color.g); ((uint16_t *)ptr)[ofs * 4 + 2] = Math::make_half_float(p_color.b); ((uint16_t *)ptr)[ofs * 4 + 3] = Math::make_half_float(p_color.a); } break; case FORMAT_RGBE9995: { - ((uint32_t *)ptr)[ofs] = p_color.to_rgbe9995(); } break; @@ -2843,24 +2908,26 @@ void Image::set_pixel(int p_x, int p_y, const Color &p_color) { } Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { - ERR_FAIL_COND_V(data.size() == 0, USED_CHANNELS_RGBA); ERR_FAIL_COND_V(is_compressed(), USED_CHANNELS_RGBA); bool r = false, g = false, b = false, a = false, c = false; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { - Color col = get_pixel(i, j); - if (col.r > 0.001) + if (col.r > 0.001) { r = true; - if (col.g > 0.001) + } + if (col.g > 0.001) { g = true; - if (col.b > 0.001) + } + if (col.b > 0.001) { b = true; - if (col.a < 0.999) + } + if (col.a < 0.999) { a = true; + } if (col.r != col.b || col.r != col.g || col.b != col.g) { c = true; @@ -2870,18 +2937,19 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { UsedChannels used_channels; - if (!c && !a) + if (!c && !a) { used_channels = USED_CHANNELS_L; - else if (!c && a) + } else if (!c && a) { used_channels = USED_CHANNELS_LA; - else if (r && !g && !b && !a) + } else if (r && !g && !b && !a) { used_channels = USED_CHANNELS_R; - else if (r && g && !b && !a) + } else if (r && g && !b && !a) { used_channels = USED_CHANNELS_RG; - else if (r && g && b && !a) + } else if (r && g && b && !a) { used_channels = USED_CHANNELS_RGB; - else + } else { used_channels = USED_CHANNELS_RGBA; + } if (p_source == COMPRESS_SOURCE_SRGB && (used_channels == USED_CHANNELS_R || used_channels == USED_CHANNELS_RG)) { //R and RG do not support SRGB @@ -2898,17 +2966,28 @@ Image::UsedChannels Image::detect_used_channels(CompressSource p_source) { void Image::optimize_channels() { switch (detect_used_channels()) { - case USED_CHANNELS_L: convert(FORMAT_L8); break; - case USED_CHANNELS_LA: convert(FORMAT_LA8); break; - case USED_CHANNELS_R: convert(FORMAT_R8); break; - case USED_CHANNELS_RG: convert(FORMAT_RG8); break; - case USED_CHANNELS_RGB: convert(FORMAT_RGB8); break; - case USED_CHANNELS_RGBA: convert(FORMAT_RGBA8); break; + case USED_CHANNELS_L: + convert(FORMAT_L8); + break; + case USED_CHANNELS_LA: + convert(FORMAT_LA8); + break; + case USED_CHANNELS_R: + convert(FORMAT_R8); + break; + case USED_CHANNELS_RG: + convert(FORMAT_RG8); + break; + case USED_CHANNELS_RGB: + convert(FORMAT_RGB8); + break; + case USED_CHANNELS_RGBA: + convert(FORMAT_RGBA8); + break; } } void Image::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_width"), &Image::get_width); ClassDB::bind_method(D_METHOD("get_height"), &Image::get_height); ClassDB::bind_method(D_METHOD("get_size"), &Image::get_size); @@ -2923,7 +3002,6 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("resize_to_po2", "square"), &Image::resize_to_po2, DEFVAL(false)); ClassDB::bind_method(D_METHOD("resize", "width", "height", "interpolation"), &Image::resize, DEFVAL(INTERPOLATE_BILINEAR)); ClassDB::bind_method(D_METHOD("shrink_x2"), &Image::shrink_x2); - ClassDB::bind_method(D_METHOD("expand_x2_hq2x"), &Image::expand_x2_hq2x); ClassDB::bind_method(D_METHOD("crop", "width", "height"), &Image::crop); ClassDB::bind_method(D_METHOD("flip_x"), &Image::flip_x); @@ -2938,6 +3016,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path"), &Image::load); ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png); + ClassDB::bind_method(D_METHOD("save_png_to_buffer"), &Image::save_png_to_buffer); ClassDB::bind_method(D_METHOD("save_exr", "path", "grayscale"), &Image::save_exr, DEFVAL(false)); ClassDB::bind_method(D_METHOD("detect_alpha"), &Image::detect_alpha); @@ -3054,17 +3133,14 @@ void Image::_bind_methods() { } void Image::set_compress_bc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { - _image_compress_bc_func = p_compress_func; } void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedChannels)) { - _image_compress_bptc_func = p_compress_func; } void Image::normalmap_to_xy() { - convert(Image::FORMAT_RGBA8); { @@ -3072,7 +3148,6 @@ void Image::normalmap_to_xy() { uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < len; i++) { - data_ptr[(i << 2) + 3] = data_ptr[(i << 2) + 0]; //x to w data_ptr[(i << 2) + 0] = data_ptr[(i << 2) + 1]; //y to xz data_ptr[(i << 2) + 2] = data_ptr[(i << 2) + 1]; @@ -3083,15 +3158,15 @@ void Image::normalmap_to_xy() { } Ref<Image> Image::rgbe_to_srgb() { - - if (data.size() == 0) + if (data.size() == 0) { return Ref<Image>(); + } ERR_FAIL_COND_V(format != FORMAT_RGBE9995, Ref<Image>()); Ref<Image> new_image; new_image.instance(); - new_image->create(width, height, 0, Image::FORMAT_RGB8); + new_image->create(width, height, false, Image::FORMAT_RGB8); for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { @@ -3107,7 +3182,6 @@ Ref<Image> Image::rgbe_to_srgb() { } Ref<Image> Image::get_image_from_mipmap(int p_mipamp) const { - int ofs, size, w, h; get_mipmap_offset_size_and_dimensions(p_mipamp, ofs, size, w, h); @@ -3149,11 +3223,15 @@ void Image::bumpmap_to_normalmap(float bump_scale) { for (int ty = 0; ty < height; ty++) { int py = ty + 1; - if (py >= height) py -= height; + if (py >= height) { + py -= height; + } for (int tx = 0; tx < width; tx++) { int px = tx + 1; - if (px >= width) px -= width; + if (px >= width) { + px -= width; + } float here = read_ptr[ty * width + tx]; float to_right = read_ptr[ty * width + px]; float above = read_ptr[py * width + tx]; @@ -3175,33 +3253,29 @@ void Image::bumpmap_to_normalmap(float bump_scale) { } void Image::srgb_to_linear() { - - if (data.size() == 0) + if (data.size() == 0) { return; + } static const uint8_t srgb2lin[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 101, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 148, 150, 152, 153, 155, 157, 159, 160, 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 188, 190, 192, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 235, 237, 239, 241, 243, 245, 248, 250, 252, 255 }; ERR_FAIL_COND(format != FORMAT_RGB8 && format != FORMAT_RGBA8); if (format == FORMAT_RGBA8) { - int len = data.size() / 4; uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < len; i++) { - data_ptr[(i << 2) + 0] = srgb2lin[data_ptr[(i << 2) + 0]]; data_ptr[(i << 2) + 1] = srgb2lin[data_ptr[(i << 2) + 1]]; data_ptr[(i << 2) + 2] = srgb2lin[data_ptr[(i << 2) + 2]]; } } else if (format == FORMAT_RGB8) { - int len = data.size() / 3; uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < len; i++) { - data_ptr[(i * 3) + 0] = srgb2lin[data_ptr[(i * 3) + 0]]; data_ptr[(i * 3) + 1] = srgb2lin[data_ptr[(i * 3) + 1]]; data_ptr[(i * 3) + 2] = srgb2lin[data_ptr[(i * 3) + 2]]; @@ -3210,18 +3284,18 @@ void Image::srgb_to_linear() { } void Image::premultiply_alpha() { - - if (data.size() == 0) + if (data.size() == 0) { return; + } - if (format != FORMAT_RGBA8) + if (format != FORMAT_RGBA8) { return; //not needed + } uint8_t *data_ptr = data.ptrw(); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { - uint8_t *ptr = &data_ptr[(i * width + j) * 4]; ptr[0] = (uint16_t(ptr[0]) * uint16_t(ptr[3])) >> 8; @@ -3232,12 +3306,13 @@ void Image::premultiply_alpha() { } void Image::fix_alpha_edges() { - - if (data.size() == 0) + if (data.size() == 0) { return; + } - if (format != FORMAT_RGBA8) + if (format != FORMAT_RGBA8) { return; //not needed + } Vector<uint8_t> dcopy = data; const uint8_t *srcptr = dcopy.ptr(); @@ -3250,12 +3325,12 @@ void Image::fix_alpha_edges() { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { - const uint8_t *rptr = &srcptr[(i * width + j) * 4]; uint8_t *wptr = &data_ptr[(i * width + j) * 4]; - if (rptr[3] >= alpha_threshold) + if (rptr[3] >= alpha_threshold) { continue; + } int closest_dist = max_dist; uint8_t closest_color[3]; @@ -3267,17 +3342,18 @@ void Image::fix_alpha_edges() { for (int k = from_y; k <= to_y; k++) { for (int l = from_x; l <= to_x; l++) { - int dy = i - k; int dx = j - l; int dist = dy * dy + dx * dx; - if (dist >= closest_dist) + if (dist >= closest_dist) { continue; + } const uint8_t *rp2 = &srcptr[(k * width + l) << 2]; - if (rp2[3] < alpha_threshold) + if (rp2[3] < alpha_threshold) { continue; + } closest_dist = dist; closest_color[0] = rp2[0]; @@ -3287,7 +3363,6 @@ void Image::fix_alpha_edges() { } if (closest_dist != max_dist) { - wptr[0] = closest_color[0]; wptr[1] = closest_color[1]; wptr[2] = closest_color[2]; @@ -3297,7 +3372,6 @@ void Image::fix_alpha_edges() { } String Image::get_format_name(Format p_format) { - ERR_FAIL_INDEX_V(p_format, FORMAT_MAX, String()); return format_names[p_format]; } @@ -3326,6 +3400,7 @@ void Image::convert_rg_to_ra_rgba8() { w[i + 2] = 0; } } + void Image::convert_ra_rgba8_to_rg() { ERR_FAIL_COND(format != FORMAT_RGBA8); ERR_FAIL_COND(!data.size()); @@ -3405,7 +3480,6 @@ void Image::renormalize_rgbe9995(uint32_t *p_rgb) { } Image::Image(const uint8_t *p_mem_png_jpg, int p_len) { - width = 0; height = 0; mipmaps = false; @@ -3421,20 +3495,12 @@ Image::Image(const uint8_t *p_mem_png_jpg, int p_len) { } Ref<Resource> Image::duplicate(bool p_subresources) const { - Ref<Image> copy; copy.instance(); copy->_copy_internals_from(*this); return copy; } -Image::Image() { - - width = 0; - height = 0; - mipmaps = false; - format = FORMAT_L8; -} - -Image::~Image() { +void Image::set_as_black() { + zeromem(data.ptrw(), data.size()); } diff --git a/core/image.h b/core/image.h index 5bd73fa677..53c203998e 100644 --- a/core/image.h +++ b/core/image.h @@ -33,7 +33,6 @@ #include "core/color.h" #include "core/math/rect2.h" - #include "core/resource.h" /** @@ -172,10 +171,11 @@ private: create(p_width, p_height, p_use_mipmaps, p_format, p_data); } - Format format; + Format format = FORMAT_L8; Vector<uint8_t> data; - int width, height; - bool mipmaps; + int width = 0; + int height = 0; + bool mipmaps = false; void _copy_internals_from(const Image &p_image) { format = p_image.format; @@ -235,7 +235,6 @@ public: void resize_to_po2(bool p_square = false); void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void shrink_x2(); - void expand_x2_hq2x(); bool is_size_po2() const; /** * Crop the image to a specific size, if larger, then the image is filled by black @@ -286,7 +285,7 @@ public: /** * create an empty image */ - Image(); + Image() {} /** * create an empty image of a specific size and format */ @@ -296,6 +295,8 @@ public: */ Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data); + ~Image() {} + enum AlphaMode { ALPHA_NONE, ALPHA_BIT, @@ -376,6 +377,8 @@ public: void set_pixelv(const Point2 &p_dst, const Color &p_color); void set_pixel(int p_x, int p_y, const Color &p_color); + void set_as_black(); + void copy_internals_from(const Ref<Image> &p_image) { ERR_FAIL_COND_MSG(p_image.is_null(), "It's not a reference to a valid Image object."); format = p_image->format; @@ -384,8 +387,6 @@ public: mipmaps = p_image->mipmaps; data = p_image->data; } - - ~Image(); }; VARIANT_ENUM_CAST(Image::Format) diff --git a/core/input/SCsub b/core/input/SCsub index d46e52a347..c641819698 100644 --- a/core/input/SCsub +++ b/core/input/SCsub @@ -8,8 +8,6 @@ import input_builders # Order matters here. Higher index controller database files write on top of lower index database files. controller_databases = [ - "#core/input/gamecontrollerdb_204.txt", - "#core/input/gamecontrollerdb_205.txt", "#core/input/gamecontrollerdb.txt", "#core/input/godotcontrollerdb.txt", ] diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 90d309c1c8..7b5abdd61b 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -4,37 +4,38 @@ # Windows 03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows, 03000000c82d00002038000000000000,8bitdo,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d000011ab000000000000,8BitDo F30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a4,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00000310000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, 03000000c82d00002028000000000000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00008010000000000000,8BitDo N30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000190000000000000,8BitDo N30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001590000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00015900000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00065280000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000130000000000000,8BitDo SF30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000061000000000000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00003028000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000351000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00001290000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d000020ab000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00004028000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00006228000000000000,8BitDo SN30 GP,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, -03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00006228000000000000,8BitDo SN30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000260000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000261000000000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000c82d00000031000000000000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows, +03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, 03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows, 030000008f0e00001200000000000000,Acme GA-02,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, 03000000fa190000f0ff000000000000,Acteck AGJ-3200,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, @@ -73,6 +74,7 @@ 03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows, 03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, 03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, +030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,y:b3,platform:Windows, 03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 03000000bd12000002e0000000000000,Dual USB Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows, 030000006f0e00003001000000000000,EA SPORTS PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -88,7 +90,6 @@ 030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, 030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, -03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, 03000000790000002201000000000000,Game Controller for PC,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, 0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows, 03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, @@ -98,6 +99,7 @@ 03000000ac0500004d04000000000000,GameSir,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, 03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000006f0e00000102000000007801,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, +030000009b2800003200000000000000,GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, 030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, @@ -146,6 +148,8 @@ 030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, 030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, 03000000bd12000003c0000000000000,JY-P70UR,a:b1,b:b0,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b4,x:b3,y:b2,platform:Windows, +03000000242f00002d00000000000000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, +03000000242f00008a00000000000000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, 03000000790000000200000000000000,King PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, 030000006d040000d1ca000000000000,Logitech ChillStream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 030000006d040000d2ca000000000000,Logitech Cordless Precision,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, @@ -302,6 +306,7 @@ 03000000790000001a18000000000000,Venom,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, 03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, 030000006f0e00000302000000000000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, +0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:+a3,righty:+a4,start:b4,x:b2,y:b3,platform:Windows, 030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000341a00000608000000000000,Xeox,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, 03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, @@ -310,7 +315,7 @@ 03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, 03000000790000004f18000000000000,ZD-T Android,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows, +030000009b2800006000000000000000,GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows, # Mac OS X 030000008f0e00000300000009010000,2In1 USB Joystick,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, @@ -330,7 +335,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, 03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X, 03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, 030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, @@ -351,6 +355,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, 030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, 030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000242f00002d00000007010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, 030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, 030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, @@ -406,6 +411,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, 030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, 030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, 030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, 03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, 03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, @@ -455,12 +461,13 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000c82d00000160000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000c82d00000260000011010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 030000005e0400008e02000020010000,8BitDo Wireless Adapter,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c82d00000031000011010000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, +05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, 030000006f0e00001302000000010000,Afterglow,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -499,6 +506,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, 03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, +03000000632500002605000010010000,HJD-X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, 030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, 030000000d0f0000c100000011010000,HORI CO. LTD. HORIPAD S,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -529,6 +537,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux, 030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux, +03000000242f00002d00000011010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +03000000242f00008a00000011010000,JYS Wireless Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux, 030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, @@ -581,6 +591,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000250900006688000000010000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux, +060000007e0500000820000000000000,Nintendo Combined Joy-Cons (joycond),a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux, +050000007e0500000920000001800000,Nintendo Switch Pro Controller (joycond),a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8,platform:Linux, +030000007e0500000920000011810000,Nintendo Switch Pro Controller Wired (joycond),a:b0,b:b1,x:b3,y:b2,back:b9,guide:b11,start:b10,leftstick:b12,rightstick:b13,leftshoulder:b5,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b7,righttrigger:b8,platform:Linux, 030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux, 050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux, @@ -593,9 +606,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, 05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, 05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, +03000000830500005020000010010000,Padix Co. Ltd. Rockfire PSX/USB Bridge,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b2,y:b3,platform:Linux, 03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, 030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e00003101000000010000,PDP EA Sports Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000006f0e0000c802000012010000,PDP Kingdom Hearts Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000006f0e0000a802000023020000,PDP Wired Controller for Xbox One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, 030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -629,6 +644,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 050000004c050000cc09000001800000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, 03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux, +030000009b2800003200000001010000,Raphnet Technologies GC/N64 to USB v3.4,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, 030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, 030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000008916000000fd000024010000,Razer Onza Tournament Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, @@ -650,9 +666,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 030000006f0e00001e01000011010000,Rock Candy PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, +03000000a30600001005000000010000,Saitek Saitek P150,platform:Linux,a:b0,b:b1,y:b4,x:b3,leftshoulder:b7,rightshoulder:b2,dpup:-a1,dpleft:-a0,dpdown:+a1,dpright:+a0,lefttrigger:b6,righttrigger:b5, 03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, 03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, -03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b0,y:b1,platform:Linux, +03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, 03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, 03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux, 03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, @@ -667,6 +684,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +03000000d11800000094000011010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, 03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux, @@ -679,16 +697,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000381000003114000075010000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux, 03000000ad1b000038f0000090040000,Street Fighter IV FightStick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, +030000003b07000004a1000000010000,Suncom SFX Plus for USB,a:b0,b:b2,x:b1,y:b3,back:b7,start:b8,leftshoulder:b6,rightshoulder:b9,leftx:a0,lefty:a1,lefttrigger:b4,righttrigger:b5,platform:Linux, 03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, 0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, +03000000457500002211000010010000,SZMY-POWER CO. LTD. GAMEPAD,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, +030000008f0e00000d31000010010000,SZMY-POWER CO. LTD. GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +03000000b50700000399000000010000,Thrustmaster Firestorm Digital 2,a:b2,b:b4,x:b3,y:b5,back:b11,start:b1,leftstick:b10,rightstick:b0,leftshoulder:b6,rightshoulder:b8,leftx:a0,lefty:a1,lefttrigger:b7,righttrigger:b9,platform:Linux, 030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, 030000004f04000026b3000002040000,Thrustmaster Gamepad GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 03000000c6240000025b000002020000,Thrustmaster GPX Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, 030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, 030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, +030000004f04000007d0000000010000,Thrustmaster T Mini Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, 030000004f04000012b3000010010000,Thrustmaster vibrating gamepad,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, 03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, 03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, @@ -721,8 +744,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux, 03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, +030000005e0400008e02000000010000,xbox360 Wireless EasySMX,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux, +030000009b2800006000000001010000,Raphnet Technologies GC/N64 to USB v3.6,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux, # Android 05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, @@ -748,6 +772,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 050000005e040000fd020000ffff3f00,Xbox One Wireless Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, 050000005e04000091020000ff073f00,Xbox Wireless Controller,a:b0,b:b1,back:b4,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android, 34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android, +7573622067616d657061642020202020,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Android, # iOS 05000000ac0500000100000000006d01,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,x:b2,y:b3,platform:iOS, diff --git a/core/input/gamecontrollerdb_204.txt b/core/input/gamecontrollerdb_204.txt deleted file mode 100644 index 7fbe925b25..0000000000 --- a/core/input/gamecontrollerdb_204.txt +++ /dev/null @@ -1,269 +0,0 @@ -# Game Controller DB for SDL in 2.0.4 format -# Source: https://github.com/gabomdq/SDL_GameControllerDB - -# Windows -02200090000000000000504944564944,8Bitdo NES30 PRO USB,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -8f0e1200000000000000504944564944,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -c0111352000000000000504944564944,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, -d81d0b00000000000000504944564944,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, -e8206058000000000000504944564944,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -5e048e02000000000000504944564944,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -791d0103000000000000504944564944,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -0d0f8500000000000000504944564944,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0d0f5e00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:a3,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0d0f5f00000000000000504944564944,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0d0f8400000000000000504944564944,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0d0f8700000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -0d0f8800000000000000504944564944,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -0d0f2700000000000000504944564944,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -28040140000000000000504944564944,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -45130010000000000000504944564944,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -d8140862000000000000504944564944,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -0d0f4000000000000000504944564944,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0d0fee00000000000000504944564944,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0d0f4d00000000000000504944564944,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -25090017000000000000504944564944,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, -d81d0f00000000000000504944564944,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -d81d1000000000000000504944564944,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows, -6f0e2401000000000000504944564944,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -6d0418c2000000000000504944564944,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -38075032000000000000504944564944,Mad Catz FightPad PRO PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -38075082000000000000504944564944,Mad Catz FightPad PRO PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -38078433000000000000504944564944,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -38078483000000000000504944564944,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -38078134000000000000504944564944,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -38078184000000000000504944564944,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -38078034000000000000504944564944,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -38078084000000000000504944564944,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -38078532000000000000504944564944,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -38073888000000000000504944564944,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -38071888000000000000504944564944,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -25090128000000000000504944564944,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, -79004318000000000000504944564944,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -8f0e1030000000000000504944564944,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, -2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -8f0e0d31000000000000504944564944,Multilaser JS071 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -bd1215d0000000000000504944564944,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, -4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, -36280100000000000000504944564944,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b15,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b14,x:b1,y:b2,platform:Windows, -4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,platform:Windows, -120cf60e000000000000504944564944,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -8f0e0300000000000000504944564944,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -10080100000000000000504944564944,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -10080300000000000000504944564944,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, -88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, -25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, -10008200000000000000504944564944,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -300f0011000000000000504944564944,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, -300f1611000000000000504944564944,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -222c0020000000000000504944564944,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, -300f1210000000000000504944564944,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -341a0104000000000000504944564944,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, -222c0223000000000000504944564944,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -222c0023000000000000504944564944,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0d0f1100000000000000504944564944,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -0d0f6a00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0d0f6b00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0d0f8a00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -0d0f8b00000000000000504944564944,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0d0f7000000000000000504944564944,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -0d0f2200000000000000504944564944,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -300f1201000000000000504944564944,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b9,rightx:a2,righty:a3,start:b4,x:b0,y:b1,platform:Windows, -300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -9b280500000000000000504944564944,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -79001100000000000000504944564944,Sega Saturn Gamepad,a:b1,b:b2,leftshoulder:b6,lefttrigger:b3,leftx:a0,lefty:a4,rightshoulder:b7,righttrigger:b0,start:b8,x:b4,y:b5,platform:Windows, -4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -ff113133000000000000504944564944,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, -4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, -66660488000000000000504944564944,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -38076652000000000000504944564944,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -63252305000000000000504944564944,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -79001b18000000000000504944564944,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, - -# Mac OS X -10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -830500000000000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X, -AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -0d0f0000000000004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, -6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, -79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, -d814000000000000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -8f0e0000000000000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, -4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -79000000000000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -81170000000000007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, -b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, -351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -4c05000000000000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -11010000000000002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, -11010000000000001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, -4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, -4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, -bd1200000000000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -10080000000000000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, -050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, -050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, -5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -5e04000000000000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -5e04000000000000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, -5e04000000000000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, - -# Linux -05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, -030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, -03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b1,y:b3,platform:Linux, -0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, -03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, -030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, -03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, -030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, -03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000016c2000010010000,Logitech Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, -05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, -03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, -030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000dd02000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, -030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, -05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, -03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, -030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000790000001100000010010000,RetroLink Saturn Classic Controller,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, -0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, -030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, -03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, -03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, -030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, -030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, -03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, -03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, -xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, - -# Android -4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, - -# iOS -4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, -4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, diff --git a/core/input/gamecontrollerdb_205.txt b/core/input/gamecontrollerdb_205.txt deleted file mode 100644 index 55c45eb148..0000000000 --- a/core/input/gamecontrollerdb_205.txt +++ /dev/null @@ -1,337 +0,0 @@ -# Game Controller DB for SDL in 2.0.5 format -# Source: https://github.com/gabomdq/SDL_GameControllerDB - -# Windows -03000000022000000090000000000000,8Bitdo NES30 PRO USB,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000203800000900000000000000,8Bitdo NES30 PRO Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows, -030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows, -03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows, -030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows, -e8206058000000000000504944564944,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005e00000000000000,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:a3,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005f00000000000000,Fighting Commander 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows, -03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows, -030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -030000006d04000016c2000000000000,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006e00000000000000,HORIPAD 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows, -03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows, -03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows, -030000006d04000019c2000000000000,Logitech Cordless RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows, -6d0418c2000000000000504944564944,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000006d04000018c2000000000000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700005032000000000000,Mad Catz FightPad PRO PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700005082000000000000,Mad Catz FightPad PRO PS4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, -03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows, -03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows, -0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows, -03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000001008000001e5000000000000,NEXT Classic USB Game Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows, -030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,start:b9,x:b2,y:b3,platform:Windows, -03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b15,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b14,x:b1,y:b2,platform:Windows, -4d6963726f736f66742050432d6a6f79,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a5,righty:a4,x:b1,y:b2,platform:Windows, -03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000888800000803000000000000,PS3,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows, -030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, -4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows, -88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows, -03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, -25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows, -03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows, -03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows, -03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows, -03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows, -03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows, -030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows, -030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000a30600000cff000000000000,Saitek P2500,a:b2,b:b3,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b9,rightx:a2,righty:a3,start:b4,x:b0,y:b1,platform:Windows, -03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows, -03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows, -03000000790000001100000000000000,Sega Saturn Gamepad,a:b1,b:b2,leftshoulder:b6,lefttrigger:b3,leftx:a0,lefty:a4,rightshoulder:b7,righttrigger:b0,start:b8,x:b4,y:b5,platform:Windows, -03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows, -030000004c050000cc09000000000000,Sony DualShock 4,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, -030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows, -03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows, -030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows, -030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows, -03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows, -03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows, -03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows, -03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows, -03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows, -03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, -xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows, - -# Mac OS X -03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -10280000000000000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -830500000000000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, -030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, -030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, -0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, -03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, -03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, -030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, -030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, -03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, -030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, -030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, -11010000000000002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, -11010000000000001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, -030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, -030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, -03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, -03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, -050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, -050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, -030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, -030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, -030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, - -# Linux -05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, -05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux, -05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux, -030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux, -03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux, -03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b1,y:b3,platform:Linux, -0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -03000000ff1100004133000010010000,GreenAsia Inc.USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux, -03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux, -030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux, -03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux, -050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux, -030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux, -03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux, -03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000006d04000016c2000010010000,Logitech Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux, -05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux, -03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux, -030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000dd02000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux, -030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux, -03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux, -05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, -05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux, -03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux, -03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux, -030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux, -030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -03000000790000001100000010010000,RetroLink Saturn Classic Controller,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux, -0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, -0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux, -030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux, -03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux, -03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux, -03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux, -030000004c050000c405000011810000,Sony DualShock 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c050000cc09000000810000,Sony DualShock 4 (CUH-ZCT2U) (Bluetooth),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000cc09000011810000,Sony DualShock 4 (CUH-ZCT2U) (USB),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004c0500006802000011810000,Sony PLAYSTATION(R)3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -050000004c0500006802000000810000,Sony PLAYSTATION(R)3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux, -03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux, -030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux, -030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux, -030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux, -030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux, -03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux, -03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux, -03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux, -03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux, -03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux, -030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux, -0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux, -030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux, -xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, - -# Android -4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android, - -# iOS -4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS, -4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS, diff --git a/core/input/godotcontrollerdb.txt b/core/input/godotcontrollerdb.txt index 472b01947b..51ddda1e4e 100644 --- a/core/input/godotcontrollerdb.txt +++ b/core/input/godotcontrollerdb.txt @@ -1,28 +1,11 @@ -# Game Controller DB for SDL in 2.0.6+ format +# Game Controller DB for Godot in SDL 2.0.10 format # Source: https://github.com/godotengine/godot # Windows -9000318000000000000504944564944,Mayflash Wiimote PC Adapter,a:b2,b:h0.4,x:b0,y:b1,back:b4,start:b5,guide:b11,leftshoulder:b6,rightshoulder:b3,leftx:a0,lefty:a1,platform:Windows, -c911f055000000000000504944564944,GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows, __XINPUT_DEVICE__,XInput Gamepad,a:b12,b:b13,x:b14,y:b15,start:b4,back:b5,leftstick:b6,rightstick:b7,leftshoulder:b8,rightshoulder:b9,dpup:b0,dpdown:b1,dpleft:b2,dpright:b3,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Windows, -# Linux -030000006f0e00001302000000010000,Afterglow Gamepad for Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, -05000000362800000100000004010000,OUYA Game Controller,leftx:a0,lefty:a1,dpdown:b9,rightstick:b7,rightshoulder:b5,rightx:a3,start:b16,righty:a4,dpleft:b10,lefttrigger:b12,x:b1,dpup:b8,back:b14,leftstick:b6,leftshoulder:b4,y:b2,a:b0,dpright:b11,righttrigger:b13,b:b3,platform:Linux, -030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftstick:b9,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,platform:Linux, -03000000fd0500002a26000000010000,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b5,rightshoulder:b7,rightx:a2,start:b11,righty:a3,dpleft:h0.8,lefttrigger:b8,x:b0,dpup:h0.1,back:b10,leftstick:b2,leftshoulder:b6,y:b1,a:b3,dpright:h0.2,righttrigger:b9,b:b4,platform:Linux, -030000006f0e00002801000011010000,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b0,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b1,dpright:h0.2,righttrigger:b7,b:b2,platform:Linux, -030000000d0f00004d00000011010000,HORI Gem Pad 3,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux, -030000005e040000ea02000001030000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux, - # Android -4f5559412047616d6520436f6e74726f,OUYA Game Controller,leftx:a1,lefty:a3,dpdown:b12,rightstick:b8,rightshoulder:b10,rightx:a6,start:b-86,righty:a7,dpleft:b13,lefttrigger:b15,x:b2,dpup:b11,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:b14,righttrigger:b16,b:b1,platform:Android, Default Android Gamepad,Default Controller,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,back:b4,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,platform:Android, -532e542e442e20496e74657261637420,3dfx InterAct HammerHead FX,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b25,rightshoulder:b27,rightx:a2,start:b31,righty:a3,dpleft:h0.8,lefttrigger:b28,x:b20,dpup:h0.1,back:b30,leftstick:b22,leftshoulder:b26,y:b21,a:b23,dpright:h0.2,righttrigger:b29,b:b24,platform:Android, -506572666f726d616e63652044657369,PDP Rock Candy Wireless Controller for PS3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:h0.2,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,platform:Android, -4d6963726f736f667420582d426f7820,Microsoft X-Box 360 pad,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a4,x:b2,dpup:h0.1,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a5,b:b1,platform:Android, -484f524920434f2e2c4c544420205041,Hori Gem Pad 3,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b6,rightshoulder:b18,rightx:a2,start:b16,righty:a3,dpleft:h0.8,lefttrigger:b9,x:b0,dpup:h0.1,back:b15,leftstick:b4,leftshoulder:b3,y:b2,a:b1,dpright:h0.2,righttrigger:b10,b:b17,platform:Android, -47656e6572696320582d426f78207061,Logitech F-310,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b8,rightshoulder:b10,rightx:a2,start:b6,righty:a3,dpleft:h0.8,lefttrigger:a5,x:b2,dpup:h0.1,leftstick:b7,leftshoulder:b9,y:b3,a:b0,dpright:h0.2,righttrigger:a4,b:b1,platform:Android, # Javascript Default HTML5 Gamepad, Default Mapping,leftx:a0,lefty:a1,dpdown:b13,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:b14,lefttrigger:a6,x:b2,dpup:b12,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:b15,righttrigger:a7,b:b1,platform:Javascript, diff --git a/core/input/input_filter.cpp b/core/input/input.cpp index 2e8442a905..4d152c1ac4 100644 --- a/core/input/input_filter.cpp +++ b/core/input/input.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* input_filter.cpp */ +/* input.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "input_filter.h" +#include "input.h" #include "core/input/default_controller_mappings.h" #include "core/input/input_map.h" @@ -39,71 +39,149 @@ #include "editor/editor_settings.h" #endif -InputFilter *InputFilter::singleton = nullptr; +static const char *_joy_buttons[JOY_SDL_BUTTONS + 1] = { + "a", + "b", + "x", + "y", + "back", + "guide", + "start", + "leftstick", + "rightstick", + "leftshoulder", + "rightshoulder", + "dpup", + "dpdown", + "dpleft", + "dpright", + nullptr +}; + +static const char *_joy_button_names[JOY_BUTTON_MAX] = { + "Face Bottom", + "Face Right", + "Face Left", + "Face Top", + "Select", + "Guide", + "Start", + "Left Stick", + "Right Stick", + "Left Shoulder", + "Right Shoulder", + "D-Pad Up", + "D-Pad Down", + "D-Pad Left", + "D-Pad Right", + "Button 15", + "Button 16", + "Button 17", + "Button 18", + "Button 19", + "Button 20", + "Button 21", + "Button 22", + "Button 23", + "Button 24", + "Button 25", + "Button 26", + "Button 27", + "Button 28", + "Button 29", + "Button 30", + "Button 31", + "Button 32", + "Button 33", + "Button 34", + "Button 35" +}; + +static const char *_joy_axes[JOY_SDL_AXES + 1] = { + "leftx", + "lefty", + "rightx", + "righty", + "lefttrigger", + "righttrigger", + nullptr +}; + +static const char *_joy_axis_names[JOY_AXIS_MAX] = { + "Left Stick X", + "Left Stick Y", + "Right Stick X", + "Right Stick Y", + "Left Trigger", + "Right Trigger", + "Joystick 3 Stick X", + "Joystick 3 Stick Y", + "Joystick 4 Stick X", + "Joystick 4 Stick Y" +}; -void (*InputFilter::set_mouse_mode_func)(InputFilter::MouseMode) = nullptr; -InputFilter::MouseMode (*InputFilter::get_mouse_mode_func)() = nullptr; -void (*InputFilter::warp_mouse_func)(const Vector2 &p_to_pos) = nullptr; -InputFilter::CursorShape (*InputFilter::get_current_cursor_shape_func)() = nullptr; -void (*InputFilter::set_custom_mouse_cursor_func)(const RES &, InputFilter::CursorShape, const Vector2 &) = nullptr; +Input *Input::singleton = nullptr; -InputFilter *InputFilter::get_singleton() { +void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr; +Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr; +void (*Input::warp_mouse_func)(const Vector2 &p_to_pos) = nullptr; +Input::CursorShape (*Input::get_current_cursor_shape_func)() = nullptr; +void (*Input::set_custom_mouse_cursor_func)(const RES &, Input::CursorShape, const Vector2 &) = nullptr; +Input *Input::get_singleton() { return singleton; } -void InputFilter::set_mouse_mode(MouseMode p_mode) { +void Input::set_mouse_mode(MouseMode p_mode) { ERR_FAIL_INDEX((int)p_mode, 4); set_mouse_mode_func(p_mode); } -InputFilter::MouseMode InputFilter::get_mouse_mode() const { - +Input::MouseMode Input::get_mouse_mode() const { return get_mouse_mode_func(); } -void InputFilter::_bind_methods() { - - ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &InputFilter::is_key_pressed); - ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &InputFilter::is_mouse_button_pressed); - ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &InputFilter::is_joy_button_pressed); - ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &InputFilter::is_action_pressed); - ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &InputFilter::is_action_just_pressed); - ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &InputFilter::is_action_just_released); - ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &InputFilter::get_action_strength); - ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &InputFilter::add_joy_mapping, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &InputFilter::remove_joy_mapping); - ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &InputFilter::joy_connection_changed); - ClassDB::bind_method(D_METHOD("is_joy_known", "device"), &InputFilter::is_joy_known); - ClassDB::bind_method(D_METHOD("get_joy_axis", "device", "axis"), &InputFilter::get_joy_axis); - ClassDB::bind_method(D_METHOD("get_joy_name", "device"), &InputFilter::get_joy_name); - ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &InputFilter::get_joy_guid); - ClassDB::bind_method(D_METHOD("get_connected_joypads"), &InputFilter::get_connected_joypads); - ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &InputFilter::get_joy_vibration_strength); - ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &InputFilter::get_joy_vibration_duration); - ClassDB::bind_method(D_METHOD("get_joy_button_string", "button_index"), &InputFilter::get_joy_button_string); - ClassDB::bind_method(D_METHOD("get_joy_button_index_from_string", "button"), &InputFilter::get_joy_button_index_from_string); - ClassDB::bind_method(D_METHOD("get_joy_axis_string", "axis_index"), &InputFilter::get_joy_axis_string); - ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &InputFilter::get_joy_axis_index_from_string); - ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &InputFilter::start_joy_vibration, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &InputFilter::stop_joy_vibration); - ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &InputFilter::vibrate_handheld, DEFVAL(500)); - ClassDB::bind_method(D_METHOD("get_gravity"), &InputFilter::get_gravity); - ClassDB::bind_method(D_METHOD("get_accelerometer"), &InputFilter::get_accelerometer); - ClassDB::bind_method(D_METHOD("get_magnetometer"), &InputFilter::get_magnetometer); - ClassDB::bind_method(D_METHOD("get_gyroscope"), &InputFilter::get_gyroscope); - ClassDB::bind_method(D_METHOD("get_last_mouse_speed"), &InputFilter::get_last_mouse_speed); - ClassDB::bind_method(D_METHOD("get_mouse_button_mask"), &InputFilter::get_mouse_button_mask); - ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &InputFilter::set_mouse_mode); - ClassDB::bind_method(D_METHOD("get_mouse_mode"), &InputFilter::get_mouse_mode); - ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &InputFilter::warp_mouse_position); - ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &InputFilter::action_press, DEFVAL(1.f)); - ClassDB::bind_method(D_METHOD("action_release", "action"), &InputFilter::action_release); - ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &InputFilter::set_default_cursor_shape, DEFVAL(CURSOR_ARROW)); - ClassDB::bind_method(D_METHOD("get_current_cursor_shape"), &InputFilter::get_current_cursor_shape); - ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &InputFilter::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); - ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &InputFilter::parse_input_event); - ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &InputFilter::set_use_accumulated_input); +void Input::_bind_methods() { + ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed); + ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed); + ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed); + ClassDB::bind_method(D_METHOD("is_action_pressed", "action"), &Input::is_action_pressed); + ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed); + ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released); + ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength); + ClassDB::bind_method(D_METHOD("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); + ClassDB::bind_method(D_METHOD("get_joy_guid", "device"), &Input::get_joy_guid); + ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads); + ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength); + ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration); + ClassDB::bind_method(D_METHOD("get_joy_button_string", "button_index"), &Input::get_joy_button_string); + ClassDB::bind_method(D_METHOD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string); + ClassDB::bind_method(D_METHOD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string); + ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string); + ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); + ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &Input::vibrate_handheld, DEFVAL(500)); + ClassDB::bind_method(D_METHOD("get_gravity"), &Input::get_gravity); + ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer); + ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer); + ClassDB::bind_method(D_METHOD("get_gyroscope"), &Input::get_gyroscope); + ClassDB::bind_method(D_METHOD("get_last_mouse_speed"), &Input::get_last_mouse_speed); + 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_position", "to"), &Input::warp_mouse_position); + ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f)); + ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release); + ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW)); + ClassDB::bind_method(D_METHOD("get_current_cursor_shape"), &Input::get_current_cursor_shape); + ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); + ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); + ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); @@ -131,22 +209,22 @@ void InputFilter::_bind_methods() { ADD_SIGNAL(MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "device"), PropertyInfo(Variant::BOOL, "connected"))); } -void InputFilter::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { +void Input::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { #ifdef TOOLS_ENABLED const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; String pf = p_function; if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) { - List<PropertyInfo> pinfo; ProjectSettings::get_singleton()->get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { const PropertyInfo &pi = E->get(); - if (!pi.name.begins_with("input/")) + if (!pi.name.begins_with("input/")) { continue; + } String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); r_options->push_back(quote_style + name + quote_style); @@ -155,8 +233,7 @@ void InputFilter::get_argument_options(const StringName &p_function, int p_idx, #endif } -void InputFilter::SpeedTrack::update(const Vector2 &p_delta_p) { - +void Input::SpeedTrack::update(const Vector2 &p_delta_p) { uint64_t tick = OS::get_singleton()->get_ticks_usec(); uint32_t tdiff = tick - last_tick; float delta_t = tdiff / 1000000.0; @@ -165,66 +242,60 @@ void InputFilter::SpeedTrack::update(const Vector2 &p_delta_p) { accum += p_delta_p; accum_t += delta_t; - if (accum_t > max_ref_frame * 10) + if (accum_t > max_ref_frame * 10) { accum_t = max_ref_frame * 10; + } while (accum_t >= min_ref_frame) { - float slice_t = min_ref_frame / accum_t; Vector2 slice = accum * slice_t; accum = accum - slice; accum_t -= min_ref_frame; - speed = (slice / min_ref_frame).linear_interpolate(speed, min_ref_frame / max_ref_frame); + speed = (slice / min_ref_frame).lerp(speed, min_ref_frame / max_ref_frame); } } -void InputFilter::SpeedTrack::reset() { +void Input::SpeedTrack::reset() { last_tick = OS::get_singleton()->get_ticks_usec(); speed = Vector2(); accum_t = 0; } -InputFilter::SpeedTrack::SpeedTrack() { - +Input::SpeedTrack::SpeedTrack() { min_ref_frame = 0.1; max_ref_frame = 0.3; reset(); } -bool InputFilter::is_key_pressed(int p_keycode) const { - +bool Input::is_key_pressed(int p_keycode) const { _THREAD_SAFE_METHOD_ return keys_pressed.has(p_keycode); } -bool InputFilter::is_mouse_button_pressed(int p_button) const { - +bool Input::is_mouse_button_pressed(int p_button) const { _THREAD_SAFE_METHOD_ return (mouse_button_mask & (1 << (p_button - 1))) != 0; } static int _combine_device(int p_value, int p_device) { - return p_value | (p_device << 20); } -bool InputFilter::is_joy_button_pressed(int p_device, int p_button) const { - +bool Input::is_joy_button_pressed(int p_device, int p_button) const { _THREAD_SAFE_METHOD_ return joy_buttons_pressed.has(_combine_device(p_button, p_device)); } -bool InputFilter::is_action_pressed(const StringName &p_action) const { - +bool Input::is_action_pressed(const StringName &p_action) const { return action_state.has(p_action) && action_state[p_action].pressed; } -bool InputFilter::is_action_just_pressed(const StringName &p_action) const { - +bool Input::is_action_just_pressed(const StringName &p_action) const { const Map<StringName, Action>::Element *E = action_state.find(p_action); - if (!E) + if (!E) { return false; + } if (Engine::get_singleton()->is_in_physics_frame()) { return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames(); @@ -233,11 +304,11 @@ bool InputFilter::is_action_just_pressed(const StringName &p_action) const { } } -bool InputFilter::is_action_just_released(const StringName &p_action) const { - +bool Input::is_action_just_released(const StringName &p_action) const { const Map<StringName, Action>::Element *E = action_state.find(p_action); - if (!E) + if (!E) { return false; + } if (Engine::get_singleton()->is_in_physics_frame()) { return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames(); @@ -246,16 +317,16 @@ bool InputFilter::is_action_just_released(const StringName &p_action) const { } } -float InputFilter::get_action_strength(const StringName &p_action) const { +float Input::get_action_strength(const StringName &p_action) const { const Map<StringName, Action>::Element *E = action_state.find(p_action); - if (!E) + if (!E) { return 0.0f; + } return E->get().strength; } -float InputFilter::get_joy_axis(int p_device, int p_axis) const { - +float Input::get_joy_axis(int p_device, int p_axis) const { _THREAD_SAFE_METHOD_ int c = _combine_device(p_axis, p_device); if (_joy_axis.has(c)) { @@ -265,13 +336,12 @@ float InputFilter::get_joy_axis(int p_device, int p_axis) const { } } -String InputFilter::get_joy_name(int p_idx) { - +String Input::get_joy_name(int p_idx) { _THREAD_SAFE_METHOD_ return joy_names[p_idx].name; -}; +} -Vector2 InputFilter::get_joy_vibration_strength(int p_device) { +Vector2 Input::get_joy_vibration_strength(int p_device) { if (joy_vibration.has(p_device)) { return Vector2(joy_vibration[p_device].weak_magnitude, joy_vibration[p_device].strong_magnitude); } else { @@ -279,7 +349,7 @@ Vector2 InputFilter::get_joy_vibration_strength(int p_device) { } } -uint64_t InputFilter::get_joy_vibration_timestamp(int p_device) { +uint64_t Input::get_joy_vibration_timestamp(int p_device) { if (joy_vibration.has(p_device)) { return joy_vibration[p_device].timestamp; } else { @@ -287,7 +357,7 @@ uint64_t InputFilter::get_joy_vibration_timestamp(int p_device) { } } -float InputFilter::get_joy_vibration_duration(int p_device) { +float Input::get_joy_vibration_duration(int p_device) { if (joy_vibration.has(p_device)) { return joy_vibration[p_device].duration; } else { @@ -296,7 +366,6 @@ float InputFilter::get_joy_vibration_duration(int p_device) { } static String _hex_str(uint8_t p_byte) { - static const char *dict = "0123456789abcdef"; char ret[3]; ret[2] = 0; @@ -305,24 +374,22 @@ static String _hex_str(uint8_t p_byte) { ret[1] = dict[p_byte & 0xf]; return ret; -}; - -void InputFilter::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) { +} +void Input::joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid) { _THREAD_SAFE_METHOD_ Joypad js; js.name = p_connected ? p_name : ""; js.uid = p_connected ? p_guid : ""; if (p_connected) { - String uidname = p_guid; if (p_guid == "") { int uidlen = MIN(p_name.length(), 16); for (int i = 0; i < uidlen; i++) { uidname = uidname + _hex_str(p_name[i]); - }; - }; + } + } js.uid = uidname; js.connected = true; int mapping = fallback_mapping; @@ -330,56 +397,49 @@ void InputFilter::joy_connection_changed(int p_idx, bool p_connected, String p_n if (js.uid == map_db[i].uid) { mapping = i; js.name = map_db[i].name; - }; - }; + } + } js.mapping = mapping; } else { js.connected = false; for (int i = 0; i < JOY_BUTTON_MAX; i++) { - - if (i < JOY_AXIS_MAX) - set_joy_axis(p_idx, i, 0.0f); - int c = _combine_device(i, p_idx); joy_buttons_pressed.erase(c); - }; - }; + } + for (int i = 0; i < JOY_AXIS_MAX; i++) { + set_joy_axis(p_idx, i, 0.0f); + } + } joy_names[p_idx] = js; emit_signal("joy_connection_changed", p_idx, p_connected); -}; - -Vector3 InputFilter::get_gravity() const { +} +Vector3 Input::get_gravity() const { _THREAD_SAFE_METHOD_ return gravity; } -Vector3 InputFilter::get_accelerometer() const { - +Vector3 Input::get_accelerometer() const { _THREAD_SAFE_METHOD_ return accelerometer; } -Vector3 InputFilter::get_magnetometer() const { - +Vector3 Input::get_magnetometer() const { _THREAD_SAFE_METHOD_ return magnetometer; } -Vector3 InputFilter::get_gyroscope() const { - +Vector3 Input::get_gyroscope() const { _THREAD_SAFE_METHOD_ return gyroscope; } -void InputFilter::parse_input_event(const Ref<InputEvent> &p_event) { - +void Input::parse_input_event(const Ref<InputEvent> &p_event) { _parse_input_event_impl(p_event, false); } -void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) { - +void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) { // Notes on mouse-touch emulation: // - Emulated mouse events are parsed, that is, re-routed to this method, so they make the same effects // as true mouse events. The only difference is the situation is flagged as emulated so they are not @@ -391,16 +451,16 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p Ref<InputEventKey> k = p_event; if (k.is_valid() && !k->is_echo() && k->get_keycode() != 0) { - if (k->is_pressed()) + if (k->is_pressed()) { keys_pressed.insert(k->get_keycode()); - else + } else { keys_pressed.erase(k->get_keycode()); + } } Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - if (mb->is_pressed()) { mouse_button_mask |= (1 << (mb->get_button_index() - 1)); } else { @@ -424,7 +484,6 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { - Point2 pos = mm->get_global_position(); if (mouse_pos != pos) { set_mouse_position(pos); @@ -445,7 +504,6 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p Ref<InputEventScreenTouch> st = p_event; if (st.is_valid()) { - if (st->is_pressed()) { SpeedTrack &track = touch_speed_track[st->get_index()]; track.reset(); @@ -456,7 +514,6 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p } if (emulate_mouse_from_touch) { - bool translate = false; if (st->is_pressed()) { if (mouse_from_touch_index == -1) { @@ -493,13 +550,11 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p Ref<InputEventScreenDrag> sd = p_event; if (sd.is_valid()) { - SpeedTrack &track = touch_speed_track[sd->get_index()]; track.update(sd->get_relative()); sd->set_speed(track.speed); if (emulate_mouse_from_touch && sd->get_index() == mouse_from_touch_index) { - Ref<InputEventMouseMotion> motion_event; motion_event.instance(); @@ -517,13 +572,13 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p Ref<InputEventJoypadButton> jb = p_event; if (jb.is_valid()) { - int c = _combine_device(jb->get_button_index(), jb->get_device()); - if (jb->is_pressed()) + if (jb->is_pressed()) { joy_buttons_pressed.insert(c); - else + } else { joy_buttons_pressed.erase(c); + } } Ref<InputEventJoypadMotion> jm = p_event; @@ -535,7 +590,6 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p Ref<InputEventGesture> ge = p_event; if (ge.is_valid()) { - if (event_dispatch_function) { event_dispatch_function(ge); } @@ -543,7 +597,6 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p for (const Map<StringName, InputMap::Action>::Element *E = InputMap::get_singleton()->get_action_map().front(); E; E = E->next()) { if (InputMap::get_singleton()->event_is_action(p_event, E->key())) { - // Save the action's state if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(E->key())) { Action action; @@ -557,18 +610,18 @@ void InputFilter::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p } } - if (event_dispatch_function) + if (event_dispatch_function) { event_dispatch_function(p_event); + } } -void InputFilter::set_joy_axis(int p_device, int p_axis, float p_value) { - +void Input::set_joy_axis(int p_device, int p_axis, float p_value) { _THREAD_SAFE_METHOD_ int c = _combine_device(p_axis, p_device); _joy_axis[c] = p_value; } -void InputFilter::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) { +void Input::start_joy_vibration(int p_device, float p_weak_magnitude, float p_strong_magnitude, float p_duration) { _THREAD_SAFE_METHOD_ if (p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { return; @@ -581,7 +634,7 @@ void InputFilter::start_joy_vibration(int p_device, float p_weak_magnitude, floa joy_vibration[p_device] = vibration; } -void InputFilter::stop_joy_vibration(int p_device) { +void Input::stop_joy_vibration(int p_device) { _THREAD_SAFE_METHOD_ VibrationInfo vibration; vibration.weak_magnitude = 0; @@ -591,64 +644,56 @@ void InputFilter::stop_joy_vibration(int p_device) { joy_vibration[p_device] = vibration; } -void InputFilter::vibrate_handheld(int p_duration_ms) { +void Input::vibrate_handheld(int p_duration_ms) { OS::get_singleton()->vibrate_handheld(p_duration_ms); } -void InputFilter::set_gravity(const Vector3 &p_gravity) { - +void Input::set_gravity(const Vector3 &p_gravity) { _THREAD_SAFE_METHOD_ gravity = p_gravity; } -void InputFilter::set_accelerometer(const Vector3 &p_accel) { - +void Input::set_accelerometer(const Vector3 &p_accel) { _THREAD_SAFE_METHOD_ accelerometer = p_accel; } -void InputFilter::set_magnetometer(const Vector3 &p_magnetometer) { - +void Input::set_magnetometer(const Vector3 &p_magnetometer) { _THREAD_SAFE_METHOD_ magnetometer = p_magnetometer; } -void InputFilter::set_gyroscope(const Vector3 &p_gyroscope) { - +void Input::set_gyroscope(const Vector3 &p_gyroscope) { _THREAD_SAFE_METHOD_ gyroscope = p_gyroscope; } -void InputFilter::set_mouse_position(const Point2 &p_posf) { - +void Input::set_mouse_position(const Point2 &p_posf) { mouse_speed_track.update(p_posf - mouse_pos); mouse_pos = p_posf; } -Point2 InputFilter::get_mouse_position() const { - +Point2 Input::get_mouse_position() const { return mouse_pos; } -Point2 InputFilter::get_last_mouse_speed() const { +Point2 Input::get_last_mouse_speed() const { return mouse_speed_track.speed; } -int InputFilter::get_mouse_button_mask() const { - +int Input::get_mouse_button_mask() const { return mouse_button_mask; // do not trust OS implementation, should remove it - OS::get_singleton()->get_mouse_button_state(); } -void InputFilter::warp_mouse_position(const Vector2 &p_to) { +void Input::warp_mouse_position(const Vector2 &p_to) { warp_mouse_func(p_to); } -Point2i InputFilter::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { - +Point2i Input::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) { // The relative distance reported for the next event after a warp is in the boundaries of the // size of the rect on that axis, but it may be greater, in which case there's not problem as fmod() // will warp it, but if the pointer has moved in the opposite direction between the pointer relocation @@ -673,11 +718,10 @@ Point2i InputFilter::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motio return rel_warped; } -void InputFilter::iteration(float p_step) { +void Input::iteration(float p_step) { } -void InputFilter::action_press(const StringName &p_action, float p_strength) { - +void Input::action_press(const StringName &p_action, float p_strength) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); @@ -688,8 +732,7 @@ void InputFilter::action_press(const StringName &p_action, float p_strength) { action_state[p_action] = action; } -void InputFilter::action_release(const StringName &p_action) { - +void Input::action_release(const StringName &p_action) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); @@ -700,20 +743,17 @@ void InputFilter::action_release(const StringName &p_action) { action_state[p_action] = action; } -void InputFilter::set_emulate_touch_from_mouse(bool p_emulate) { - +void Input::set_emulate_touch_from_mouse(bool p_emulate) { emulate_touch_from_mouse = p_emulate; } -bool InputFilter::is_emulating_touch_from_mouse() const { - +bool Input::is_emulating_touch_from_mouse() const { return emulate_touch_from_mouse; } // Calling this whenever the game window is focused helps unstucking the "touch mouse" // if the OS or its abstraction class hasn't properly reported that touch pointers raised -void InputFilter::ensure_touch_mouse_raised() { - +void Input::ensure_touch_mouse_raised() { if (mouse_from_touch_index != -1) { mouse_from_touch_index = -1; @@ -731,25 +771,22 @@ void InputFilter::ensure_touch_mouse_raised() { } } -void InputFilter::set_emulate_mouse_from_touch(bool p_emulate) { - +void Input::set_emulate_mouse_from_touch(bool p_emulate) { emulate_mouse_from_touch = p_emulate; } -bool InputFilter::is_emulating_mouse_from_touch() const { - +bool Input::is_emulating_mouse_from_touch() const { return emulate_mouse_from_touch; } -InputFilter::CursorShape InputFilter::get_default_cursor_shape() const { - +Input::CursorShape Input::get_default_cursor_shape() const { return default_shape; } -void InputFilter::set_default_cursor_shape(CursorShape p_shape) { - - if (default_shape == p_shape) +void Input::set_default_cursor_shape(CursorShape p_shape) { + if (default_shape == p_shape) { return; + } default_shape = p_shape; // The default shape is set in Viewport::_gui_input_event. To instantly @@ -761,19 +798,19 @@ void InputFilter::set_default_cursor_shape(CursorShape p_shape) { parse_input_event(mm); } -InputFilter::CursorShape InputFilter::get_current_cursor_shape() const { - +Input::CursorShape Input::get_current_cursor_shape() const { return get_current_cursor_shape_func(); } -void InputFilter::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { - if (Engine::get_singleton()->is_editor_hint()) +void Input::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { + if (Engine::get_singleton()->is_editor_hint()) { return; + } set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot); } -void InputFilter::accumulate_input_event(const Ref<InputEvent> &p_event) { +void Input::accumulate_input_event(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!use_accumulated_input) { @@ -786,39 +823,37 @@ void InputFilter::accumulate_input_event(const Ref<InputEvent> &p_event) { accumulated_events.push_back(p_event); } -void InputFilter::flush_accumulated_events() { +void Input::flush_accumulated_events() { while (accumulated_events.front()) { parse_input_event(accumulated_events.front()->get()); accumulated_events.pop_front(); } } -void InputFilter::set_use_accumulated_input(bool p_enable) { - +void Input::set_use_accumulated_input(bool p_enable) { use_accumulated_input = p_enable; } -void InputFilter::release_pressed_events() { - +void Input::release_pressed_events() { flush_accumulated_events(); // this is needed to release actions strengths keys_pressed.clear(); joy_buttons_pressed.clear(); _joy_axis.clear(); - for (Map<StringName, InputFilter::Action>::Element *E = action_state.front(); E; E = E->next()) { - if (E->get().pressed) + for (Map<StringName, Input::Action>::Element *E = action_state.front(); E; E = E->next()) { + if (E->get().pressed) { action_release(E->key()); + } } } -void InputFilter::set_event_dispatch_function(EventDispatchFunc p_function) { +void Input::set_event_dispatch_function(EventDispatchFunc p_function) { event_dispatch_function = p_function; } -void InputFilter::joy_button(int p_device, int p_button, bool p_pressed) { - +void Input::joy_button(int p_device, int p_button, bool p_pressed) { _THREAD_SAFE_METHOD_; Joypad &joy = joy_names[p_device]; //printf("got button %i, mapping is %i\n", p_button, joy.mapping); @@ -831,21 +866,9 @@ void InputFilter::joy_button(int p_device, int p_button, bool p_pressed) { return; } - const Map<int, JoyEvent>::Element *el = map_db[joy.mapping].buttons.find(p_button); - if (!el) { - //don't process un-mapped events for now, it could mess things up badly for devices with additional buttons/axis - //return _button_event(p_last_id, p_device, p_button, p_pressed); - return; - } + JoyEvent map = _get_mapped_button_event(map_db[joy.mapping], p_button); - JoyEvent map = el->get(); if (map.type == TYPE_BUTTON) { - //fake additional axis event for triggers - if (map.index == JOY_L2 || map.index == JOY_R2) { - float value = p_pressed ? 1.0f : 0.0f; - int axis = map.index == JOY_L2 ? JOY_ANALOG_L2 : JOY_ANALOG_R2; - _axis_event(p_device, axis, value); - } _button_event(p_device, map.index, p_pressed); return; } @@ -856,8 +879,7 @@ void InputFilter::joy_button(int p_device, int p_button, bool p_pressed) { // no event? } -void InputFilter::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { - +void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { _THREAD_SAFE_METHOD_; ERR_FAIL_INDEX(p_axis, JOY_AXIS_MAX); @@ -869,13 +891,10 @@ void InputFilter::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { } if (p_value.value > joy.last_axis[p_axis]) { - if (p_value.value < joy.last_axis[p_axis] + joy.filter) { - return; } } else if (p_value.value > joy.last_axis[p_axis] - joy.filter) { - return; } @@ -899,34 +918,21 @@ void InputFilter::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { if (joy.mapping == -1) { _axis_event(p_device, p_axis, val); return; - }; - - const Map<int, JoyEvent>::Element *el = map_db[joy.mapping].axis.find(p_axis); - if (!el) { - //return _axis_event(p_last_id, p_device, p_axis, p_value); - return; - }; + } - JoyEvent map = el->get(); + JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis, p_value); if (map.type == TYPE_BUTTON) { - //send axis event for triggers - if (map.index == JOY_L2 || map.index == JOY_R2) { - float value = p_value.min == 0 ? p_value.value : 0.5f + p_value.value / 2.0f; - int axis = map.index == JOY_L2 ? JOY_ANALOG_L2 : JOY_ANALOG_R2; - _axis_event(p_device, axis, value); - } - - if (map.index == JOY_DPAD_UP || map.index == JOY_DPAD_DOWN) { + if (map.index == JOY_BUTTON_DPAD_UP || map.index == JOY_BUTTON_DPAD_DOWN) { bool pressed = p_value.value != 0.0f; - int button = p_value.value < 0 ? JOY_DPAD_UP : JOY_DPAD_DOWN; + int button = p_value.value < 0 ? JOY_BUTTON_DPAD_UP : JOY_BUTTON_DPAD_DOWN; if (!pressed) { - if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_UP, p_device))) { - _button_event(p_device, JOY_DPAD_UP, false); + if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_UP, p_device))) { + _button_event(p_device, JOY_BUTTON_DPAD_UP, false); } - if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_DOWN, p_device))) { - _button_event(p_device, JOY_DPAD_DOWN, false); + if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_DOWN, p_device))) { + _button_event(p_device, JOY_BUTTON_DPAD_DOWN, false); } } if (pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) { @@ -935,16 +941,17 @@ void InputFilter::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { _button_event(p_device, button, true); return; } - if (map.index == JOY_DPAD_LEFT || map.index == JOY_DPAD_RIGHT) { + + if (map.index == JOY_BUTTON_DPAD_LEFT || map.index == JOY_BUTTON_DPAD_RIGHT) { bool pressed = p_value.value != 0.0f; - int button = p_value.value < 0 ? JOY_DPAD_LEFT : JOY_DPAD_RIGHT; + int button = p_value.value < 0 ? JOY_BUTTON_DPAD_LEFT : JOY_BUTTON_DPAD_RIGHT; if (!pressed) { - if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_LEFT, p_device))) { - _button_event(p_device, JOY_DPAD_LEFT, false); + if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_LEFT, p_device))) { + _button_event(p_device, JOY_BUTTON_DPAD_LEFT, false); } - if (joy_buttons_pressed.has(_combine_device(JOY_DPAD_RIGHT, p_device))) { - _button_event(p_device, JOY_DPAD_RIGHT, false); + if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_RIGHT, p_device))) { + _button_event(p_device, JOY_BUTTON_DPAD_RIGHT, false); } } if (pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) { @@ -953,36 +960,50 @@ void InputFilter::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { _button_event(p_device, button, true); return; } + float deadzone = p_value.min == 0 ? 0.5f : 0.0f; bool pressed = p_value.value > deadzone; if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) { // button already pressed or released, this is an axis bounce value return; } + _button_event(p_device, map.index, pressed); return; } if (map.type == TYPE_AXIS) { - - _axis_event(p_device, map.index, val); + _axis_event(p_device, map.index, map.value); return; } //printf("invalid mapping\n"); } -void InputFilter::joy_hat(int p_device, int p_val) { - +void Input::joy_hat(int p_device, int p_val) { _THREAD_SAFE_METHOD_; const Joypad &joy = joy_names[p_device]; - const JoyEvent *map; + JoyEvent map[HAT_MAX]; - if (joy.mapping == -1) { - map = hat_map_default; - } else { - map = map_db[joy.mapping].hat; - }; + map[HAT_UP].type = TYPE_BUTTON; + map[HAT_UP].index = JOY_BUTTON_DPAD_UP; + map[HAT_UP].value = 0; + + map[HAT_RIGHT].type = TYPE_BUTTON; + map[HAT_RIGHT].index = JOY_BUTTON_DPAD_RIGHT; + map[HAT_RIGHT].value = 0; + + map[HAT_DOWN].type = TYPE_BUTTON; + map[HAT_DOWN].index = JOY_BUTTON_DPAD_DOWN; + map[HAT_DOWN].value = 0; + + map[HAT_LEFT].type = TYPE_BUTTON; + map[HAT_LEFT].index = JOY_BUTTON_DPAD_LEFT; + map[HAT_LEFT].value = 0; + + if (joy.mapping != -1) { + _get_mapped_hat_events(map_db[joy.mapping], 0, map); + } int cur_val = joy_names[p_device].hat_current; @@ -1003,8 +1024,7 @@ void InputFilter::joy_hat(int p_device, int p_val) { joy_names[p_device].hat_current = p_val; } -void InputFilter::_button_event(int p_device, int p_index, bool p_pressed) { - +void Input::_button_event(int p_device, int p_index, bool p_pressed) { Ref<InputEventJoypadButton> ievent; ievent.instance(); ievent->set_device(p_device); @@ -1014,8 +1034,7 @@ void InputFilter::_button_event(int p_device, int p_index, bool p_pressed) { parse_input_event(ievent); } -void InputFilter::_axis_event(int p_device, int p_axis, float p_value) { - +void Input::_axis_event(int p_device, int p_axis, float p_value) { Ref<InputEventJoypadMotion> ievent; ievent.instance(); ievent->set_device(p_device); @@ -1023,52 +1042,147 @@ void InputFilter::_axis_event(int p_device, int p_axis, float p_value) { ievent->set_axis_value(p_value); parse_input_event(ievent); -}; - -InputFilter::JoyEvent InputFilter::_find_to_event(String p_to) { - - // string names of the SDL buttons in the same order as input_event.h godot buttons - static const char *buttons[] = { "a", "b", "x", "y", "leftshoulder", "rightshoulder", "lefttrigger", "righttrigger", "leftstick", "rightstick", "back", "start", "dpup", "dpdown", "dpleft", "dpright", "guide", nullptr }; - - static const char *axis[] = { "leftx", "lefty", "rightx", "righty", nullptr }; +} - JoyEvent ret; - ret.type = -1; - ret.index = 0; +Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button) { + JoyEvent event; + event.type = TYPE_MAX; + + for (int i = 0; i < mapping.bindings.size(); i++) { + const JoyBinding binding = mapping.bindings[i]; + if (binding.inputType == TYPE_BUTTON && binding.input.button == p_button) { + event.type = binding.outputType; + switch (binding.outputType) { + case TYPE_BUTTON: + event.index = binding.output.button; + return event; + case TYPE_AXIS: + event.index = binding.output.axis.axis; + return event; + default: + ERR_PRINT_ONCE("Joypad button mapping error."); + } + } + } + return event; +} - int i = 0; - while (buttons[i]) { +Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, const JoyAxis &p_value) { + JoyEvent event; + event.type = TYPE_MAX; - if (p_to == buttons[i]) { - ret.type = TYPE_BUTTON; - ret.index = i; - ret.value = 0; - return ret; - }; - ++i; - }; + for (int i = 0; i < mapping.bindings.size(); i++) { + const JoyBinding binding = mapping.bindings[i]; + if (binding.inputType == TYPE_AXIS && binding.input.axis.axis == p_axis) { + float value = p_value.value; + if (binding.input.axis.invert) { + value = -value; + } + if (binding.input.axis.range == FULL_AXIS || + (binding.input.axis.range == POSITIVE_HALF_AXIS && value > 0) || + (binding.input.axis.range == NEGATIVE_HALF_AXIS && value < 0)) { + event.type = binding.outputType; + switch (binding.outputType) { + case TYPE_BUTTON: + event.index = binding.output.button; + return event; + case TYPE_AXIS: + event.index = binding.output.axis.axis; + event.value = value; + if (binding.output.axis.range != binding.input.axis.range) { + float shifted_positive_value = 0; + switch (binding.input.axis.range) { + case POSITIVE_HALF_AXIS: + shifted_positive_value = value; + break; + case NEGATIVE_HALF_AXIS: + shifted_positive_value = value + 1; + break; + case FULL_AXIS: + shifted_positive_value = (value + 1) / 2; + break; + } + switch (binding.output.axis.range) { + case POSITIVE_HALF_AXIS: + event.value = shifted_positive_value; + break; + case NEGATIVE_HALF_AXIS: + event.value = shifted_positive_value - 1; + break; + case FULL_AXIS: + event.value = (shifted_positive_value * 2) - 1; + break; + } + } + return event; + default: + ERR_PRINT_ONCE("Joypad axis mapping error."); + } + } + } + } + return event; +} - i = 0; - while (axis[i]) { +void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[]) { + for (int i = 0; i < mapping.bindings.size(); i++) { + const JoyBinding binding = mapping.bindings[i]; + if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) { + int index; + switch (binding.input.hat.hat_mask) { + case HAT_MASK_UP: + index = 0; + break; + case HAT_MASK_RIGHT: + index = 1; + break; + case HAT_MASK_DOWN: + index = 2; + break; + case HAT_MASK_LEFT: + index = 3; + break; + default: + ERR_PRINT_ONCE("Joypad button mapping error."); + continue; + } - if (p_to == axis[i]) { - ret.type = TYPE_AXIS; - ret.index = i; - ret.value = 0; - return ret; - }; - ++i; - }; + r_events[index].type = binding.outputType; + switch (binding.outputType) { + case TYPE_BUTTON: + r_events[index].index = binding.output.button; + break; + case TYPE_AXIS: + r_events[index].index = binding.output.axis.axis; + break; + default: + ERR_PRINT_ONCE("Joypad button mapping error."); + } + } + } +} - return ret; -}; +JoyButtonList Input::_get_output_button(String output) { + for (int i = 0; _joy_buttons[i]; i++) { + if (output == _joy_buttons[i]) { + return JoyButtonList(i); + } + } + return JoyButtonList::JOY_INVALID_BUTTON; +} -void InputFilter::parse_mapping(String p_mapping) { +JoyAxisList Input::_get_output_axis(String output) { + for (int i = 0; _joy_axes[i]; i++) { + if (output == _joy_axes[i]) { + return JoyAxisList(i); + } + } + return JoyAxisList::JOY_INVALID_AXIS; +} +void Input::parse_mapping(String p_mapping) { _THREAD_SAFE_METHOD_; JoyDeviceMapping mapping; - for (int i = 0; i < HAT_MAX; ++i) - mapping.hat[i].index = 1024 + i; Vector<String> entry = p_mapping.split(","); if (entry.size() < 2) { @@ -1083,52 +1197,89 @@ void InputFilter::parse_mapping(String p_mapping) { int idx = 1; while (++idx < entry.size()) { - - if (entry[idx] == "") + if (entry[idx] == "") { continue; + } - String from = entry[idx].get_slice(":", 1).replace(" ", ""); - String to = entry[idx].get_slice(":", 0).replace(" ", ""); + String output = entry[idx].get_slice(":", 0).replace(" ", ""); + String input = entry[idx].get_slice(":", 1).replace(" ", ""); + ERR_CONTINUE_MSG(output.length() < 1 || input.length() < 2, + String(entry[idx] + "\nInvalid device mapping entry: " + entry[idx])); - JoyEvent to_event = _find_to_event(to); - if (to_event.type == -1) + if (output == "platform") { continue; + } - String etype = from.substr(0, 1); - if (etype == "a") { + JoyAxisRange output_range = FULL_AXIS; + if (output[0] == '+' || output[0] == '-') { + ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx])); + output = output.right(1); + if (output[0] == '+') { + output_range = POSITIVE_HALF_AXIS; + } else if (output[0] == '-') { + output_range = NEGATIVE_HALF_AXIS; + } + } - int aid = from.substr(1, from.length() - 1).to_int(); - mapping.axis[aid] = to_event; + JoyAxisRange input_range = FULL_AXIS; + if (input[0] == '+') { + input_range = POSITIVE_HALF_AXIS; + input = input.right(1); + } else if (input[0] == '-') { + input_range = NEGATIVE_HALF_AXIS; + input = input.right(1); + } + bool invert_axis = false; + if (input[input.length() - 1] == '~') { + invert_axis = true; + } - } else if (etype == "b") { + JoyButtonList output_button = _get_output_button(output); + JoyAxisList output_axis = _get_output_axis(output); + ERR_CONTINUE_MSG(output_button == JOY_INVALID_BUTTON && output_axis == JOY_INVALID_AXIS, + String(entry[idx] + "\nUnrecognised output string: " + output)); + ERR_CONTINUE_MSG(output_button != JOY_INVALID_BUTTON && output_axis != JOY_INVALID_AXIS, + String("BUG: Output string matched both button and axis: " + output)); + + JoyBinding binding; + if (output_button != JOY_INVALID_BUTTON) { + binding.outputType = TYPE_BUTTON; + binding.output.button = output_button; + } else if (output_axis != JOY_INVALID_AXIS) { + binding.outputType = TYPE_AXIS; + binding.output.axis.axis = output_axis; + binding.output.axis.range = output_range; + } - int bid = from.substr(1, from.length() - 1).to_int(); - mapping.buttons[bid] = to_event; + switch (input[0]) { + case 'b': + binding.inputType = TYPE_BUTTON; + binding.input.button = input.right(1).to_int(); + break; + case 'a': + binding.inputType = TYPE_AXIS; + binding.input.axis.axis = input.right(1).to_int(); + binding.input.axis.range = input_range; + binding.input.axis.invert = invert_axis; + break; + case 'h': + ERR_CONTINUE_MSG(input.length() != 4 || input[2] != '.', + String(entry[idx] + "\nInvalid hat input: " + input)); + binding.inputType = TYPE_HAT; + binding.input.hat.hat = input.substr(1, 1).to_int(); + binding.input.hat.hat_mask = static_cast<HatMask>(input.right(3).to_int()); + break; + default: + ERR_CONTINUE_MSG(true, String(entry[idx] + "\nUnrecognised input string: " + input)); + } - } else if (etype == "h") { + mapping.bindings.push_back(binding); + } - int hat_value = from.get_slice(".", 1).to_int(); - switch (hat_value) { - case 1: - mapping.hat[HAT_UP] = to_event; - break; - case 2: - mapping.hat[HAT_RIGHT] = to_event; - break; - case 4: - mapping.hat[HAT_DOWN] = to_event; - break; - case 8: - mapping.hat[HAT_LEFT] = to_event; - break; - }; - }; - }; map_db.push_back(mapping); - //printf("added mapping with uuid %ls\n", mapping.uid.c_str()); -}; +} -void InputFilter::add_joy_mapping(String p_mapping, bool p_update_existing) { +void Input::add_joy_mapping(String p_mapping, bool p_update_existing) { parse_mapping(p_mapping); if (p_update_existing) { Vector<String> entry = p_mapping.split(","); @@ -1141,7 +1292,7 @@ void InputFilter::add_joy_mapping(String p_mapping, bool p_update_existing) { } } -void InputFilter::remove_joy_mapping(String p_guid) { +void Input::remove_joy_mapping(String p_guid) { for (int i = map_db.size() - 1; i >= 0; i--) { if (p_guid == map_db[i].uid) { map_db.remove(i); @@ -1154,8 +1305,7 @@ void InputFilter::remove_joy_mapping(String p_guid) { } } -void InputFilter::set_fallback_mapping(String p_guid) { - +void Input::set_fallback_mapping(String p_guid) { for (int i = 0; i < map_db.size(); i++) { if (map_db[i].uid == p_guid) { fallback_mapping = i; @@ -1165,17 +1315,17 @@ void InputFilter::set_fallback_mapping(String p_guid) { } //platforms that use the remapping system can override and call to these ones -bool InputFilter::is_joy_known(int p_device) { +bool Input::is_joy_known(int p_device) { int mapping = joy_names[p_device].mapping; return mapping != -1 ? (mapping != fallback_mapping) : false; } -String InputFilter::get_joy_guid(int p_device) const { +String Input::get_joy_guid(int p_device) const { ERR_FAIL_COND_V(!joy_names.has(p_device), ""); return joy_names[p_device].uid; } -Array InputFilter::get_connected_joypads() { +Array Input::get_connected_joypads() { Array ret; Map<int, Joypad>::Element *elem = joy_names.front(); while (elem) { @@ -1187,53 +1337,21 @@ Array InputFilter::get_connected_joypads() { return ret; } -static const char *_buttons[JOY_BUTTON_MAX] = { - "Face Button Bottom", - "Face Button Right", - "Face Button Left", - "Face Button Top", - "L", - "R", - "L2", - "R2", - "L3", - "R3", - "Select", - "Start", - "DPAD Up", - "DPAD Down", - "DPAD Left", - "DPAD Right" -}; - -static const char *_axes[JOY_AXIS_MAX] = { - "Left Stick X", - "Left Stick Y", - "Right Stick X", - "Right Stick Y", - "", - "", - "L2", - "R2", - "", - "" -}; - -String InputFilter::get_joy_button_string(int p_button) { - ERR_FAIL_INDEX_V(p_button, JOY_BUTTON_MAX, ""); - return _buttons[p_button]; +String Input::get_joy_button_string(int p_button) { + ERR_FAIL_INDEX_V(p_button, JOY_BUTTON_MAX, "Invalid button"); + return _joy_button_names[p_button]; } -int InputFilter::get_joy_button_index_from_string(String p_button) { +int Input::get_joy_button_index_from_string(String p_button) { for (int i = 0; i < JOY_BUTTON_MAX; i++) { - if (p_button == _buttons[i]) { + if (p_button == _joy_button_names[i]) { return i; } } - ERR_FAIL_V(-1); + ERR_FAIL_V(JOY_INVALID_BUTTON); } -int InputFilter::get_unused_joy_id() { +int Input::get_unused_joy_id() { for (int i = 0; i < JOYPADS_MAX; i++) { if (!joy_names.has(i) || !joy_names[i].connected) { return i; @@ -1242,49 +1360,22 @@ int InputFilter::get_unused_joy_id() { return -1; } -String InputFilter::get_joy_axis_string(int p_axis) { - ERR_FAIL_INDEX_V(p_axis, JOY_AXIS_MAX, ""); - return _axes[p_axis]; +String Input::get_joy_axis_string(int p_axis) { + ERR_FAIL_INDEX_V(p_axis, JOY_AXIS_MAX, "Invalid axis"); + return _joy_axis_names[p_axis]; } -int InputFilter::get_joy_axis_index_from_string(String p_axis) { +int Input::get_joy_axis_index_from_string(String p_axis) { for (int i = 0; i < JOY_AXIS_MAX; i++) { - if (p_axis == _axes[i]) { + if (p_axis == _joy_axis_names[i]) { return i; } } - ERR_FAIL_V(-1); + ERR_FAIL_V(JOY_INVALID_AXIS); } -InputFilter::InputFilter() { - +Input::Input() { singleton = this; - use_accumulated_input = true; - mouse_button_mask = 0; - mouse_window = 0; - emulate_touch_from_mouse = false; - emulate_mouse_from_touch = false; - mouse_from_touch_index = -1; - event_dispatch_function = nullptr; - default_shape = CURSOR_ARROW; - - hat_map_default[HAT_UP].type = TYPE_BUTTON; - hat_map_default[HAT_UP].index = JOY_DPAD_UP; - hat_map_default[HAT_UP].value = 0; - - hat_map_default[HAT_RIGHT].type = TYPE_BUTTON; - hat_map_default[HAT_RIGHT].index = JOY_DPAD_RIGHT; - hat_map_default[HAT_RIGHT].value = 0; - - hat_map_default[HAT_DOWN].type = TYPE_BUTTON; - hat_map_default[HAT_DOWN].index = JOY_DPAD_DOWN; - hat_map_default[HAT_DOWN].value = 0; - - hat_map_default[HAT_LEFT].type = TYPE_BUTTON; - hat_map_default[HAT_LEFT].index = JOY_DPAD_LEFT; - hat_map_default[HAT_LEFT].value = 0; - - fallback_mapping = -1; // Parse default mappings. { @@ -1299,8 +1390,9 @@ InputFilter::InputFilter() { if (env_mapping != "") { Vector<String> entries = env_mapping.split("\n"); for (int i = 0; i < entries.size(); i++) { - if (entries[i] == "") + if (entries[i] == "") { continue; + } parse_mapping(entries[i]); } } diff --git a/core/input/input_filter.h b/core/input/input.h index 908a005228..91e3b83b95 100644 --- a/core/input/input_filter.h +++ b/core/input/input.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* input_filter.h */ +/* input.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -35,12 +35,11 @@ #include "core/object.h" #include "core/os/thread_safe.h" -class InputFilter : public Object { - - GDCLASS(InputFilter, Object); +class Input : public Object { + GDCLASS(Input, Object); _THREAD_SAFE_CLASS_ - static InputFilter *singleton; + static Input *singleton; public: enum MouseMode { @@ -100,7 +99,7 @@ public: typedef void (*EventDispatchFunc)(const Ref<InputEvent> &p_event); private: - int mouse_button_mask; + int mouse_button_mask = 0; Set<int> keys_pressed; Set<int> joy_buttons_pressed; @@ -111,7 +110,7 @@ private: Vector3 magnetometer; Vector3 gyroscope; Vector2 mouse_pos; - int64_t mouse_window; + int64_t mouse_window = 0; struct Action { uint64_t physics_frame; @@ -122,22 +121,13 @@ private: Map<StringName, Action> action_state; - bool emulate_touch_from_mouse; - bool emulate_mouse_from_touch; + bool emulate_touch_from_mouse = false; + bool emulate_mouse_from_touch = false; + bool use_accumulated_input = false; - int mouse_from_touch_index; - - struct VibrationInfo { - float weak_magnitude; - float strong_magnitude; - float duration; // Duration in seconds - uint64_t timestamp; - }; - - Map<int, VibrationInfo> joy_vibration; + int mouse_from_touch_index = -1; struct SpeedTrack { - uint64_t last_tick; Vector2 speed; Vector2 accum; @@ -153,37 +143,21 @@ private: struct Joypad { StringName name; StringName uid; - bool connected; - bool last_buttons[JOY_BUTTON_MAX + 19]; //apparently SDL specifies 35 possible buttons on android - float last_axis[JOY_AXIS_MAX]; - float filter; - int last_hat; - int mapping; - int hat_current; - - Joypad() { - for (int i = 0; i < JOY_AXIS_MAX; i++) { - - last_axis[i] = 0.0f; - } - for (int i = 0; i < JOY_BUTTON_MAX + 19; i++) { - - last_buttons[i] = false; - } - connected = false; - last_hat = HAT_MASK_CENTER; - filter = 0.01f; - mapping = -1; - hat_current = 0; - } + bool connected = false; + bool last_buttons[JOY_BUTTON_MAX] = { false }; + float last_axis[JOY_AXIS_MAX] = { 0.0f }; + float filter = 0.01f; + int last_hat = HAT_MASK_CENTER; + int mapping = -1; + int hat_current = 0; }; SpeedTrack mouse_speed_track; Map<int, SpeedTrack> touch_speed_track; Map<int, Joypad> joy_names; - int fallback_mapping; + int fallback_mapping = -1; - CursorShape default_shape; + CursorShape default_shape = CURSOR_ARROW; enum JoyType { TYPE_BUTTON, @@ -192,26 +166,61 @@ private: TYPE_MAX, }; + enum JoyAxisRange { + NEGATIVE_HALF_AXIS = -1, + FULL_AXIS = 0, + POSITIVE_HALF_AXIS = 1 + }; + struct JoyEvent { int type; int index; - int value; + float value; }; - struct JoyDeviceMapping { + struct JoyBinding { + JoyType inputType; + union { + int button; + + struct { + int axis; + JoyAxisRange range; + bool invert; + } axis; + + struct { + int hat; + HatMask hat_mask; + } hat; + } input; + + JoyType outputType; + union { + JoyButtonList button; + + struct { + JoyAxisList axis; + JoyAxisRange range; + } axis; + + } output; + }; + + struct JoyDeviceMapping { String uid; String name; - Map<int, JoyEvent> buttons; - Map<int, JoyEvent> axis; - JoyEvent hat[HAT_MAX]; + Vector<JoyBinding> bindings; }; - JoyEvent hat_map_default[HAT_MAX]; - Vector<JoyDeviceMapping> map_db; - JoyEvent _find_to_event(String p_to); + JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button); + JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, const JoyAxis &p_value); + void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]); + JoyButtonList _get_output_button(String output); + JoyAxisList _get_output_axis(String output); void _button_event(int p_device, int p_index, bool p_pressed); void _axis_event(int p_device, int p_axis, float p_value); float _handle_deadzone(int p_device, int p_axis, float p_value); @@ -219,7 +228,7 @@ private: void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); List<Ref<InputEvent>> accumulated_events; - bool use_accumulated_input; + friend class DisplayServer; static void (*set_mouse_mode_func)(MouseMode); @@ -229,9 +238,18 @@ private: static CursorShape (*get_current_cursor_shape_func)(); static void (*set_custom_mouse_cursor_func)(const RES &, CursorShape, const Vector2 &); - EventDispatchFunc event_dispatch_function; + EventDispatchFunc event_dispatch_function = nullptr; protected: + struct VibrationInfo { + float weak_magnitude; + float strong_magnitude; + float duration; // Duration in seconds + uint64_t timestamp; + }; + + Map<int, VibrationInfo> joy_vibration; + static void _bind_methods(); public: @@ -239,7 +257,7 @@ public: MouseMode get_mouse_mode() const; void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; - static InputFilter *get_singleton(); + static Input *get_singleton(); bool is_key_pressed(int p_keycode) const; bool is_mouse_button_pressed(int p_button) const; @@ -299,7 +317,7 @@ public: CursorShape get_default_cursor_shape() const; void set_default_cursor_shape(CursorShape p_shape); CursorShape get_current_cursor_shape() const; - void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = InputFilter::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); + void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape = Input::CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()); void parse_mapping(String p_mapping); void joy_button(int p_device, int p_button, bool p_pressed); @@ -328,10 +346,10 @@ public: void set_event_dispatch_function(EventDispatchFunc p_function); - InputFilter(); + Input(); }; -VARIANT_ENUM_CAST(InputFilter::MouseMode); -VARIANT_ENUM_CAST(InputFilter::CursorShape); +VARIANT_ENUM_CAST(Input::MouseMode); +VARIANT_ENUM_CAST(Input::CursorShape); #endif // INPUT_H diff --git a/core/input/input_builders.py b/core/input/input_builders.py index 53b90f2073..748ec06133 100644 --- a/core/input/input_builders.py +++ b/core/input/input_builders.py @@ -42,18 +42,7 @@ def make_default_controller_mappings(target, source, env): src_path, current_platform, platform_mappings[current_platform][guid] ) ) - valid_mapping = True - for input_map in line_parts[2:]: - if "+" in input_map or "-" in input_map or "~" in input_map: - g.write( - "// WARNING - DISCARDED UNSUPPORTED MAPPING TYPE FROM DATABASE {}: {} {}\n".format( - src_path, current_platform, line - ) - ) - valid_mapping = False - break - if valid_mapping: - platform_mappings[current_platform][guid] = line + platform_mappings[current_platform][guid] = line platform_variables = { "Linux": "#if X11_ENABLED", diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 80219331c0..6ba082f86f 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -45,26 +45,22 @@ int InputEvent::get_device() const { } bool InputEvent::is_action(const StringName &p_action) const { - return InputMap::get_singleton()->event_is_action(Ref<InputEvent>((InputEvent *)this), p_action); } bool InputEvent::is_action_pressed(const StringName &p_action, bool p_allow_echo) const { - bool pressed; bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed); return valid && pressed && (p_allow_echo || !is_echo()); } bool InputEvent::is_action_released(const StringName &p_action) const { - bool pressed; bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed); return valid && !pressed; } float InputEvent::get_action_strength(const StringName &p_action) const { - bool pressed; float strength; bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed, &strength); @@ -72,42 +68,34 @@ float InputEvent::get_action_strength(const StringName &p_action) const { } bool InputEvent::is_pressed() const { - return false; } bool InputEvent::is_echo() const { - return false; } Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - return Ref<InputEvent>((InputEvent *)this); } String InputEvent::as_text() const { - return String(); } bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { - return false; } bool InputEvent::shortcut_match(const Ref<InputEvent> &p_event) const { - return false; } bool InputEvent::is_action_type() const { - return false; } void InputEvent::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_device", "device"), &InputEvent::set_device); ClassDB::bind_method(D_METHOD("get_device"), &InputEvent::get_device); @@ -132,14 +120,9 @@ void InputEvent::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "device"), "set_device", "get_device"); } -InputEvent::InputEvent() { - - device = 0; -} -//////////////// +/////////////////////////////////// void InputEventFromWindow::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_window_id", "id"), &InputEventFromWindow::set_window_id); ClassDB::bind_method(D_METHOD("get_window_id"), &InputEventFromWindow::get_window_id); ADD_PROPERTY(PropertyInfo(Variant::INT, "window_id"), "set_window_id", "get_window_id"); @@ -148,64 +131,54 @@ void InputEventFromWindow::_bind_methods() { void InputEventFromWindow::set_window_id(int64_t p_id) { window_id = p_id; } + int64_t InputEventFromWindow::get_window_id() const { return window_id; } -InputEventFromWindow::InputEventFromWindow() { - window_id = 0; -} - -////////////////// +/////////////////////////////////// void InputEventWithModifiers::set_shift(bool p_enabled) { - shift = p_enabled; } bool InputEventWithModifiers::get_shift() const { - return shift; } void InputEventWithModifiers::set_alt(bool p_enabled) { - alt = p_enabled; } -bool InputEventWithModifiers::get_alt() const { +bool InputEventWithModifiers::get_alt() const { return alt; } void InputEventWithModifiers::set_control(bool p_enabled) { - control = p_enabled; } -bool InputEventWithModifiers::get_control() const { +bool InputEventWithModifiers::get_control() const { return control; } void InputEventWithModifiers::set_metakey(bool p_enabled) { - meta = p_enabled; } -bool InputEventWithModifiers::get_metakey() const { +bool InputEventWithModifiers::get_metakey() const { return meta; } void InputEventWithModifiers::set_command(bool p_enabled) { - command = p_enabled; } -bool InputEventWithModifiers::get_command() const { +bool InputEventWithModifiers::get_command() const { return command; } void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModifiers *event) { - set_alt(event->get_alt()); set_shift(event->get_shift()); set_control(event->get_control()); @@ -213,7 +186,6 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif } void InputEventWithModifiers::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt); ClassDB::bind_method(D_METHOD("get_alt"), &InputEventWithModifiers::get_alt); @@ -236,101 +208,89 @@ void InputEventWithModifiers::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command"), "set_command", "get_command"); } -InputEventWithModifiers::InputEventWithModifiers() { - - alt = false; - shift = false; - control = false; - meta = false; -} - -////////////////////////////////// +/////////////////////////////////// void InputEventKey::set_pressed(bool p_pressed) { - pressed = p_pressed; } bool InputEventKey::is_pressed() const { - return pressed; } void InputEventKey::set_keycode(uint32_t p_keycode) { - keycode = p_keycode; } uint32_t InputEventKey::get_keycode() const { - return keycode; } void InputEventKey::set_physical_keycode(uint32_t p_keycode) { - physical_keycode = p_keycode; } uint32_t InputEventKey::get_physical_keycode() const { - return physical_keycode; } void InputEventKey::set_unicode(uint32_t p_unicode) { - unicode = p_unicode; } uint32_t InputEventKey::get_unicode() const { - return unicode; } void InputEventKey::set_echo(bool p_enable) { - echo = p_enable; } bool InputEventKey::is_echo() const { - return echo; } uint32_t InputEventKey::get_keycode_with_modifiers() const { - uint32_t sc = keycode; - if (get_control()) + if (get_control()) { sc |= KEY_MASK_CTRL; - if (get_alt()) + } + if (get_alt()) { sc |= KEY_MASK_ALT; - if (get_shift()) + } + if (get_shift()) { sc |= KEY_MASK_SHIFT; - if (get_metakey()) + } + if (get_metakey()) { sc |= KEY_MASK_META; + } return sc; } uint32_t InputEventKey::get_physical_keycode_with_modifiers() const { - uint32_t sc = physical_keycode; - if (get_control()) + if (get_control()) { sc |= KEY_MASK_CTRL; - if (get_alt()) + } + if (get_alt()) { sc |= KEY_MASK_ALT; - if (get_shift()) + } + if (get_shift()) { sc |= KEY_MASK_SHIFT; - if (get_metakey()) + } + if (get_metakey()) { sc |= KEY_MASK_META; + } return sc; } String InputEventKey::as_text() const { - String kc = keycode_get_string(keycode); - if (kc == String()) + if (kc == String()) { return kc; + } if (get_metakey()) { kc = find_keycode_name(KEY_META) + ("+" + kc); @@ -348,10 +308,10 @@ String InputEventKey::as_text() const { } bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { - Ref<InputEventKey> key = p_event; - if (key.is_null()) + if (key.is_null()) { return false; + } bool match = false; if (get_keycode() == 0) { @@ -366,19 +326,21 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed match = get_keycode() == key->get_keycode() && (!key->is_pressed() || (code & event_code) == code); } if (match) { - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = key->is_pressed(); - if (p_strength != nullptr) + } + if (p_strength != nullptr) { *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + } } return match; } bool InputEventKey::shortcut_match(const Ref<InputEvent> &p_event) const { - Ref<InputEventKey> key = p_event; - if (key.is_null()) + if (key.is_null()) { return false; + } uint32_t code = get_keycode_with_modifiers(); uint32_t event_code = key->get_keycode_with_modifiers(); @@ -387,7 +349,6 @@ bool InputEventKey::shortcut_match(const Ref<InputEvent> &p_event) const { } void InputEventKey::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventKey::set_pressed); ClassDB::bind_method(D_METHOD("set_keycode", "keycode"), &InputEventKey::set_keycode); @@ -411,46 +372,33 @@ void InputEventKey::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo"); } -InputEventKey::InputEventKey() { - - pressed = false; - keycode = 0; - physical_keycode = 0; - unicode = 0; ///unicode - echo = false; -} - -//////////////////////////////////////// +/////////////////////////////////// void InputEventMouse::set_button_mask(int p_mask) { - button_mask = p_mask; } -int InputEventMouse::get_button_mask() const { +int InputEventMouse::get_button_mask() const { return button_mask; } void InputEventMouse::set_position(const Vector2 &p_pos) { - pos = p_pos; } -Vector2 InputEventMouse::get_position() const { +Vector2 InputEventMouse::get_position() const { return pos; } void InputEventMouse::set_global_position(const Vector2 &p_global_pos) { - global_pos = p_global_pos; } -Vector2 InputEventMouse::get_global_position() const { +Vector2 InputEventMouse::get_global_position() const { return global_pos; } void InputEventMouse::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_button_mask", "button_mask"), &InputEventMouse::set_button_mask); ClassDB::bind_method(D_METHOD("get_button_mask"), &InputEventMouse::get_button_mask); @@ -465,52 +413,41 @@ void InputEventMouse::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position"), "set_global_position", "get_global_position"); } -InputEventMouse::InputEventMouse() { - - button_mask = 0; -} - -/////////////////////////////////////// +/////////////////////////////////// void InputEventMouseButton::set_factor(float p_factor) { - factor = p_factor; } -float InputEventMouseButton::get_factor() { - +float InputEventMouseButton::get_factor() const { return factor; } void InputEventMouseButton::set_button_index(int p_index) { - button_index = p_index; } -int InputEventMouseButton::get_button_index() const { +int InputEventMouseButton::get_button_index() const { return button_index; } void InputEventMouseButton::set_pressed(bool p_pressed) { - pressed = p_pressed; } -bool InputEventMouseButton::is_pressed() const { +bool InputEventMouseButton::is_pressed() const { return pressed; } void InputEventMouseButton::set_doubleclick(bool p_doubleclick) { - doubleclick = p_doubleclick; } -bool InputEventMouseButton::is_doubleclick() const { +bool InputEventMouseButton::is_doubleclick() const { return doubleclick; } Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Vector2 g = get_global_position(); Vector2 l = p_xform.xform(get_position() + p_local_ofs); @@ -534,24 +471,25 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co } bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { - Ref<InputEventMouseButton> mb = p_event; - if (mb.is_null()) + if (mb.is_null()) { return false; + } bool match = mb->button_index == button_index; if (match) { - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = mb->is_pressed(); - if (p_strength != nullptr) + } + if (p_strength != nullptr) { *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + } } return match; } String InputEventMouseButton::as_text() const { - String button_index_string = ""; switch (get_button_index()) { case BUTTON_LEFT: @@ -589,7 +527,6 @@ String InputEventMouseButton::as_text() const { } void InputEventMouseButton::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMouseButton::set_factor); ClassDB::bind_method(D_METHOD("get_factor"), &InputEventMouseButton::get_factor); @@ -608,58 +545,41 @@ void InputEventMouseButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "doubleclick"), "set_doubleclick", "is_doubleclick"); } -InputEventMouseButton::InputEventMouseButton() { - - factor = 1; - button_index = 0; - pressed = false; - doubleclick = false; -} - -//////////////////////////////////////////// +/////////////////////////////////// void InputEventMouseMotion::set_tilt(const Vector2 &p_tilt) { - tilt = p_tilt; } Vector2 InputEventMouseMotion::get_tilt() const { - return tilt; } void InputEventMouseMotion::set_pressure(float p_pressure) { - pressure = p_pressure; } float InputEventMouseMotion::get_pressure() const { - return pressure; } void InputEventMouseMotion::set_relative(const Vector2 &p_relative) { - relative = p_relative; } Vector2 InputEventMouseMotion::get_relative() const { - return relative; } void InputEventMouseMotion::set_speed(const Vector2 &p_speed) { - speed = p_speed; } Vector2 InputEventMouseMotion::get_speed() const { - return speed; } Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Vector2 g = get_global_position(); Vector2 l = p_xform.xform(get_position() + p_local_ofs); Vector2 r = p_xform.basis_xform(get_relative()); @@ -686,7 +606,6 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co } String InputEventMouseMotion::as_text() const { - String button_mask_string = ""; switch (get_button_mask()) { case BUTTON_MASK_LEFT: @@ -708,14 +627,14 @@ String InputEventMouseMotion::as_text() const { button_mask_string = itos(get_button_mask()); break; } - return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")"; + return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + "), pressure=(" + rtos(get_pressure()) + "), tilt=(" + String(get_tilt()) + ")"; } bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { - Ref<InputEventMouseMotion> motion = p_event; - if (motion.is_null()) + if (motion.is_null()) { return false; + } if (get_window_id() != motion->get_window_id()) { return false; @@ -754,7 +673,6 @@ bool InputEventMouseMotion::accumulate(const Ref<InputEvent> &p_event) { } void InputEventMouseMotion::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_tilt", "tilt"), &InputEventMouseMotion::set_tilt); ClassDB::bind_method(D_METHOD("get_tilt"), &InputEventMouseMotion::get_tilt); @@ -773,50 +691,41 @@ void InputEventMouseMotion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed"); } -InputEventMouseMotion::InputEventMouseMotion() { - - pressure = 0; -} - -//////////////////////////////////////// +/////////////////////////////////// void InputEventJoypadMotion::set_axis(int p_axis) { - axis = p_axis; } int InputEventJoypadMotion::get_axis() const { - return axis; } void InputEventJoypadMotion::set_axis_value(float p_value) { - axis_value = p_value; } float InputEventJoypadMotion::get_axis_value() const { - return axis_value; } bool InputEventJoypadMotion::is_pressed() const { - return Math::abs(axis_value) >= 0.5f; } bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { - Ref<InputEventJoypadMotion> jm = p_event; - if (jm.is_null()) + if (jm.is_null()) { return false; + } bool match = (axis == jm->axis); // Matches even if not in the same direction, but returns a "not pressed" event. if (match) { bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0); bool pressed = same_direction ? Math::abs(jm->get_axis_value()) >= p_deadzone : false; - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = pressed; + } if (p_strength != nullptr) { if (pressed) { if (p_deadzone == 1.0f) { @@ -833,12 +742,10 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool * } String InputEventJoypadMotion::as_text() const { - return "InputEventJoypadMotion : axis=" + itos(axis) + ", axis_value=" + String(Variant(axis_value)); } void InputEventJoypadMotion::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_axis", "axis"), &InputEventJoypadMotion::set_axis); ClassDB::bind_method(D_METHOD("get_axis"), &InputEventJoypadMotion::get_axis); @@ -849,74 +756,65 @@ void InputEventJoypadMotion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "axis_value"), "set_axis_value", "get_axis_value"); } -InputEventJoypadMotion::InputEventJoypadMotion() { - - axis = 0; - axis_value = 0; -} -///////////////////////////////// +/////////////////////////////////// void InputEventJoypadButton::set_button_index(int p_index) { - button_index = p_index; } int InputEventJoypadButton::get_button_index() const { - return button_index; } void InputEventJoypadButton::set_pressed(bool p_pressed) { - pressed = p_pressed; } -bool InputEventJoypadButton::is_pressed() const { +bool InputEventJoypadButton::is_pressed() const { return pressed; } void InputEventJoypadButton::set_pressure(float p_pressure) { - pressure = p_pressure; } -float InputEventJoypadButton::get_pressure() const { +float InputEventJoypadButton::get_pressure() const { return pressure; } bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { - Ref<InputEventJoypadButton> jb = p_event; - if (jb.is_null()) + if (jb.is_null()) { return false; + } bool match = button_index == jb->button_index; if (match) { - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = jb->is_pressed(); - if (p_strength != nullptr) + } + if (p_strength != nullptr) { *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + } } return match; } bool InputEventJoypadButton::shortcut_match(const Ref<InputEvent> &p_event) const { - Ref<InputEventJoypadButton> button = p_event; - if (button.is_null()) + if (button.is_null()) { return false; + } return button_index == button->button_index; } String InputEventJoypadButton::as_text() const { - return "InputEventJoypadButton : button_index=" + itos(button_index) + ", pressed=" + (pressed ? "true" : "false") + ", pressure=" + String(Variant(pressure)); } void InputEventJoypadButton::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_button_index", "button_index"), &InputEventJoypadButton::set_button_index); ClassDB::bind_method(D_METHOD("get_button_index"), &InputEventJoypadButton::get_button_index); @@ -931,44 +829,33 @@ void InputEventJoypadButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); } -InputEventJoypadButton::InputEventJoypadButton() { - - button_index = 0; - pressure = 0; - pressed = false; -} - -////////////////////////////////////////////// +/////////////////////////////////// void InputEventScreenTouch::set_index(int p_index) { - index = p_index; } -int InputEventScreenTouch::get_index() const { +int InputEventScreenTouch::get_index() const { return index; } void InputEventScreenTouch::set_position(const Vector2 &p_pos) { - pos = p_pos; } -Vector2 InputEventScreenTouch::get_position() const { +Vector2 InputEventScreenTouch::get_position() const { return pos; } void InputEventScreenTouch::set_pressed(bool p_pressed) { - pressed = p_pressed; } -bool InputEventScreenTouch::is_pressed() const { +bool InputEventScreenTouch::is_pressed() const { return pressed; } Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Ref<InputEventScreenTouch> st; st.instance(); st->set_device(get_device()); @@ -981,12 +868,10 @@ Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, co } String InputEventScreenTouch::as_text() const { - return "InputEventScreenTouch : index=" + itos(index) + ", pressed=" + (pressed ? "true" : "false") + ", position=(" + String(get_position()) + ")"; } 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); @@ -1001,53 +886,41 @@ void InputEventScreenTouch::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); } -InputEventScreenTouch::InputEventScreenTouch() { - - index = 0; - pressed = false; -} - -///////////////////////////// +/////////////////////////////////// void InputEventScreenDrag::set_index(int p_index) { - index = p_index; } int InputEventScreenDrag::get_index() const { - return index; } void InputEventScreenDrag::set_position(const Vector2 &p_pos) { - pos = p_pos; } -Vector2 InputEventScreenDrag::get_position() const { +Vector2 InputEventScreenDrag::get_position() const { return pos; } void InputEventScreenDrag::set_relative(const Vector2 &p_relative) { - relative = p_relative; } -Vector2 InputEventScreenDrag::get_relative() const { +Vector2 InputEventScreenDrag::get_relative() const { return relative; } void InputEventScreenDrag::set_speed(const Vector2 &p_speed) { - speed = p_speed; } -Vector2 InputEventScreenDrag::get_speed() const { +Vector2 InputEventScreenDrag::get_speed() const { return speed; } Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Ref<InputEventScreenDrag> sd; sd.instance(); @@ -1064,12 +937,10 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con } String InputEventScreenDrag::as_text() const { - return "InputEventScreenDrag : index=" + itos(index) + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")"; } void InputEventScreenDrag::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenDrag::set_index); ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenDrag::get_index); @@ -1088,27 +959,21 @@ void InputEventScreenDrag::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "speed"), "set_speed", "get_speed"); } -InputEventScreenDrag::InputEventScreenDrag() { - - index = 0; -} -///////////////////////////// +/////////////////////////////////// void InputEventAction::set_action(const StringName &p_action) { - action = p_action; } -StringName InputEventAction::get_action() const { +StringName InputEventAction::get_action() const { return action; } void InputEventAction::set_pressed(bool p_pressed) { - pressed = p_pressed; } -bool InputEventAction::is_pressed() const { +bool InputEventAction::is_pressed() const { return pressed; } @@ -1121,40 +986,40 @@ float InputEventAction::get_strength() const { } bool InputEventAction::shortcut_match(const Ref<InputEvent> &p_event) const { - if (p_event.is_null()) + if (p_event.is_null()) { return false; + } return p_event->is_action(action); } bool InputEventAction::is_action(const StringName &p_action) const { - return action == p_action; } bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { - Ref<InputEventAction> act = p_event; - if (act.is_null()) + if (act.is_null()) { return false; + } bool match = action == act->action; if (match) { - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = act->pressed; - if (p_strength != nullptr) + } + if (p_strength != nullptr) { *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + } } return match; } String InputEventAction::as_text() const { - return "InputEventAction : action=" + action + ", pressed=(" + (pressed ? "true" : "false"); } void InputEventAction::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_action", "action"), &InputEventAction::set_action); ClassDB::bind_method(D_METHOD("get_action"), &InputEventAction::get_action); @@ -1171,19 +1036,13 @@ void InputEventAction::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "strength", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_strength", "get_strength"); } -InputEventAction::InputEventAction() { - pressed = false; - strength = 1.0f; -} -///////////////////////////// +/////////////////////////////////// void InputEventGesture::set_position(const Vector2 &p_pos) { - pos = p_pos; } void InputEventGesture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventGesture::set_position); ClassDB::bind_method(D_METHOD("get_position"), &InputEventGesture::get_position); @@ -1191,23 +1050,20 @@ void InputEventGesture::_bind_methods() { } Vector2 InputEventGesture::get_position() const { - return pos; } -///////////////////////////// -void InputEventMagnifyGesture::set_factor(real_t p_factor) { +/////////////////////////////////// +void InputEventMagnifyGesture::set_factor(real_t p_factor) { factor = p_factor; } real_t InputEventMagnifyGesture::get_factor() const { - return factor; } Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Ref<InputEventMagnifyGesture> ev; ev.instance(); @@ -1223,26 +1079,19 @@ Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, } String InputEventMagnifyGesture::as_text() const { - return "InputEventMagnifyGesture : factor=" + rtos(get_factor()) + ", position=(" + String(get_position()) + ")"; } void InputEventMagnifyGesture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_factor", "factor"), &InputEventMagnifyGesture::set_factor); ClassDB::bind_method(D_METHOD("get_factor"), &InputEventMagnifyGesture::get_factor); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "factor"), "set_factor", "get_factor"); } -InputEventMagnifyGesture::InputEventMagnifyGesture() { - - factor = 1.0; -} -///////////////////////////// +/////////////////////////////////// void InputEventPanGesture::set_delta(const Vector2 &p_delta) { - delta = p_delta; } @@ -1251,7 +1100,6 @@ Vector2 InputEventPanGesture::get_delta() const { } Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs) const { - Ref<InputEventPanGesture> ev; ev.instance(); @@ -1267,26 +1115,19 @@ Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, con } String InputEventPanGesture::as_text() const { - return "InputEventPanGesture : delta=(" + String(get_delta()) + "), position=(" + String(get_position()) + ")"; } void InputEventPanGesture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_delta", "delta"), &InputEventPanGesture::set_delta); ClassDB::bind_method(D_METHOD("get_delta"), &InputEventPanGesture::get_delta); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "delta"), "set_delta", "get_delta"); } -InputEventPanGesture::InputEventPanGesture() { - - delta = Vector2(0, 0); -} -///////////////////////////// +/////////////////////////////////// void InputEventMIDI::set_channel(const int p_channel) { - channel = p_channel; } @@ -1295,7 +1136,6 @@ int InputEventMIDI::get_channel() const { } void InputEventMIDI::set_message(const int p_message) { - message = p_message; } @@ -1304,7 +1144,6 @@ int InputEventMIDI::get_message() const { } void InputEventMIDI::set_pitch(const int p_pitch) { - pitch = p_pitch; } @@ -1313,7 +1152,6 @@ int InputEventMIDI::get_pitch() const { } void InputEventMIDI::set_velocity(const int p_velocity) { - velocity = p_velocity; } @@ -1322,7 +1160,6 @@ int InputEventMIDI::get_velocity() const { } void InputEventMIDI::set_instrument(const int p_instrument) { - instrument = p_instrument; } @@ -1331,7 +1168,6 @@ int InputEventMIDI::get_instrument() const { } void InputEventMIDI::set_pressure(const int p_pressure) { - pressure = p_pressure; } @@ -1340,7 +1176,6 @@ int InputEventMIDI::get_pressure() const { } void InputEventMIDI::set_controller_number(const int p_controller_number) { - controller_number = p_controller_number; } @@ -1349,7 +1184,6 @@ int InputEventMIDI::get_controller_number() const { } void InputEventMIDI::set_controller_value(const int p_controller_value) { - controller_value = p_controller_value; } @@ -1358,12 +1192,10 @@ int InputEventMIDI::get_controller_value() const { } String InputEventMIDI::as_text() const { - return "InputEventMIDI : channel=(" + itos(get_channel()) + "), message=(" + itos(get_message()) + ")"; } void InputEventMIDI::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_channel", "channel"), &InputEventMIDI::set_channel); ClassDB::bind_method(D_METHOD("get_channel"), &InputEventMIDI::get_channel); ClassDB::bind_method(D_METHOD("set_message", "message"), &InputEventMIDI::set_message); @@ -1390,15 +1222,3 @@ void InputEventMIDI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_number"), "set_controller_number", "get_controller_number"); ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_value"), "set_controller_value", "get_controller_value"); } - -InputEventMIDI::InputEventMIDI() { - - channel = 0; - message = 0; - pitch = 0; - velocity = 0; - instrument = 0; - pressure = 0; - controller_number = 0; - controller_value = 0; -} diff --git a/core/input/input_event.h b/core/input/input_event.h index 2fdcdd0319..dd1cc11982 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -59,98 +59,84 @@ enum ButtonList { BUTTON_MASK_XBUTTON2 = (1 << (BUTTON_XBUTTON2 - 1)) }; -enum JoystickList { - - JOY_BUTTON_0 = 0, - JOY_BUTTON_1 = 1, - JOY_BUTTON_2 = 2, - JOY_BUTTON_3 = 3, - JOY_BUTTON_4 = 4, - JOY_BUTTON_5 = 5, - JOY_BUTTON_6 = 6, - JOY_BUTTON_7 = 7, - JOY_BUTTON_8 = 8, - JOY_BUTTON_9 = 9, - JOY_BUTTON_10 = 10, - JOY_BUTTON_11 = 11, - JOY_BUTTON_12 = 12, - JOY_BUTTON_13 = 13, - JOY_BUTTON_14 = 14, - JOY_BUTTON_15 = 15, - JOY_BUTTON_MAX = 16, - - JOY_L = JOY_BUTTON_4, - JOY_R = JOY_BUTTON_5, - JOY_L2 = JOY_BUTTON_6, - JOY_R2 = JOY_BUTTON_7, - JOY_L3 = JOY_BUTTON_8, - JOY_R3 = JOY_BUTTON_9, - JOY_SELECT = JOY_BUTTON_10, - JOY_START = JOY_BUTTON_11, - JOY_DPAD_UP = JOY_BUTTON_12, - JOY_DPAD_DOWN = JOY_BUTTON_13, - JOY_DPAD_LEFT = JOY_BUTTON_14, - JOY_DPAD_RIGHT = JOY_BUTTON_15, - - JOY_SONY_CIRCLE = JOY_BUTTON_1, - JOY_SONY_X = JOY_BUTTON_0, - JOY_SONY_SQUARE = JOY_BUTTON_2, - JOY_SONY_TRIANGLE = JOY_BUTTON_3, - - JOY_XBOX_A = JOY_BUTTON_0, - JOY_XBOX_B = JOY_BUTTON_1, - JOY_XBOX_X = JOY_BUTTON_2, - JOY_XBOX_Y = JOY_BUTTON_3, - - JOY_DS_A = JOY_BUTTON_1, - JOY_DS_B = JOY_BUTTON_0, - JOY_DS_X = JOY_BUTTON_3, - JOY_DS_Y = JOY_BUTTON_2, - - JOY_WII_C = JOY_BUTTON_5, - JOY_WII_Z = JOY_BUTTON_6, - - JOY_WII_MINUS = JOY_BUTTON_10, - JOY_WII_PLUS = JOY_BUTTON_11, - - JOY_VR_GRIP = JOY_BUTTON_2, - JOY_VR_PAD = JOY_BUTTON_14, - JOY_VR_TRIGGER = JOY_BUTTON_15, - - JOY_OCULUS_AX = JOY_BUTTON_7, - JOY_OCULUS_BY = JOY_BUTTON_1, - JOY_OCULUS_MENU = JOY_BUTTON_3, - - JOY_OPENVR_MENU = JOY_BUTTON_1, - - // end of history - - JOY_AXIS_0 = 0, - JOY_AXIS_1 = 1, - JOY_AXIS_2 = 2, - JOY_AXIS_3 = 3, - JOY_AXIS_4 = 4, - JOY_AXIS_5 = 5, - JOY_AXIS_6 = 6, - JOY_AXIS_7 = 7, - JOY_AXIS_8 = 8, - JOY_AXIS_9 = 9, - JOY_AXIS_MAX = 10, - - JOY_ANALOG_LX = JOY_AXIS_0, - JOY_ANALOG_LY = JOY_AXIS_1, - - JOY_ANALOG_RX = JOY_AXIS_2, - JOY_ANALOG_RY = JOY_AXIS_3, - - JOY_ANALOG_L2 = JOY_AXIS_6, - JOY_ANALOG_R2 = JOY_AXIS_7, - - JOY_VR_ANALOG_TRIGGER = JOY_AXIS_2, - JOY_VR_ANALOG_GRIP = JOY_AXIS_4, - - JOY_OPENVR_TOUCHPADX = JOY_AXIS_0, - JOY_OPENVR_TOUCHPADY = JOY_AXIS_1, +enum JoyButtonList { + + JOY_INVALID_BUTTON = -1, + + // SDL Buttons + JOY_BUTTON_A = 0, + JOY_BUTTON_B = 1, + JOY_BUTTON_X = 2, + JOY_BUTTON_Y = 3, + JOY_BUTTON_BACK = 4, + JOY_BUTTON_GUIDE = 5, + JOY_BUTTON_START = 6, + JOY_BUTTON_LEFT_STICK = 7, + JOY_BUTTON_RIGHT_STICK = 8, + JOY_BUTTON_LEFT_SHOULDER = 9, + JOY_BUTTON_RIGHT_SHOULDER = 10, + JOY_BUTTON_DPAD_UP = 11, + JOY_BUTTON_DPAD_DOWN = 12, + JOY_BUTTON_DPAD_LEFT = 13, + JOY_BUTTON_DPAD_RIGHT = 14, + JOY_SDL_BUTTONS = 15, + + // Sony Buttons + JOY_SONY_X = JOY_BUTTON_A, + JOY_SONY_CROSS = JOY_BUTTON_A, + JOY_SONY_CIRCLE = JOY_BUTTON_B, + JOY_SONY_SQUARE = JOY_BUTTON_X, + JOY_SONY_TRIANGLE = JOY_BUTTON_Y, + JOY_SONY_SELECT = JOY_BUTTON_BACK, + JOY_SONY_START = JOY_BUTTON_START, + JOY_SONY_PS = JOY_BUTTON_GUIDE, + JOY_SONY_L1 = JOY_BUTTON_LEFT_SHOULDER, + JOY_SONY_R1 = JOY_BUTTON_RIGHT_SHOULDER, + JOY_SONY_L3 = JOY_BUTTON_LEFT_STICK, + JOY_SONY_R3 = JOY_BUTTON_RIGHT_STICK, + + // Xbox Buttons + JOY_XBOX_A = JOY_BUTTON_A, + JOY_XBOX_B = JOY_BUTTON_B, + JOY_XBOX_X = JOY_BUTTON_X, + JOY_XBOX_Y = JOY_BUTTON_Y, + JOY_XBOX_BACK = JOY_BUTTON_BACK, + JOY_XBOX_START = JOY_BUTTON_START, + JOY_XBOX_HOME = JOY_BUTTON_GUIDE, + JOY_XBOX_LS = JOY_BUTTON_LEFT_STICK, + JOY_XBOX_RS = JOY_BUTTON_RIGHT_STICK, + JOY_XBOX_LB = JOY_BUTTON_LEFT_SHOULDER, + JOY_XBOX_RB = JOY_BUTTON_RIGHT_SHOULDER, + + JOY_BUTTON_MAX = 36 // Apparently Android supports up to 36 buttons. +}; + +enum JoyAxisList { + + JOY_INVALID_AXIS = -1, + + // SDL Axes + JOY_AXIS_LEFT_X = 0, + JOY_AXIS_LEFT_Y = 1, + JOY_AXIS_RIGHT_X = 2, + JOY_AXIS_RIGHT_Y = 3, + JOY_AXIS_TRIGGER_LEFT = 4, + JOY_AXIS_TRIGGER_RIGHT = 5, + JOY_SDL_AXES = 6, + + // Joystick axes. + JOY_AXIS_0_X = 0, + JOY_AXIS_0_Y = 1, + JOY_AXIS_1_X = 2, + JOY_AXIS_1_Y = 3, + JOY_AXIS_2_X = 4, + JOY_AXIS_2_Y = 5, + JOY_AXIS_3_X = 6, + JOY_AXIS_3_Y = 7, + JOY_AXIS_4_X = 8, + JOY_AXIS_4_Y = 9, + + JOY_AXIS_MAX = 10 // OpenVR supports up to 5 Joysticks making a total of 10 axes. }; enum MidiMessageList { @@ -171,7 +157,7 @@ enum MidiMessageList { class InputEvent : public Resource { GDCLASS(InputEvent, Resource); - int device; + int device = 0; protected: static void _bind_methods(); @@ -191,7 +177,6 @@ public: // To be removed someday, since they do not make sense for all events virtual bool is_pressed() const; virtual bool is_echo() const; - // ...-. virtual String as_text() const; @@ -202,14 +187,14 @@ public: virtual bool is_action_type() const; virtual bool accumulate(const Ref<InputEvent> &p_event) { return false; } - InputEvent(); + + InputEvent() {} }; class InputEventFromWindow : public InputEvent { - GDCLASS(InputEventFromWindow, InputEvent); - int64_t window_id; + int64_t window_id = 0; protected: static void _bind_methods(); @@ -218,28 +203,27 @@ public: void set_window_id(int64_t p_id); int64_t get_window_id() const; - InputEventFromWindow(); + InputEventFromWindow() {} }; class InputEventWithModifiers : public InputEventFromWindow { GDCLASS(InputEventWithModifiers, InputEventFromWindow); - bool shift; - bool alt; + bool shift = false; + bool alt = false; #ifdef APPLE_STYLE_KEYS union { bool command; - bool meta; //< windows/mac key + bool meta = false; //< windows/mac key }; - bool control; + bool control = false; #else union { bool command; //< windows/mac key - bool control; + bool control = false; }; - bool meta; //< windows/mac key - + bool meta = false; //< windows/mac key #endif protected: @@ -263,20 +247,19 @@ public: void set_modifiers_from_event(const InputEventWithModifiers *event); - InputEventWithModifiers(); + InputEventWithModifiers() {} }; class InputEventKey : public InputEventWithModifiers { - GDCLASS(InputEventKey, InputEventWithModifiers); - bool pressed; /// otherwise release + bool pressed = false; /// otherwise release - uint32_t keycode; ///< check keyboard.h , KeyCode enum, without modifier masks - uint32_t physical_keycode; - uint32_t unicode; ///unicode + uint32_t keycode = 0; ///< check keyboard.h , KeyCode enum, without modifier masks + uint32_t physical_keycode = 0; + uint32_t unicode = 0; ///unicode - bool echo; /// true if this is an echo key + bool echo = false; /// true if this is an echo key protected: static void _bind_methods(); @@ -307,14 +290,13 @@ public: virtual String as_text() const; - InputEventKey(); + InputEventKey() {} }; class InputEventMouse : public InputEventWithModifiers { - GDCLASS(InputEventMouse, InputEventWithModifiers); - int button_mask; + int button_mask = 0; Vector2 pos; Vector2 global_pos; @@ -332,24 +314,23 @@ public: void set_global_position(const Vector2 &p_global_pos); Vector2 get_global_position() const; - InputEventMouse(); + InputEventMouse() {} }; class InputEventMouseButton : public InputEventMouse { - GDCLASS(InputEventMouseButton, InputEventMouse); - float factor; - int button_index; - bool pressed; //otherwise released - bool doubleclick; //last even less than doubleclick time + float factor = 1; + int button_index = 0; + bool pressed = false; //otherwise released + bool doubleclick = false; //last even less than doubleclick time protected: static void _bind_methods(); public: void set_factor(float p_factor); - float get_factor(); + float get_factor() const; void set_button_index(int p_index); int get_button_index() const; @@ -366,15 +347,14 @@ public: virtual bool is_action_type() const { return true; } virtual String as_text() const; - InputEventMouseButton(); + InputEventMouseButton() {} }; class InputEventMouseMotion : public InputEventMouse { - GDCLASS(InputEventMouseMotion, InputEventMouse); Vector2 tilt; - float pressure; + float pressure = 0; Vector2 relative; Vector2 speed; @@ -399,14 +379,13 @@ public: virtual bool accumulate(const Ref<InputEvent> &p_event); - InputEventMouseMotion(); + InputEventMouseMotion() {} }; class InputEventJoypadMotion : public InputEvent { - GDCLASS(InputEventJoypadMotion, InputEvent); - int axis; ///< Joypad axis - float axis_value; ///< -1 to 1 + int axis = 0; ///< Joypad axis + float axis_value = 0; ///< -1 to 1 protected: static void _bind_methods(); @@ -425,15 +404,15 @@ public: virtual bool is_action_type() const { return true; } virtual String as_text() const; - InputEventJoypadMotion(); + InputEventJoypadMotion() {} }; class InputEventJoypadButton : public InputEvent { GDCLASS(InputEventJoypadButton, InputEvent); - int button_index; - bool pressed; - float pressure; //0 to 1 + int button_index = 0; + bool pressed = false; + float pressure = 0; //0 to 1 protected: static void _bind_methods(); @@ -453,14 +432,14 @@ public: virtual bool is_action_type() const { return true; } virtual String as_text() const; - InputEventJoypadButton(); + InputEventJoypadButton() {} }; class InputEventScreenTouch : public InputEventFromWindow { GDCLASS(InputEventScreenTouch, InputEventFromWindow); - int index; + int index = 0; Vector2 pos; - bool pressed; + bool pressed = false; protected: static void _bind_methods(); @@ -478,13 +457,12 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; virtual String as_text() const; - InputEventScreenTouch(); + InputEventScreenTouch() {} }; class InputEventScreenDrag : public InputEventFromWindow { - GDCLASS(InputEventScreenDrag, InputEventFromWindow); - int index; + int index = 0; Vector2 pos; Vector2 relative; Vector2 speed; @@ -508,16 +486,15 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; virtual String as_text() const; - InputEventScreenDrag(); + InputEventScreenDrag() {} }; class InputEventAction : public InputEvent { - GDCLASS(InputEventAction, InputEvent); StringName action; - bool pressed; - float strength; + bool pressed = false; + float strength = 1.0f; protected: static void _bind_methods(); @@ -540,11 +517,10 @@ public: virtual bool is_action_type() const { return true; } virtual String as_text() const; - InputEventAction(); + InputEventAction() {} }; class InputEventGesture : public InputEventWithModifiers { - GDCLASS(InputEventGesture, InputEventWithModifiers); Vector2 pos; @@ -558,9 +534,8 @@ public: }; class InputEventMagnifyGesture : public InputEventGesture { - GDCLASS(InputEventMagnifyGesture, InputEventGesture); - real_t factor; + real_t factor = 1.0; protected: static void _bind_methods(); @@ -572,11 +547,10 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; virtual String as_text() const; - InputEventMagnifyGesture(); + InputEventMagnifyGesture() {} }; class InputEventPanGesture : public InputEventGesture { - GDCLASS(InputEventPanGesture, InputEventGesture); Vector2 delta; @@ -590,20 +564,20 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; virtual String as_text() const; - InputEventPanGesture(); + InputEventPanGesture() {} }; class InputEventMIDI : public InputEvent { GDCLASS(InputEventMIDI, InputEvent); - int channel; - int message; - int pitch; - int velocity; - int instrument; - int pressure; - int controller_number; - int controller_value; + int channel = 0; + int message = 0; + int pitch = 0; + int velocity = 0; + int instrument = 0; + int pressure = 0; + int controller_number = 0; + int controller_value = 0; protected: static void _bind_methods(); @@ -635,7 +609,7 @@ public: virtual String as_text() const; - InputEventMIDI(); + InputEventMIDI() {} }; #endif // INPUT_EVENT_H diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 6b6acf062d..ac032b7d10 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -38,7 +38,6 @@ InputMap *InputMap::singleton = nullptr; int InputMap::ALL_DEVICES = -1; void InputMap::_bind_methods() { - ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action); ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions); ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.5f)); @@ -49,13 +48,12 @@ void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event); ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event); ClassDB::bind_method(D_METHOD("action_erase_events", "action"), &InputMap::action_erase_events); - ClassDB::bind_method(D_METHOD("get_action_list", "action"), &InputMap::_get_action_list); + ClassDB::bind_method(D_METHOD("action_get_events", "action"), &InputMap::_action_get_events); ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action); ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals); } void InputMap::add_action(const StringName &p_action, float p_deadzone) { - ERR_FAIL_COND_MSG(input_map.has(p_action), "InputMap already has action '" + String(p_action) + "'."); input_map[p_action] = Action(); static int last_id = 1; @@ -65,20 +63,18 @@ void InputMap::add_action(const StringName &p_action, float p_deadzone) { } void InputMap::erase_action(const StringName &p_action) { - ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); input_map.erase(p_action); } Array InputMap::_get_actions() { - Array ret; List<StringName> actions = get_actions(); - if (actions.empty()) + if (actions.empty()) { return ret; + } for (const List<StringName>::Element *E = actions.front(); E; E = E->next()) { - ret.push_back(E->get()); } @@ -86,7 +82,6 @@ Array InputMap::_get_actions() { } List<StringName> InputMap::get_actions() const { - List<StringName> actions = List<StringName>(); if (input_map.empty()) { return actions; @@ -100,9 +95,7 @@ List<StringName> InputMap::get_actions() const { } List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const { - for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) { - const Ref<InputEvent> e = E->get(); //if (e.type != Ref<InputEvent>::KEY && e.device != p_event.device) -- unsure about the KEY comparison, why is this here? @@ -120,56 +113,50 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re } bool InputMap::has_action(const StringName &p_action) const { - return input_map.has(p_action); } void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) { - ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); input_map[p_action].deadzone = p_deadzone; } void InputMap::action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event) { - ERR_FAIL_COND_MSG(p_event.is_null(), "It's not a reference to a valid InputEvent object."); ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); - if (_find_event(input_map[p_action], p_event)) + if (_find_event(input_map[p_action], p_event)) { return; //already gots + } input_map[p_action].inputs.push_back(p_event); } bool InputMap::action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event) { - ERR_FAIL_COND_V_MSG(!input_map.has(p_action), false, "Request for nonexistent InputMap action '" + String(p_action) + "'."); return (_find_event(input_map[p_action], p_event) != nullptr); } void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event) { - ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event); - if (E) + if (E) { input_map[p_action].inputs.erase(E); + } } void InputMap::action_erase_events(const StringName &p_action) { - ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); input_map[p_action].inputs.clear(); } -Array InputMap::_get_action_list(const StringName &p_action) { - +Array InputMap::_action_get_events(const StringName &p_action) { Array ret; - const List<Ref<InputEvent>> *al = get_action_list(p_action); + const List<Ref<InputEvent>> *al = action_get_events(p_action); if (al) { for (const List<Ref<InputEvent>>::Element *E = al->front(); E; E = E->next()) { - ret.push_back(E->get()); } } @@ -177,11 +164,11 @@ Array InputMap::_get_action_list(const StringName &p_action) { return ret; } -const List<Ref<InputEvent>> *InputMap::get_action_list(const StringName &p_action) { - +const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_action) { const Map<StringName, Action>::Element *E = input_map.find(p_action); - if (!E) + if (!E) { return nullptr; + } return &E->get().inputs; } @@ -196,10 +183,12 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str Ref<InputEventAction> input_event_action = p_event; if (input_event_action.is_valid()) { - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = input_event_action->is_pressed(); - if (p_strength != nullptr) + } + if (p_strength != nullptr) { *p_strength = (p_pressed != nullptr && *p_pressed) ? input_event_action->get_strength() : 0.0f; + } return input_event_action->get_action() == p_action; } @@ -207,10 +196,12 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str float strength; List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength); if (event != nullptr) { - if (p_pressed != nullptr) + if (p_pressed != nullptr) { *p_pressed = pressed; - if (p_strength != nullptr) + } + if (p_strength != nullptr) { *p_strength = strength; + } return true; } else { return false; @@ -222,7 +213,6 @@ const Map<StringName, InputMap::Action> &InputMap::get_action_map() const { } void InputMap::load_from_globals() { - input_map.clear(); List<PropertyInfo> pinfo; @@ -231,8 +221,9 @@ void InputMap::load_from_globals() { for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { const PropertyInfo &pi = E->get(); - if (!pi.name.begins_with("input/")) + if (!pi.name.begins_with("input/")) { continue; + } String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); @@ -243,15 +234,15 @@ void InputMap::load_from_globals() { add_action(name, deadzone); for (int i = 0; i < events.size(); i++) { Ref<InputEvent> event = events[i]; - if (event.is_null()) + if (event.is_null()) { continue; + } action_add_event(name, event); } } } void InputMap::load_default() { - Ref<InputEventKey> key; add_action("ui_accept"); @@ -332,7 +323,6 @@ void InputMap::load_default() { } InputMap::InputMap() { - ERR_FAIL_COND_MSG(singleton, "Singleton in InputMap already exist."); singleton = this; } diff --git a/core/input/input_map.h b/core/input/input_map.h index e03bc5fd4f..548553ed31 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -35,7 +35,6 @@ #include "core/object.h" class InputMap : public Object { - GDCLASS(InputMap, Object); public: @@ -57,7 +56,7 @@ private: List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr) const; - Array _get_action_list(const StringName &p_action); + Array _action_get_events(const StringName &p_action); Array _get_actions(); protected: @@ -77,7 +76,7 @@ public: void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event); void action_erase_events(const StringName &p_action); - const List<Ref<InputEvent>> *get_action_list(const StringName &p_action); + const List<Ref<InputEvent>> *action_get_events(const StringName &p_action); bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const; bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr) const; diff --git a/core/io/compression.cpp b/core/io/compression.cpp index 20c9fdca6f..99ca8107e4 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -40,10 +40,8 @@ #include <zstd.h> int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) { - switch (p_mode) { case MODE_FASTLZ: { - if (p_src_size < 16) { uint8_t src[16]; zeromem(&src[p_src_size], 16 - p_src_size); @@ -56,7 +54,6 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, } break; case MODE_DEFLATE: case MODE_GZIP: { - int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16; z_stream strm; @@ -65,8 +62,9 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, strm.opaque = Z_NULL; int level = p_mode == MODE_DEFLATE ? zlib_level : gzip_level; int err = deflateInit2(&strm, level, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY); - if (err != Z_OK) + if (err != Z_OK) { return -1; + } strm.avail_in = p_src_size; int aout = deflateBound(&strm, p_src_size); @@ -97,19 +95,17 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, } int Compression::get_max_compressed_buffer_size(int p_src_size, Mode p_mode) { - switch (p_mode) { case MODE_FASTLZ: { - int ss = p_src_size + p_src_size * 6 / 100; - if (ss < 66) + if (ss < 66) { ss = 66; + } return ss; } break; case MODE_DEFLATE: case MODE_GZIP: { - int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16; z_stream strm; @@ -117,14 +113,14 @@ int Compression::get_max_compressed_buffer_size(int p_src_size, Mode p_mode) { strm.zfree = zipio_free; strm.opaque = Z_NULL; int err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, window_bits, 8, Z_DEFAULT_STRATEGY); - if (err != Z_OK) + if (err != Z_OK) { return -1; + } int aout = deflateBound(&strm, p_src_size); deflateEnd(&strm); return aout; } break; case MODE_ZSTD: { - return ZSTD_compressBound(p_src_size); } break; } @@ -133,10 +129,8 @@ int Compression::get_max_compressed_buffer_size(int p_src_size, Mode p_mode) { } int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode) { - switch (p_mode) { case MODE_FASTLZ: { - int ret_size = 0; if (p_dst_max_size < 16) { @@ -150,7 +144,6 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p } break; case MODE_DEFLATE: case MODE_GZIP: { - int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16; z_stream strm; diff --git a/core/io/compression.h b/core/io/compression.h index 8354b581fa..f195f96ba5 100644 --- a/core/io/compression.h +++ b/core/io/compression.h @@ -34,7 +34,6 @@ #include "core/typedefs.h" class Compression { - public: static int zlib_level; static int gzip_level; @@ -53,7 +52,7 @@ public: static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD); static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD); - Compression(); + Compression() {} }; #endif // COMPRESSION_H diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 73230e3a3c..1af9142317 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -35,14 +35,12 @@ #include "core/variant_parser.h" PackedStringArray ConfigFile::_get_sections() const { - List<String> s; get_sections(&s); PackedStringArray arr; arr.resize(s.size()); int idx = 0; for (const List<String>::Element *E = s.front(); E; E = E->next()) { - arr.set(idx++, E->get()); } @@ -50,14 +48,12 @@ PackedStringArray ConfigFile::_get_sections() const { } PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const { - List<String> s; get_section_keys(p_section, &s); PackedStringArray arr; arr.resize(s.size()); int idx = 0; for (const List<String>::Element *E = s.front(); E; E = E->next()) { - arr.set(idx++, E->get()); } @@ -65,11 +61,11 @@ PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const { } void ConfigFile::set_value(const String &p_section, const String &p_key, const Variant &p_value) { - if (p_value.get_type() == Variant::NIL) { //erase - if (!values.has(p_section)) + if (!values.has(p_section)) { return; // ? + } values[p_section].erase(p_key); if (values[p_section].empty()) { values.erase(p_section); @@ -83,8 +79,8 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V values[p_section][p_key] = p_value; } } -Variant ConfigFile::get_value(const String &p_section, const String &p_key, Variant p_default) const { +Variant ConfigFile::get_value(const String &p_section, const String &p_key, Variant p_default) const { if (!values.has(p_section) || !values[p_section].has(p_key)) { ERR_FAIL_COND_V_MSG(p_default.get_type() == Variant::NIL, Variant(), vformat("Couldn't find the given section \"%s\" and key \"%s\", and no default was given.", p_section, p_key)); @@ -95,24 +91,23 @@ Variant ConfigFile::get_value(const String &p_section, const String &p_key, Vari } bool ConfigFile::has_section(const String &p_section) const { - return values.has(p_section); } -bool ConfigFile::has_section_key(const String &p_section, const String &p_key) const { - if (!values.has(p_section)) +bool ConfigFile::has_section_key(const String &p_section, const String &p_key) const { + if (!values.has(p_section)) { return false; + } return values[p_section].has(p_key); } void ConfigFile::get_sections(List<String> *r_sections) const { - for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::ConstElement E = values.front(); E; E = E.next()) { r_sections->push_back(E.key()); } } -void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const { +void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) const { ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot get keys from nonexistent section \"%s\".", p_section)); for (OrderedHashMap<String, Variant>::ConstElement E = values[p_section].front(); E; E = E.next()) { @@ -121,13 +116,11 @@ void ConfigFile::get_section_keys(const String &p_section, List<String> *r_keys) } void ConfigFile::erase_section(const String &p_section) { - ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot erase nonexistent section \"%s\".", p_section)); values.erase(p_section); } void ConfigFile::erase_section_key(const String &p_section, const String &p_key) { - ERR_FAIL_COND_MSG(!values.has(p_section), vformat("Cannot erase key \"%s\" from nonexistent section \"%s\".", p_key, p_section)); ERR_FAIL_COND_MSG(!values[p_section].has(p_key), vformat("Cannot erase nonexistent key \"%s\" from section \"%s\".", p_key, p_section)); @@ -135,13 +128,13 @@ void ConfigFile::erase_section_key(const String &p_section, const String &p_key) } Error ConfigFile::save(const String &p_path) { - Error err; FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err); if (err) { - if (file) + if (file) { memdelete(file); + } return err; } @@ -149,12 +142,12 @@ Error ConfigFile::save(const String &p_path) { } Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_key) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err); - if (err) + if (err) { return err; + } FileAccessEncrypted *fae = memnew(FileAccessEncrypted); err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_WRITE_AES256); @@ -167,12 +160,12 @@ Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_ } Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err); - if (err) + if (err) { return err; + } FileAccessEncrypted *fae = memnew(FileAccessEncrypted); err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_WRITE_AES256); @@ -186,15 +179,13 @@ Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass } Error ConfigFile::_internal_save(FileAccess *file) { - for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) { - - if (E != values.front()) + if (E != values.front()) { file->store_string("\n"); + } file->store_string("[" + E.key() + "]\n\n"); for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) { - String vstr; VariantWriter::write_to_string(F.get(), vstr); file->store_string(F.key() + "=" + vstr + "\n"); @@ -207,23 +198,23 @@ Error ConfigFile::_internal_save(FileAccess *file) { } Error ConfigFile::load(const String &p_path) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (!f) + if (!f) { return err; + } return _internal_load(p_path, f); } Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_key) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (err) + if (err) { return err; + } FileAccessEncrypted *fae = memnew(FileAccessEncrypted); err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_READ); @@ -236,12 +227,12 @@ Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_ } Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); - if (err) + if (err) { return err; + } FileAccessEncrypted *fae = memnew(FileAccessEncrypted); err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_READ); @@ -255,7 +246,6 @@ Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass } Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) { - VariantParser::StreamFile stream; stream.f = f; @@ -267,14 +257,12 @@ Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) { } Error ConfigFile::parse(const String &p_data) { - VariantParser::StreamString stream; stream.s = p_data; return _parse("<string>", &stream); } Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) { - String assign; Variant value; VariantParser::Tag next_tag; @@ -285,7 +273,6 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) String section; while (true) { - assign = Variant(); next_tag.fields.clear(); next_tag.name = String(); @@ -309,7 +296,6 @@ Error ConfigFile::_parse(const String &p_path, VariantParser::Stream *p_stream) } void ConfigFile::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_value", "section", "key", "value"), &ConfigFile::set_value); ClassDB::bind_method(D_METHOD("get_value", "section", "key", "default"), &ConfigFile::get_value, DEFVAL(Variant())); diff --git a/core/io/config_file.h b/core/io/config_file.h index 39fc2ab412..ae06960f02 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -37,7 +37,6 @@ #include "core/variant_parser.h" class ConfigFile : public Reference { - GDCLASS(ConfigFile, Reference); OrderedHashMap<String, OrderedHashMap<String, Variant>> values; diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp index 5bda06e5b9..e43b1f5385 100644 --- a/core/io/dtls_server.cpp +++ b/core/io/dtls_server.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "dtls_server.h" + #include "core/os/file_access.h" #include "core/project_settings.h" @@ -36,8 +37,10 @@ DTLSServer *(*DTLSServer::_create)() = nullptr; bool DTLSServer::available = false; DTLSServer *DTLSServer::create() { - - return _create(); + if (_create) { + return _create(); + } + return nullptr; } bool DTLSServer::is_available() { @@ -45,10 +48,6 @@ bool DTLSServer::is_available() { } void DTLSServer::_bind_methods() { - ClassDB::bind_method(D_METHOD("setup", "key", "certificate", "chain"), &DTLSServer::setup, DEFVAL(Ref<X509Certificate>())); ClassDB::bind_method(D_METHOD("take_connection", "udp_peer"), &DTLSServer::take_connection); } - -DTLSServer::DTLSServer() { -} diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h index 7b08138f7f..ae1d3bcd98 100644 --- a/core/io/dtls_server.h +++ b/core/io/dtls_server.h @@ -51,7 +51,7 @@ public: virtual void stop() = 0; virtual Ref<PacketPeerDTLS> take_connection(Ref<PacketPeerUDP> p_peer) = 0; - DTLSServer(); + DTLSServer() {} }; #endif // DTLS_SERVER_H diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp index ab0fb3943c..6208f3a4d1 100644 --- a/core/io/file_access_buffered.cpp +++ b/core/io/file_access_buffered.cpp @@ -33,28 +33,23 @@ #include "core/error_macros.h" Error FileAccessBuffered::set_error(Error p_error) const { - return (last_error = p_error); } void FileAccessBuffered::set_cache_size(int p_size) { - cache_size = p_size; } int FileAccessBuffered::get_cache_size() { - return cache_size; } int FileAccessBuffered::cache_data_left() const { - if (file.offset >= file.size) { return 0; } if (cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size()) { - return read_data_block(file.offset, cache_size); } @@ -62,37 +57,30 @@ int FileAccessBuffered::cache_data_left() const { } void FileAccessBuffered::seek(size_t p_position) { - file.offset = p_position; } void FileAccessBuffered::seek_end(int64_t p_position) { - file.offset = file.size + p_position; } size_t FileAccessBuffered::get_position() const { - return file.offset; } size_t FileAccessBuffered::get_len() const { - return file.size; } bool FileAccessBuffered::eof_reached() const { - return file.offset > file.size; } uint8_t FileAccessBuffered::get_8() const { - ERR_FAIL_COND_V_MSG(!file.open, 0, "Can't get data, when file is not opened."); uint8_t byte = 0; if (cache_data_left() >= 1) { - byte = cache.buffer[file.offset - cache.offset]; } @@ -102,15 +90,12 @@ uint8_t FileAccessBuffered::get_8() const { } int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { - ERR_FAIL_COND_V_MSG(!file.open, -1, "Can't get buffer, when file is not opened."); if (p_length > cache_size) { - int total_read = 0; if (!(cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size())) { - int size = (cache.buffer.size() - (file.offset - cache.offset)); size = size - (size % 4); //const uint8_t* read = cache.buffer.ptr(); @@ -134,7 +119,6 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { int to_read = p_length; int total_read = 0; while (to_read > 0) { - int left = cache_data_left(); if (left == 0) { file.offset += to_read; @@ -158,19 +142,9 @@ int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { } bool FileAccessBuffered::is_open() const { - return file.open; } Error FileAccessBuffered::get_error() const { - return last_error; } - -FileAccessBuffered::FileAccessBuffered() { - - cache_size = DEFAULT_CACHE_SIZE; -} - -FileAccessBuffered::~FileAccessBuffered() { -} diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h index a6177c20be..61c0fa7489 100644 --- a/core/io/file_access_buffered.h +++ b/core/io/file_access_buffered.h @@ -36,14 +36,13 @@ #include "core/ustring.h" class FileAccessBuffered : public FileAccess { - public: enum { DEFAULT_CACHE_SIZE = 128 * 1024, }; private: - int cache_size; + int cache_size = DEFAULT_CACHE_SIZE; int cache_data_left() const; mutable Error last_error; @@ -52,7 +51,6 @@ protected: Error set_error(Error p_error) const; mutable struct File { - bool open; int size; int offset; @@ -61,12 +59,11 @@ protected: } file; mutable struct Cache { - Vector<uint8_t> buffer; int offset; } cache; - virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const = 0; + virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = nullptr) const = 0; void set_cache_size(int p_size); int get_cache_size(); @@ -87,8 +84,8 @@ public: virtual Error get_error() const; - FileAccessBuffered(); - virtual ~FileAccessBuffered(); + FileAccessBuffered() {} + virtual ~FileAccessBuffered() {} }; #endif diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h index 6ec77d503b..f22e54e154 100644 --- a/core/io/file_access_buffered_fa.h +++ b/core/io/file_access_buffered_fa.h @@ -35,22 +35,18 @@ template <class T> class FileAccessBufferedFA : public FileAccessBuffered { - T f; int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const { - ERR_FAIL_COND_V_MSG(!f.is_open(), -1, "Can't read data block when file is not opened."); ((T *)&f)->seek(p_offset); if (p_dest) { - f.get_buffer(p_dest, p_size); return p_size; } else { - cache.offset = p_offset; cache.buffer.resize(p_size); @@ -62,43 +58,37 @@ class FileAccessBufferedFA : public FileAccessBuffered { f.get_buffer(cache.buffer.ptrw(), p_size); return p_size; - }; - }; + } + } static FileAccess *create() { - return memnew(FileAccessBufferedFA<T>()); - }; + } protected: virtual void _set_access_type(AccessType p_access) { f._set_access_type(p_access); FileAccessBuffered::_set_access_type(p_access); - }; + } public: void flush() { - f.flush(); - }; + } void store_8(uint8_t p_dest) { - f.store_8(p_dest); - }; + } void store_buffer(const uint8_t *p_src, int p_length) { - f.store_buffer(p_src, p_length); - }; + } bool file_exists(const String &p_name) { - return f.file_exists(p_name); - }; + } Error _open(const String &p_path, int p_mode_flags) { - close(); Error ret = f._open(p_path, p_mode_flags); @@ -116,10 +106,9 @@ public: cache.offset = 0; return set_error(OK); - }; + } void close() { - f.close(); file.offset = 0; @@ -130,16 +119,9 @@ public: cache.buffer.resize(0); cache.offset = 0; set_error(OK); - }; - - /* - static void make_default() { - FileAccess::create_func = FileAccessBufferedFA<T>::create; - }; - */ + } virtual uint64_t _get_modified_time(const String &p_file) { - return f._get_modified_time(p_file); } @@ -151,9 +133,7 @@ public: return f._set_unix_permissions(p_file, p_permissions); } - FileAccessBufferedFA(){ - - }; + FileAccessBufferedFA() {} }; #endif // FILE_ACCESS_BUFFERED_FA_H diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index c76142d22d..7817ccb773 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -33,13 +33,13 @@ #include "core/print_string.h" void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) { - magic = p_magic.ascii().get_data(); - if (magic.length() > 4) + if (magic.length() > 4) { magic = magic.substr(0, 4); - else { - while (magic.length() < 4) + } else { + while (magic.length() < 4) { magic += " "; + } } cmode = p_mode; @@ -59,7 +59,6 @@ void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_ } Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { - f = p_base; cmode = (Compression::Mode)f->get_32(); block_size = f->get_32(); @@ -72,7 +71,6 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { int acc_ofs = f->get_position() + bc * 4; int max_bs = 0; for (int i = 0; i < bc; i++) { - ReadBlock rb; rb.offset = acc_ofs; rb.csize = f->get_32(); @@ -98,11 +96,11 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) { } Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { - ERR_FAIL_COND_V(p_mode_flags == READ_WRITE, ERR_UNAVAILABLE); - if (f) + if (f) { close(); + } Error err; f = FileAccess::open(p_path, p_mode_flags, &err); @@ -114,7 +112,6 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { } if (p_mode_flags & WRITE) { - buffer.clear(); writing = true; write_pos = 0; @@ -125,7 +122,6 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { //don't store anything else unless it's done saving! } else { - char rmagic[5]; f->get_buffer((uint8_t *)rmagic, 4); rmagic[4] = 0; @@ -138,10 +134,11 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { return OK; } -void FileAccessCompressed::close() { - if (!f) +void FileAccessCompressed::close() { + if (!f) { return; + } if (writing) { //save block table and all compressed blocks @@ -159,7 +156,6 @@ void FileAccessCompressed::close() { Vector<int> block_sizes; for (int i = 0; i < bc; i++) { - int bl = i == (bc - 1) ? write_max % block_size : block_size; uint8_t *bp = &write_ptr[i * block_size]; @@ -172,15 +168,15 @@ void FileAccessCompressed::close() { } f->seek(16); //ok write block sizes - for (int i = 0; i < bc; i++) + for (int i = 0; i < bc; i++) { f->store_32(block_sizes[i]); + } f->seek_end(); f->store_buffer((const uint8_t *)mgc.get_data(), mgc.length()); //magic at the end too buffer.clear(); } else { - comp_buffer.clear(); buffer.clear(); read_blocks.clear(); @@ -191,21 +187,17 @@ void FileAccessCompressed::close() { } bool FileAccessCompressed::is_open() const { - return f != nullptr; } void FileAccessCompressed::seek(size_t p_position) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); if (writing) { - ERR_FAIL_COND(p_position > write_max); write_pos = p_position; } else { - ERR_FAIL_COND(p_position > read_total); if (p_position == read_total) { at_end = true; @@ -214,7 +206,6 @@ void FileAccessCompressed::seek(size_t p_position) { read_eof = false; int block_idx = p_position / block_size; if (block_idx != read_block) { - read_block = block_idx; f->seek(read_blocks[read_block].offset); f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize); @@ -228,32 +219,26 @@ void FileAccessCompressed::seek(size_t p_position) { } void FileAccessCompressed::seek_end(int64_t p_position) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); if (writing) { - seek(write_max + p_position); } else { - seek(read_total + p_position); } } -size_t FileAccessCompressed::get_position() const { +size_t FileAccessCompressed::get_position() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); if (writing) { - return write_pos; } else { - return read_block * block_size + read_pos; } } -size_t FileAccessCompressed::get_len() const { +size_t FileAccessCompressed::get_len() const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); if (writing) { - return write_max; } else { return read_total; @@ -261,7 +246,6 @@ size_t FileAccessCompressed::get_len() const { } bool FileAccessCompressed::eof_reached() const { - ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use."); if (writing) { return false; @@ -271,7 +255,6 @@ bool FileAccessCompressed::eof_reached() const { } uint8_t FileAccessCompressed::get_8() const { - ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode."); @@ -301,8 +284,8 @@ uint8_t FileAccessCompressed::get_8() const { return ret; } -int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const { +int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const { ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use."); ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode."); @@ -312,7 +295,6 @@ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const { } for (int i = 0; i < p_length; i++) { - p_dst[i] = read_ptr[read_pos]; read_pos++; if (read_pos >= read_block_size) { @@ -328,8 +310,9 @@ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const { } else { read_block--; at_end = true; - if (i < p_length - 1) + if (i < p_length - 1) { read_eof = true; + } return i; } } @@ -339,7 +322,6 @@ int FileAccessCompressed::get_buffer(uint8_t *p_dst, int p_length) const { } Error FileAccessCompressed::get_error() const { - return read_eof ? ERR_FILE_EOF : OK; } @@ -351,7 +333,6 @@ void FileAccessCompressed::flush() { } void FileAccessCompressed::store_8(uint8_t p_dest) { - ERR_FAIL_COND_MSG(!f, "File must be opened before use."); ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); @@ -360,25 +341,26 @@ void FileAccessCompressed::store_8(uint8_t p_dest) { } bool FileAccessCompressed::file_exists(const String &p_name) { - FileAccess *fa = FileAccess::open(p_name, FileAccess::READ); - if (!fa) + if (!fa) { return false; + } memdelete(fa); return true; } uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) { - - if (f) + if (f) { return f->get_modified_time(p_file); - else + } else { return 0; + } } uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) { - if (f) + if (f) { return f->_get_unix_permissions(p_file); + } return 0; } @@ -389,27 +371,8 @@ Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t return FAILED; } -FileAccessCompressed::FileAccessCompressed() : - cmode(Compression::MODE_ZSTD), - writing(false), - write_ptr(nullptr), - write_buffer_size(0), - write_max(0), - block_size(0), - read_eof(false), - at_end(false), - read_ptr(nullptr), - read_block(0), - read_block_count(0), - read_block_size(0), - read_pos(0), - read_total(0), - magic("GCMP"), - f(nullptr) { -} - FileAccessCompressed::~FileAccessCompressed() { - - if (f) + if (f) { close(); + } } diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index 0bb311faa8..52284b347e 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -35,16 +35,15 @@ #include "core/os/file_access.h" class FileAccessCompressed : public FileAccess { - - Compression::Mode cmode; - bool writing; - uint32_t write_pos; - uint8_t *write_ptr; - uint32_t write_buffer_size; - uint32_t write_max; - uint32_t block_size; - mutable bool read_eof; - mutable bool at_end; + Compression::Mode cmode = Compression::MODE_ZSTD; + bool writing = false; + uint32_t write_pos = 0; + uint8_t *write_ptr = nullptr; + uint32_t write_buffer_size = 0; + uint32_t write_max = 0; + uint32_t block_size = 0; + mutable bool read_eof = false; + mutable bool at_end = false; struct ReadBlock { int csize; @@ -52,17 +51,17 @@ class FileAccessCompressed : public FileAccess { }; mutable Vector<uint8_t> comp_buffer; - uint8_t *read_ptr; - mutable int read_block; - int read_block_count; - mutable int read_block_size; - mutable int read_pos; + uint8_t *read_ptr = nullptr; + mutable int read_block = 0; + int read_block_count = 0; + mutable int read_block_size = 0; + mutable int read_pos = 0; Vector<ReadBlock> read_blocks; - uint32_t read_total; + uint32_t read_total = 0; - String magic; + String magic = "GCMP"; mutable Vector<uint8_t> buffer; - FileAccess *f; + FileAccess *f = nullptr; public: void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, int p_block_size = 4096); @@ -94,7 +93,7 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file); virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); - FileAccessCompressed(); + FileAccessCompressed() {} virtual ~FileAccessCompressed(); }; diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index a5b3807789..5938914cb0 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -40,7 +40,6 @@ #define COMP_MAGIC 0x43454447 Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode) { - ERR_FAIL_COND_V_MSG(file != nullptr, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open."); ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER); @@ -48,7 +47,6 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8 eofed = false; if (p_mode == MODE_WRITE_AES256) { - data.clear(); writing = true; file = p_base; @@ -56,7 +54,6 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8 key = p_key; } else if (p_mode == MODE_READ) { - writing = false; key = p_key; uint32_t magic = p_base->get_32(); @@ -85,7 +82,6 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8 ctx.set_decode_key(key.ptrw(), 256); for (size_t i = 0; i < ds; i += 16) { - ctx.decrypt_ecb(&data.write[i], &data.write[i]); } @@ -103,13 +99,11 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8 } Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode) { - String cs = p_key.md5_text(); ERR_FAIL_COND_V(cs.length() != 32, ERR_INVALID_PARAMETER); Vector<uint8_t> key; key.resize(32); for (int i = 0; i < 32; i++) { - key.write[i] = cs[i]; } @@ -117,16 +111,15 @@ Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const Str } Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) { - return OK; } -void FileAccessEncrypted::close() { - if (!file) +void FileAccessEncrypted::close() { + if (!file) { return; + } if (writing) { - Vector<uint8_t> compressed; size_t len = data.size(); if (len % 16) { @@ -146,7 +139,6 @@ void FileAccessEncrypted::close() { ctx.set_encode_key(key.ptrw(), 256); for (size_t i = 0; i < len; i += 16) { - ctx.encrypt_ecb(&compressed.write[i], &compressed.write[i]); } @@ -163,7 +155,6 @@ void FileAccessEncrypted::close() { data.clear(); } else { - file->close(); memdelete(file); data.clear(); @@ -172,55 +163,51 @@ void FileAccessEncrypted::close() { } bool FileAccessEncrypted::is_open() const { - return file != nullptr; } String FileAccessEncrypted::get_path() const { - - if (file) + if (file) { return file->get_path(); - else + } else { return ""; + } } String FileAccessEncrypted::get_path_absolute() const { - - if (file) + if (file) { return file->get_path_absolute(); - else + } else { return ""; + } } void FileAccessEncrypted::seek(size_t p_position) { - - if (p_position > (size_t)data.size()) + if (p_position > (size_t)data.size()) { p_position = data.size(); + } pos = p_position; eofed = false; } void FileAccessEncrypted::seek_end(int64_t p_position) { - seek(data.size() + p_position); } -size_t FileAccessEncrypted::get_position() const { +size_t FileAccessEncrypted::get_position() const { return pos; } -size_t FileAccessEncrypted::get_len() const { +size_t FileAccessEncrypted::get_len() const { return data.size(); } bool FileAccessEncrypted::eof_reached() const { - return eofed; } uint8_t FileAccessEncrypted::get_8() const { - ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode."); if (pos >= data.size()) { eofed = true; @@ -231,13 +218,12 @@ uint8_t FileAccessEncrypted::get_8() const { pos++; return b; } -int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const { +int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const { ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode."); int to_copy = MIN(p_length, data.size() - pos); for (int i = 0; i < to_copy; i++) { - p_dst[i] = data[pos++]; } @@ -249,25 +235,19 @@ int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const { } Error FileAccessEncrypted::get_error() const { - return eofed ? ERR_FILE_EOF : OK; } void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) { - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); if (pos < data.size()) { - for (int i = 0; i < p_length; i++) { - store_8(p_src[i]); } } else if (pos == data.size()) { - data.resize(pos + p_length); for (int i = 0; i < p_length; i++) { - data.write[pos + i] = p_src[i]; } pos += p_length; @@ -281,7 +261,6 @@ void FileAccessEncrypted::flush() { } void FileAccessEncrypted::store_8(uint8_t p_dest) { - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); if (pos < data.size()) { @@ -294,21 +273,19 @@ void FileAccessEncrypted::store_8(uint8_t p_dest) { } bool FileAccessEncrypted::file_exists(const String &p_name) { - FileAccess *fa = FileAccess::open(p_name, FileAccess::READ); - if (!fa) + if (!fa) { return false; + } memdelete(fa); return true; } uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) { - return 0; } uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) { - return 0; } @@ -317,17 +294,8 @@ Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t return ERR_UNAVAILABLE; } -FileAccessEncrypted::FileAccessEncrypted() { - - file = nullptr; - pos = 0; - eofed = false; - mode = MODE_MAX; - writing = false; -} - FileAccessEncrypted::~FileAccessEncrypted() { - - if (file) + if (file) { close(); + } } diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index 7a9f4ecdd8..e269c1e30c 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -42,15 +42,15 @@ public: }; private: - Mode mode; + Mode mode = MODE_MAX; Vector<uint8_t> key; - bool writing; - FileAccess *file; + bool writing = false; + FileAccess *file = nullptr; size_t base; size_t length; Vector<uint8_t> data; - mutable int pos; - mutable bool eofed; + mutable int pos = 0; + mutable bool eofed = false; public: Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode); @@ -85,7 +85,7 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file); virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions); - FileAccessEncrypted(); + FileAccessEncrypted() {} ~FileAccessEncrypted(); }; diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index a2379ce88f..a65ff92a89 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -38,36 +38,34 @@ static Map<String, Vector<uint8_t>> *files = nullptr; void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) { - if (!files) { files = memnew((Map<String, Vector<uint8_t>>)); } String name; - if (ProjectSettings::get_singleton()) + if (ProjectSettings::get_singleton()) { name = ProjectSettings::get_singleton()->globalize_path(p_name); - else + } else { name = p_name; + } //name = DirAccess::normalize_path(name); (*files)[name] = p_data; } void FileAccessMemory::cleanup() { - - if (!files) + if (!files) { return; + } memdelete(files); } FileAccess *FileAccessMemory::create() { - return memnew(FileAccessMemory); } bool FileAccessMemory::file_exists(const String &p_name) { - String name = fix_path(p_name); //name = DirAccess::normalize_path(name); @@ -75,7 +73,6 @@ bool FileAccessMemory::file_exists(const String &p_name) { } Error FileAccessMemory::open_custom(const uint8_t *p_data, int p_len) { - data = (uint8_t *)p_data; length = p_len; pos = 0; @@ -83,7 +80,6 @@ Error FileAccessMemory::open_custom(const uint8_t *p_data, int p_len) { } Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) { - ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND); String name = fix_path(p_path); @@ -100,46 +96,38 @@ Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) { } void FileAccessMemory::close() { - data = nullptr; } bool FileAccessMemory::is_open() const { - return data != nullptr; } void FileAccessMemory::seek(size_t p_position) { - ERR_FAIL_COND(!data); pos = p_position; } void FileAccessMemory::seek_end(int64_t p_position) { - ERR_FAIL_COND(!data); pos = length + p_position; } size_t FileAccessMemory::get_position() const { - ERR_FAIL_COND_V(!data, 0); return pos; } size_t FileAccessMemory::get_len() const { - ERR_FAIL_COND_V(!data, 0); return length; } bool FileAccessMemory::eof_reached() const { - return pos > length; } uint8_t FileAccessMemory::get_8() const { - uint8_t ret = 0; if (pos < length) { ret = data[pos]; @@ -150,7 +138,6 @@ uint8_t FileAccessMemory::get_8() const { } int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const { - ERR_FAIL_COND_V(!data, -1); int left = length - pos; @@ -158,7 +145,7 @@ int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const { if (read < p_length) { WARN_PRINT("Reading less data than requested"); - }; + } copymem(p_dst, &data[pos], read); pos += p_length; @@ -167,7 +154,6 @@ int FileAccessMemory::get_buffer(uint8_t *p_dst, int p_length) const { } Error FileAccessMemory::get_error() const { - return pos >= length ? ERR_FILE_EOF : OK; } @@ -176,14 +162,12 @@ void FileAccessMemory::flush() { } void FileAccessMemory::store_8(uint8_t p_byte) { - ERR_FAIL_COND(!data); ERR_FAIL_COND(pos >= length); data[pos++] = p_byte; } void FileAccessMemory::store_buffer(const uint8_t *p_src, int p_length) { - int left = length - pos; int write = MIN(p_length, left); if (write < p_length) { @@ -193,8 +177,3 @@ void FileAccessMemory::store_buffer(const uint8_t *p_src, int p_length) { copymem(&data[pos], p_src, write); pos += p_length; } - -FileAccessMemory::FileAccessMemory() { - - data = nullptr; -} diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 2db14db265..1a9bd3fbbb 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -34,8 +34,7 @@ #include "core/os/file_access.h" class FileAccessMemory : public FileAccess { - - uint8_t *data; + uint8_t *data = nullptr; int length; mutable int pos; @@ -73,7 +72,7 @@ public: virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; } virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; } - FileAccessMemory(); + FileAccessMemory() {} }; #endif // FILE_ACCESS_MEMORY_H diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index a3f307393f..6890740d90 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -41,19 +41,16 @@ #define DEBUG_TIME(m_what) void FileAccessNetworkClient::lock_mutex() { - mutex.lock(); lockcount++; } void FileAccessNetworkClient::unlock_mutex() { - lockcount--; mutex.unlock(); } void FileAccessNetworkClient::put_32(int p_32) { - uint8_t buf[4]; encode_uint32(p_32, buf); client->put_data(buf, 4); @@ -61,7 +58,6 @@ void FileAccessNetworkClient::put_32(int p_32) { } void FileAccessNetworkClient::put_64(int64_t p_64) { - uint8_t buf[8]; encode_uint64(p_64, buf); client->put_data(buf, 8); @@ -69,24 +65,20 @@ void FileAccessNetworkClient::put_64(int64_t p_64) { } int FileAccessNetworkClient::get_32() { - uint8_t buf[4]; client->get_data(buf, 4); return decode_uint32(buf); } int64_t FileAccessNetworkClient::get_64() { - uint8_t buf[8]; client->get_data(buf, 8); return decode_uint64(buf); } void FileAccessNetworkClient::_thread_func() { - client->set_no_delay(true); while (!quit) { - DEBUG_PRINT("SEM WAIT - " + itos(sem->get())); sem.wait(); DEBUG_TIME("sem_unlock"); @@ -123,13 +115,12 @@ void FileAccessNetworkClient::_thread_func() { } } - if (accesses.has(id)) + if (accesses.has(id)) { fa = accesses[id]; + } switch (response) { - case FileAccessNetwork::RESPONSE_OPEN: { - DEBUG_TIME("sem_open"); int status = get_32(); if (status != OK) { @@ -143,7 +134,6 @@ void FileAccessNetworkClient::_thread_func() { } break; case FileAccessNetwork::RESPONSE_DATA: { - int64_t offset = get_64(); uint32_t len = get_32(); @@ -151,19 +141,18 @@ void FileAccessNetworkClient::_thread_func() { block.resize(len); client->get_data(block.ptrw(), len); - if (fa) //may have been queued + if (fa) { //may have been queued fa->_set_block(offset, block); + } } break; case FileAccessNetwork::RESPONSE_FILE_EXISTS: { - int status = get_32(); fa->exists_modtime = status != 0; fa->sem.post(); } break; case FileAccessNetwork::RESPONSE_GET_MODTIME: { - uint64_t status = get_64(); fa->exists_modtime = status; fa->sem.post(); @@ -176,14 +165,12 @@ void FileAccessNetworkClient::_thread_func() { } void FileAccessNetworkClient::_thread_func(void *s) { - FileAccessNetworkClient *self = (FileAccessNetworkClient *)s; self->_thread_func(); } Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const String &p_password) { - IP_Address ip; if (p_host.is_valid_ip_address()) { @@ -222,17 +209,11 @@ Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const S FileAccessNetworkClient *FileAccessNetworkClient::singleton = nullptr; FileAccessNetworkClient::FileAccessNetworkClient() { - - thread = nullptr; - quit = false; singleton = this; - last_id = 0; client.instance(); - lockcount = 0; } FileAccessNetworkClient::~FileAccessNetworkClient() { - if (thread) { quit = true; sem.post(); @@ -242,7 +223,6 @@ FileAccessNetworkClient::~FileAccessNetworkClient() { } 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) { @@ -264,11 +244,11 @@ void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) } void FileAccessNetwork::_respond(size_t p_len, Error p_status) { - DEBUG_PRINT("GOT RESPONSE - len: " + itos(p_len) + " status: " + itos(p_status)); response = p_status; - if (response != OK) + if (response != OK) { return; + } opened = true; total_size = p_len; int pc = ((total_size - 1) / page_size) + 1; @@ -276,10 +256,10 @@ void FileAccessNetwork::_respond(size_t p_len, Error p_status) { } Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) { - ERR_FAIL_COND_V(p_mode_flags != READ, ERR_UNAVAILABLE); - if (opened) + if (opened) { close(); + } FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; DEBUG_PRINT("open: " + p_path); @@ -311,9 +291,9 @@ Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) { } void FileAccessNetwork::close() { - - if (!opened) + if (!opened) { return; + } FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; @@ -325,13 +305,12 @@ void FileAccessNetwork::close() { opened = false; nc->unlock_mutex(); } -bool FileAccessNetwork::is_open() const { +bool FileAccessNetwork::is_open() const { return opened; } void FileAccessNetwork::seek(size_t p_position) { - ERR_FAIL_COND_MSG(!opened, "File must be opened before use."); eof_flag = p_position > total_size; @@ -343,39 +322,35 @@ void FileAccessNetwork::seek(size_t p_position) { } void FileAccessNetwork::seek_end(int64_t p_position) { - seek(total_size + p_position); } -size_t FileAccessNetwork::get_position() const { +size_t FileAccessNetwork::get_position() const { ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use."); return pos; } -size_t FileAccessNetwork::get_len() const { +size_t FileAccessNetwork::get_len() const { ERR_FAIL_COND_V_MSG(!opened, 0, "File must be opened before use."); return total_size; } bool FileAccessNetwork::eof_reached() const { - ERR_FAIL_COND_V_MSG(!opened, false, "File must be opened before use."); return eof_flag; } uint8_t FileAccessNetwork::get_8() const { - uint8_t v; get_buffer(&v, 1); return v; } void FileAccessNetwork::_queue_page(int p_page) const { - - if (p_page >= pages.size()) + if (p_page >= pages.size()) { return; + } if (pages[p_page].buffer.empty() && !pages[p_page].queued) { - FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; { MutexLock lock(nc->blockrequest_mutex); @@ -394,7 +369,6 @@ void FileAccessNetwork::_queue_page(int p_page) const { } int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { - //bool eof=false; if (pos + p_length > total_size) { eof_flag = true; @@ -408,7 +382,6 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { uint8_t *buff = last_page_buff; for (int i = 0; i < p_length; i++) { - int page = pos / page_size; if (page != last_page) { @@ -416,7 +389,6 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { if (pages[page].buffer.empty()) { waiting_on_page = page; for (int j = 0; j < read_ahead; j++) { - _queue_page(page + j); } buffer_mutex.unlock(); @@ -424,9 +396,7 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { page_sem.wait(); DEBUG_PRINT("done"); } else { - for (int j = 0; j < read_ahead; j++) { - _queue_page(page + j); } //queue pages @@ -446,7 +416,6 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { } Error FileAccessNetwork::get_error() const { - return pos == total_size ? ERR_FILE_EOF : OK; } @@ -455,12 +424,10 @@ void FileAccessNetwork::flush() { } void FileAccessNetwork::store_8(uint8_t p_dest) { - ERR_FAIL(); } bool FileAccessNetwork::file_exists(const String &p_path) { - FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; nc->lock_mutex(); nc->put_32(id); @@ -477,7 +444,6 @@ bool FileAccessNetwork::file_exists(const String &p_path) { } uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) { - FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; nc->lock_mutex(); nc->put_32(id); @@ -504,7 +470,6 @@ Error FileAccessNetwork::_set_unix_permissions(const String &p_file, uint32_t p_ } void FileAccessNetwork::configure() { - GLOBAL_DEF("network/remote_fs/page_size", 65536); ProjectSettings::get_singleton()->set_custom_property_info("network/remote_fs/page_size", PropertyInfo(Variant::INT, "network/remote_fs/page_size", PROPERTY_HINT_RANGE, "1,65536,1,or_greater")); //is used as denominator and can't be zero GLOBAL_DEF("network/remote_fs/page_read_ahead", 4); @@ -512,10 +477,6 @@ void FileAccessNetwork::configure() { } FileAccessNetwork::FileAccessNetwork() { - - eof_flag = false; - opened = false; - pos = 0; FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; nc->lock_mutex(); id = nc->last_id++; @@ -523,13 +484,9 @@ FileAccessNetwork::FileAccessNetwork() { nc->unlock_mutex(); page_size = GLOBAL_GET("network/remote_fs/page_size"); read_ahead = GLOBAL_GET("network/remote_fs/page_read_ahead"); - last_activity_val = 0; - waiting_on_page = -1; - last_page = -1; } FileAccessNetwork::~FileAccessNetwork() { - close(); FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index 7f664b46f7..dc5ce1e883 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -39,9 +39,7 @@ class FileAccessNetwork; class FileAccessNetworkClient { - struct BlockRequest { - int id; uint64_t offset; int size; @@ -50,13 +48,14 @@ class FileAccessNetworkClient { List<BlockRequest> block_requests; Semaphore sem; - Thread *thread; - bool quit; + Thread *thread = nullptr; + bool quit = false; Mutex mutex; Mutex blockrequest_mutex; Map<int, FileAccessNetwork *> accesses; Ref<StreamPeerTCP> client; - int last_id; + int last_id = 0; + int lockcount = 0; Vector<uint8_t> block; @@ -67,7 +66,6 @@ class FileAccessNetworkClient { void put_64(int64_t p_64); int get_32(); int64_t get_64(); - int lockcount; void lock_mutex(); void unlock_mutex(); @@ -84,31 +82,26 @@ public: }; class FileAccessNetwork : public FileAccess { - Semaphore sem; Semaphore page_sem; Mutex buffer_mutex; - bool opened; + bool opened = false; size_t total_size; - mutable size_t pos; + mutable size_t pos = 0; int id; - mutable bool eof_flag; - mutable int last_page; - mutable uint8_t *last_page_buff; + mutable bool eof_flag = false; + mutable int last_page = -1; + mutable uint8_t *last_page_buff = nullptr; int page_size; int read_ahead; - mutable int waiting_on_page; - mutable int last_activity_val; + mutable int waiting_on_page = -1; + struct Page { - int activity; - bool queued; + int activity = 0; + bool queued = false; Vector<uint8_t> buffer; - Page() { - activity = 0; - queued = false; - } }; mutable Vector<Page> pages; diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 0a7dee9444..37240f234a 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -35,20 +35,16 @@ #include <stdio.h> Error PackedData::add_pack(const String &p_path, bool p_replace_files) { - for (int i = 0; i < sources.size(); i++) { - if (sources[i]->try_open_pack(p_path, p_replace_files)) { - return OK; - }; - }; + } + } return ERR_FILE_UNRECOGNIZED; -}; +} void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) { - PathMD5 pmd5(path.md5_buffer()); //printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b); @@ -58,12 +54,14 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o pf.pack = pkg_path; pf.offset = ofs; pf.size = size; - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) { pf.md5[i] = p_md5[i]; + } pf.src = p_src; - if (!exists || p_replace_files) + if (!exists || p_replace_files) { files[pmd5] = pf; + } if (!exists) { //search for dir @@ -75,9 +73,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o Vector<String> ds = p.get_base_dir().split("/"); for (int j = 0; j < ds.size(); j++) { - if (!cd->subdirs.has(ds[j])) { - PackedDir *pd = memnew(PackedDir); pd->name = ds[j]; pd->parent = cd; @@ -97,33 +93,28 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o } void PackedData::add_pack_source(PackSource *p_source) { - if (p_source != nullptr) { sources.push_back(p_source); } -}; +} PackedData *PackedData::singleton = nullptr; PackedData::PackedData() { - singleton = this; root = memnew(PackedDir); - root->parent = nullptr; - disabled = false; add_pack_source(memnew(PackedSourcePCK)); } void PackedData::_free_packed_dirs(PackedDir *p_dir) { - - for (Map<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next()) + for (Map<String, PackedDir *>::Element *E = p_dir->subdirs.front(); E; E = E->next()) { _free_packed_dirs(E->get()); + } memdelete(p_dir); } PackedData::~PackedData() { - for (int i = 0; i < sources.size(); i++) { memdelete(sources[i]); } @@ -133,10 +124,10 @@ PackedData::~PackedData() { ////////////////////////////////////////////////////////////////// bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) { - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - if (!f) + if (!f) { return false; + } uint32_t magic = f->get_32(); @@ -146,7 +137,6 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) f->seek(f->get_position() - 4); magic = f->get_32(); if (magic != PACK_HEADER_MAGIC) { - f->close(); memdelete(f); return false; @@ -158,7 +148,6 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) magic = f->get_32(); if (magic != PACK_HEADER_MAGIC) { - f->close(); memdelete(f); return false; @@ -189,7 +178,6 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) int file_count = f->get_32(); for (int i = 0; i < file_count; i++) { - uint32_t sl = f->get_32(); CharString cs; cs.resize(sl + 1); @@ -204,38 +192,33 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files) uint8_t md5[16]; f->get_buffer(md5, 16); PackedData::get_singleton()->add_path(p_path, path, ofs, size, md5, this, p_replace_files); - }; + } f->close(); memdelete(f); return true; -}; +} FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) { - return memnew(FileAccessPack(p_path, *p_file)); -}; +} ////////////////////////////////////////////////////////////////// Error FileAccessPack::_open(const String &p_path, int p_mode_flags) { - ERR_FAIL_V(ERR_UNAVAILABLE); return ERR_UNAVAILABLE; } void FileAccessPack::close() { - f->close(); } bool FileAccessPack::is_open() const { - return f->is_open(); } void FileAccessPack::seek(size_t p_position) { - if (p_position > pf.size) { eof = true; } else { @@ -245,26 +228,24 @@ void FileAccessPack::seek(size_t p_position) { f->seek(pf.offset + p_position); pos = p_position; } -void FileAccessPack::seek_end(int64_t p_position) { +void FileAccessPack::seek_end(int64_t p_position) { seek(pf.size + p_position); } -size_t FileAccessPack::get_position() const { +size_t FileAccessPack::get_position() const { return pos; } -size_t FileAccessPack::get_len() const { +size_t FileAccessPack::get_len() const { return pf.size; } bool FileAccessPack::eof_reached() const { - return eof; } uint8_t FileAccessPack::get_8() const { - if (pos >= pf.size) { eof = true; return 0; @@ -275,9 +256,9 @@ uint8_t FileAccessPack::get_8() const { } int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const { - - if (eof) + if (eof) { return 0; + } uint64_t to_read = p_length; if (to_read + pos > pf.size) { @@ -287,8 +268,9 @@ int FileAccessPack::get_buffer(uint8_t *p_dst, int p_length) const { pos += p_length; - if (to_read <= 0) + if (to_read <= 0) { return 0; + } f->get_buffer(p_dst, to_read); return to_read; @@ -300,36 +282,31 @@ void FileAccessPack::set_endian_swap(bool p_swap) { } Error FileAccessPack::get_error() const { - - if (eof) + if (eof) { return ERR_FILE_EOF; + } return OK; } void FileAccessPack::flush() { - ERR_FAIL(); } void FileAccessPack::store_8(uint8_t p_dest) { - ERR_FAIL(); } void FileAccessPack::store_buffer(const uint8_t *p_src, int p_length) { - ERR_FAIL(); } bool FileAccessPack::file_exists(const String &p_name) { - return false; } FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) : pf(p_file), f(FileAccess::open(pf.pack, FileAccess::READ)) { - ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'."); f->seek(pf.offset); @@ -338,8 +315,9 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil } FileAccessPack::~FileAccessPack() { - if (f) + if (f) { memdelete(f); + } } ////////////////////////////////////////////////////////////////////////////////// @@ -347,17 +325,14 @@ FileAccessPack::~FileAccessPack() { ////////////////////////////////////////////////////////////////////////////////// Error DirAccessPack::list_dir_begin() { - list_dirs.clear(); list_files.clear(); for (Map<String, PackedData::PackedDir *>::Element *E = current->subdirs.front(); E; E = E->next()) { - list_dirs.push_back(E->key()); } for (Set<String>::Element *E = current->files.front(); E; E = E->next()) { - list_files.push_back(E->get()); } @@ -365,7 +340,6 @@ Error DirAccessPack::list_dir_begin() { } String DirAccessPack::get_next() { - if (list_dirs.size()) { cdir = true; String d = list_dirs.front()->get(); @@ -380,31 +354,29 @@ String DirAccessPack::get_next() { return String(); } } -bool DirAccessPack::current_is_dir() const { +bool DirAccessPack::current_is_dir() const { return cdir; } -bool DirAccessPack::current_is_hidden() const { +bool DirAccessPack::current_is_hidden() const { return false; } -void DirAccessPack::list_dir_end() { +void DirAccessPack::list_dir_end() { list_dirs.clear(); list_files.clear(); } int DirAccessPack::get_drive_count() { - return 0; } -String DirAccessPack::get_drive(int p_drive) { +String DirAccessPack::get_drive(int p_drive) { return ""; } Error DirAccessPack::change_dir(String p_dir) { - String nd = p_dir.replace("\\", "/"); bool absolute = false; if (nd.begins_with("res://")) { @@ -414,7 +386,9 @@ Error DirAccessPack::change_dir(String p_dir) { nd = nd.simplify_path(); - if (nd == "") nd = "."; + if (nd == "") { + nd = "."; + } if (nd.begins_with("/")) { nd = nd.replace_first("/", ""); @@ -425,13 +399,13 @@ Error DirAccessPack::change_dir(String p_dir) { PackedData::PackedDir *pd; - if (absolute) + if (absolute) { pd = PackedData::get_singleton()->root; - else + } else { pd = current; + } for (int i = 0; i < paths.size(); i++) { - String p = paths[i]; if (p == ".") { continue; @@ -440,11 +414,9 @@ Error DirAccessPack::change_dir(String p_dir) { pd = pd->parent; } } else if (pd->subdirs.has(p)) { - pd = pd->subdirs[p]; } else { - return ERR_INVALID_PARAMETER; } } @@ -455,7 +427,6 @@ Error DirAccessPack::change_dir(String p_dir) { } String DirAccessPack::get_current_dir(bool p_include_drive) { - PackedData::PackedDir *pd = current; String p = current->name; @@ -468,35 +439,30 @@ String DirAccessPack::get_current_dir(bool p_include_drive) { } bool DirAccessPack::file_exists(String p_file) { - p_file = fix_path(p_file); return current->files.has(p_file); } bool DirAccessPack::dir_exists(String p_dir) { - p_dir = fix_path(p_dir); return current->subdirs.has(p_dir); } Error DirAccessPack::make_dir(String p_dir) { - return ERR_UNAVAILABLE; } Error DirAccessPack::rename(String p_from, String p_to) { - return ERR_UNAVAILABLE; } -Error DirAccessPack::remove(String p_name) { +Error DirAccessPack::remove(String p_name) { return ERR_UNAVAILABLE; } size_t DirAccessPack::get_space_left() { - return 0; } @@ -505,10 +471,5 @@ String DirAccessPack::get_filesystem_type() const { } DirAccessPack::DirAccessPack() { - current = PackedData::get_singleton()->root; - cdir = false; -} - -DirAccessPack::~DirAccessPack() { } diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 8df6826ac9..348bc0c450 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -51,7 +51,6 @@ class PackedData { public: struct PackedFile { - String pack; uint64_t offset; //if offset is ZERO, the file was ERASED uint64_t size; @@ -61,17 +60,16 @@ public: private: struct PackedDir { - PackedDir *parent; + PackedDir *parent = nullptr; String name; Map<String, PackedDir *> subdirs; Set<String> files; }; struct PathMD5 { - uint64_t a; - uint64_t b; + uint64_t a = 0; + uint64_t b = 0; bool operator<(const PathMD5 &p_md5) const { - if (p_md5.a == a) { return b < p_md5.b; } else { @@ -81,16 +79,14 @@ private: bool operator==(const PathMD5 &p_md5) const { return a == p_md5.a && b == p_md5.b; - }; + } - PathMD5() { - a = b = 0; - }; + PathMD5() {} PathMD5(const Vector<uint8_t> p_buf) { a = *((uint64_t *)&p_buf[0]); b = *((uint64_t *)&p_buf[8]); - }; + } }; Map<PathMD5, PackedFile> files; @@ -98,10 +94,9 @@ private: Vector<PackSource *> sources; PackedDir *root; - //Map<String,PackedDir*> dirs; static PackedData *singleton; - bool disabled; + bool disabled = false; void _free_packed_dirs(PackedDir *p_dir); @@ -123,7 +118,6 @@ public: }; class PackSource { - public: virtual bool try_open_pack(const String &p_path, bool p_replace_files) = 0; virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0; @@ -131,14 +125,12 @@ public: }; class PackedSourcePCK : public PackSource { - public: virtual bool try_open_pack(const String &p_path, bool p_replace_files); virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file); }; class FileAccessPack : public FileAccess { - PackedData::PackedFile pf; mutable size_t pos; @@ -181,29 +173,28 @@ public: }; FileAccess *PackedData::try_open_path(const String &p_path) { - PathMD5 pmd5(p_path.md5_buffer()); Map<PathMD5, PackedFile>::Element *E = files.find(pmd5); - if (!E) + if (!E) { return nullptr; //not found - if (E->get().offset == 0) + } + if (E->get().offset == 0) { return nullptr; //was erased + } return E->get().src->get_file(p_path, &E->get()); } bool PackedData::has_path(const String &p_path) { - return files.has(PathMD5(p_path.md5_buffer())); } class DirAccessPack : public DirAccess { - PackedData::PackedDir *current; List<String> list_dirs; List<String> list_files; - bool cdir; + bool cdir = false; public: virtual Error list_dir_begin(); @@ -231,7 +222,7 @@ public: virtual String get_filesystem_type() const; DirAccessPack(); - ~DirAccessPack(); + ~DirAccessPack() {} }; #endif // FILE_ACCESS_PACK_H diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 57de66afaf..c3a62706c7 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -40,7 +40,6 @@ ZipArchive *ZipArchive::instance = nullptr; extern "C" { static void *godot_open(void *data, const char *p_fname, int mode) { - if (mode & ZLIB_FILEFUNC_MODE_WRITE) { return nullptr; } @@ -52,30 +51,25 @@ static void *godot_open(void *data, const char *p_fname, int mode) { } static uLong godot_read(void *data, void *fdata, void *buf, uLong size) { - FileAccess *f = (FileAccess *)data; f->get_buffer((uint8_t *)buf, size); return size; } static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong size) { - return 0; } static long godot_tell(voidpf opaque, voidpf stream) { - FileAccess *f = (FileAccess *)opaque; return f->get_position(); } static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { - FileAccess *f = (FileAccess *)opaque; int pos = offset; switch (origin) { - case ZLIB_FILEFUNC_SEEK_CUR: pos = f->get_position() + offset; break; @@ -91,32 +85,27 @@ static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { } static int godot_close(voidpf opaque, voidpf stream) { - FileAccess *f = (FileAccess *)opaque; f->close(); return 0; } static int godot_testerror(voidpf opaque, voidpf stream) { - FileAccess *f = (FileAccess *)opaque; return f->get_error() != OK ? 1 : 0; } static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) { - return memalloc(items * size); } static void godot_free(voidpf opaque, voidpf address) { - memfree(address); } } // extern "C" void ZipArchive::close_handle(unzFile p_file) const { - ERR_FAIL_COND_MSG(!p_file, "Cannot close a file if none is open."); FileAccess *f = (FileAccess *)unzGetOpaque(p_file); unzCloseCurrentFile(p_file); @@ -125,7 +114,6 @@ void ZipArchive::close_handle(unzFile p_file) const { } unzFile ZipArchive::get_file_handle(String p_file) const { - ERR_FAIL_COND_V_MSG(!file_exists(p_file), nullptr, "File '" + p_file + " doesn't exist."); File file = files[p_file]; @@ -152,7 +140,6 @@ unzFile ZipArchive::get_file_handle(String p_file) const { ERR_FAIL_COND_V(!pkg, nullptr); int unz_err = unzGoToFilePos(pkg, &file.file_pos); if (unz_err != UNZ_OK || unzOpenCurrentFile(pkg) != UNZ_OK) { - unzClose(pkg); ERR_FAIL_V(nullptr); } @@ -161,16 +148,17 @@ unzFile ZipArchive::get_file_handle(String p_file) const { } bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files) { - //printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); - if (p_path.get_extension().nocasecmp_to("zip") != 0 && p_path.get_extension().nocasecmp_to("pcz") != 0) + if (p_path.get_extension().nocasecmp_to("zip") != 0 && p_path.get_extension().nocasecmp_to("pcz") != 0) { return false; + } zlib_filefunc_def io; FileAccess *fa = FileAccess::open(p_path, FileAccess::READ); - if (!fa) + if (!fa) { return false; + } io.opaque = fa; io.zopen_file = godot_open; io.zread_file = godot_read; @@ -195,7 +183,6 @@ bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files) { int pkg_num = packages.size() - 1; for (uint64_t i = 0; i < gi.number_entry; i++) { - char filename_inzip[256]; unz_file_info64 file_info; @@ -222,17 +209,14 @@ bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files) { } bool ZipArchive::file_exists(String p_name) const { - return files.has(p_name); } FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) { - return memnew(FileAccessZip(p_path, *p_file)); } ZipArchive *ZipArchive::get_singleton() { - if (instance == nullptr) { instance = memnew(ZipArchive); } @@ -241,15 +225,11 @@ ZipArchive *ZipArchive::get_singleton() { } ZipArchive::ZipArchive() { - instance = this; - //fa_create_func = FileAccess::get_create_func(); } ZipArchive::~ZipArchive() { - for (int i = 0; i < packages.size(); i++) { - FileAccess *f = (FileAccess *)unzGetOpaque(packages[i].zfile); unzClose(packages[i].zfile); memdelete(f); @@ -259,7 +239,6 @@ ZipArchive::~ZipArchive() { } Error FileAccessZip::_open(const String &p_path, int p_mode_flags) { - close(); ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED); @@ -275,9 +254,9 @@ Error FileAccessZip::_open(const String &p_path, int p_mode_flags) { } void FileAccessZip::close() { - - if (!zfile) + if (!zfile) { return; + } ZipArchive *arch = ZipArchive::get_singleton(); ERR_FAIL_COND(!arch); @@ -286,65 +265,57 @@ void FileAccessZip::close() { } bool FileAccessZip::is_open() const { - return zfile != nullptr; } void FileAccessZip::seek(size_t p_position) { - ERR_FAIL_COND(!zfile); unzSeekCurrentFile(zfile, p_position); } void FileAccessZip::seek_end(int64_t p_position) { - ERR_FAIL_COND(!zfile); unzSeekCurrentFile(zfile, get_len() + p_position); } size_t FileAccessZip::get_position() const { - ERR_FAIL_COND_V(!zfile, 0); return unztell(zfile); } size_t FileAccessZip::get_len() const { - ERR_FAIL_COND_V(!zfile, 0); return file_info.uncompressed_size; } bool FileAccessZip::eof_reached() const { - ERR_FAIL_COND_V(!zfile, true); return at_eof; } uint8_t FileAccessZip::get_8() const { - uint8_t ret = 0; get_buffer(&ret, 1); return ret; } int FileAccessZip::get_buffer(uint8_t *p_dst, int p_length) const { - ERR_FAIL_COND_V(!zfile, -1); at_eof = unzeof(zfile); - if (at_eof) + if (at_eof) { return 0; + } int read = unzReadCurrentFile(zfile, p_dst, p_length); ERR_FAIL_COND_V(read < 0, read); - if (read < p_length) + if (read < p_length) { at_eof = true; + } return read; } Error FileAccessZip::get_error() const { - if (!zfile) { - return ERR_UNCONFIGURED; } if (eof_reached()) { @@ -355,28 +326,23 @@ Error FileAccessZip::get_error() const { } void FileAccessZip::flush() { - ERR_FAIL(); } void FileAccessZip::store_8(uint8_t p_dest) { - ERR_FAIL(); } bool FileAccessZip::file_exists(const String &p_name) { - return false; } -FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) : - zfile(nullptr) { +FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file) { _open(p_path, FileAccess::READ); } FileAccessZip::~FileAccessZip() { - close(); } -#endif +#endif // MINIZIP_ENABLED diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index d5ce7d7a8d..776e830f36 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -41,22 +41,17 @@ #include <stdlib.h> class ZipArchive : public PackSource { - public: struct File { - - int package; + int package = -1; unz_file_pos file_pos; - File() { - - package = -1; - }; + File() {} }; private: struct Package { String filename; - unzFile zfile; + unzFile zfile = nullptr; }; Vector<Package> packages; @@ -84,7 +79,6 @@ public: }; class FileAccessZip : public FileAccess { - unzFile zfile; unz_file_info64 file_info; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 56f8f1ff91..40debae9e5 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -47,7 +47,6 @@ const char *HTTPClient::_methods[METHOD_MAX] = { #ifndef JAVASCRIPT_ENABLED Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, bool p_verify_host) { - close(); conn_port = p_port; @@ -58,10 +57,8 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, String host_lower = conn_host.to_lower(); if (host_lower.begins_with("http://")) { - conn_host = conn_host.substr(7, conn_host.length() - 7); } else if (host_lower.begins_with("https://")) { - ssl = true; conn_host = conn_host.substr(8, conn_host.length() - 8); } @@ -97,7 +94,6 @@ Error HTTPClient::connect_to_host(const String &p_host, int p_port, bool p_ssl, } void HTTPClient::set_connection(const Ref<StreamPeer> &p_connection) { - ERR_FAIL_COND_MSG(p_connection.is_null(), "Connection is not a reference to a valid StreamPeer object."); close(); @@ -106,12 +102,10 @@ void HTTPClient::set_connection(const Ref<StreamPeer> &p_connection) { } Ref<StreamPeer> HTTPClient::get_connection() const { - return connection; } Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body) { - ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); @@ -179,7 +173,6 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector } Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) { - ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); @@ -235,27 +228,23 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str } bool HTTPClient::has_response() const { - return response_headers.size() != 0; } bool HTTPClient::is_response_chunked() const { - return chunked; } int HTTPClient::get_response_code() const { - return response_num; } Error HTTPClient::get_response_headers(List<String> *r_response) { - - if (!response_headers.size()) + if (!response_headers.size()) { return ERR_INVALID_PARAMETER; + } for (int i = 0; i < response_headers.size(); i++) { - r_response->push_back(response_headers[i]); } @@ -265,15 +254,14 @@ Error HTTPClient::get_response_headers(List<String> *r_response) { } void HTTPClient::close() { - - if (tcp_connection->get_status() != StreamPeerTCP::STATUS_NONE) + if (tcp_connection->get_status() != StreamPeerTCP::STATUS_NONE) { tcp_connection->disconnect_from_host(); + } connection.unref(); status = STATUS_DISCONNECTED; head_request = false; if (resolving != IP::RESOLVER_INVALID_ID) { - IP::get_singleton()->erase_resolve_item(resolving); resolving = IP::RESOLVER_INVALID_ID; } @@ -283,16 +271,14 @@ void HTTPClient::close() { body_size = -1; body_left = 0; chunk_left = 0; - chunk_trailer_part = 0; + chunk_trailer_part = false; read_until_eof = false; response_num = 0; handshaking = false; } Error HTTPClient::poll() { - switch (status) { - case STATUS_RESOLVING: { ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG); @@ -302,7 +288,6 @@ Error HTTPClient::poll() { return OK; // Still resolving case IP::RESOLVER_STATUS_DONE: { - IP_Address host = IP::get_singleton()->get_resolve_item_address(resolving); Error err = tcp_connection->connect_to_host(host, conn_port); IP::get_singleton()->erase_resolve_item(resolving); @@ -316,7 +301,6 @@ Error HTTPClient::poll() { } break; case IP::RESOLVER_STATUS_NONE: case IP::RESOLVER_STATUS_ERROR: { - IP::get_singleton()->erase_resolve_item(resolving); resolving = IP::RESOLVER_INVALID_ID; close(); @@ -326,10 +310,8 @@ Error HTTPClient::poll() { } } break; case STATUS_CONNECTING: { - StreamPeerTCP::Status s = tcp_connection->get_status(); switch (s) { - case StreamPeerTCP::STATUS_CONNECTING: { return OK; } break; @@ -379,7 +361,6 @@ Error HTTPClient::poll() { } break; case StreamPeerTCP::STATUS_ERROR: case StreamPeerTCP::STATUS_NONE: { - close(); status = STATUS_CANT_CONNECT; return ERR_CANT_CONNECT; @@ -404,7 +385,6 @@ Error HTTPClient::poll() { return OK; } break; case STATUS_REQUESTING: { - while (true) { uint8_t byte; int rec = 0; @@ -415,15 +395,15 @@ Error HTTPClient::poll() { return ERR_CONNECTION_ERROR; } - if (rec == 0) + if (rec == 0) { return OK; // Still requesting, keep trying! + } response_str.push_back(byte); int rs = response_str.size(); if ( (rs >= 2 && response_str[rs - 2] == '\n' && response_str[rs - 1] == '\n') || (rs >= 4 && response_str[rs - 4] == '\r' && response_str[rs - 3] == '\n' && response_str[rs - 2] == '\r' && response_str[rs - 1] == '\n')) { - // End of response, parse. response_str.push_back(0); String response; @@ -445,11 +425,11 @@ Error HTTPClient::poll() { bool keep_alive = true; for (int i = 0; i < responses.size(); i++) { - String header = responses[i].strip_edges(); String s = header.to_lower(); - if (s.length() == 0) + if (s.length() == 0) { continue; + } if (s.begins_with("content-length:")) { body_size = s.substr(s.find(":") + 1, s.length()).strip_edges().to_int(); body_left = body_size; @@ -464,11 +444,9 @@ Error HTTPClient::poll() { } if (i == 0 && responses[i].begins_with("HTTP")) { - String num = responses[i].get_slicec(' ', 1); response_num = num.to_int(); } else { - response_headers.push_back(header); } } @@ -480,14 +458,11 @@ Error HTTPClient::poll() { } if (body_size != -1 || chunked) { - status = STATUS_BODY; } else if (!keep_alive) { - read_until_eof = true; status = STATUS_BODY; } else { - status = STATUS_CONNECTED; } return OK; @@ -513,29 +488,26 @@ Error HTTPClient::poll() { } int HTTPClient::get_response_body_length() const { - return body_size; } PackedByteArray HTTPClient::read_response_body_chunk() { - ERR_FAIL_COND_V(status != STATUS_BODY, PackedByteArray()); PackedByteArray ret; Error err = OK; if (chunked) { - while (true) { - if (chunk_trailer_part) { // We need to consume the trailer part too or keep-alive will break uint8_t b; int rec = 0; err = _get_http_data(&b, 1, rec); - if (rec == 0) + if (rec == 0) { break; + } chunk.push_back(b); int cs = chunk.size(); @@ -557,8 +529,9 @@ PackedByteArray HTTPClient::read_response_body_chunk() { int rec = 0; err = _get_http_data(&b, 1, rec); - if (rec == 0) + if (rec == 0) { break; + } chunk.push_back(b); @@ -569,18 +542,17 @@ PackedByteArray HTTPClient::read_response_body_chunk() { } if (chunk.size() > 2 && chunk[chunk.size() - 2] == '\r' && chunk[chunk.size() - 1] == '\n') { - int len = 0; for (int i = 0; i < chunk.size() - 2; i++) { char c = chunk[i]; int v = 0; - if (c >= '0' && c <= '9') + if (c >= '0' && c <= '9') { v = c - '0'; - else if (c >= 'a' && c <= 'f') + } else if (c >= 'a' && c <= 'f') { v = c - 'a' + 10; - else if (c >= 'A' && c <= 'F') + } else if (c >= 'A' && c <= 'F') { v = c - 'A' + 10; - else { + } else { ERR_PRINT("HTTP Chunk len not in hex!!"); status = STATUS_CONNECTION_ERROR; break; @@ -605,7 +577,6 @@ PackedByteArray HTTPClient::read_response_body_chunk() { chunk.resize(chunk_left); } } else { - int rec = 0; err = _get_http_data(&chunk.write[chunk.size() - chunk_left], chunk_left, rec); if (rec == 0) { @@ -614,7 +585,6 @@ PackedByteArray HTTPClient::read_response_body_chunk() { chunk_left -= rec; if (chunk_left == 0) { - if (chunk[chunk.size() - 2] != '\r' || chunk[chunk.size() - 1] != '\n') { ERR_PRINT("HTTP Invalid chunk terminator (not \\r\\n)"); status = STATUS_CONNECTION_ERROR; @@ -632,7 +602,6 @@ PackedByteArray HTTPClient::read_response_body_chunk() { } } else { - int to_read = !read_until_eof ? MIN(body_left, read_chunk_size) : read_chunk_size; ret.resize(to_read); int _offset = 0; @@ -652,24 +621,21 @@ PackedByteArray HTTPClient::read_response_body_chunk() { body_left -= rec; } } - if (err != OK) + if (err != OK) { break; + } } } if (err != OK) { - close(); if (err == ERR_FILE_EOF) { - status = STATUS_DISCONNECTED; // Server disconnected } else { - status = STATUS_CONNECTION_ERROR; } } else if (body_left == 0 && !chunked && !read_until_eof) { - status = STATUS_CONNECTED; } @@ -677,24 +643,19 @@ PackedByteArray HTTPClient::read_response_body_chunk() { } HTTPClient::Status HTTPClient::get_status() const { - return status; } void HTTPClient::set_blocking_mode(bool p_enable) { - blocking = p_enable; } bool HTTPClient::is_blocking_mode_enabled() const { - return blocking; } Error HTTPClient::_get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - if (blocking) { - // We can't use StreamPeer.get_data, since when reaching EOF we will get an // error without knowing how many bytes we received. Error err = ERR_FILE_EOF; @@ -729,27 +690,10 @@ int HTTPClient::get_read_chunk_size() const { } HTTPClient::HTTPClient() { - tcp_connection.instance(); - resolving = IP::RESOLVER_INVALID_ID; - status = STATUS_DISCONNECTED; - head_request = false; - conn_port = -1; - body_size = -1; - chunked = false; - body_left = 0; - read_until_eof = false; - chunk_left = 0; - chunk_trailer_part = false; - response_num = 0; - ssl = false; - blocking = false; - handshaking = false; - read_chunk_size = 4096; } -HTTPClient::~HTTPClient() { -} +HTTPClient::~HTTPClient() {} #endif // #ifndef JAVASCRIPT_ENABLED @@ -784,15 +728,15 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) { } Dictionary HTTPClient::_get_response_headers_as_dictionary() { - List<String> rh; get_response_headers(&rh); Dictionary ret; for (const List<String>::Element *E = rh.front(); E; E = E->next()) { const String &s = E->get(); int sp = s.find(":"); - if (sp == -1) + if (sp == -1) { continue; + } String key = s.substr(0, sp).strip_edges(); String value = s.substr(sp + 1, s.length()).strip_edges(); ret[key] = value; @@ -802,7 +746,6 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() { } PackedStringArray HTTPClient::_get_response_headers() { - List<String> rh; get_response_headers(&rh); PackedStringArray ret; @@ -816,7 +759,6 @@ PackedStringArray HTTPClient::_get_response_headers() { } void HTTPClient::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port", "use_ssl", "verify_host"), &HTTPClient::connect_to_host, DEFVAL(-1), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("set_connection", "connection"), &HTTPClient::set_connection); ClassDB::bind_method(D_METHOD("get_connection"), &HTTPClient::get_connection); diff --git a/core/io/http_client.h b/core/io/http_client.h index 03ba20f8dd..1dc1f3d76a 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -37,7 +37,6 @@ #include "core/reference.h" class HTTPClient : public Reference { - GDCLASS(HTTPClient, Reference); public: @@ -158,32 +157,32 @@ private: }; #ifndef JAVASCRIPT_ENABLED - Status status; - IP::ResolverID resolving; - int conn_port; + Status status = STATUS_DISCONNECTED; + IP::ResolverID resolving = IP::RESOLVER_INVALID_ID; + int conn_port = -1; String conn_host; - bool ssl; - bool ssl_verify_host; - bool blocking; - bool handshaking; - bool head_request; + bool ssl = false; + bool ssl_verify_host = false; + bool blocking = false; + bool handshaking = false; + bool head_request = false; Vector<uint8_t> response_str; - bool chunked; + bool chunked = false; Vector<uint8_t> chunk; - int chunk_left; - bool chunk_trailer_part; - int body_size; - int body_left; - bool read_until_eof; + int chunk_left = 0; + bool chunk_trailer_part = false; + int body_size = -1; + int body_left = 0; + bool read_until_eof = false; Ref<StreamPeerTCP> tcp_connection; Ref<StreamPeer> connection; - int response_num; + int response_num = 0; Vector<String> response_headers; - int read_chunk_size; + int read_chunk_size = 4096; Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received); diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index 2770adbd36..b1e92eb87f 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -33,13 +33,12 @@ #include "core/print_string.h" bool ImageFormatLoader::recognize(const String &p_extension) const { - List<String> extensions; get_recognized_extensions(&extensions); for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - - if (E->get().nocasecmp_to(p_extension) == 0) + if (E->get().nocasecmp_to(p_extension) == 0) { return true; + } } return false; @@ -61,43 +60,41 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c String extension = p_file.get_extension(); for (int i = 0; i < loader.size(); i++) { - - if (!loader[i]->recognize(extension)) + if (!loader[i]->recognize(extension)) { continue; + } Error err = loader[i]->load_image(p_image, f, p_force_linear, p_scale); if (err != OK) { ERR_PRINT("Error loading image: " + p_file); } if (err != ERR_FILE_UNRECOGNIZED) { - - if (!p_custom) + if (!p_custom) { memdelete(f); + } return err; } } - if (!p_custom) + if (!p_custom) { memdelete(f); + } return ERR_FILE_UNRECOGNIZED; } void ImageLoader::get_recognized_extensions(List<String> *p_extensions) { - for (int i = 0; i < loader.size(); i++) { - loader[i]->get_recognized_extensions(p_extensions); } } ImageFormatLoader *ImageLoader::recognize(const String &p_extension) { - for (int i = 0; i < loader.size(); i++) { - - if (loader[i]->recognize(p_extension)) + if (loader[i]->recognize(p_extension)) { return loader[i]; + } } return nullptr; @@ -106,22 +103,18 @@ ImageFormatLoader *ImageLoader::recognize(const String &p_extension) { Vector<ImageFormatLoader *> ImageLoader::loader; void ImageLoader::add_image_format_loader(ImageFormatLoader *p_loader) { - loader.push_back(p_loader); } void ImageLoader::remove_image_format_loader(ImageFormatLoader *p_loader) { - loader.erase(p_loader); } const Vector<ImageFormatLoader *> &ImageLoader::get_image_format_loaders() { - return loader; } void ImageLoader::cleanup() { - while (loader.size()) { remove_image_format_loader(loader[0]); } @@ -129,8 +122,7 @@ void ImageLoader::cleanup() { ///////////////// -RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { if (r_error) { @@ -192,16 +184,13 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin } void ResourceFormatLoaderImage::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("image"); } bool ResourceFormatLoaderImage::handles_type(const String &p_type) const { - return p_type == "Image"; } String ResourceFormatLoaderImage::get_resource_type(const String &p_path) const { - return p_path.get_extension().to_lower() == "image" ? "Image" : String(); } diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 18b4df98f7..9682f144c7 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -53,7 +53,6 @@ public: }; class ImageLoader { - static Vector<ImageFormatLoader *> loader; friend class ResourceFormatLoaderImage; @@ -73,7 +72,7 @@ public: class ResourceFormatLoaderImage : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 5de7fb7186..24b8ec7cc1 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -39,9 +39,7 @@ VARIANT_ENUM_CAST(IP::ResolverStatus); /************* RESOLVER ******************/ struct _IP_ResolverPrivate { - struct QueueItem { - volatile IP::ResolverStatus status; IP_Address response; String hostname; @@ -56,16 +54,16 @@ struct _IP_ResolverPrivate { QueueItem() { clear(); - }; + } }; QueueItem queue[IP::RESOLVER_MAX_QUERIES]; IP::ResolverID find_empty_id() const { - for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) { - if (queue[i].status == IP::RESOLVER_STATUS_NONE) + if (queue[i].status == IP::RESOLVER_STATUS_NONE) { return i; + } } return IP::RESOLVER_INVALID_ID; } @@ -78,26 +76,24 @@ struct _IP_ResolverPrivate { bool thread_abort; void resolve_queues() { - for (int i = 0; i < IP::RESOLVER_MAX_QUERIES; i++) { - - if (queue[i].status != IP::RESOLVER_STATUS_WAITING) + if (queue[i].status != IP::RESOLVER_STATUS_WAITING) { continue; + } queue[i].response = IP::get_singleton()->resolve_hostname(queue[i].hostname, queue[i].type); - if (!queue[i].response.is_valid()) + if (!queue[i].response.is_valid()) { queue[i].status = IP::RESOLVER_STATUS_ERROR; - else + } else { queue[i].status = IP::RESOLVER_STATUS_DONE; + } } } static void _thread_function(void *self) { - _IP_ResolverPrivate *ipr = (_IP_ResolverPrivate *)self; while (!ipr->thread_abort) { - ipr->sem.wait(); MutexLock lock(ipr->mutex); @@ -113,7 +109,6 @@ struct _IP_ResolverPrivate { }; IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) { - MutexLock lock(resolver->mutex); String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type); @@ -128,7 +123,6 @@ IP_Address IP::resolve_hostname(const String &p_hostname, IP::Type p_type) { } IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Type p_type) { - MutexLock lock(resolver->mutex); ResolverID id = resolver->find_empty_id(); @@ -147,17 +141,17 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ } else { resolver->queue[id].response = IP_Address(); resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING; - if (resolver->thread) + if (resolver->thread) { resolver->sem.post(); - else + } else { resolver->resolve_queues(); + } } return id; } IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const { - ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP::RESOLVER_STATUS_NONE); MutexLock lock(resolver->mutex); @@ -171,7 +165,6 @@ IP::ResolverStatus IP::get_resolve_item_status(ResolverID p_id) const { } IP_Address IP::get_resolve_item_address(ResolverID p_id) const { - ERR_FAIL_INDEX_V(p_id, IP::RESOLVER_MAX_QUERIES, IP_Address()); MutexLock lock(resolver->mutex); @@ -186,7 +179,6 @@ IP_Address IP::get_resolve_item_address(ResolverID p_id) const { } void IP::erase_resolve_item(ResolverID p_id) { - ERR_FAIL_INDEX(p_id, IP::RESOLVER_MAX_QUERIES); MutexLock lock(resolver->mutex); @@ -195,7 +187,6 @@ void IP::erase_resolve_item(ResolverID p_id) { } void IP::clear_cache(const String &p_hostname) { - MutexLock lock(resolver->mutex); if (p_hostname.empty()) { @@ -209,7 +200,6 @@ void IP::clear_cache(const String &p_hostname) { } Array IP::_get_local_addresses() const { - Array addresses; List<IP_Address> ip_addresses; get_local_addresses(&ip_addresses); @@ -221,7 +211,6 @@ Array IP::_get_local_addresses() const { } Array IP::_get_local_interfaces() const { - Array results; Map<String, Interface_Info> interfaces; get_local_interfaces(&interfaces); @@ -245,7 +234,6 @@ Array IP::_get_local_interfaces() const { } void IP::get_local_addresses(List<IP_Address> *r_addresses) const { - Map<String, Interface_Info> interfaces; get_local_interfaces(&interfaces); for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) { @@ -256,7 +244,6 @@ void IP::get_local_addresses(List<IP_Address> *r_addresses) const { } void IP::_bind_methods() { - ClassDB::bind_method(D_METHOD("resolve_hostname", "host", "ip_type"), &IP::resolve_hostname, DEFVAL(IP::TYPE_ANY)); ClassDB::bind_method(D_METHOD("resolve_hostname_queue_item", "host", "ip_type"), &IP::resolve_hostname_queue_item, DEFVAL(IP::TYPE_ANY)); ClassDB::bind_method(D_METHOD("get_resolve_item_status", "id"), &IP::get_resolve_item_status); @@ -283,21 +270,18 @@ void IP::_bind_methods() { IP *IP::singleton = nullptr; IP *IP::get_singleton() { - return singleton; } IP *(*IP::_create)() = nullptr; IP *IP::create() { - ERR_FAIL_COND_V_MSG(singleton, nullptr, "IP singleton already exist."); ERR_FAIL_COND_V(!_create, nullptr); return _create(); } IP::IP() { - singleton = this; resolver = memnew(_IP_ResolverPrivate); @@ -312,7 +296,6 @@ IP::IP() { } IP::~IP() { - #ifndef NO_THREADS if (resolver->thread) { resolver->thread_abort = true; diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index f5fd8ae205..c7a0ae5605 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -39,40 +39,40 @@ IP_Address::operator Variant() const { #include <string.h> IP_Address::operator String() const { - - if (wildcard) + if (wildcard) { return "*"; + } - if (!valid) + if (!valid) { return ""; + } - if (is_ipv4()) + if (is_ipv4()) { // IPv4 address mapped to IPv6 return itos(field8[12]) + "." + itos(field8[13]) + "." + itos(field8[14]) + "." + itos(field8[15]); + } String ret; for (int i = 0; i < 8; i++) { - if (i > 0) + if (i > 0) { ret = ret + ":"; + } uint16_t num = (field8[i * 2] << 8) + field8[i * 2 + 1]; ret = ret + String::num_int64(num, 16); - }; + } return ret; } static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) { - uint16_t ret = 0; for (int i = p_start; i < p_start + 4; i++) { - if (i >= p_string.length()) { break; - }; + } int n = 0; CharType c = p_string[i]; if (c >= '0' && c <= '9') { - n = c - '0'; } else if (c >= 'a' && c <= 'f') { n = 10 + (c - 'a'); @@ -82,17 +82,16 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) { break; } else { ERR_FAIL_MSG("Invalid character in IPv6 address: " + p_string + "."); - }; + } ret = ret << 4; ret += n; - }; + } p_dst[0] = ret >> 8; p_dst[1] = ret & 0xff; -}; +} void IP_Address::_parse_ipv6(const String &p_string) { - static const int parts_total = 8; int parts[parts_total] = { 0 }; int parts_count = 0; @@ -102,20 +101,17 @@ void IP_Address::_parse_ipv6(const String &p_string) { int parts_idx = 0; for (int i = 0; i < p_string.length(); i++) { - CharType c = p_string[i]; if (c == ':') { - if (i == 0) { continue; // next must be a ":" - }; + } if (!part_found) { part_skip = true; parts[parts_idx++] = -1; - }; + } part_found = false; } else if (c == '.') { - part_ipv4 = true; } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { @@ -123,58 +119,54 @@ void IP_Address::_parse_ipv6(const String &p_string) { parts[parts_idx++] = i; part_found = true; ++parts_count; - }; + } } else { ERR_FAIL_MSG("Invalid character in IPv6 address: " + p_string + "."); - }; - }; + } + } int parts_extra = 0; if (part_skip) { parts_extra = parts_total - parts_count; - }; + } int idx = 0; for (int i = 0; i < parts_idx; i++) { - if (parts[i] == -1) { - for (int j = 0; j < parts_extra; j++) { field16[idx++] = 0; - }; + } continue; - }; + } if (part_ipv4 && i == parts_idx - 1) { _parse_ipv4(p_string, parts[i], (uint8_t *)&field16[idx]); // should be the last one } else { _parse_hex(p_string, parts[i], (uint8_t *)&(field16[idx++])); - }; - }; -}; + } + } +} void IP_Address::_parse_ipv4(const String &p_string, int p_start, uint8_t *p_ret) { - String ip; if (p_start != 0) { ip = p_string.substr(p_start, p_string.length() - p_start); } else { ip = p_string; - }; + } int slices = ip.get_slice_count("."); ERR_FAIL_COND_MSG(slices != 4, "Invalid IP address string: " + ip + "."); for (int i = 0; i < 4; i++) { p_ret[i] = ip.get_slicec('.', i).to_int(); } -}; +} void IP_Address::clear() { - memset(&field8[0], 0, sizeof(field8)); valid = false; wildcard = false; -}; +} bool IP_Address::is_ipv4() const { return (field32[0] == 0 && field32[1] == 0 && field16[4] == 0 && field16[5] == 0xffff); @@ -199,12 +191,12 @@ const uint8_t *IP_Address::get_ipv6() const { void IP_Address::set_ipv6(const uint8_t *p_buf) { clear(); valid = true; - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) { field8[i] = p_buf[i]; + } } IP_Address::IP_Address(const String &p_string) { - clear(); if (p_string == "*") { @@ -228,15 +220,13 @@ IP_Address::IP_Address(const String &p_string) { } _FORCE_INLINE_ static void _32_to_buf(uint8_t *p_dst, uint32_t p_n) { - p_dst[0] = (p_n >> 24) & 0xff; p_dst[1] = (p_n >> 16) & 0xff; p_dst[2] = (p_n >> 8) & 0xff; p_dst[3] = (p_n >> 0) & 0xff; -}; +} IP_Address::IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, bool is_v6) { - clear(); valid = true; if (!is_v6) { @@ -247,7 +237,6 @@ IP_Address::IP_Address(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d, b field8[14] = p_c; field8[15] = p_d; } else { - _32_to_buf(&field8[0], p_a); _32_to_buf(&field8[4], p_b); _32_to_buf(&field8[8], p_c); diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 89cf37ff8f..2f8f83503e 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -34,7 +34,6 @@ #include "core/ustring.h" struct IP_Address { - private: union { uint8_t field8[16]; @@ -52,19 +51,32 @@ protected: public: //operator Variant() const; bool operator==(const IP_Address &p_ip) const { - if (p_ip.valid != valid) return false; - if (!valid) return false; - for (int i = 0; i < 4; i++) - if (field32[i] != p_ip.field32[i]) + if (p_ip.valid != valid) { + return false; + } + if (!valid) { + return false; + } + for (int i = 0; i < 4; i++) { + if (field32[i] != p_ip.field32[i]) { return false; + } + } return true; } + bool operator!=(const IP_Address &p_ip) const { - if (p_ip.valid != valid) return true; - if (!valid) return true; - for (int i = 0; i < 4; i++) - if (field32[i] != p_ip.field32[i]) + if (p_ip.valid != valid) { + return true; + } + if (!valid) { + return true; + } + for (int i = 0; i < 4; i++) { + if (field32[i] != p_ip.field32[i]) { return true; + } + } return false; } diff --git a/core/io/json.cpp b/core/io/json.cpp index 3a0edceb81..1c603865ad 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -46,17 +46,16 @@ const char *JSON::tk_name[TK_MAX] = { }; static String _make_indent(const String &p_indent, int p_size) { - String indent_text = ""; if (!p_indent.empty()) { - for (int i = 0; i < p_size; i++) + for (int i = 0; i < p_size; i++) { indent_text += p_indent; + } } return indent_text; } String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys) { - String colon = ":"; String end_statement = ""; @@ -66,18 +65,20 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ } switch (p_var.get_type()) { - - case Variant::NIL: return "null"; - case Variant::BOOL: return p_var.operator bool() ? "true" : "false"; - case Variant::INT: return itos(p_var); - case Variant::FLOAT: return rtos(p_var); + case Variant::NIL: + return "null"; + case Variant::BOOL: + return p_var.operator bool() ? "true" : "false"; + case Variant::INT: + return itos(p_var); + case Variant::FLOAT: + return rtos(p_var); case Variant::PACKED_INT32_ARRAY: case Variant::PACKED_INT64_ARRAY: case Variant::PACKED_FLOAT32_ARRAY: case Variant::PACKED_FLOAT64_ARRAY: case Variant::PACKED_STRING_ARRAY: case Variant::ARRAY: { - String s = "["; s += end_statement; Array a = p_var; @@ -90,20 +91,19 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ } s += end_statement + _make_indent(p_indent, p_cur_indent) + "]"; return s; - }; + } case Variant::DICTIONARY: { - String s = "{"; s += end_statement; Dictionary d = p_var; List<Variant> keys; d.get_key_list(&keys); - if (p_sort_keys) + if (p_sort_keys) { keys.sort(); + } for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - if (E != keys.front()) { s += ","; s += end_statement; @@ -115,69 +115,59 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ s += end_statement + _make_indent(p_indent, p_cur_indent) + "}"; return s; - }; - default: return "\"" + String(p_var).json_escape() + "\""; + } + default: + return "\"" + String(p_var).json_escape() + "\""; } } String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys) { - return _print_var(p_var, p_indent, 0, p_sort_keys); } Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) { - while (p_len > 0) { switch (p_str[index]) { - case '\n': { - line++; index++; break; - }; + } case 0: { r_token.type = TK_EOF; return OK; } break; case '{': { - r_token.type = TK_CURLY_BRACKET_OPEN; index++; return OK; - }; + } case '}': { - r_token.type = TK_CURLY_BRACKET_CLOSE; index++; return OK; - }; + } case '[': { - r_token.type = TK_BRACKET_OPEN; index++; return OK; - }; + } case ']': { - r_token.type = TK_BRACKET_CLOSE; index++; return OK; - }; + } case ':': { - r_token.type = TK_COLON; index++; return OK; - }; + } case ',': { - r_token.type = TK_COMMA; index++; return OK; - }; + } case '"': { - index++; String str; while (true) { @@ -198,12 +188,21 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to CharType res = 0; switch (next) { - - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { // hex number for (int j = 0; j < 4; j++) { @@ -213,7 +212,6 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to return ERR_PARSE_ERROR; } if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { - r_err_str = "Malformed hex constant in string"; return ERR_PARSE_ERROR; } @@ -245,8 +243,9 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to str += res; } else { - if (p_str[index] == '\n') + if (p_str[index] == '\n') { line++; + } str += p_str[index]; } index++; @@ -258,7 +257,6 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to } break; default: { - if (p_str[index] <= 32) { index++; break; @@ -274,11 +272,9 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to return OK; } else if ((p_str[index] >= 'A' && p_str[index] <= 'Z') || (p_str[index] >= 'a' && p_str[index] <= 'z')) { - String id; while ((p_str[index] >= 'A' && p_str[index] <= 'Z') || (p_str[index] >= 'a' && p_str[index] <= 'z')) { - id += p_str[index]; index++; } @@ -298,45 +294,41 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to } Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { - if (token.type == TK_CURLY_BRACKET_OPEN) { - Dictionary d; Error err = _parse_object(d, p_str, index, p_len, line, r_err_str); - if (err) + if (err) { return err; + } value = d; return OK; } else if (token.type == TK_BRACKET_OPEN) { - Array a; Error err = _parse_array(a, p_str, index, p_len, line, r_err_str); - if (err) + if (err) { return err; + } value = a; return OK; } else if (token.type == TK_IDENTIFIER) { - String id = token.value; - if (id == "true") + if (id == "true") { value = true; - else if (id == "false") + } else if (id == "false") { value = false; - else if (id == "null") + } else if (id == "null") { value = Variant(); - else { + } else { r_err_str = "Expected 'true','false' or 'null', got '" + id + "'."; return ERR_PARSE_ERROR; } return OK; } else if (token.type == TK_NUMBER) { - value = token.value; return OK; } else if (token.type == TK_STRING) { - value = token.value; return OK; } else { @@ -346,25 +338,21 @@ Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, in } Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { - Token token; bool need_comma = false; while (index < p_len) { - Error err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token.type == TK_BRACKET_CLOSE) { - return OK; } if (need_comma) { - if (token.type != TK_COMMA) { - r_err_str = "Expected ','"; return ERR_PARSE_ERROR; } else { @@ -375,8 +363,9 @@ Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_ Variant v; err = _parse_value(v, token, p_str, index, p_len, line, r_err_str); - if (err) + if (err) { return err; + } array.push_back(v); need_comma = true; @@ -386,29 +375,24 @@ Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_ } Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { - bool at_key = true; String key; Token token; bool need_comma = false; while (index < p_len) { - if (at_key) { - Error err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token.type == TK_CURLY_BRACKET_CLOSE) { - return OK; } if (need_comma) { - if (token.type != TK_COMMA) { - r_err_str = "Expected '}' or ','"; return ERR_PARSE_ERROR; } else { @@ -418,31 +402,31 @@ Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, } if (token.type != TK_STRING) { - r_err_str = "Expected key"; return ERR_PARSE_ERROR; } key = token.value; err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token.type != TK_COLON) { - r_err_str = "Expected ':'"; return ERR_PARSE_ERROR; } at_key = false; } else { - Error err = _get_token(p_str, index, p_len, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } Variant v; err = _parse_value(v, token, p_str, index, p_len, line, r_err_str); - if (err) + if (err) { return err; + } object[key] = v; need_comma = true; at_key = true; @@ -453,7 +437,6 @@ Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, } Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) { - const CharType *str = p_json.ptr(); int idx = 0; int len = p_json.length(); @@ -462,8 +445,9 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int & String aux_key; Error err = _get_token(str, idx, len, token, r_err_line, r_err_str); - if (err) + if (err) { return err; + } err = _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str); diff --git a/core/io/json.h b/core/io/json.h index 2e851afcf4..4fc5630a93 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -34,7 +34,6 @@ #include "core/variant.h" class JSON { - enum TokenType { TK_CURLY_BRACKET_OPEN, TK_CURLY_BRACKET_CLOSE, @@ -58,7 +57,6 @@ class JSON { }; struct Token { - TokenType type; Variant value; }; diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 48aebeda3d..ef78b1194e 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -34,17 +34,6 @@ #include "core/os/os.h" #include "core/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 - #if defined(MINGW_ENABLED) || defined(_MSC_VER) #define sprintf sprintf_s #endif @@ -60,18 +49,29 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c 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; + 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) + if (p_rationale && *p_rationale) { err_details = p_rationale; - else + } else { err_details = p_code; + } logf_error("%s: %s\n", err_type, err_details); logf_error(" at: %s (%s:%i) - %s\n", p_function, p_file, p_line, p_code); @@ -103,8 +103,6 @@ void Logger::logf_error(const char *p_format, ...) { va_end(argp); } -Logger::~Logger() {} - void RotatedFileLogger::close_file() { if (file) { memdelete(file); @@ -181,8 +179,7 @@ void RotatedFileLogger::rotate_file() { RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) : base_path(p_base_path.simplify_path()), - max_files(p_max_files > 0 ? p_max_files : 1), - file(nullptr) { + max_files(p_max_files > 0 ? p_max_files : 1) { rotate_file(); } @@ -237,8 +234,6 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) { } } -StdLogger::~StdLogger() {} - CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) : loggers(p_loggers) { } diff --git a/core/io/logger.h b/core/io/logger.h index 7028551185..277be9ed35 100644 --- a/core/io/logger.h +++ b/core/io/logger.h @@ -55,17 +55,16 @@ public: void logf(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; void logf_error(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; - virtual ~Logger(); + 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) _PRINTF_FORMAT_ATTRIBUTE_2_0; - virtual ~StdLogger(); + virtual ~StdLogger() {} }; /** @@ -78,7 +77,7 @@ class RotatedFileLogger : public Logger { String base_path; int max_files; - FileAccess *file; + FileAccess *file = nullptr; void rotate_file_without_closing(); void close_file(); diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 81bc45b2f7..eb39b1433f 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -49,13 +49,9 @@ void EncodedObjectAsID::set_object_id(ObjectID p_id) { } ObjectID EncodedObjectAsID::get_object_id() const { - return id; } -EncodedObjectAsID::EncodedObjectAsID() { -} - #define _S(a) ((int32_t)a) #define ERR_FAIL_ADD_OF(a, b, err) ERR_FAIL_COND_V(_S(b) < 0 || _S(a) < 0 || _S(a) > INT_MAX - _S(b), err) #define ERR_FAIL_MUL_OF(a, b, err) ERR_FAIL_COND_V(_S(a) < 0 || _S(b) <= 0 || _S(a) > INT_MAX / _S(b), err) @@ -100,7 +96,6 @@ static Error _decode_string(const uint8_t *&buf, int &len, int *r_len, String &r } Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len, bool p_allow_objects) { - const uint8_t *buf = p_buffer; int len = p_len; @@ -112,95 +107,95 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int buf += 4; len -= 4; - if (r_len) + if (r_len) { *r_len = 4; + } switch (type & ENCODE_MASK) { - case Variant::NIL: { - r_variant = Variant(); } break; case Variant::BOOL: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); bool val = decode_uint32(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4; + } } break; case Variant::INT: { - if (type & ENCODE_FLAG_64) { ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); int64_t val = decode_uint64(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 8; + } } else { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t val = decode_uint32(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4; + } } } break; case Variant::FLOAT: { - if (type & ENCODE_FLAG_64) { ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); double val = decode_double(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 8; + } } else { ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); float val = decode_float(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4; + } } } break; case Variant::STRING: { - String str; Error err = _decode_string(buf, len, r_len, str); - if (err) + if (err) { return err; + } r_variant = str; } break; // math types case Variant::VECTOR2: { - ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA); Vector2 val; val.x = decode_float(&buf[0]); val.y = decode_float(&buf[4]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 2; + } } break; case Variant::VECTOR2I: { - ERR_FAIL_COND_V(len < 4 * 2, ERR_INVALID_DATA); Vector2i val; val.x = decode_uint32(&buf[0]); val.y = decode_uint32(&buf[4]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 2; + } } break; case Variant::RECT2: { - ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); Rect2 val; val.position.x = decode_float(&buf[0]); @@ -209,12 +204,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.size.y = decode_float(&buf[12]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 4; + } } break; case Variant::RECT2I: { - ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); Rect2i val; val.position.x = decode_uint32(&buf[0]); @@ -223,12 +218,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.size.y = decode_uint32(&buf[12]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 4; + } } break; case Variant::VECTOR3: { - ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA); Vector3 val; val.x = decode_float(&buf[0]); @@ -236,12 +231,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.z = decode_float(&buf[8]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 3; + } } break; case Variant::VECTOR3I: { - ERR_FAIL_COND_V(len < 4 * 3, ERR_INVALID_DATA); Vector3i val; val.x = decode_uint32(&buf[0]); @@ -249,29 +244,28 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.z = decode_uint32(&buf[8]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 3; + } } break; case Variant::TRANSFORM2D: { - ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA); Transform2D val; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { - val.elements[i][j] = decode_float(&buf[(i * 2 + j) * 4]); } } r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 6; + } } break; case Variant::PLANE: { - ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); Plane val; val.normal.x = decode_float(&buf[0]); @@ -280,12 +274,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.d = decode_float(&buf[12]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 4; + } } break; case Variant::QUAT: { - ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); Quat val; val.x = decode_float(&buf[0]); @@ -294,12 +288,12 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.w = decode_float(&buf[12]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 4; + } } break; case Variant::AABB: { - ERR_FAIL_COND_V(len < 4 * 6, ERR_INVALID_DATA); AABB val; val.position.x = decode_float(&buf[0]); @@ -310,34 +304,32 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.size.z = decode_float(&buf[20]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 6; + } } break; case Variant::BASIS: { - ERR_FAIL_COND_V(len < 4 * 9, ERR_INVALID_DATA); Basis val; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - val.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]); } } r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 9; + } } break; case Variant::TRANSFORM: { - ERR_FAIL_COND_V(len < 4 * 12, ERR_INVALID_DATA); Transform val; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - val.basis.elements[i][j] = decode_float(&buf[(i * 3 + j) * 4]); } } @@ -347,14 +339,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 12; + } } break; // misc types case Variant::COLOR: { - ERR_FAIL_COND_V(len < 4 * 4, ERR_INVALID_DATA); Color val; val.r = decode_float(&buf[0]); @@ -363,22 +355,22 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int val.a = decode_float(&buf[12]); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4 * 4; + } } break; case Variant::STRING_NAME: { - String str; Error err = _decode_string(buf, len, r_len, str); - if (err) + if (err) { return err; + } r_variant = StringName(str); } break; case Variant::NODE_PATH: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t strlen = decode_uint32(buf); @@ -395,25 +387,28 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int len -= 12; buf += 12; - if (flags & 2) // Obsolete format with property separate from subpath + if (flags & 2) { // Obsolete format with property separate from subpath subnamecount++; + } uint32_t total = namecount + subnamecount; - if (r_len) + if (r_len) { (*r_len) += 12; + } for (uint32_t i = 0; i < total; i++) { - String str; Error err = _decode_string(buf, len, r_len, str); - if (err) + if (err) { return err; + } - if (i < namecount) + if (i < namecount) { names.push_back(str); - else + } else { subnames.push_back(str); + } } r_variant = NodePath(names, subnames, flags & 1); @@ -426,17 +421,16 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::_RID: { - r_variant = RID(); } break; case Variant::OBJECT: { - if (type & ENCODE_FLAG_OBJECT_AS_ID) { //this _is_ allowed ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); ObjectID val = ObjectID(decode_uint64(buf)); - if (r_len) + if (r_len) { (*r_len) += 8; + } if (val.is_null()) { r_variant = (Object *)nullptr; @@ -453,13 +447,13 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int String str; Error err = _decode_string(buf, len, r_len, str); - if (err) + if (err) { return err; + } if (str == String()) { r_variant = (Object *)nullptr; } else { - Object *obj = ClassDB::instance(str); ERR_FAIL_COND_V(!obj, ERR_UNAVAILABLE); @@ -473,17 +467,18 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } for (int i = 0; i < count; i++) { - str = String(); err = _decode_string(buf, len, r_len, str); - if (err) + if (err) { return err; + } Variant value; int used; err = decode_variant(value, buf, len, &used, p_allow_objects); - if (err) + if (err) { return err; + } buf += used; len -= used; @@ -505,16 +500,13 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::CALLABLE: { - r_variant = Callable(); } break; case Variant::SIGNAL: { - r_variant = Signal(); } break; case Variant::DICTIONARY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); // bool shared = count&0x80000000; @@ -530,7 +522,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Dictionary d; for (int i = 0; i < count; i++) { - Variant key, value; int used; @@ -559,7 +550,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); // bool shared = count&0x80000000; @@ -575,7 +565,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Array varr; for (int i = 0; i < count; i++) { - int used = 0; Variant v; Error err = decode_variant(v, buf, len, &used, p_allow_objects); @@ -594,7 +583,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int // arrays case Variant::PACKED_BYTE_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); buf += 4; @@ -607,7 +595,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int data.resize(count); uint8_t *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { - w[i] = buf[i]; } } @@ -615,14 +602,14 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int r_variant = data; if (r_len) { - if (count % 4) + if (count % 4) { (*r_len) += 4 - count % 4; + } (*r_len) += 4 + count; } } break; case Variant::PACKED_INT32_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); buf += 4; @@ -637,7 +624,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int data.resize(count); int32_t *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { - w[i] = decode_uint32(&buf[i * 4]); } } @@ -648,7 +634,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::PACKED_INT64_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int64_t count = decode_uint64(buf); buf += 4; @@ -663,7 +648,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int data.resize(count); int64_t *w = data.ptrw(); for (int64_t i = 0; i < count; i++) { - w[i] = decode_uint64(&buf[i * 8]); } } @@ -674,7 +658,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::PACKED_FLOAT32_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); buf += 4; @@ -689,7 +672,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int data.resize(count); float *w = data.ptrw(); for (int32_t i = 0; i < count; i++) { - w[i] = decode_float(&buf[i * 4]); } } @@ -701,7 +683,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::PACKED_FLOAT64_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int64_t count = decode_uint64(buf); buf += 4; @@ -716,7 +697,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int data.resize(count); double *w = data.ptrw(); for (int64_t i = 0; i < count; i++) { - w[i] = decode_double(&buf[i * 8]); } } @@ -728,7 +708,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::PACKED_STRING_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); @@ -736,16 +715,17 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int buf += 4; len -= 4; - if (r_len) + if (r_len) { (*r_len) += 4; + } //printf("string count: %i\n",count); for (int32_t i = 0; i < count; i++) { - String str; Error err = _decode_string(buf, len, r_len, str); - if (err) + if (err) { return err; + } strings.push_back(str); } @@ -754,7 +734,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } break; case Variant::PACKED_VECTOR2_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); buf += 4; @@ -773,22 +752,21 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Vector2 *w = varray.ptrw(); for (int32_t i = 0; i < count; i++) { - w[i].x = decode_float(buf + i * 4 * 2 + 4 * 0); w[i].y = decode_float(buf + i * 4 * 2 + 4 * 1); } int adv = 4 * 2 * count; - if (r_len) + if (r_len) { (*r_len) += adv; + } } r_variant = varray; } break; case Variant::PACKED_VECTOR3_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); buf += 4; @@ -808,7 +786,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Vector3 *w = varray.ptrw(); for (int32_t i = 0; i < count; i++) { - w[i].x = decode_float(buf + i * 4 * 3 + 4 * 0); w[i].y = decode_float(buf + i * 4 * 3 + 4 * 1); w[i].z = decode_float(buf + i * 4 * 3 + 4 * 2); @@ -816,15 +793,15 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int int adv = 4 * 3 * count; - if (r_len) + if (r_len) { (*r_len) += adv; + } } r_variant = varray; } break; case Variant::PACKED_COLOR_ARRAY: { - ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t count = decode_uint32(buf); buf += 4; @@ -844,7 +821,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int Color *w = carray.ptrw(); for (int32_t i = 0; i < count; i++) { - w[i].r = decode_float(buf + i * 4 * 4 + 4 * 0); w[i].g = decode_float(buf + i * 4 * 4 + 4 * 1); w[i].b = decode_float(buf + i * 4 * 4 + 4 * 2); @@ -853,8 +829,9 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int int adv = 4 * 4 * count; - if (r_len) + if (r_len) { (*r_len) += adv; + } } r_variant = carray; @@ -869,7 +846,6 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) { - CharString utf8 = p_string.utf8(); if (buf) { @@ -889,7 +865,6 @@ static void _encode_string(const String &p_string, uint8_t *&buf, int &r_len) { } Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects) { - uint8_t *buf = r_buffer; r_len = 0; @@ -897,7 +872,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo uint32_t flags = 0; switch (p_variant.get_type()) { - case Variant::INT: { int64_t val = p_variant; if (val > (int64_t)INT_MAX || val < (int64_t)INT_MIN) { @@ -905,7 +879,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; case Variant::FLOAT: { - double d = p_variant; float f = d; if (double(f) != d) { @@ -913,7 +886,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; case Variant::OBJECT: { - // Test for potential wrong values sent by the debugger when it breaks. Object *obj = p_variant.get_validated_object(); if (!obj) { @@ -940,13 +912,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; switch (p_variant.get_type()) { - case Variant::NIL: { - //nothing to do } break; case Variant::BOOL: { - if (buf) { encode_uint32(p_variant.operator bool(), buf); } @@ -955,7 +924,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::INT: { - if (flags & ENCODE_FLAG_64) { //64 bits if (buf) { @@ -972,7 +940,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; case Variant::FLOAT: { - if (flags & ENCODE_FLAG_64) { if (buf) { encode_double(p_variant.operator double(), buf); @@ -981,7 +948,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 8; } else { - if (buf) { encode_float(p_variant.operator float(), buf); } @@ -991,14 +957,14 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::NODE_PATH: { - NodePath np = p_variant; if (buf) { encode_uint32(uint32_t(np.get_name_count()) | 0x80000000, buf); //for compatibility with the old format encode_uint32(np.get_subname_count(), buf + 4); uint32_t np_flags = 0; - if (np.is_absolute()) + if (np.is_absolute()) { np_flags |= 1; + } encode_uint32(np_flags, buf + 8); @@ -1010,20 +976,21 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo int total = np.get_name_count() + np.get_subname_count(); for (int i = 0; i < total; i++) { - String str; - if (i < np.get_name_count()) + if (i < np.get_name_count()) { str = np.get_name(i); - else + } else { str = np.get_subname(i - np.get_name_count()); + } CharString utf8 = str.utf8(); int pad = 0; - if (utf8.length() % 4) + if (utf8.length() % 4) { pad = 4 - utf8.length() % 4; + } if (buf) { encode_uint32(utf8.length(), buf); @@ -1037,19 +1004,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::STRING: { - _encode_string(p_variant, buf, r_len); } break; case Variant::STRING_NAME: { - _encode_string(p_variant, buf, r_len); } break; // math types case Variant::VECTOR2: { - if (buf) { Vector2 v2 = p_variant; encode_float(v2.x, &buf[0]); @@ -1060,7 +1024,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::VECTOR2I: { - if (buf) { Vector2i v2 = p_variant; encode_uint32(v2.x, &buf[0]); @@ -1071,7 +1034,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::RECT2: { - if (buf) { Rect2 r2 = p_variant; encode_float(r2.position.x, &buf[0]); @@ -1083,7 +1045,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::RECT2I: { - if (buf) { Rect2i r2 = p_variant; encode_uint32(r2.position.x, &buf[0]); @@ -1095,7 +1056,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::VECTOR3: { - if (buf) { Vector3 v3 = p_variant; encode_float(v3.x, &buf[0]); @@ -1107,7 +1067,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::VECTOR3I: { - if (buf) { Vector3i v3 = p_variant; encode_uint32(v3.x, &buf[0]); @@ -1119,12 +1078,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::TRANSFORM2D: { - if (buf) { Transform2D val = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { - copymem(&buf[(i * 2 + j) * 4], &val.elements[i][j], sizeof(float)); } } @@ -1134,7 +1091,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::PLANE: { - if (buf) { Plane p = p_variant; encode_float(p.normal.x, &buf[0]); @@ -1147,7 +1103,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::QUAT: { - if (buf) { Quat q = p_variant; encode_float(q.x, &buf[0]); @@ -1160,7 +1115,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::AABB: { - if (buf) { AABB aabb = p_variant; encode_float(aabb.position.x, &buf[0]); @@ -1175,12 +1129,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::BASIS: { - if (buf) { Basis val = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - copymem(&buf[(i * 3 + j) * 4], &val.elements[i][j], sizeof(float)); } } @@ -1190,12 +1142,10 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::TRANSFORM: { - if (buf) { Transform val = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - copymem(&buf[(i * 3 + j) * 4], &val.basis.elements[i][j], sizeof(float)); } } @@ -1211,7 +1161,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo // misc types case Variant::COLOR: { - if (buf) { Color c = p_variant; encode_float(c.r, &buf[0]); @@ -1224,18 +1173,13 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::_RID: { - } break; case Variant::CALLABLE: { - } break; case Variant::SIGNAL: { - } break; case Variant::OBJECT: { - if (p_full_objects) { - Object *obj = p_variant; if (!obj) { if (buf) { @@ -1251,9 +1195,9 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo int pc = 0; for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } pc++; } @@ -1265,25 +1209,26 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } _encode_string(E->get().name, buf, r_len); int len; Error err = encode_variant(obj->get(E->get().name), buf, len, p_full_objects); - if (err) + if (err) { return err; + } ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; - if (buf) + if (buf) { buf += len; + } } } } else { if (buf) { - Object *obj = p_variant.get_validated_object(); ObjectID id; if (obj) { @@ -1298,7 +1243,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::DICTIONARY: { - Dictionary d = p_variant; if (buf) { @@ -1311,7 +1255,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - /* CharString utf8 = E->->utf8(); @@ -1329,20 +1272,21 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo encode_variant(E->get(), buf, len, p_full_objects); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; - if (buf) + if (buf) { buf += len; + } Variant *v = d.getptr(E->get()); ERR_FAIL_COND_V(!v, ERR_BUG); encode_variant(*v, buf, len, p_full_objects); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; - if (buf) + if (buf) { buf += len; + } } } break; case Variant::ARRAY: { - Array v = p_variant; if (buf) { @@ -1353,19 +1297,18 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; for (int i = 0; i < v.size(); i++) { - int len; encode_variant(v.get(i), buf, len, p_full_objects); ERR_FAIL_COND_V(len % 4, ERR_BUG); r_len += len; - if (buf) + if (buf) { buf += len; + } } } break; // arrays case Variant::PACKED_BYTE_ARRAY: { - Vector<uint8_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(uint8_t); @@ -1381,13 +1324,13 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 + datalen * datasize; while (r_len % 4) { r_len++; - if (buf) + if (buf) { *(buf++) = 0; + } } } break; case Variant::PACKED_INT32_ARRAY: { - Vector<int32_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(int32_t); @@ -1396,15 +1339,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo encode_uint32(datalen, buf); buf += 4; const int32_t *r = data.ptr(); - for (int32_t i = 0; i < datalen; i++) + for (int32_t i = 0; i < datalen; i++) { encode_uint32(r[i], &buf[i * datasize]); + } } r_len += 4 + datalen * datasize; } break; case Variant::PACKED_INT64_ARRAY: { - Vector<int64_t> data = p_variant; int datalen = data.size(); int datasize = sizeof(int64_t); @@ -1413,15 +1356,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo encode_uint64(datalen, buf); buf += 4; const int64_t *r = data.ptr(); - for (int64_t i = 0; i < datalen; i++) + for (int64_t i = 0; i < datalen; i++) { encode_uint64(r[i], &buf[i * datasize]); + } } r_len += 4 + datalen * datasize; } break; case Variant::PACKED_FLOAT32_ARRAY: { - Vector<float> data = p_variant; int datalen = data.size(); int datasize = sizeof(float); @@ -1430,15 +1373,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo encode_uint32(datalen, buf); buf += 4; const float *r = data.ptr(); - for (int i = 0; i < datalen; i++) + for (int i = 0; i < datalen; i++) { encode_float(r[i], &buf[i * datasize]); + } } r_len += 4 + datalen * datasize; } break; case Variant::PACKED_FLOAT64_ARRAY: { - Vector<double> data = p_variant; int datalen = data.size(); int datasize = sizeof(double); @@ -1447,15 +1390,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo encode_uint32(datalen, buf); buf += 4; const double *r = data.ptr(); - for (int i = 0; i < datalen; i++) + for (int i = 0; i < datalen; i++) { encode_double(r[i], &buf[i * datasize]); + } } r_len += 4 + datalen * datasize; } break; case Variant::PACKED_STRING_ARRAY: { - Vector<String> data = p_variant; int len = data.size(); @@ -1467,7 +1410,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; for (int i = 0; i < len; i++) { - CharString utf8 = data.get(i).utf8(); if (buf) { @@ -1480,14 +1422,14 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 + utf8.length() + 1; while (r_len % 4) { r_len++; //pad - if (buf) + if (buf) { *(buf++) = 0; + } } } } break; case Variant::PACKED_VECTOR2_ARRAY: { - Vector<Vector2> data = p_variant; int len = data.size(); @@ -1499,9 +1441,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; if (buf) { - for (int i = 0; i < len; i++) { - Vector2 v = data.get(i); encode_float(v.x, &buf[0]); @@ -1514,7 +1454,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::PACKED_VECTOR3_ARRAY: { - Vector<Vector3> data = p_variant; int len = data.size(); @@ -1526,9 +1465,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; if (buf) { - for (int i = 0; i < len; i++) { - Vector3 v = data.get(i); encode_float(v.x, &buf[0]); @@ -1542,7 +1479,6 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::PACKED_COLOR_ARRAY: { - Vector<Color> data = p_variant; int len = data.size(); @@ -1554,9 +1490,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4; if (buf) { - for (int i = 0; i < len; i++) { - Color c = data.get(i); encode_float(c.r, &buf[0]); diff --git a/core/io/marshalls.h b/core/io/marshalls.h index d029ed238c..c8ed497528 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -41,21 +41,17 @@ */ union MarshallFloat { - uint32_t i; ///< int float f; ///< float }; union MarshallDouble { - uint64_t l; ///< long long double d; ///< double }; static inline unsigned int encode_uint16(uint16_t p_uint, uint8_t *p_arr) { - for (int i = 0; i < 2; i++) { - *p_arr = p_uint & 0xFF; p_arr++; p_uint >>= 8; @@ -65,9 +61,7 @@ static inline unsigned int encode_uint16(uint16_t p_uint, uint8_t *p_arr) { } static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) { - for (int i = 0; i < 4; i++) { - *p_arr = p_uint & 0xFF; p_arr++; p_uint >>= 8; @@ -77,7 +71,6 @@ static inline unsigned int encode_uint32(uint32_t p_uint, uint8_t *p_arr) { } static inline unsigned int encode_float(float p_float, uint8_t *p_arr) { - MarshallFloat mf; mf.f = p_float; encode_uint32(mf.i, p_arr); @@ -86,9 +79,7 @@ static inline unsigned int encode_float(float p_float, uint8_t *p_arr) { } static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) { - for (int i = 0; i < 8; i++) { - *p_arr = p_uint & 0xFF; p_arr++; p_uint >>= 8; @@ -98,7 +89,6 @@ static inline unsigned int encode_uint64(uint64_t p_uint, uint8_t *p_arr) { } static inline unsigned int encode_double(double p_double, uint8_t *p_arr) { - MarshallDouble md; md.d = p_double; encode_uint64(md.l, p_arr); @@ -107,30 +97,27 @@ static inline unsigned int encode_double(double p_double, uint8_t *p_arr) { } static inline int encode_cstring(const char *p_string, uint8_t *p_data) { - int len = 0; while (*p_string) { - if (p_data) { - *p_data = (uint8_t)*p_string; p_data++; } p_string++; len++; - }; + } - if (p_data) *p_data = 0; + if (p_data) { + *p_data = 0; + } return len + 1; } static inline uint16_t decode_uint16(const uint8_t *p_arr) { - uint16_t u = 0; for (int i = 0; i < 2; i++) { - uint16_t b = *p_arr; b <<= (i * 8); u |= b; @@ -141,11 +128,9 @@ static inline uint16_t decode_uint16(const uint8_t *p_arr) { } static inline uint32_t decode_uint32(const uint8_t *p_arr) { - uint32_t u = 0; for (int i = 0; i < 4; i++) { - uint32_t b = *p_arr; b <<= (i * 8); u |= b; @@ -156,18 +141,15 @@ static inline uint32_t decode_uint32(const uint8_t *p_arr) { } static inline float decode_float(const uint8_t *p_arr) { - MarshallFloat mf; mf.i = decode_uint32(p_arr); return mf.f; } static inline uint64_t decode_uint64(const uint8_t *p_arr) { - uint64_t u = 0; for (int i = 0; i < 8; i++) { - uint64_t b = (*p_arr) & 0xFF; b <<= (i * 8); u |= b; @@ -178,7 +160,6 @@ static inline uint64_t decode_uint64(const uint8_t *p_arr) { } static inline double decode_double(const uint8_t *p_arr) { - MarshallDouble md; md.l = decode_uint64(p_arr); return md.d; @@ -196,7 +177,7 @@ public: void set_object_id(ObjectID p_id); ObjectID get_object_id() const; - EncodedObjectAsID(); + EncodedObjectAsID() {} }; Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = nullptr, bool p_allow_objects = false); diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 3bec52416e..2f17d9e746 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -33,6 +33,7 @@ #include "core/debugger/engine_debugger.h" #include "core/io/marshalls.h" #include "scene/main/node.h" + #include <stdint.h> #define NODE_ID_COMPRESSION_SHIFT 3 @@ -44,9 +45,7 @@ #endif _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_master, bool &r_skip_rpc) { - switch (mode) { - case MultiplayerAPI::RPC_MODE_DISABLED: { // Do nothing. } break; @@ -54,8 +53,9 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas // Do nothing also. Remote cannot produce a local call. } break; case MultiplayerAPI::RPC_MODE_MASTERSYNC: { - if (is_master) + if (is_master) { r_skip_rpc = true; // I am the master, so skip remote call. + } [[fallthrough]]; } case MultiplayerAPI::RPC_MODE_REMOTESYNC: @@ -64,8 +64,9 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas return true; } break; case MultiplayerAPI::RPC_MODE_MASTER: { - if (is_master) + if (is_master) { r_skip_rpc = true; // I am the master, so skip remote call. + } return is_master; } break; case MultiplayerAPI::RPC_MODE_PUPPET: { @@ -77,7 +78,6 @@ _FORCE_INLINE_ bool _should_call_local(MultiplayerAPI::RPCMode mode, bool is_mas _FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, int p_remote_id) { switch (mode) { - case MultiplayerAPI::RPC_MODE_DISABLED: { return false; } break; @@ -99,17 +99,17 @@ _FORCE_INLINE_ bool _can_call_mode(Node *p_node, MultiplayerAPI::RPCMode mode, i } void MultiplayerAPI::poll() { - - if (!network_peer.is_valid() || network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) + if (!network_peer.is_valid() || network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED) { return; + } network_peer->poll(); - if (!network_peer.is_valid()) // It's possible that polling might have resulted in a disconnection, so check here. + if (!network_peer.is_valid()) { // It's possible that polling might have resulted in a disconnection, so check here. return; + } while (network_peer->get_available_packet_count()) { - int sender = network_peer->get_packet_peer(); const uint8_t *packet; int len; @@ -143,8 +143,9 @@ void MultiplayerAPI::set_root_node(Node *p_node) { } void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer) { - - if (p_peer == network_peer) return; // Nothing to do + if (p_peer == network_peer) { + return; // Nothing to do + } ERR_FAIL_COND_MSG(p_peer.is_valid() && p_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_DISCONNECTED, "Supplied NetworkedMultiplayerPeer must be connecting or connected."); @@ -183,6 +184,7 @@ void _profile_node_data(const String &p_what, ObjectID p_id) { EngineDebugger::profiler_add_frame_data("multiplayer", values); } } + void _profile_bandwidth_data(const String &p_inout, int p_size) { if (EngineDebugger::is_profiling("multiplayer")) { Array values; @@ -206,7 +208,6 @@ int get_packet_len(uint32_t p_node_target, int p_packet_len) { } void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(root_node == nullptr, "Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it."); ERR_FAIL_COND_MSG(p_packet_len < 1, "Invalid packet received. Size too small."); @@ -218,20 +219,16 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ uint8_t packet_type = p_packet[0] & 7; switch (packet_type) { - case NETWORK_COMMAND_SIMPLIFY_PATH: { - _process_simplify_path(p_from, p_packet, p_packet_len); } break; case NETWORK_COMMAND_CONFIRM_PATH: { - _process_confirm_path(p_from, p_packet, p_packet_len); } break; case NETWORK_COMMAND_REMOTE_CALL: case NETWORK_COMMAND_REMOTE_SET: { - // Extract packet meta int packet_min_size = 1; int name_id_offset = 1; @@ -302,25 +299,21 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ const int packet_len = get_packet_len(node_target, p_packet_len); if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { - _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size); } else { - _process_rset(node, name_id, p_from, p_packet, packet_len, packet_min_size); } } break; case NETWORK_COMMAND_RAW: { - _process_raw(p_from, p_packet, p_packet_len); } break; } } Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uint32_t p_node_target, int p_packet_len) { - Node *node = nullptr; if (p_node_target & 0x80000000) { @@ -337,8 +330,9 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uin node = root_node->get_node(np); - if (!node) + if (!node) { ERR_PRINT("Failed to get path from RPC: " + String(np) + "."); + } } else { // Use cached path. int id = p_node_target; @@ -353,14 +347,14 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uin // Do proper caching later. node = root_node->get_node(ni->path); - if (!node) + if (!node) { ERR_PRINT("Failed to get cached path from RPC: " + String(ni->path) + "."); + } } return node; } void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { - ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RPC on this node. @@ -413,7 +407,6 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, p_offset += len; } else { for (int i = 0; i < argc; i++) { - ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); int vlen; @@ -436,7 +429,6 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, } void MultiplayerAPI::_process_rset(Node *p_node, const uint16_t p_rpc_property_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { - ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RSET on this node. @@ -470,7 +462,6 @@ void MultiplayerAPI::_process_rset(Node *p_node, const uint16_t p_rpc_property_i } void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 38, "Invalid packet received. Size too small."); int ofs = 1; @@ -519,7 +510,6 @@ void MultiplayerAPI::_process_simplify_path(int p_from, const uint8_t *p_packet, } void MultiplayerAPI::_process_confirm_path(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 3, "Invalid packet received. Size too small."); const bool valid_rpc_checksum = p_packet[1]; @@ -546,12 +536,13 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC List<int> peers_to_add; // If one is missing, take note to add it. for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { - - if (p_target < 0 && E->get() == -p_target) + if (p_target < 0 && E->get() == -p_target) { continue; // Continue, excluded. + } - if (p_target > 0 && E->get() != p_target) + if (p_target > 0 && E->get() != p_target) { continue; // Continue, not for this peer. + } Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get()); @@ -567,7 +558,6 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC } if (peers_to_add.size() > 0) { - // Those that need to be added, send a message for this. // Encode function name. @@ -592,7 +582,6 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC ofs += encode_cstring(path.get_data(), &packet.write[ofs]); for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) { - network_peer->set_target_peer(E->get()); // To all of you. network_peer->set_transfer_mode(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); network_peer->put_packet(packet.ptr(), packet.size()); @@ -617,7 +606,6 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC #define ENCODE_32 2 << 5 #define ENCODE_64 3 << 5 Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len) { - // Unreachable because `VARIANT_MAX` == 27 and `ENCODE_VARIANT_MASK` == 31 CRASH_COND(p_variant.get_type() > VARIANT_META_TYPE_MASK); @@ -679,8 +667,9 @@ Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uin default: // Any other case is not yet compressed. Error err = encode_variant(p_variant, r_buffer, r_len, allow_object_decoding); - if (err != OK) + if (err != OK) { return err; + } if (r_buffer) { // The first byte is not used by the marshaling, so store the type // so we know how to decompress and decode this variant. @@ -690,8 +679,8 @@ Error MultiplayerAPI::_encode_and_compress_variant(const Variant &p_variant, uin return OK; } -Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) { +Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len) { const uint8_t *buf = p_buffer; int len = p_len; @@ -705,55 +694,61 @@ Error MultiplayerAPI::_decode_and_decompress_variant(Variant &r_variant, const u case Variant::BOOL: { bool val = (buf[0] & VARIANT_META_BOOL_MASK) > 0; r_variant = val; - if (r_len) + if (r_len) { *r_len = 1; + } } break; case Variant::INT: { buf += 1; len -= 1; - if (r_len) + if (r_len) { *r_len = 1; + } if (encode_mode == ENCODE_8) { // 8 bits. ERR_FAIL_COND_V(len < 1, ERR_INVALID_DATA); int8_t val = buf[0]; r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 1; + } } else if (encode_mode == ENCODE_16) { // 16 bits. ERR_FAIL_COND_V(len < 2, ERR_INVALID_DATA); int16_t val = decode_uint16(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 2; + } } else if (encode_mode == ENCODE_32) { // 32 bits. ERR_FAIL_COND_V(len < 4, ERR_INVALID_DATA); int32_t val = decode_uint32(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 4; + } } else { // 64 bits. ERR_FAIL_COND_V(len < 8, ERR_INVALID_DATA); int64_t val = decode_uint64(buf); r_variant = val; - if (r_len) + if (r_len) { (*r_len) += 8; + } } } break; default: Error err = decode_variant(r_variant, p_buffer, p_len, r_len, allow_object_decoding); - if (err != OK) + if (err != OK) { return err; + } } return OK; } void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p_set, const StringName &p_name, const Variant **p_arg, int p_argcount) { - ERR_FAIL_COND_MSG(network_peer.is_null(), "Attempt to remote call/set when networking is not active in SceneTree."); ERR_FAIL_COND_MSG(network_peer->get_connection_status() == NetworkedMultiplayerPeer::CONNECTION_CONNECTING, "Attempt to remote call/set when networking is not connected yet in SceneTree."); @@ -787,8 +782,9 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p int ofs = 0; -#define MAKE_ROOM(m_amount) \ - if (packet_cache.size() < m_amount) packet_cache.resize(m_amount); +#define MAKE_ROOM(m_amount) \ + if (packet_cache.size() < m_amount) \ + packet_cache.resize(m_amount); // Encode meta. // The meta is composed by a single byte that contains (starting from the least segnificant bit): @@ -838,7 +834,6 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p } if (p_set) { - // Take the rpc property ID uint16_t property_id = p_from->get_node_rset_property_id(p_name); if (property_id == UINT16_MAX && p_from->get_script_instance()) { @@ -931,7 +926,6 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p network_peer->set_transfer_mode(p_unreliable ? NetworkedMultiplayerPeer::TRANSFER_MODE_UNRELIABLE : NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); if (has_all_peers) { - // They all have verified paths, so send fast. network_peer->set_target_peer(p_to); // To all of you. network_peer->put_packet(packet_cache.ptr(), ofs); // A message with love. @@ -948,12 +942,13 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p encode_cstring(pname.get_data(), &(packet_cache.write[ofs])); for (Set<int>::Element *E = connected_peers.front(); E; E = E->next()) { - - if (p_to < 0 && E->get() == -p_to) + if (p_to < 0 && E->get() == -p_to) { continue; // Continue, excluded. + } - if (p_to > 0 && E->get() != p_to) + if (p_to > 0 && E->get() != p_to) { continue; // Continue, not for this peer. + } Map<int, bool>::Element *F = psc->confirmed_peers.find(E->get()); ERR_CONTINUE(!F); // Should never happen. @@ -995,22 +990,18 @@ void MultiplayerAPI::_del_peer(int p_id) { } void MultiplayerAPI::_connected_to_server() { - emit_signal("connected_to_server"); } void MultiplayerAPI::_connection_failed() { - emit_signal("connection_failed"); } void MultiplayerAPI::_server_disconnected() { - emit_signal("server_disconnected"); } void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) { - ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to call an RPC while no network peer is active."); ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to call an RPC on a node which is not inside SceneTree."); ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to call an RPC via a network peer which is not connected."); @@ -1037,7 +1028,6 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const } if (!skip_rpc) { - #ifdef DEBUG_ENABLED _profile_node_data("out_rpc", p_node->get_instance_id()); #endif @@ -1078,7 +1068,6 @@ void MultiplayerAPI::rpcp(Node *p_node, int p_peer_id, bool p_unreliable, const } void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) { - ERR_FAIL_COND_MSG(!network_peer.is_valid(), "Trying to RSET while no network peer is active."); ERR_FAIL_COND_MSG(!p_node->is_inside_tree(), "Trying to RSET on a node which is not inside SceneTree."); ERR_FAIL_COND_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, "Trying to send an RSET via a network peer which is not connected."); @@ -1143,7 +1132,6 @@ void MultiplayerAPI::rsetp(Node *p_node, int p_peer_id, bool p_unreliable, const } Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMultiplayerPeer::TransferMode p_mode) { - ERR_FAIL_COND_V_MSG(p_data.size() < 1, ERR_INVALID_DATA, "Trying to send an empty raw packet."); ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), ERR_UNCONFIGURED, "Trying to send a raw packet while no network peer is active."); ERR_FAIL_COND_V_MSG(network_peer->get_connection_status() != NetworkedMultiplayerPeer::CONNECTION_CONNECTED, ERR_UNCONFIGURED, "Trying to send a raw packet via a network peer which is not connected."); @@ -1160,7 +1148,6 @@ Error MultiplayerAPI::send_bytes(Vector<uint8_t> p_data, int p_to, NetworkedMult } void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_packet_len) { - ERR_FAIL_COND_MSG(p_packet_len < 2, "Invalid packet received. Size too small."); Vector<uint8_t> out; @@ -1174,32 +1161,27 @@ void MultiplayerAPI::_process_raw(int p_from, const uint8_t *p_packet, int p_pac } int MultiplayerAPI::get_network_unique_id() const { - ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), 0, "No network peer is assigned. Unable to get unique network ID."); return network_peer->get_unique_id(); } bool MultiplayerAPI::is_network_server() const { - // XXX Maybe fail silently? Maybe should actually return true to make development of both local and online multiplayer easier? ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), false, "No network peer is assigned. I can't be a server."); return network_peer->is_server(); } void MultiplayerAPI::set_refuse_new_network_connections(bool p_refuse) { - ERR_FAIL_COND_MSG(!network_peer.is_valid(), "No network peer is assigned. Unable to set 'refuse_new_connections'."); network_peer->set_refuse_new_connections(p_refuse); } bool MultiplayerAPI::is_refusing_new_network_connections() const { - ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), false, "No network peer is assigned. Unable to get 'refuse_new_connections'."); return network_peer->is_refusing_new_connections(); } Vector<int> MultiplayerAPI::get_network_connected_peers() const { - ERR_FAIL_COND_V_MSG(!network_peer.is_valid(), Vector<int>(), "No network peer is assigned. Assume no peers are connected."); Vector<int> ret; @@ -1211,12 +1193,10 @@ Vector<int> MultiplayerAPI::get_network_connected_peers() const { } void MultiplayerAPI::set_allow_object_decoding(bool p_enable) { - allow_object_decoding = p_enable; } bool MultiplayerAPI::is_object_decoding_allowed() const { - return allow_object_decoding; } @@ -1259,10 +1239,7 @@ void MultiplayerAPI::_bind_methods() { BIND_ENUM_CONSTANT(RPC_MODE_PUPPETSYNC); } -MultiplayerAPI::MultiplayerAPI() : - allow_object_decoding(false) { - rpc_sender_id = 0; - root_node = nullptr; +MultiplayerAPI::MultiplayerAPI() { clear(); } diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index 4eb4a53e99..06eab7796c 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -35,7 +35,6 @@ #include "core/reference.h" class MultiplayerAPI : public Reference { - GDCLASS(MultiplayerAPI, Reference); private: @@ -56,14 +55,14 @@ private: }; Ref<NetworkedMultiplayerPeer> network_peer; - int rpc_sender_id; + int rpc_sender_id = 0; Set<int> connected_peers; HashMap<NodePath, PathSentCache> path_send_cache; Map<int, PathGetCache> path_get_cache; int last_send_cache_id; Vector<uint8_t> packet_cache; - Node *root_node; - bool allow_object_decoding; + Node *root_node = nullptr; + bool allow_object_decoding = false; protected: static void _bind_methods(); diff --git a/core/io/net_socket.cpp b/core/io/net_socket.cpp index 838c674cec..130a2e245e 100644 --- a/core/io/net_socket.cpp +++ b/core/io/net_socket.cpp @@ -33,9 +33,9 @@ NetSocket *(*NetSocket::_create)() = nullptr; NetSocket *NetSocket::create() { - - if (_create) + if (_create) { return _create(); + } ERR_PRINT("Unable to create network socket, platform not supported"); return nullptr; diff --git a/core/io/net_socket.h b/core/io/net_socket.h index 376fd87a27..746945eced 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -35,7 +35,6 @@ #include "core/reference.h" class NetSocket : public Reference { - protected: static NetSocket *(*_create)(); diff --git a/core/io/networked_multiplayer_peer.cpp b/core/io/networked_multiplayer_peer.cpp index b2f810d212..f521f2bb79 100644 --- a/core/io/networked_multiplayer_peer.cpp +++ b/core/io/networked_multiplayer_peer.cpp @@ -31,7 +31,6 @@ #include "networked_multiplayer_peer.h" void NetworkedMultiplayerPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_transfer_mode", "mode"), &NetworkedMultiplayerPeer::set_transfer_mode); ClassDB::bind_method(D_METHOD("get_transfer_mode"), &NetworkedMultiplayerPeer::get_transfer_mode); ClassDB::bind_method(D_METHOD("set_target_peer", "id"), &NetworkedMultiplayerPeer::set_target_peer); @@ -66,6 +65,3 @@ void NetworkedMultiplayerPeer::_bind_methods() { ADD_SIGNAL(MethodInfo("connection_succeeded")); ADD_SIGNAL(MethodInfo("connection_failed")); } - -NetworkedMultiplayerPeer::NetworkedMultiplayerPeer() { -} diff --git a/core/io/networked_multiplayer_peer.h b/core/io/networked_multiplayer_peer.h index c1f1924051..dc76237f45 100644 --- a/core/io/networked_multiplayer_peer.h +++ b/core/io/networked_multiplayer_peer.h @@ -34,7 +34,6 @@ #include "core/io/packet_peer.h" class NetworkedMultiplayerPeer : public PacketPeer { - GDCLASS(NetworkedMultiplayerPeer, PacketPeer); protected: @@ -74,7 +73,7 @@ public: virtual ConnectionStatus get_connection_status() const = 0; - NetworkedMultiplayerPeer(); + NetworkedMultiplayerPeer() {} }; VARIANT_ENUM_CAST(NetworkedMultiplayerPeer::TransferMode) diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index 38abb5c0d6..dacd548a3e 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -35,13 +35,7 @@ /* helpers / binders */ -PacketPeer::PacketPeer() : - last_get_error(OK), - encode_buffer_max_size(8 * 1024 * 1024) { -} - void PacketPeer::set_encode_buffer_max_size(int p_max_size) { - ERR_FAIL_COND_MSG(p_max_size < 1024, "Max encode buffer must be at least 1024 bytes"); ERR_FAIL_COND_MSG(p_max_size > 256 * 1024 * 1024, "Max encode buffer cannot exceed 256 MiB"); encode_buffer_max_size = next_power_of_2(p_max_size); @@ -49,59 +43,61 @@ void PacketPeer::set_encode_buffer_max_size(int p_max_size) { } int PacketPeer::get_encode_buffer_max_size() const { - return encode_buffer_max_size; } Error PacketPeer::get_packet_buffer(Vector<uint8_t> &r_buffer) { - const uint8_t *buffer; int buffer_size; Error err = get_packet(&buffer, buffer_size); - if (err) + if (err) { return err; + } r_buffer.resize(buffer_size); - if (buffer_size == 0) + if (buffer_size == 0) { return OK; + } uint8_t *w = r_buffer.ptrw(); - for (int i = 0; i < buffer_size; i++) + for (int i = 0; i < buffer_size; i++) { w[i] = buffer[i]; + } return OK; } Error PacketPeer::put_packet_buffer(const Vector<uint8_t> &p_buffer) { - int len = p_buffer.size(); - if (len == 0) + if (len == 0) { return OK; + } const uint8_t *r = p_buffer.ptr(); return put_packet(&r[0], len); } Error PacketPeer::get_var(Variant &r_variant, bool p_allow_objects) { - const uint8_t *buffer; int buffer_size; Error err = get_packet(&buffer, buffer_size); - if (err) + if (err) { return err; + } return decode_variant(r_variant, buffer, buffer_size, nullptr, p_allow_objects); } Error PacketPeer::put_var(const Variant &p_packet, bool p_full_objects) { - int len; Error err = encode_variant(p_packet, nullptr, len, p_full_objects); // compute len first - if (err) + if (err) { return err; + } - if (len == 0) + if (len == 0) { return OK; + } ERR_FAIL_COND_V_MSG(len > encode_buffer_max_size, ERR_OUT_OF_MEMORY, "Failed to encode variant, encode size is bigger then encode_buffer_max_size. Consider raising it via 'set_encode_buffer_max_size'."); @@ -128,20 +124,18 @@ Variant PacketPeer::_bnd_get_var(bool p_allow_objects) { Error PacketPeer::_put_packet(const Vector<uint8_t> &p_buffer) { return put_packet_buffer(p_buffer); } -Vector<uint8_t> PacketPeer::_get_packet() { +Vector<uint8_t> PacketPeer::_get_packet() { Vector<uint8_t> raw; last_get_error = get_packet_buffer(raw); return raw; } Error PacketPeer::_get_packet_error() const { - return last_get_error; } void PacketPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_var", "allow_objects"), &PacketPeer::_bnd_get_var, DEFVAL(false)); ClassDB::bind_method(D_METHOD("put_var", "var", "full_objects"), &PacketPeer::put_var, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet); @@ -153,18 +147,16 @@ void PacketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_encode_buffer_max_size", "max_size"), &PacketPeer::set_encode_buffer_max_size); ADD_PROPERTY(PropertyInfo(Variant::INT, "encode_buffer_max_size"), "set_encode_buffer_max_size", "get_encode_buffer_max_size"); -}; +} /***************/ void PacketPeerStream::_set_stream_peer(REF p_peer) { - ERR_FAIL_COND_MSG(p_peer.is_null(), "It's not a reference to a valid Resource object."); set_stream_peer(p_peer); } void PacketPeerStream::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_stream_peer", "peer"), &PacketPeerStream::set_stream_peer); ClassDB::bind_method(D_METHOD("get_stream_peer"), &PacketPeerStream::get_stream_peer); ClassDB::bind_method(D_METHOD("set_input_buffer_max_size", "max_size_bytes"), &PacketPeerStream::set_input_buffer_max_size); @@ -178,16 +170,17 @@ void PacketPeerStream::_bind_methods() { } Error PacketPeerStream::_poll_buffer() const { - ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED); int read = 0; ERR_FAIL_COND_V(input_buffer.size() < ring_buffer.space_left(), ERR_UNAVAILABLE); Error err = peer->get_partial_data(input_buffer.ptrw(), ring_buffer.space_left(), read); - if (err) + if (err) { return err; - if (read == 0) + } + if (read == 0) { return OK; + } int w = ring_buffer.write(&input_buffer[0], read); ERR_FAIL_COND_V(w != read, ERR_BUG); @@ -196,7 +189,6 @@ Error PacketPeerStream::_poll_buffer() const { } int PacketPeerStream::get_available_packet_count() const { - _poll_buffer(); uint32_t remaining = ring_buffer.data_left(); @@ -205,14 +197,14 @@ int PacketPeerStream::get_available_packet_count() const { int count = 0; while (remaining >= 4) { - uint8_t lbuf[4]; ring_buffer.copy(lbuf, ofs, 4); uint32_t len = decode_uint32(lbuf); remaining -= 4; ofs += 4; - if (len > remaining) + if (len > remaining) { break; + } remaining -= len; ofs += len; count++; @@ -222,7 +214,6 @@ int PacketPeerStream::get_available_packet_count() const { } Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED); _poll_buffer(); @@ -244,50 +235,48 @@ Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) } Error PacketPeerStream::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED); Error err = _poll_buffer(); //won't hurt to poll here too - if (err) + if (err) { return err; + } - if (p_buffer_size == 0) + if (p_buffer_size == 0) { return OK; + } ERR_FAIL_COND_V(p_buffer_size < 0, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_buffer_size + 4 > output_buffer.size(), ERR_INVALID_PARAMETER); encode_uint32(p_buffer_size, output_buffer.ptrw()); uint8_t *dst = &output_buffer.write[4]; - for (int i = 0; i < p_buffer_size; i++) + for (int i = 0; i < p_buffer_size; i++) { dst[i] = p_buffer[i]; + } return peer->put_data(&output_buffer[0], p_buffer_size + 4); } int PacketPeerStream::get_max_packet_size() const { - return output_buffer.size(); } void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) { - //ERR_FAIL_COND(p_peer.is_null()); if (p_peer.ptr() != peer.ptr()) { ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer - }; + } peer = p_peer; } Ref<StreamPeer> PacketPeerStream::get_stream_peer() const { - return peer; } void PacketPeerStream::set_input_buffer_max_size(int p_max_size) { - ERR_FAIL_COND_MSG(p_max_size < 0, "Max size of input buffer size cannot be smaller than 0."); //warning may lose packets ERR_FAIL_COND_MSG(ring_buffer.data_left(), "Buffer in use, resizing would cause loss of data."); @@ -296,22 +285,18 @@ void PacketPeerStream::set_input_buffer_max_size(int p_max_size) { } int PacketPeerStream::get_input_buffer_max_size() const { - return input_buffer.size() - 4; } void PacketPeerStream::set_output_buffer_max_size(int p_max_size) { - output_buffer.resize(next_power_of_2(p_max_size + 4)); } int PacketPeerStream::get_output_buffer_max_size() const { - return output_buffer.size() - 4; } PacketPeerStream::PacketPeerStream() { - int rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2"); ring_buffer.resize(rbsize); diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 62144259cc..f0ba50087f 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -36,7 +36,6 @@ #include "core/ring_buffer.h" class PacketPeer : public Reference { - GDCLASS(PacketPeer, Reference); Variant _bnd_get_var(bool p_allow_objects = false); @@ -47,9 +46,9 @@ class PacketPeer : public Reference { Vector<uint8_t> _get_packet(); Error _get_packet_error() const; - mutable Error last_get_error; + mutable Error last_get_error = OK; - int encode_buffer_max_size; + int encode_buffer_max_size = 8 * 1024 * 1024; Vector<uint8_t> encode_buffer; public: @@ -70,12 +69,11 @@ public: void set_encode_buffer_max_size(int p_max_size); int get_encode_buffer_max_size() const; - PacketPeer(); + PacketPeer() {} ~PacketPeer() {} }; class PacketPeerStream : public PacketPeer { - GDCLASS(PacketPeerStream, PacketPeer); //the way the buffers work sucks, will change later diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp index 6da115eed2..632f86a9f6 100644 --- a/core/io/packet_peer_dtls.cpp +++ b/core/io/packet_peer_dtls.cpp @@ -36,8 +36,10 @@ PacketPeerDTLS *(*PacketPeerDTLS::_create)() = nullptr; bool PacketPeerDTLS::available = false; PacketPeerDTLS *PacketPeerDTLS::create() { - - return _create(); + if (_create) { + return _create(); + } + return nullptr; } bool PacketPeerDTLS::is_available() { @@ -45,7 +47,6 @@ bool PacketPeerDTLS::is_available() { } void PacketPeerDTLS::_bind_methods() { - ClassDB::bind_method(D_METHOD("poll"), &PacketPeerDTLS::poll); ClassDB::bind_method(D_METHOD("connect_to_peer", "packet_peer", "validate_certs", "for_hostname", "valid_certificate"), &PacketPeerDTLS::connect_to_peer, DEFVAL(true), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); ClassDB::bind_method(D_METHOD("get_status"), &PacketPeerDTLS::get_status); @@ -57,6 +58,3 @@ void PacketPeerDTLS::_bind_methods() { BIND_ENUM_CONSTANT(STATUS_ERROR); BIND_ENUM_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH); } - -PacketPeerDTLS::PacketPeerDTLS() { -} diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h index 4f9f4535bc..c2ff4e1a7f 100644 --- a/core/io/packet_peer_dtls.h +++ b/core/io/packet_peer_dtls.h @@ -60,7 +60,7 @@ public: static PacketPeerDTLS *create(); static bool is_available(); - PacketPeerDTLS(); + PacketPeerDTLS() {} }; VARIANT_ENUM_CAST(PacketPeerDTLS::Status); diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index f800ffc3db..862fca96fc 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -33,18 +33,17 @@ #include "core/io/ip.h" void PacketPeerUDP::set_blocking_mode(bool p_enable) { - blocking = p_enable; } void PacketPeerUDP::set_broadcast_enabled(bool p_enabled) { broadcast = p_enabled; - if (_sock.is_valid() && _sock->is_open()) + if (_sock.is_valid() && _sock->is_open()) { _sock->set_broadcasting_enabled(p_enabled); + } } Error PacketPeerUDP::join_multicast_group(IP_Address p_multi_address, String p_if_name) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!p_multi_address.is_valid(), ERR_INVALID_PARAMETER); @@ -59,26 +58,24 @@ Error PacketPeerUDP::join_multicast_group(IP_Address p_multi_address, String p_i } Error PacketPeerUDP::leave_multicast_group(IP_Address p_multi_address, String p_if_name) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!_sock->is_open(), ERR_UNCONFIGURED); return _sock->leave_multicast_group(p_multi_address, p_if_name); } String PacketPeerUDP::_get_packet_ip() const { - return get_packet_address(); } Error PacketPeerUDP::_set_dest_address(const String &p_address, int p_port) { - IP_Address ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { ip = IP::get_singleton()->resolve_hostname(p_address); - if (!ip.is_valid()) + if (!ip.is_valid()) { return ERR_CANT_RESOLVE; + } } set_dest_address(ip, p_port); @@ -86,22 +83,23 @@ Error PacketPeerUDP::_set_dest_address(const String &p_address, int p_port) { } int PacketPeerUDP::get_available_packet_count() const { - // TODO we should deprecate this, and expose poll instead! Error err = const_cast<PacketPeerUDP *>(this)->_poll(); - if (err != OK) + if (err != OK) { return -1; + } return queue_count; } Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { - Error err = _poll(); - if (err != OK) + if (err != OK) { return err; - if (queue_count == 0) + } + if (queue_count == 0) { return ERR_UNAVAILABLE; + } uint32_t size = 0; uint8_t ipv6[16]; @@ -117,7 +115,6 @@ Error PacketPeerUDP::get_packet(const uint8_t **r_buffer, int &r_buffer_size) { } Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!peer_addr.is_valid(), ERR_UNCONFIGURED); @@ -139,10 +136,11 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) { err = _sock->sendto(p_buffer, p_buffer_size, sent, peer_addr, peer_port); } if (err != OK) { - if (err != ERR_BUSY) + if (err != ERR_BUSY) { return FAILED; - else if (!blocking) + } else if (!blocking) { return ERR_BUSY; + } // Keep trying to send full packet continue; } @@ -154,12 +152,10 @@ Error PacketPeerUDP::put_packet(const uint8_t *p_buffer, int p_buffer_size) { } int PacketPeerUDP::get_max_packet_size() const { - return 512; // uhm maybe not } Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_recv_buffer_size) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -167,13 +163,15 @@ Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_ Error err; IP::Type ip_type = IP::TYPE_ANY; - if (p_bind_address.is_valid()) + if (p_bind_address.is_valid()) { ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + } err = _sock->open(NetSocket::TYPE_UDP, ip_type); - if (err != OK) + if (err != OK) { return ERR_CANT_CREATE; + } _sock->set_blocking_enabled(false); _sock->set_reuse_address_enabled(true); @@ -245,22 +243,20 @@ bool PacketPeerUDP::is_connected_to_host() const { } void PacketPeerUDP::close() { - - if (_sock.is_valid()) + if (_sock.is_valid()) { _sock->close(); + } rb.resize(16); queue_count = 0; connected = false; } Error PacketPeerUDP::wait() { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); return _sock->poll(NetSocket::POLL_TYPE_IN, -1); } Error PacketPeerUDP::_poll() { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); if (!_sock->is_open()) { @@ -282,8 +278,9 @@ Error PacketPeerUDP::_poll() { } if (err != OK) { - if (err == ERR_BUSY) + if (err == ERR_BUSY) { break; + } return FAILED; } @@ -304,30 +301,26 @@ Error PacketPeerUDP::_poll() { return OK; } -bool PacketPeerUDP::is_listening() const { +bool PacketPeerUDP::is_listening() const { return _sock.is_valid() && _sock->is_open(); } IP_Address PacketPeerUDP::get_packet_address() const { - return packet_ip; } int PacketPeerUDP::get_packet_port() const { - return packet_port; } void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) { - ERR_FAIL_COND_MSG(connected, "Destination address cannot be set for connected sockets"); peer_addr = p_address; peer_port = p_port; } void PacketPeerUDP::_bind_methods() { - ClassDB::bind_method(D_METHOD("listen", "port", "bind_address", "recv_buf_size"), &PacketPeerUDP::listen, DEFVAL("*"), DEFVAL(65536)); ClassDB::bind_method(D_METHOD("close"), &PacketPeerUDP::close); ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait); @@ -343,17 +336,10 @@ void PacketPeerUDP::_bind_methods() { } PacketPeerUDP::PacketPeerUDP() : - packet_port(0), - queue_count(0), - peer_port(0), - connected(false), - blocking(true), - broadcast(false), _sock(Ref<NetSocket>(NetSocket::create())) { rb.resize(16); } PacketPeerUDP::~PacketPeerUDP() { - close(); } diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index b5a9fc9ec3..23fc5460a6 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -47,14 +47,14 @@ protected: uint8_t recv_buffer[PACKET_BUFFER_SIZE]; uint8_t packet_buffer[PACKET_BUFFER_SIZE]; IP_Address packet_ip; - int packet_port; - int queue_count; + int packet_port = 0; + int queue_count = 0; IP_Address peer_addr; - int peer_port; - bool connected; - bool blocking; - bool broadcast; + int peer_port = 0; + bool connected = false; + bool blocking = true; + bool broadcast = false; Ref<NetSocket> _sock; static void _bind_methods(); diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 5c4b3379ee..374b2a5e07 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -35,34 +35,31 @@ #include "core/version.h" static uint64_t _align(uint64_t p_n, int p_alignment) { - - if (p_alignment == 0) + if (p_alignment == 0) { return p_n; + } uint64_t rest = p_n % p_alignment; - if (rest == 0) + if (rest == 0) { return p_n; - else + } else { return p_n + (p_alignment - rest); -}; + } +} static void _pad(FileAccess *p_file, int p_bytes) { - for (int i = 0; i < p_bytes; i++) { - p_file->store_8(0); - }; -}; + } +} void PCKPacker::_bind_methods() { - ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment"), &PCKPacker::pck_start, DEFVAL(0)); ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path"), &PCKPacker::add_file); ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false)); -}; +} Error PCKPacker::pck_start(const String &p_file, int p_alignment) { - if (file != nullptr) { memdelete(file); } @@ -80,21 +77,19 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment) { file->store_32(VERSION_PATCH); for (int i = 0; i < 16; i++) { - file->store_32(0); // reserved - }; + } files.clear(); return OK; -}; +} Error PCKPacker::add_file(const String &p_file, const String &p_src) { - FileAccess *f = FileAccess::open(p_src, FileAccess::READ); if (!f) { return ERR_FILE_CANT_OPEN; - }; + } File pf; pf.path = p_file; @@ -108,10 +103,9 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src) { memdelete(f); return OK; -}; +} Error PCKPacker::flush(bool p_verbose) { - ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use."); // write the index @@ -119,7 +113,6 @@ Error PCKPacker::flush(bool p_verbose) { file->store_32(files.size()); for (int i = 0; i < files.size(); i++) { - file->store_pascal_string(files[i].path); files.write[i].offset_offset = file->get_position(); file->store_64(0); // offset @@ -130,7 +123,7 @@ Error PCKPacker::flush(bool p_verbose) { file->store_32(0); file->store_32(0); file->store_32(0); - }; + } uint64_t ofs = file->get_position(); ofs = _align(ofs, alignment); @@ -142,15 +135,13 @@ Error PCKPacker::flush(bool p_verbose) { int count = 0; for (int i = 0; i < files.size(); i++) { - FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ); uint64_t to_write = files[i].size; while (to_write > 0) { - int read = src->get_buffer(buf, MIN(to_write, buf_max)); file->store_buffer(buf, read); to_write -= read; - }; + } uint64_t pos = file->get_position(); file->seek(files[i].offset_offset); // go back to store the file's offset @@ -167,27 +158,23 @@ Error PCKPacker::flush(bool p_verbose) { if (count % 100 == 0) { printf("%i/%i (%.2f)\r", count, files.size(), float(count) / files.size() * 100); fflush(stdout); - }; - }; - }; + } + } + } - if (p_verbose) + if (p_verbose) { printf("\n"); + } file->close(); memdelete_arr(buf); return OK; -}; - -PCKPacker::PCKPacker() { - - file = nullptr; -}; +} PCKPacker::~PCKPacker() { if (file != nullptr) { memdelete(file); - }; + } file = nullptr; -}; +} diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index 6058de8345..2929967a68 100644 --- a/core/io/pck_packer.h +++ b/core/io/pck_packer.h @@ -36,16 +36,14 @@ class FileAccess; class PCKPacker : public Reference { - GDCLASS(PCKPacker, Reference); - FileAccess *file; + FileAccess *file = nullptr; int alignment; static void _bind_methods(); struct File { - String path; String src_path; int size; @@ -58,7 +56,7 @@ public: Error add_file(const String &p_file, const String &p_src); Error flush(bool p_verbose = false); - PCKPacker(); + PCKPacker() {} ~PCKPacker(); }; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index a640565ecf..5097f6d98b 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -94,24 +94,24 @@ enum { }; void ResourceLoaderBinary::_advance_padding(uint32_t p_len) { - uint32_t extra = 4 - (p_len % 4); if (extra < 4) { - for (uint32_t i = 0; i < extra; i++) + for (uint32_t i = 0; i < extra; i++) { f->get_8(); //pad to 32 + } } } StringName ResourceLoaderBinary::_get_string() { - uint32_t id = f->get_32(); if (id & 0x80000000) { uint32_t len = id & 0x7FFFFFFF; if ((int)len > str_buf.size()) { str_buf.resize(len); } - if (len == 0) + if (len == 0) { return StringName(); + } f->get_buffer((uint8_t *)&str_buf[0], len); String s; s.parse_utf8(&str_buf[0]); @@ -122,42 +122,32 @@ StringName ResourceLoaderBinary::_get_string() { } Error ResourceLoaderBinary::parse_variant(Variant &r_v) { - uint32_t type = f->get_32(); print_bl("find property of type: " + itos(type)); switch (type) { - case VARIANT_NIL: { - r_v = Variant(); } break; case VARIANT_BOOL: { - r_v = bool(f->get_32()); } break; case VARIANT_INT: { - r_v = int(f->get_32()); } break; case VARIANT_INT64: { - r_v = int64_t(f->get_64()); } break; case VARIANT_FLOAT: { - r_v = f->get_real(); } break; case VARIANT_DOUBLE: { - r_v = f->get_double(); } break; case VARIANT_STRING: { - r_v = get_unicode_string(); } break; case VARIANT_VECTOR2: { - Vector2 v; v.x = f->get_real(); v.y = f->get_real(); @@ -165,7 +155,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_VECTOR2I: { - Vector2i v; v.x = f->get_32(); v.y = f->get_32(); @@ -173,7 +162,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_RECT2: { - Rect2 v; v.position.x = f->get_real(); v.position.y = f->get_real(); @@ -183,7 +171,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_RECT2I: { - Rect2i v; v.position.x = f->get_32(); v.position.y = f->get_32(); @@ -193,7 +180,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_VECTOR3: { - Vector3 v; v.x = f->get_real(); v.y = f->get_real(); @@ -201,7 +187,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = v; } break; case VARIANT_VECTOR3I: { - Vector3i v; v.x = f->get_32(); v.y = f->get_32(); @@ -209,7 +194,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = v; } break; case VARIANT_PLANE: { - Plane v; v.normal.x = f->get_real(); v.normal.y = f->get_real(); @@ -227,7 +211,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_AABB: { - AABB v; v.position.x = f->get_real(); v.position.y = f->get_real(); @@ -239,7 +222,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_MATRIX32: { - Transform2D v; v.elements[0].x = f->get_real(); v.elements[0].y = f->get_real(); @@ -251,7 +233,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_MATRIX3: { - Basis v; v.elements[0].x = f->get_real(); v.elements[0].y = f->get_real(); @@ -266,7 +247,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_TRANSFORM: { - Transform v; v.basis.elements[0].x = f->get_real(); v.basis.elements[0].y = f->get_real(); @@ -283,7 +263,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = v; } break; case VARIANT_COLOR: { - Color v; v.r = f->get_real(); v.g = f->get_real(); @@ -293,12 +272,10 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_STRING_NAME: { - r_v = StringName(get_unicode_string()); } break; case VARIANT_NODE_PATH: { - Vector<StringName> names; Vector<StringName> subnames; bool absolute; @@ -311,10 +288,12 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { subname_count += 1; // has a property field, so we should count it as well } - for (int i = 0; i < name_count; i++) + for (int i = 0; i < name_count; i++) { names.push_back(_get_string()); - for (uint32_t i = 0; i < subname_count; i++) + } + for (uint32_t i = 0; i < subname_count; i++) { subnames.push_back(_get_string()); + } NodePath np = NodePath(names, subnames, absolute); @@ -322,15 +301,12 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_RID: { - r_v = f->get_32(); } break; case VARIANT_OBJECT: { - uint32_t objtype = f->get_32(); switch (objtype) { - case OBJECT_EMPTY: { //do none @@ -338,11 +314,19 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { case OBJECT_INTERNAL_RESOURCE: { uint32_t index = f->get_32(); String path = res_path + "::" + itos(index); - RES res = ResourceLoader::load(path); - if (res.is_null()) { - WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); + + if (use_nocache) { + if (!internal_index_cache.has(path)) { + WARN_PRINT(String("Couldn't load resource (no cache): " + path).utf8().get_data()); + } + r_v = internal_index_cache[path]; + } else { + RES res = ResourceLoader::load(path); + if (res.is_null()) { + WARN_PRINT(String("Couldn't load resource: " + path).utf8().get_data()); + } + r_v = res; } - r_v = res; } break; case OBJECT_EXTERNAL_RESOURCE: { @@ -376,7 +360,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { WARN_PRINT("Broken external resource! (index out of size)"); r_v = Variant(); } else { - if (external_resources[erindex].cache.is_null()) { //cache not here yet, wait for it? if (use_sub_threads) { @@ -385,10 +368,8 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { if (err != OK || external_resources[erindex].cache.is_null()) { if (!ResourceLoader::get_abort_on_missing_resources()) { - ResourceLoader::notify_dependency_error(local_path, external_resources[erindex].path, external_resources[erindex].type); } else { - error = ERR_FILE_MISSING_DEPENDENCIES; ERR_FAIL_V_MSG(error, "Can't load dependency: " + external_resources[erindex].path + "."); } @@ -401,23 +382,19 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; default: { - ERR_FAIL_V(ERR_FILE_CORRUPT); } break; } } break; case VARIANT_CALLABLE: { - r_v = Callable(); } break; case VARIANT_SIGNAL: { - r_v = Signal(); } break; case VARIANT_DICTIONARY: { - uint32_t len = f->get_32(); Dictionary d; //last bit means shared len &= 0x7FFFFFFF; @@ -433,7 +410,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = d; } break; case VARIANT_ARRAY: { - uint32_t len = f->get_32(); Array a; //last bit means shared len &= 0x7FFFFFFF; @@ -448,7 +424,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_RAW_ARRAY: { - uint32_t len = f->get_32(); Vector<uint8_t> array; @@ -461,7 +436,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_INT32_ARRAY: { - uint32_t len = f->get_32(); Vector<int32_t> array; @@ -472,7 +446,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len; i++) { - ptr[i] = BSWAP32(ptr[i]); } } @@ -482,7 +455,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = array; } break; case VARIANT_INT64_ARRAY: { - uint32_t len = f->get_32(); Vector<int64_t> array; @@ -493,7 +465,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint64_t *ptr = (uint64_t *)w.ptr(); for (int i = 0; i < len; i++) { - ptr[i] = BSWAP64(ptr[i]); } } @@ -503,7 +474,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = array; } break; case VARIANT_FLOAT32_ARRAY: { - uint32_t len = f->get_32(); Vector<float> array; @@ -514,7 +484,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len; i++) { - ptr[i] = BSWAP32(ptr[i]); } } @@ -524,7 +493,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = array; } break; case VARIANT_FLOAT64_ARRAY: { - uint32_t len = f->get_32(); Vector<double> array; @@ -535,7 +503,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint64_t *ptr = (uint64_t *)w.ptr(); for (int i = 0; i < len; i++) { - ptr[i] = BSWAP64(ptr[i]); } } @@ -545,19 +512,18 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { r_v = array; } break; case VARIANT_STRING_ARRAY: { - uint32_t len = f->get_32(); Vector<String> array; array.resize(len); String *w = array.ptrw(); - for (uint32_t i = 0; i < len; i++) + for (uint32_t i = 0; i < len; i++) { w[i] = get_unicode_string(); + } r_v = array; } break; case VARIANT_VECTOR2_ARRAY: { - uint32_t len = f->get_32(); Vector<Vector2> array; @@ -569,7 +535,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len * 2; i++) { - ptr[i] = BSWAP32(ptr[i]); } } @@ -584,7 +549,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_VECTOR3_ARRAY: { - uint32_t len = f->get_32(); Vector<Vector3> array; @@ -596,7 +560,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len * 3; i++) { - ptr[i] = BSWAP32(ptr[i]); } } @@ -611,7 +574,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } break; case VARIANT_COLOR_ARRAY: { - uint32_t len = f->get_32(); Vector<Color> array; @@ -623,7 +585,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { { uint32_t *ptr = (uint32_t *)w.ptr(); for (int i = 0; i < len * 4; i++) { - ptr[i] = BSWAP32(ptr[i]); } } @@ -645,23 +606,21 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) { } void ResourceLoaderBinary::set_local_path(const String &p_local_path) { - res_path = p_local_path; } Ref<Resource> ResourceLoaderBinary::get_resource() { - return resource; } -Error ResourceLoaderBinary::load() { - if (error != OK) +Error ResourceLoaderBinary::load() { + if (error != OK) { return error; + } int stage = 0; for (int i = 0; i < external_resources.size(); i++) { - String path = external_resources[i].path; if (remaps.has(path)) { @@ -680,10 +639,8 @@ Error ResourceLoaderBinary::load() { if (external_resources[i].cache.is_null()) { if (!ResourceLoader::get_abort_on_missing_resources()) { - ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type); } else { - error = ERR_FILE_MISSING_DEPENDENCIES; ERR_FAIL_V_MSG(error, "Can't load dependency: " + path + "."); } @@ -693,10 +650,8 @@ Error ResourceLoaderBinary::load() { Error err = ResourceLoader::load_threaded_request(path, external_resources[i].type, use_sub_threads, local_path); if (err != OK) { if (!ResourceLoader::get_abort_on_missing_resources()) { - ResourceLoader::notify_dependency_error(local_path, path, external_resources[i].type); } else { - error = ERR_FILE_MISSING_DEPENDENCIES; ERR_FAIL_V_MSG(error, "Can't load dependency: " + path + "."); } @@ -707,7 +662,6 @@ Error ResourceLoaderBinary::load() { } for (int i = 0; i < internal_resources.size(); i++) { - bool main = i == (internal_resources.size() - 1); //maybe it is loaded already @@ -715,24 +669,26 @@ Error ResourceLoaderBinary::load() { int subindex = 0; if (!main) { - path = internal_resources[i].path; + if (path.begins_with("local://")) { path = path.replace_first("local://", ""); subindex = path.to_int(); path = res_path + "::" + path; } - if (ResourceCache::has(path)) { - //already loaded, don't do anything - stage++; - error = OK; - continue; + if (!use_nocache) { + if (ResourceCache::has(path)) { + //already loaded, don't do anything + stage++; + error = OK; + continue; + } } } else { - - if (!ResourceCache::has(res_path)) + if (!use_nocache && !ResourceCache::has(res_path)) { path = res_path; + } } uint64_t offset = internal_resources[i].offset; @@ -757,15 +713,20 @@ Error ResourceLoaderBinary::load() { RES res = RES(r); - r->set_path(path); + if (path != String()) { + r->set_path(path); + } r->set_subindex(subindex); + if (!main) { + internal_index_cache[path] = res; + } + int pc = f->get_32(); //set properties for (int j = 0; j < pc; j++) { - StringName name = _get_string(); if (name == StringName()) { @@ -776,8 +737,9 @@ Error ResourceLoaderBinary::load() { Variant value; error = parse_variant(value); - if (error) + if (error) { return error; + } res->set(name, value); } @@ -793,7 +755,6 @@ Error ResourceLoaderBinary::load() { resource_cache.push_back(res); if (main) { - f->close(); resource = res; resource->set_as_translation_remapped(translation_remapped); @@ -806,19 +767,16 @@ Error ResourceLoaderBinary::load() { } void ResourceLoaderBinary::set_translation_remapped(bool p_remapped) { - translation_remapped = p_remapped; } static void save_ustring(FileAccess *f, const String &p_string) { - CharString utf8 = p_string.utf8(); f->store_32(utf8.length() + 1); f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1); } static String get_ustring(FileAccess *f) { - int len = f->get_32(); Vector<char> str_buf; str_buf.resize(len); @@ -829,13 +787,13 @@ static String get_ustring(FileAccess *f) { } String ResourceLoaderBinary::get_unicode_string() { - int len = f->get_32(); if (len > str_buf.size()) { str_buf.resize(len); } - if (len == 0) + if (len == 0) { return String(); + } f->get_buffer((uint8_t *)&str_buf[0], len); String s; s.parse_utf8(&str_buf[0]); @@ -843,13 +801,12 @@ String ResourceLoaderBinary::get_unicode_string() { } void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) { - open(p_f); - if (error) + if (error) { return; + } for (int i = 0; i < external_resources.size(); i++) { - String dep = external_resources[i].path; if (p_add_types && external_resources[i].type != String()) { @@ -861,7 +818,6 @@ void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dep } void ResourceLoaderBinary::open(FileAccess *p_f) { - error = OK; f = p_f; @@ -906,7 +862,6 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { print_bl("format: " + itos(ver_format)); if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { - f->close(); ERR_FAIL_MSG("File format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path + "."); } @@ -916,13 +871,13 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { print_bl("type: " + type); importmd_ofs = f->get_64(); - for (int i = 0; i < 14; i++) + for (int i = 0; i < 14; i++) { f->get_32(); //skip a few reserved fields + } uint32_t string_table_size = f->get_32(); string_map.resize(string_table_size); for (uint32_t i = 0; i < string_table_size; i++) { - StringName s = get_unicode_string(); string_map.write[i] = s; } @@ -931,7 +886,6 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { uint32_t ext_resources_size = f->get_32(); for (uint32_t i = 0; i < ext_resources_size; i++) { - ExtResource er; er.type = get_unicode_string(); @@ -944,7 +898,6 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { uint32_t int_resources_size = f->get_32(); for (uint32_t i = 0; i < int_resources_size; i++) { - IntResource ir; ir.path = get_unicode_string(); ir.offset = f->get_64(); @@ -954,7 +907,6 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { print_bl("int resources: " + itos(int_resources_size)); if (f->eof_reached()) { - error = ERR_FILE_CORRUPT; f->close(); ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + "."); @@ -962,7 +914,6 @@ void ResourceLoaderBinary::open(FileAccess *p_f) { } String ResourceLoaderBinary::recognize(FileAccess *p_f) { - error = OK; f = p_f; @@ -996,7 +947,6 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) { uint32_t ver_format = f->get_32(); if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { - f->close(); return ""; } @@ -1006,27 +956,16 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) { return type; } -ResourceLoaderBinary::ResourceLoaderBinary() : - translation_remapped(false), - ver_format(0), - f(nullptr), - importmd_ofs(0), - error(OK) { - - progress = nullptr; - use_sub_threads = false; -} - ResourceLoaderBinary::~ResourceLoaderBinary() { - - if (f) + if (f) { memdelete(f); + } } -RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - - if (r_error) +RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_FILE_CANT_OPEN; + } Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -1034,6 +973,7 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'."); ResourceLoaderBinary loader; + loader.use_nocache = p_no_cache; loader.use_sub_threads = p_use_sub_threads; loader.progress = r_progress; String path = p_original_path != "" ? p_original_path : p_path; @@ -1055,7 +995,6 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi } void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { - if (p_type == "") { get_recognized_extensions(p_extensions); return; @@ -1071,8 +1010,8 @@ void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String p_extensions->push_back(ext); } } -void ResourceFormatLoaderBinary::get_recognized_extensions(List<String> *p_extensions) const { +void ResourceFormatLoaderBinary::get_recognized_extensions(List<String> *p_extensions) const { List<String> extensions; ClassDB::get_resource_base_extensions(&extensions); extensions.sort(); @@ -1084,12 +1023,10 @@ void ResourceFormatLoaderBinary::get_recognized_extensions(List<String> *p_exten } bool ResourceFormatLoaderBinary::handles_type(const String &p_type) const { - return true; //handles all } void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_path + "'."); @@ -1101,7 +1038,6 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str } Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { - //Error error=OK; FileAccess *f = FileAccess::open(p_path, FileAccess::READ); @@ -1167,7 +1103,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons uint32_t ver_format = f->get_32(); if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) { - memdelete(f); memdelete(fw); DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -1199,7 +1134,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons } if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { - memdelete(f); memdelete(fw); ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "File format '" + itos(FORMAT_VERSION) + "." + itos(ver_major) + "." + itos(ver_minor) + "' is too new! Please upgrade to a new engine version: " + local_path + "."); @@ -1228,7 +1162,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons fw->store_32(string_table_size); for (uint32_t i = 0; i < string_table_size; i++) { - String s = get_ustring(f); save_ustring(fw, s); } @@ -1237,7 +1170,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons uint32_t ext_resources_size = f->get_32(); fw->store_32(ext_resources_size); for (uint32_t i = 0; i < ext_resources_size; i++) { - String type = get_ustring(f); String path = get_ustring(f); @@ -1268,7 +1200,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons fw->store_32(int_resources_size); for (uint32_t i = 0; i < int_resources_size; i++) { - String path = get_ustring(f); uint64_t offset = f->get_64(); save_ustring(fw, path); @@ -1302,7 +1233,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons } String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const { - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); if (!f) { return ""; //could not rwead @@ -1321,36 +1251,30 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const /////////////////////////////////////////////////////////// void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) { - int extra = 4 - (p_bytes % 4); if (extra < 4) { - for (int i = 0; i < extra; i++) + for (int i = 0; i < extra; i++) { f->store_8(0); //pad to 32 + } } } void ResourceFormatSaverBinaryInstance::_write_variant(const Variant &p_property, const PropertyInfo &p_hint) { - write_variant(f, p_property, resource_set, external_resources, string_map, p_hint); } void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) { - switch (p_property.get_type()) { - case Variant::NIL: { - f->store_32(VARIANT_NIL); // don't store anything } break; case Variant::BOOL: { - f->store_32(VARIANT_BOOL); bool val = p_property; f->store_32(val); } break; case Variant::INT: { - int64_t val = p_property; if (val > 0x7FFFFFFF || val < -(int64_t)0x80000000) { f->store_32(VARIANT_INT64); @@ -1363,28 +1287,24 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::FLOAT: { - double d = p_property; float fl = d; if (double(fl) != d) { f->store_32(VARIANT_DOUBLE); f->store_double(d); } else { - f->store_32(VARIANT_FLOAT); f->store_real(fl); } } break; case Variant::STRING: { - f->store_32(VARIANT_STRING); String val = p_property; save_unicode_string(f, val); } break; case Variant::VECTOR2: { - f->store_32(VARIANT_VECTOR2); Vector2 val = p_property; f->store_real(val.x); @@ -1392,7 +1312,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::VECTOR2I: { - f->store_32(VARIANT_VECTOR2I); Vector2i val = p_property; f->store_32(val.x); @@ -1400,7 +1319,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::RECT2: { - f->store_32(VARIANT_RECT2); Rect2 val = p_property; f->store_real(val.position.x); @@ -1410,7 +1328,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::RECT2I: { - f->store_32(VARIANT_RECT2I); Rect2i val = p_property; f->store_32(val.position.x); @@ -1420,7 +1337,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::VECTOR3: { - f->store_32(VARIANT_VECTOR3); Vector3 val = p_property; f->store_real(val.x); @@ -1429,7 +1345,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::VECTOR3I: { - f->store_32(VARIANT_VECTOR3I); Vector3i val = p_property; f->store_32(val.x); @@ -1438,7 +1353,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PLANE: { - f->store_32(VARIANT_PLANE); Plane val = p_property; f->store_real(val.normal.x); @@ -1448,7 +1362,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::QUAT: { - f->store_32(VARIANT_QUAT); Quat val = p_property; f->store_real(val.x); @@ -1458,7 +1371,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::AABB: { - f->store_32(VARIANT_AABB); AABB val = p_property; f->store_real(val.position.x); @@ -1470,7 +1382,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::TRANSFORM2D: { - f->store_32(VARIANT_MATRIX32); Transform2D val = p_property; f->store_real(val.elements[0].x); @@ -1482,7 +1393,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::BASIS: { - f->store_32(VARIANT_MATRIX3); Basis val = p_property; f->store_real(val.elements[0].x); @@ -1497,7 +1407,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::TRANSFORM: { - f->store_32(VARIANT_TRANSFORM); Transform val = p_property; f->store_real(val.basis.elements[0].x); @@ -1515,7 +1424,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::COLOR: { - f->store_32(VARIANT_COLOR); Color val = p_property; f->store_real(val.r); @@ -1525,7 +1433,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::STRING_NAME: { - f->store_32(VARIANT_STRING_NAME); String val = p_property; save_unicode_string(f, val); @@ -1537,8 +1444,9 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia NodePath np = p_property; f->store_16(np.get_name_count()); uint16_t snc = np.get_subname_count(); - if (np.is_absolute()) + if (np.is_absolute()) { snc |= 0x8000; + } f->store_16(snc); for (int i = 0; i < np.get_name_count(); i++) { if (string_map.has(np.get_name(i))) { @@ -1557,14 +1465,12 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::_RID: { - f->store_32(VARIANT_RID); WARN_PRINT("Can't save RIDs."); RID val = p_property; f->store_32(val.get_id()); } break; case Variant::OBJECT: { - f->store_32(VARIANT_OBJECT); RES res = p_property; if (res.is_null()) { @@ -1576,7 +1482,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX); f->store_32(external_resources[res]); } else { - if (!resource_set.has(res)) { f->store_32(OBJECT_EMPTY); ERR_FAIL_MSG("Resource was not pre cached for the resource section, most likely due to circular reference."); @@ -1589,18 +1494,15 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::CALLABLE: { - f->store_32(VARIANT_CALLABLE); WARN_PRINT("Can't save Callables."); } break; case Variant::SIGNAL: { - f->store_32(VARIANT_SIGNAL); WARN_PRINT("Can't save Signals."); } break; case Variant::DICTIONARY: { - f->store_32(VARIANT_DICTIONARY); Dictionary d = p_property; f->store_32(uint32_t(d.size())); @@ -1609,7 +1511,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - /* if (!_check_type(dict[E->get()])) continue; @@ -1621,18 +1522,15 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::ARRAY: { - f->store_32(VARIANT_ARRAY); Array a = p_property; f->store_32(uint32_t(a.size())); for (int i = 0; i < a.size(); i++) { - write_variant(f, a[i], resource_set, external_resources, string_map); } } break; case Variant::PACKED_BYTE_ARRAY: { - f->store_32(VARIANT_RAW_ARRAY); Vector<uint8_t> arr = p_property; int len = arr.size(); @@ -1643,29 +1541,28 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PACKED_INT32_ARRAY: { - f->store_32(VARIANT_INT32_ARRAY); Vector<int32_t> arr = p_property; int len = arr.size(); f->store_32(len); const int32_t *r = arr.ptr(); - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { f->store_32(r[i]); + } } break; case Variant::PACKED_INT64_ARRAY: { - f->store_32(VARIANT_INT64_ARRAY); Vector<int64_t> arr = p_property; int len = arr.size(); f->store_32(len); const int64_t *r = arr.ptr(); - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { f->store_64(r[i]); + } } break; case Variant::PACKED_FLOAT32_ARRAY: { - f->store_32(VARIANT_FLOAT32_ARRAY); Vector<float> arr = p_property; int len = arr.size(); @@ -1677,7 +1574,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PACKED_FLOAT64_ARRAY: { - f->store_32(VARIANT_FLOAT64_ARRAY); Vector<double> arr = p_property; int len = arr.size(); @@ -1689,7 +1585,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PACKED_STRING_ARRAY: { - f->store_32(VARIANT_STRING_ARRAY); Vector<String> arr = p_property; int len = arr.size(); @@ -1701,7 +1596,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PACKED_VECTOR3_ARRAY: { - f->store_32(VARIANT_VECTOR3_ARRAY); Vector<Vector3> arr = p_property; int len = arr.size(); @@ -1715,7 +1609,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PACKED_VECTOR2_ARRAY: { - f->store_32(VARIANT_VECTOR2_ARRAY); Vector<Vector2> arr = p_property; int len = arr.size(); @@ -1728,7 +1621,6 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; case Variant::PACKED_COLOR_ARRAY: { - f->store_32(VARIANT_COLOR_ARRAY); Vector<Color> arr = p_property; int len = arr.size(); @@ -1743,21 +1635,19 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } break; default: { - ERR_FAIL_MSG("Invalid variant."); } } } void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant, bool p_main) { - switch (p_variant.get_type()) { case Variant::OBJECT: { - RES res = p_variant; - if (res.is_null() || external_resources.has(res)) + if (res.is_null() || external_resources.has(res)) { return; + } if (!p_main && (!bundle_resources) && res->get_path().length() && res->get_path().find("::") == -1) { if (res->get_path() == path) { @@ -1769,17 +1659,16 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant return; } - if (resource_set.has(res)) + if (resource_set.has(res)) { return; + } List<PropertyInfo> property_list; res->get_property_list(&property_list); for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) { - if (E->get().usage & PROPERTY_USAGE_STORAGE) { - Variant value = res->get(E->get().name); if (E->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) { RES sres = value; @@ -1803,11 +1692,9 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant } break; case Variant::ARRAY: { - Array varray = p_variant; int len = varray.size(); for (int i = 0; i < len; i++) { - const Variant &v = varray.get(i); _find_resources(v); } @@ -1815,12 +1702,10 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant } break; case Variant::DICTIONARY: { - Dictionary d = p_variant; List<Variant> keys; d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - _find_resources(E->get()); Variant v = d[E->get()]; _find_resources(v); @@ -1829,10 +1714,12 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant case Variant::NODE_PATH: { //take the chance and save node path strings NodePath np = p_variant; - for (int i = 0; i < np.get_name_count(); i++) + for (int i = 0; i < np.get_name_count(); i++) { get_string_index(np.get_name(i)); - for (int i = 0; i < np.get_subname_count(); i++) + } + for (int i = 0; i < np.get_subname_count(); i++) { get_string_index(np.get_subname(i)); + } } break; default: { @@ -1841,7 +1728,6 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant } void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len) { - CharString utf8 = p_string.utf8(); if (p_bit_on_len) { f->store_32((utf8.length() + 1) | 0x80000000); @@ -1852,10 +1738,10 @@ void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const } int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string) { - StringName s = p_string; - if (string_map.has(s)) + if (string_map.has(s)) { return string_map[s]; + } string_map[s] = strings.size(); strings.push_back(s); @@ -1863,15 +1749,15 @@ int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string) } Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - Error err; if (p_flags & ResourceSaver::FLAG_COMPRESS) { FileAccessCompressed *fac = memnew(FileAccessCompressed); fac->configure("RSCC"); f = fac; err = fac->_open(p_path, FileAccess::WRITE); - if (err) + if (err) { memdelete(f); + } } else { f = FileAccess::open(p_path, FileAccess::WRITE, &err); @@ -1885,8 +1771,9 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p big_endian = p_flags & ResourceSaver::FLAG_SAVE_BIG_ENDIAN; takeover_paths = p_flags & ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS; - if (!p_path.begins_with("res://")) + if (!p_path.begins_with("res://")) { takeover_paths = false; + } local_path = p_path.get_base_dir(); path = ProjectSettings::get_singleton()->localize_path(p_path); @@ -1902,8 +1789,9 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p if (big_endian) { f->store_32(1); f->set_endian_swap(true); - } else + } else { f->store_32(0); + } f->store_32(0); //64 bits file, false for now f->store_32(VERSION_MAJOR); @@ -1918,15 +1806,14 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p save_unicode_string(f, p_resource->get_class()); f->store_64(0); //offset to import metadata - for (int i = 0; i < 14; i++) + for (int i = 0; i < 14; i++) { f->store_32(0); // reserved + } List<ResourceData> resources; { - for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { - ResourceData &rd = resources.push_back(ResourceData())->get(); rd.type = E->get()->get_class(); @@ -1934,9 +1821,9 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p E->get()->get_property_list(&property_list); for (List<PropertyInfo>::Element *F = property_list.front(); F; F = F->next()) { - - if (skip_editor && F->get().name.begins_with("__editor")) + if (skip_editor && F->get().name.begins_with("__editor")) { continue; + } if ((F->get().usage & PROPERTY_USAGE_STORAGE)) { Property p; p.name_idx = get_string_index(F->get().name); @@ -1981,7 +1868,6 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p } for (int i = 0; i < save_order.size(); i++) { - save_unicode_string(f, save_order[i]->get_save_class()); String path = save_order[i]->get_path(); path = relative_paths ? local_path.path_to_file(path) : path; @@ -1993,10 +1879,8 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p Set<int> used_indices; for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { - RES r = E->get(); if (r->get_path() == "" || r->get_path().find("::") != -1) { - if (r->get_subindex() != 0) { if (used_indices.has(r->get_subindex())) { r->set_subindex(0); //repeated @@ -2008,7 +1892,6 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p } for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) { - RES r = E->get(); if (r->get_path() == "" || r->get_path().find("::") != -1) { if (r->get_subindex() == 0) { @@ -2039,7 +1922,6 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p //now actually save the resources for (List<ResourceData>::Element *E = resources.front(); E; E = E->next()) { - ResourceData &rd = E->get(); ofs_table.push_back(f->get_position()); @@ -2047,7 +1929,6 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p f->store_32(rd.properties.size()); for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) { - Property &p = F->get(); f->store_32(p.name_idx); _write_variant(p.value, F->get().pi); @@ -2076,28 +1957,25 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p } Error ResourceFormatSaverBinary::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - String local_path = ProjectSettings::get_singleton()->localize_path(p_path); ResourceFormatSaverBinaryInstance saver; return saver.save(local_path, p_resource, p_flags); } bool ResourceFormatSaverBinary::recognize(const RES &p_resource) const { - return true; //all recognized } void ResourceFormatSaverBinary::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - String base = p_resource->get_base_extension().to_lower(); p_extensions->push_back(base); - if (base != "res") + if (base != "res") { p_extensions->push_back("res"); + } } ResourceFormatSaverBinary *ResourceFormatSaverBinary::singleton = nullptr; ResourceFormatSaverBinary::ResourceFormatSaverBinary() { - singleton = this; } diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index da67e1e648..54cddca49e 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -36,17 +36,16 @@ #include "core/os/file_access.h" class ResourceLoaderBinary { - - bool translation_remapped; + bool translation_remapped = false; String local_path; String res_path; String type; Ref<Resource> resource; - uint32_t ver_format; + uint32_t ver_format = 0; - FileAccess *f; + FileAccess *f = nullptr; - uint64_t importmd_ofs; + uint64_t importmd_ofs = 0; Vector<char> str_buf; List<RES> resource_cache; @@ -61,8 +60,8 @@ class ResourceLoaderBinary { RES cache; }; - bool use_sub_threads; - float *progress; + bool use_sub_threads = false; + float *progress = nullptr; Vector<ExtResource> external_resources; struct IntResource { @@ -71,12 +70,15 @@ class ResourceLoaderBinary { }; Vector<IntResource> internal_resources; + Map<String, RES> internal_index_cache; String get_unicode_string(); void _advance_padding(uint32_t p_len); Map<String, String> remaps; - Error error; + Error error = OK; + + bool use_nocache = false; friend class ResourceFormatLoaderBinary; @@ -95,13 +97,13 @@ public: String recognize(FileAccess *p_f); void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types); - ResourceLoaderBinary(); + ResourceLoaderBinary() {} ~ResourceLoaderBinary(); }; class ResourceFormatLoaderBinary : public ResourceFormatLoader { public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); 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; @@ -111,7 +113,6 @@ public: }; class ResourceFormatSaverBinaryInstance { - String local_path; String path; @@ -144,7 +145,6 @@ class ResourceFormatSaverBinaryInstance { }; struct ResourceData { - String type; List<Property> properties; }; diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index ceb73cab77..9ed159bd20 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -38,7 +38,6 @@ bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceIm } 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); @@ -64,7 +63,6 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy String error_text; bool path_found = false; //first match must have priority while (true) { - assign = Variant(); next_tag.fields.clear(); next_tag.name = String(); @@ -91,7 +89,7 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy r_path_and_type.path = value; path_found = true; //first match must have priority } else if (assign == "type") { - r_path_and_type.type = value; + r_path_and_type.type = ClassDB::get_compatibility_remapped_class(value); } else if (assign == "importer") { r_path_and_type.importer = value; } else if (assign == "group_file") { @@ -117,20 +115,19 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy return OK; } -RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { PathAndType pat; Error err = _get_path_and_type(p_path, pat); if (err != OK) { - - if (r_error) + if (r_error) { *r_error = err; + } return RES(); } - RES res = ResourceLoader::_load(pat.path, p_path, pat.type, false, r_error, p_use_sub_threads, r_progress); + RES res = ResourceLoader::_load(pat.path, p_path, pat.type, p_no_cache, r_error, p_use_sub_threads, r_progress); #ifdef TOOLS_ENABLED if (res.is_valid()) { @@ -143,7 +140,6 @@ RES ResourceFormatImporter::load(const String &p_path, const String &p_original_ } void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extensions) const { - Set<String> found; for (int i = 0; i < importers.size(); i++) { @@ -159,7 +155,6 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension } void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { - if (p_type == "") { get_recognized_extensions(p_extensions); return; @@ -169,11 +164,13 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_ for (int i = 0; i < importers.size(); i++) { String res_type = importers[i]->get_resource_type(); - if (res_type == String()) + if (res_type == String()) { continue; + } - if (!ClassDB::is_parent_class(res_type, p_type)) + if (!ClassDB::is_parent_class(res_type, p_type)) { continue; + } List<String> local_exts; importers[i]->get_recognized_extensions(&local_exts); @@ -187,26 +184,21 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_ } bool ResourceFormatImporter::exists(const String &p_path) const { - return FileAccess::exists(p_path + ".import"); } bool ResourceFormatImporter::recognize_path(const String &p_path, const String &p_for_type) const { - return FileAccess::exists(p_path + ".import"); } 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); @@ -214,37 +206,35 @@ int ResourceFormatImporter::get_import_order(const String &p_path) const { importer = get_importer_by_name(pat.importer); } } else { - importer = get_importer_by_extension(p_path.get_extension().to_lower()); } - if (importer.is_valid()) + if (importer.is_valid()) { return importer->get_import_order(); + } return 0; } bool ResourceFormatImporter::handles_type(const String &p_type) const { - for (int i = 0; i < importers.size(); i++) { - String res_type = importers[i]->get_resource_type(); - if (res_type == String()) + if (res_type == String()) { continue; - if (ClassDB::is_parent_class(res_type, p_type)) + } + if (ClassDB::is_parent_class(res_type, p_type)) { return true; + } } return true; } String ResourceFormatImporter::get_internal_resource_path(const String &p_path) const { - PathAndType pat; Error err = _get_path_and_type(p_path, pat); if (err != OK) { - return String(); } @@ -252,12 +242,12 @@ String ResourceFormatImporter::get_internal_resource_path(const String &p_path) } void ResourceFormatImporter::get_internal_resource_path_list(const String &p_path, List<String> *r_paths) { - Error err; FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err); - if (!f) + if (!f) { return; + } VariantParser::StreamFile stream; stream.f = f; @@ -269,7 +259,6 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat int lines = 0; String error_text; while (true) { - assign = Variant(); next_tag.fields.clear(); next_tag.name = String(); @@ -298,7 +287,6 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat } String ResourceFormatImporter::get_import_group_file(const String &p_path) const { - bool valid = true; PathAndType pat; _get_path_and_type(p_path, pat, &valid); @@ -306,7 +294,6 @@ String ResourceFormatImporter::get_import_group_file(const String &p_path) const } bool ResourceFormatImporter::is_import_valid(const String &p_path) const { - bool valid = true; PathAndType pat; _get_path_and_type(p_path, pat, &valid); @@ -314,12 +301,10 @@ bool ResourceFormatImporter::is_import_valid(const String &p_path) const { } String ResourceFormatImporter::get_resource_type(const String &p_path) const { - PathAndType pat; Error err = _get_path_and_type(p_path, pat); if (err != OK) { - return ""; } @@ -331,7 +316,6 @@ Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) cons Error err = _get_path_and_type(p_path, pat); if (err != OK) { - return Variant(); } @@ -339,12 +323,10 @@ Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) cons } void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - PathAndType pat; Error err = _get_path_and_type(p_path, pat); if (err != OK) { - return; } @@ -352,7 +334,6 @@ void ResourceFormatImporter::get_dependencies(const String &p_path, List<String> } Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) const { - for (int i = 0; i < importers.size(); i++) { if (importers[i]->get_importer_name() == p_name) { return importers[i]; @@ -363,7 +344,6 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String } void ResourceFormatImporter::get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter>> *r_importers) { - for (int i = 0; i < importers.size(); i++) { List<String> local_exts; importers[i]->get_recognized_extensions(&local_exts); @@ -376,12 +356,10 @@ void ResourceFormatImporter::get_importers_for_extension(const String &p_extensi } Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) const { - Ref<ResourceImporter> importer; float priority = 0; for (int i = 0; i < importers.size(); i++) { - List<String> local_exts; importers[i]->get_recognized_extensions(&local_exts); for (List<String>::Element *F = local_exts.front(); F; F = F->next()) { @@ -396,12 +374,10 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St } String ResourceFormatImporter::get_import_base_path(const String &p_for_file) const { - return "res://.import/" + p_for_file.get_file() + "-" + p_for_file.md5_text(); } bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) const { - bool valid = true; PathAndType pat; _get_path_and_type(p_path, pat, &valid); @@ -422,7 +398,6 @@ bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) con } String ResourceFormatImporter::get_import_settings_hash() const { - Vector<Ref<ResourceImporter>> sorted_importers = importers; sorted_importers.sort_custom<SortImporterByName>(); diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index dbac80599a..d31a9a0194 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -36,7 +36,6 @@ class ResourceImporter; class ResourceFormatImporter : public ResourceFormatLoader { - struct PathAndType { String path; String type; @@ -58,7 +57,7 @@ class ResourceFormatImporter : public ResourceFormatLoader { public: static ResourceFormatImporter *get_singleton() { return singleton; } - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const; @@ -93,7 +92,6 @@ public: }; class ResourceImporter : public Reference { - GDCLASS(ResourceImporter, Reference); public: diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 05a41013c2..f9d2c9067c 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -33,7 +33,6 @@ #include "core/io/resource_importer.h" #include "core/os/file_access.h" #include "core/os/os.h" -#include "core/path_remap.h" #include "core/print_string.h" #include "core/project_settings.h" #include "core/translation.h" @@ -50,7 +49,6 @@ Ref<ResourceFormatLoader> ResourceLoader::loader[ResourceLoader::MAX_LOADERS]; int ResourceLoader::loader_count = 0; bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_for_type) const { - String extension = p_path.get_extension(); List<String> extensions; @@ -61,16 +59,15 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_ } for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - - if (E->get().nocasecmp_to(extension) == 0) + if (E->get().nocasecmp_to(extension) == 0) { return true; + } } return false; } bool ResourceFormatLoader::handles_type(const String &p_type) const { - if (get_script_instance() && get_script_instance()->has_method("handles_type")) { // I guess custom loaders for custom resources should use "Resource" return get_script_instance()->call("handles_type", p_type); @@ -80,7 +77,6 @@ bool ResourceFormatLoader::handles_type(const String &p_type) const { } String ResourceFormatLoader::get_resource_type(const String &p_path) const { - if (get_script_instance() && get_script_instance()->has_method("get_resource_type")) { return get_script_instance()->call("get_resource_type", p_path); } @@ -89,13 +85,12 @@ String ResourceFormatLoader::get_resource_type(const String &p_path) const { } void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const { - - if (p_type == "" || handles_type(p_type)) + if (p_type == "" || handles_type(p_type)) { get_recognized_extensions(p_extensions); + } } void ResourceLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) { - for (int i = 0; i < loader_count; i++) { loader[i]->get_recognized_extensions_for_type(p_type, p_extensions); } @@ -106,7 +101,6 @@ bool ResourceFormatLoader::exists(const String &p_path) const { } void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) const { - if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { PackedStringArray exts = get_script_instance()->call("get_recognized_extensions"); @@ -119,20 +113,19 @@ void ResourceFormatLoader::get_recognized_extensions(List<String> *p_extensions) } } -RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - +RES ResourceFormatLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { if (get_script_instance() && get_script_instance()->has_method("load")) { Variant res = get_script_instance()->call("load", p_path, p_original_path, p_use_sub_threads); if (res.get_type() == Variant::INT) { - - if (r_error) + if (r_error) { *r_error = (Error)res.operator int64_t(); + } } else { - - if (r_error) + if (r_error) { *r_error = OK; + } return res; } @@ -143,7 +136,6 @@ RES ResourceFormatLoader::load(const String &p_path, const String &p_original_pa } void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - if (get_script_instance() && get_script_instance()->has_method("get_dependencies")) { PackedStringArray deps = get_script_instance()->call("get_dependencies", p_path, p_add_types); @@ -157,9 +149,7 @@ void ResourceFormatLoader::get_dependencies(const String &p_path, List<String> * } Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { - if (get_script_instance() && get_script_instance()->has_method("rename_dependencies")) { - Dictionary deps_dict; for (Map<String, String>::Element *E = p_map.front(); E; E = E->next()) { deps_dict[E->key()] = E->value(); @@ -173,7 +163,6 @@ Error ResourceFormatLoader::rename_dependencies(const String &p_path, const Map< } void ResourceFormatLoader::_bind_methods() { - { MethodInfo info = MethodInfo(Variant::NIL, "load", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "original_path")); info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; @@ -190,17 +179,15 @@ void ResourceFormatLoader::_bind_methods() { /////////////////////////////////// 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 p_use_sub_threads, float *r_progress) { - 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, p_use_sub_threads, r_progress); + RES res = loader[i]->load(p_path, p_original_path != String() ? p_original_path : p_path, r_error, p_use_sub_threads, r_progress, p_no_cache); if (res.is_null()) { continue; } @@ -219,7 +206,6 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c } void ResourceLoader::_thread_load_function(void *p_userdata) { - ThreadLoadTask &load_task = *(ThreadLoadTask *)p_userdata; load_task.loader_id = Thread::get_caller_id(); @@ -238,7 +224,6 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { load_task.status = THREAD_LOAD_LOADED; } if (load_task.semaphore) { - if (load_task.start_next && thread_waiting_count > 0) { thread_waiting_count--; //thread loading count remains constant, this ends but another one begins @@ -259,8 +244,9 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { if (load_task.resource.is_valid()) { load_task.resource->set_path(load_task.local_path); - if (load_task.xl_remapped) + if (load_task.xl_remapped) { load_task.resource->set_as_translation_remapped(true); + } #ifdef TOOLS_ENABLED @@ -279,13 +265,14 @@ void ResourceLoader::_thread_load_function(void *p_userdata) { thread_load_mutex->unlock(); } -Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, const String &p_source_resource) { +Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, const String &p_source_resource) { String local_path; - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { local_path = "res://" + p_path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(p_path); + } thread_load_mutex->lock(); @@ -388,7 +375,6 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String & } float ResourceLoader::_dependency_get_progress(const String &p_path) { - if (thread_load_tasks.has(p_path)) { ThreadLoadTask &load_task = thread_load_tasks[p_path]; int dep_count = load_task.sub_tasks.size(); @@ -411,12 +397,12 @@ float ResourceLoader::_dependency_get_progress(const String &p_path) { } ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, float *r_progress) { - String local_path; - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { local_path = "res://" + p_path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(p_path); + } thread_load_mutex->lock(); if (!thread_load_tasks.has(local_path)) { @@ -434,13 +420,14 @@ ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const return status; } -RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { +RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { String local_path; - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { local_path = "res://" + p_path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(p_path); + } thread_load_mutex->lock(); if (!thread_load_tasks.has(local_path)) { @@ -517,18 +504,18 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) { } RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p_no_cache, Error *r_error) { - - if (r_error) + if (r_error) { *r_error = ERR_CANT_OPEN; + } String local_path; - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { local_path = "res://" + p_path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(p_path); + } if (!p_no_cache) { - thread_load_mutex->lock(); //Is it already being loaded? poll until done @@ -593,7 +580,6 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p return load_threaded_get(p_path, r_error); } else { - bool xl_remapped = false; String path = _path_remap(local_path, &xl_remapped); @@ -610,8 +596,9 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p return RES(); } - if (xl_remapped) + if (xl_remapped) { res->set_as_translation_remapped(true); + } #ifdef TOOLS_ENABLED @@ -628,15 +615,14 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, bool p } bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) { - String local_path; - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { local_path = "res://" + p_path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(p_path); + } if (ResourceCache::has(local_path)) { - return true; // If cached, it probably exists } @@ -645,20 +631,19 @@ bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) { // 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(path, p_type_hint)) { continue; } - if (loader[i]->exists(path)) + if (loader[i]->exists(path)) { return true; + } } return false; } void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front) { - ERR_FAIL_COND(p_format_loader.is_null()); ERR_FAIL_COND(loader_count >= MAX_LOADERS); @@ -674,14 +659,14 @@ void ResourceLoader::add_resource_format_loader(Ref<ResourceFormatLoader> p_form } void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader) { - ERR_FAIL_COND(p_format_loader.is_null()); // Find loader int i = 0; for (; i < loader_count; ++i) { - if (loader[i] == p_format_loader) + if (loader[i] == p_format_loader) { break; + } } ERR_FAIL_COND(i >= loader_count); // Not found @@ -695,19 +680,19 @@ void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_f } int ResourceLoader::get_import_order(const String &p_path) { - String path = _path_remap(p_path); String local_path; - if (path.is_rel_path()) + if (path.is_rel_path()) { local_path = "res://" + path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(path); + } for (int i = 0; i < loader_count; i++) { - - if (!loader[i]->recognize_path(local_path)) + if (!loader[i]->recognize_path(local_path)) { continue; + } /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; @@ -723,15 +708,16 @@ String ResourceLoader::get_import_group_file(const String &p_path) { String path = _path_remap(p_path); String local_path; - if (path.is_rel_path()) + if (path.is_rel_path()) { local_path = "res://" + path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(path); + } for (int i = 0; i < loader_count; i++) { - - if (!loader[i]->recognize_path(local_path)) + if (!loader[i]->recognize_path(local_path)) { continue; + } /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; @@ -744,19 +730,19 @@ String ResourceLoader::get_import_group_file(const String &p_path) { } bool ResourceLoader::is_import_valid(const String &p_path) { - String path = _path_remap(p_path); String local_path; - if (path.is_rel_path()) + if (path.is_rel_path()) { local_path = "res://" + path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(path); + } for (int i = 0; i < loader_count; i++) { - - if (!loader[i]->recognize_path(local_path)) + if (!loader[i]->recognize_path(local_path)) { continue; + } /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; @@ -769,19 +755,19 @@ bool ResourceLoader::is_import_valid(const String &p_path) { } bool ResourceLoader::is_imported(const String &p_path) { - String path = _path_remap(p_path); String local_path; - if (path.is_rel_path()) + if (path.is_rel_path()) { local_path = "res://" + path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(path); + } for (int i = 0; i < loader_count; i++) { - - if (!loader[i]->recognize_path(local_path)) + if (!loader[i]->recognize_path(local_path)) { continue; + } /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; @@ -794,19 +780,19 @@ bool ResourceLoader::is_imported(const String &p_path) { } void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) { - String path = _path_remap(p_path); String local_path; - if (path.is_rel_path()) + if (path.is_rel_path()) { local_path = "res://" + path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(path); + } for (int i = 0; i < loader_count; i++) { - - if (!loader[i]->recognize_path(local_path)) + if (!loader[i]->recognize_path(local_path)) { continue; + } /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; @@ -817,19 +803,19 @@ void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_depe } Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) { - String path = _path_remap(p_path); String local_path; - if (path.is_rel_path()) + if (path.is_rel_path()) { local_path = "res://" + path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(path); + } for (int i = 0; i < loader_count; i++) { - - if (!loader[i]->recognize_path(local_path)) + if (!loader[i]->recognize_path(local_path)) { continue; + } /* if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint)) continue; @@ -842,15 +828,14 @@ Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String } String ResourceLoader::get_resource_type(const String &p_path) { - String local_path; - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { local_path = "res://" + p_path; - else + } else { local_path = ProjectSettings::get_singleton()->localize_path(p_path); + } for (int i = 0; i < loader_count; i++) { - String result = loader[i]->get_resource_type(local_path); if (result != "") { return result; @@ -861,7 +846,6 @@ String ResourceLoader::get_resource_type(const String &p_path) { } String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) { - String new_path = p_path; if (translation_remaps.has(p_path)) { @@ -920,7 +904,6 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem FileAccess *f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err); if (f) { - VariantParser::StreamFile stream; stream.f = f; @@ -931,7 +914,6 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem int lines = 0; String error_text; while (true) { - assign = Variant(); next_tag.fields.clear(); next_tag.name = String(); @@ -960,9 +942,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem } String ResourceLoader::import_remap(const String &p_path) { - if (ResourceFormatImporter::get_singleton()->recognize_path(p_path)) { - return ResourceFormatImporter::get_singleton()->get_internal_resource_path(p_path); } @@ -974,7 +954,6 @@ String ResourceLoader::path_remap(const String &p_path) { } void ResourceLoader::reload_translation_remaps() { - if (ResourceCache::lock) { ResourceCache::lock->read_lock(); } @@ -999,15 +978,14 @@ void ResourceLoader::reload_translation_remaps() { } void ResourceLoader::load_translation_remaps() { - - if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) + if (!ProjectSettings::get_singleton()->has_setting("locale/translation_remaps")) { return; + } Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps"); List<Variant> keys; remaps.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - Array langs = remaps[E->get()]; Vector<String> lang_remaps; lang_remaps.resize(langs.size()); @@ -1024,9 +1002,9 @@ void ResourceLoader::clear_translation_remaps() { } void ResourceLoader::load_path_remaps() { - - if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) + if (!ProjectSettings::get_singleton()->has_setting("path_remap/remapped_paths")) { return; + } Vector<String> remaps = ProjectSettings::get_singleton()->get("path_remap/remapped_paths"); int rc = remaps.size(); @@ -1034,13 +1012,11 @@ void ResourceLoader::load_path_remaps() { const String *r = remaps.ptr(); for (int i = 0; i < rc; i += 2) { - path_remaps[r[i]] = r[i + 1]; } } void ResourceLoader::clear_path_remaps() { - path_remaps.clear(); } @@ -1060,9 +1036,9 @@ Ref<ResourceFormatLoader> ResourceLoader::_find_custom_resource_format_loader(St } bool ResourceLoader::add_custom_resource_format_loader(String script_path) { - - if (_find_custom_resource_format_loader(script_path).is_valid()) + if (_find_custom_resource_format_loader(script_path).is_valid()) { return false; + } Ref<Resource> res = ResourceLoader::load(script_path); ERR_FAIL_COND_V(res.is_null(), false); @@ -1085,10 +1061,10 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) { } void ResourceLoader::remove_custom_resource_format_loader(String script_path) { - Ref<ResourceFormatLoader> custom_loader = _find_custom_resource_format_loader(script_path); - if (custom_loader.is_valid()) + if (custom_loader.is_valid()) { remove_resource_format_loader(custom_loader); + } } void ResourceLoader::add_custom_loaders() { @@ -1100,7 +1076,6 @@ void ResourceLoader::add_custom_loaders() { ScriptServer::get_global_class_list(&global_classes); for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { - StringName class_name = E->get(); StringName base_class = ScriptServer::get_global_class_native_base(class_name); @@ -1112,7 +1087,6 @@ void ResourceLoader::add_custom_loaders() { } void ResourceLoader::remove_custom_loaders() { - Vector<Ref<ResourceFormatLoader>> custom_loaders; for (int i = 0; i < loader_count; ++i) { if (loader[i]->get_script_instance()) { @@ -1135,7 +1109,6 @@ void ResourceLoader::initialize() { } void ResourceLoader::finalize() { - memdelete(thread_load_mutex); memdelete(thread_load_semaphore); } diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index be4adf9091..9322b5273a 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -36,14 +36,13 @@ #include "core/resource.h" class ResourceFormatLoader : public Reference { - GDCLASS(ResourceFormatLoader, Reference); protected: static void _bind_methods(); public: - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual bool exists(const String &p_path) const; virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual void get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const; @@ -67,7 +66,6 @@ typedef Error (*ResourceLoaderImport)(const String &p_path); typedef void (*ResourceLoadedCallback)(RES p_resource, const String &p_path); class ResourceLoader { - enum { MAX_LOADERS = 64 }; @@ -160,7 +158,9 @@ public: static bool get_timestamp_on_load() { return timestamp_on_load; } static void notify_load_error(const String &p_err) { - if (err_notify) err_notify(err_notify_ud, p_err); + if (err_notify) { + err_notify(err_notify_ud, p_err); + } } static void set_error_notify_func(void *p_ud, ResourceLoadErrorNotify p_err_notify) { err_notify = p_err_notify; @@ -168,7 +168,9 @@ public: } static void notify_dependency_error(const String &p_path, const String &p_dependency, const String &p_type) { - if (dep_err_notify) dep_err_notify(dep_err_notify_ud, p_path, p_dependency, p_type); + if (dep_err_notify) { + dep_err_notify(dep_err_notify_ud, p_path, p_dependency, p_type); + } } static void set_dependency_error_notify_func(void *p_ud, DependencyErrorNotify p_err_notify) { dep_err_notify = p_err_notify; diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index 09128adb50..a8da215b61 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -41,7 +41,6 @@ bool ResourceSaver::timestamp_on_save = false; ResourceSavedCallback ResourceSaver::save_callback = nullptr; Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - if (get_script_instance() && get_script_instance()->has_method("save")) { return (Error)get_script_instance()->call("save", p_path, p_resource, p_flags).operator int64_t(); } @@ -50,7 +49,6 @@ Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uin } bool ResourceFormatSaver::recognize(const RES &p_resource) const { - if (get_script_instance() && get_script_instance()->has_method("recognize")) { return get_script_instance()->call("recognize", p_resource); } @@ -59,7 +57,6 @@ bool ResourceFormatSaver::recognize(const RES &p_resource) const { } void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { - if (get_script_instance() && get_script_instance()->has_method("get_recognized_extensions")) { PackedStringArray exts = get_script_instance()->call("get_recognized_extensions", p_resource); @@ -73,7 +70,6 @@ void ResourceFormatSaver::get_recognized_extensions(const RES &p_resource, List< } void ResourceFormatSaver::_bind_methods() { - { PropertyInfo arg0 = PropertyInfo(Variant::STRING, "path"); PropertyInfo arg1 = PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"); @@ -86,40 +82,40 @@ void ResourceFormatSaver::_bind_methods() { } Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { - String extension = p_path.get_extension(); Error err = ERR_FILE_UNRECOGNIZED; for (int i = 0; i < saver_count; i++) { - - if (!saver[i]->recognize(p_resource)) + if (!saver[i]->recognize(p_resource)) { continue; + } List<String> extensions; bool recognized = false; saver[i]->get_recognized_extensions(p_resource, &extensions); for (List<String>::Element *E = extensions.front(); E; E = E->next()) { - - if (E->get().nocasecmp_to(extension) == 0) + if (E->get().nocasecmp_to(extension) == 0) { recognized = true; + } } - if (!recognized) + if (!recognized) { continue; + } String old_path = p_resource->get_path(); String local_path = ProjectSettings::get_singleton()->localize_path(p_path); RES rwcopy = p_resource; - if (p_flags & FLAG_CHANGE_PATH) + if (p_flags & FLAG_CHANGE_PATH) { rwcopy->set_path(local_path); + } err = saver[i]->save(p_path, p_resource, p_flags); if (err == OK) { - #ifdef TOOLS_ENABLED ((Resource *)p_resource.ptr())->set_edited(false); @@ -130,11 +126,13 @@ Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t } #endif - if (p_flags & FLAG_CHANGE_PATH) + if (p_flags & FLAG_CHANGE_PATH) { rwcopy->set_path(old_path); + } - if (save_callback && p_path.begins_with("res://")) + if (save_callback && p_path.begins_with("res://")) { save_callback(p_resource, p_path); + } return OK; } @@ -144,20 +142,16 @@ Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t } void ResourceSaver::set_save_callback(ResourceSavedCallback p_callback) { - save_callback = p_callback; } void ResourceSaver::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) { - for (int i = 0; i < saver_count; i++) { - saver[i]->get_recognized_extensions(p_resource, p_extensions); } } void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front) { - ERR_FAIL_COND_MSG(p_format_saver.is_null(), "It's not a reference to a valid ResourceFormatSaver object."); ERR_FAIL_COND(saver_count >= MAX_SAVERS); @@ -173,14 +167,14 @@ void ResourceSaver::add_resource_format_saver(Ref<ResourceFormatSaver> p_format_ } void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver) { - ERR_FAIL_COND_MSG(p_format_saver.is_null(), "It's not a reference to a valid ResourceFormatSaver object."); // Find saver int i = 0; for (; i < saver_count; ++i) { - if (saver[i] == p_format_saver) + if (saver[i] == p_format_saver) { break; + } } ERR_FAIL_COND(i >= saver_count); // Not found @@ -203,9 +197,9 @@ Ref<ResourceFormatSaver> ResourceSaver::_find_custom_resource_format_saver(Strin } bool ResourceSaver::add_custom_resource_format_saver(String script_path) { - - if (_find_custom_resource_format_saver(script_path).is_valid()) + if (_find_custom_resource_format_saver(script_path).is_valid()) { return false; + } Ref<Resource> res = ResourceLoader::load(script_path); ERR_FAIL_COND_V(res.is_null(), false); @@ -228,10 +222,10 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) { } void ResourceSaver::remove_custom_resource_format_saver(String script_path) { - Ref<ResourceFormatSaver> custom_saver = _find_custom_resource_format_saver(script_path); - if (custom_saver.is_valid()) + if (custom_saver.is_valid()) { remove_resource_format_saver(custom_saver); + } } void ResourceSaver::add_custom_savers() { @@ -243,7 +237,6 @@ void ResourceSaver::add_custom_savers() { ScriptServer::get_global_class_list(&global_classes); for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) { - StringName class_name = E->get(); StringName base_class = ScriptServer::get_global_class_native_base(class_name); @@ -255,7 +248,6 @@ void ResourceSaver::add_custom_savers() { } void ResourceSaver::remove_custom_savers() { - Vector<Ref<ResourceFormatSaver>> custom_savers; for (int i = 0; i < saver_count; ++i) { if (saver[i]->get_script_instance()) { diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 2ddebf0581..8b4cdd86f8 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -50,7 +50,6 @@ public: typedef void (*ResourceSavedCallback)(Ref<Resource> p_resource, const String &p_path); class ResourceSaver { - enum { MAX_SAVERS = 64 }; diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index b28b17aa95..403f61bb24 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -33,16 +33,15 @@ #include "core/io/marshalls.h" Error StreamPeer::_put_data(const Vector<uint8_t> &p_data) { - int len = p_data.size(); - if (len == 0) + if (len == 0) { return OK; + } const uint8_t *r = p_data.ptr(); return put_data(&r[0], len); } Array StreamPeer::_put_partial_data(const Vector<uint8_t> &p_data) { - Array ret; int len = p_data.size(); @@ -65,13 +64,11 @@ Array StreamPeer::_put_partial_data(const Vector<uint8_t> &p_data) { } Array StreamPeer::_get_data(int p_bytes) { - Array ret; Vector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { - ret.push_back(ERR_OUT_OF_MEMORY); ret.push_back(Vector<uint8_t>()); return ret; @@ -86,13 +83,11 @@ Array StreamPeer::_get_data(int p_bytes) { } Array StreamPeer::_get_partial_data(int p_bytes) { - Array ret; Vector<uint8_t> data; data.resize(p_bytes); if (data.size() != p_bytes) { - ret.push_back(ERR_OUT_OF_MEMORY); ret.push_back(Vector<uint8_t>()); return ret; @@ -105,7 +100,6 @@ Array StreamPeer::_get_partial_data(int p_bytes) { if (err != OK) { data.resize(0); } else if (received != data.size()) { - data.resize(received); } @@ -115,12 +109,10 @@ Array StreamPeer::_get_partial_data(int p_bytes) { } void StreamPeer::set_big_endian(bool p_enable) { - big_endian = p_enable; } bool StreamPeer::is_big_endian_enabled() const { - return big_endian; } @@ -129,11 +121,10 @@ void StreamPeer::put_u8(uint8_t p_val) { } void StreamPeer::put_8(int8_t p_val) { - put_data((const uint8_t *)&p_val, 1); } -void StreamPeer::put_u16(uint16_t p_val) { +void StreamPeer::put_u16(uint16_t p_val) { if (big_endian) { p_val = BSWAP16(p_val); } @@ -141,8 +132,8 @@ void StreamPeer::put_u16(uint16_t p_val) { encode_uint16(p_val, buf); put_data(buf, 2); } -void StreamPeer::put_16(int16_t p_val) { +void StreamPeer::put_16(int16_t p_val) { if (big_endian) { p_val = BSWAP16(p_val); } @@ -150,8 +141,8 @@ void StreamPeer::put_16(int16_t p_val) { encode_uint16(p_val, buf); put_data(buf, 2); } -void StreamPeer::put_u32(uint32_t p_val) { +void StreamPeer::put_u32(uint32_t p_val) { if (big_endian) { p_val = BSWAP32(p_val); } @@ -159,8 +150,8 @@ void StreamPeer::put_u32(uint32_t p_val) { encode_uint32(p_val, buf); put_data(buf, 4); } -void StreamPeer::put_32(int32_t p_val) { +void StreamPeer::put_32(int32_t p_val) { if (big_endian) { p_val = BSWAP32(p_val); } @@ -168,8 +159,8 @@ void StreamPeer::put_32(int32_t p_val) { encode_uint32(p_val, buf); put_data(buf, 4); } -void StreamPeer::put_u64(uint64_t p_val) { +void StreamPeer::put_u64(uint64_t p_val) { if (big_endian) { p_val = BSWAP64(p_val); } @@ -177,8 +168,8 @@ void StreamPeer::put_u64(uint64_t p_val) { encode_uint64(p_val, buf); put_data(buf, 8); } -void StreamPeer::put_64(int64_t p_val) { +void StreamPeer::put_64(int64_t p_val) { if (big_endian) { p_val = BSWAP64(p_val); } @@ -186,8 +177,8 @@ void StreamPeer::put_64(int64_t p_val) { encode_uint64(p_val, buf); put_data(buf, 8); } -void StreamPeer::put_float(float p_val) { +void StreamPeer::put_float(float p_val) { uint8_t buf[4]; encode_float(p_val, buf); @@ -198,8 +189,8 @@ void StreamPeer::put_float(float p_val) { put_data(buf, 4); } -void StreamPeer::put_double(double p_val) { +void StreamPeer::put_double(double p_val) { uint8_t buf[8]; encode_double(p_val, buf); if (big_endian) { @@ -208,20 +199,20 @@ void StreamPeer::put_double(double p_val) { } put_data(buf, 8); } -void StreamPeer::put_string(const String &p_string) { +void StreamPeer::put_string(const String &p_string) { CharString cs = p_string.ascii(); put_u32(cs.length()); put_data((const uint8_t *)cs.get_data(), cs.length()); } -void StreamPeer::put_utf8_string(const String &p_string) { +void StreamPeer::put_utf8_string(const String &p_string) { CharString cs = p_string.utf8(); put_u32(cs.length()); put_data((const uint8_t *)cs.get_data(), cs.length()); } -void StreamPeer::put_var(const Variant &p_variant, bool p_full_objects) { +void StreamPeer::put_var(const Variant &p_variant, bool p_full_objects) { int len = 0; Vector<uint8_t> buf; encode_variant(p_variant, nullptr, len, p_full_objects); @@ -232,19 +223,18 @@ void StreamPeer::put_var(const Variant &p_variant, bool p_full_objects) { } uint8_t StreamPeer::get_u8() { - uint8_t buf[1]; get_data(buf, 1); return buf[0]; } -int8_t StreamPeer::get_8() { +int8_t StreamPeer::get_8() { uint8_t buf[1]; get_data(buf, 1); return buf[0]; } -uint16_t StreamPeer::get_u16() { +uint16_t StreamPeer::get_u16() { uint8_t buf[2]; get_data(buf, 2); uint16_t r = decode_uint16(buf); @@ -253,8 +243,8 @@ uint16_t StreamPeer::get_u16() { } return r; } -int16_t StreamPeer::get_16() { +int16_t StreamPeer::get_16() { uint8_t buf[2]; get_data(buf, 2); uint16_t r = decode_uint16(buf); @@ -263,8 +253,8 @@ int16_t StreamPeer::get_16() { } return r; } -uint32_t StreamPeer::get_u32() { +uint32_t StreamPeer::get_u32() { uint8_t buf[4]; get_data(buf, 4); uint32_t r = decode_uint32(buf); @@ -273,8 +263,8 @@ uint32_t StreamPeer::get_u32() { } return r; } -int32_t StreamPeer::get_32() { +int32_t StreamPeer::get_32() { uint8_t buf[4]; get_data(buf, 4); uint32_t r = decode_uint32(buf); @@ -283,8 +273,8 @@ int32_t StreamPeer::get_32() { } return r; } -uint64_t StreamPeer::get_u64() { +uint64_t StreamPeer::get_u64() { uint8_t buf[8]; get_data(buf, 8); uint64_t r = decode_uint64(buf); @@ -293,8 +283,8 @@ uint64_t StreamPeer::get_u64() { } return r; } -int64_t StreamPeer::get_64() { +int64_t StreamPeer::get_64() { uint8_t buf[8]; get_data(buf, 8); uint64_t r = decode_uint64(buf); @@ -303,8 +293,8 @@ int64_t StreamPeer::get_64() { } return r; } -float StreamPeer::get_float() { +float StreamPeer::get_float() { uint8_t buf[4]; get_data(buf, 4); @@ -317,7 +307,6 @@ float StreamPeer::get_float() { } double StreamPeer::get_double() { - uint8_t buf[8]; get_data(buf, 8); @@ -328,10 +317,11 @@ double StreamPeer::get_double() { return decode_double(buf); } -String StreamPeer::get_string(int p_bytes) { - if (p_bytes < 0) +String StreamPeer::get_string(int p_bytes) { + if (p_bytes < 0) { p_bytes = get_u32(); + } ERR_FAIL_COND_V(p_bytes < 0, String()); Vector<char> buf; @@ -342,10 +332,11 @@ String StreamPeer::get_string(int p_bytes) { buf.write[p_bytes] = 0; return buf.ptr(); } -String StreamPeer::get_utf8_string(int p_bytes) { - if (p_bytes < 0) +String StreamPeer::get_utf8_string(int p_bytes) { + if (p_bytes < 0) { p_bytes = get_u32(); + } ERR_FAIL_COND_V(p_bytes < 0, String()); Vector<uint8_t> buf; @@ -358,8 +349,8 @@ String StreamPeer::get_utf8_string(int p_bytes) { ret.parse_utf8((const char *)buf.ptr(), buf.size()); return ret; } -Variant StreamPeer::get_var(bool p_allow_objects) { +Variant StreamPeer::get_var(bool p_allow_objects) { int len = get_32(); Vector<uint8_t> var; Error err = var.resize(len); @@ -375,7 +366,6 @@ Variant StreamPeer::get_var(bool p_allow_objects) { } void StreamPeer::_bind_methods() { - ClassDB::bind_method(D_METHOD("put_data", "data"), &StreamPeer::_put_data); ClassDB::bind_method(D_METHOD("put_partial_data", "data"), &StreamPeer::_put_partial_data); @@ -417,10 +407,10 @@ void StreamPeer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "big_endian"), "set_big_endian", "is_big_endian_enabled"); } + //////////////////////////////// void StreamPeerBuffer::_bind_methods() { - 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_position"), &StreamPeerBuffer::get_position); @@ -434,9 +424,9 @@ void StreamPeerBuffer::_bind_methods() { } Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) { - - if (p_bytes <= 0) + if (p_bytes <= 0) { return OK; + } if (pointer + p_bytes > data.size()) { data.resize(pointer + p_bytes); @@ -450,23 +440,21 @@ Error StreamPeerBuffer::put_data(const uint8_t *p_data, int p_bytes) { } Error StreamPeerBuffer::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { - r_sent = p_bytes; return put_data(p_data, p_bytes); } Error StreamPeerBuffer::get_data(uint8_t *p_buffer, int p_bytes) { - int recv; get_partial_data(p_buffer, p_bytes, recv); - if (recv != p_bytes) + if (recv != p_bytes) { return ERR_INVALID_PARAMETER; + } return OK; } Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - if (pointer + p_bytes > data.size()) { r_received = data.size() - pointer; if (r_received <= 0) { @@ -487,57 +475,44 @@ Error StreamPeerBuffer::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_ } int StreamPeerBuffer::get_available_bytes() const { - return data.size() - pointer; } void StreamPeerBuffer::seek(int p_pos) { - ERR_FAIL_COND(p_pos < 0); ERR_FAIL_COND(p_pos > data.size()); pointer = p_pos; } -int StreamPeerBuffer::get_size() const { +int StreamPeerBuffer::get_size() const { return data.size(); } int StreamPeerBuffer::get_position() const { - return pointer; } void StreamPeerBuffer::resize(int p_size) { - data.resize(p_size); } void StreamPeerBuffer::set_data_array(const Vector<uint8_t> &p_data) { - data = p_data; pointer = 0; } Vector<uint8_t> StreamPeerBuffer::get_data_array() const { - return data; } void StreamPeerBuffer::clear() { - data.resize(0); pointer = 0; } Ref<StreamPeerBuffer> StreamPeerBuffer::duplicate() const { - Ref<StreamPeerBuffer> spb; spb.instance(); spb->data = data; return spb; } - -StreamPeerBuffer::StreamPeerBuffer() { - - pointer = 0; -} diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 9358a2c07c..ec0b989ed8 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -47,7 +47,7 @@ protected: Array _get_data(int p_bytes); Array _get_partial_data(int p_bytes); - bool big_endian; + bool big_endian = false; public: virtual Error put_data(const uint8_t *p_data, int p_bytes) = 0; ///< put a whole chunk of data, blocking until it sent @@ -89,15 +89,14 @@ public: String get_utf8_string(int p_bytes = -1); Variant get_var(bool p_allow_objects = false); - StreamPeer() { big_endian = false; } + StreamPeer() {} }; class StreamPeerBuffer : public StreamPeer { - GDCLASS(StreamPeerBuffer, StreamPeer); Vector<uint8_t> data; - int pointer; + int pointer = 0; protected: static void _bind_methods(); @@ -123,7 +122,7 @@ public: Ref<StreamPeerBuffer> duplicate() const; - StreamPeerBuffer(); + StreamPeerBuffer() {} }; #endif // STREAM_PEER_H diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp index d98935f77c..3dc31c6769 100644 --- a/core/io/stream_peer_ssl.cpp +++ b/core/io/stream_peer_ssl.cpp @@ -35,9 +35,9 @@ StreamPeerSSL *(*StreamPeerSSL::_create)() = nullptr; StreamPeerSSL *StreamPeerSSL::create() { - - if (_create) + if (_create) { return _create(); + } return nullptr; } @@ -56,7 +56,6 @@ bool StreamPeerSSL::is_blocking_handshake_enabled() const { } void StreamPeerSSL::_bind_methods() { - ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSSL::poll); ClassDB::bind_method(D_METHOD("accept_stream", "stream", "private_key", "certificate", "chain"), &StreamPeerSSL::accept_stream, DEFVAL(Ref<X509Certificate>())); ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname", "valid_certificate"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); @@ -73,7 +72,3 @@ void StreamPeerSSL::_bind_methods() { BIND_ENUM_CONSTANT(STATUS_ERROR); BIND_ENUM_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH); } - -StreamPeerSSL::StreamPeerSSL() { - blocking_handshake = true; -} diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h index de3cb09c60..81b95b856d 100644 --- a/core/io/stream_peer_ssl.h +++ b/core/io/stream_peer_ssl.h @@ -43,7 +43,7 @@ protected: static bool available; - bool blocking_handshake; + bool blocking_handshake = true; public: enum Status { @@ -68,7 +68,7 @@ public: static bool is_available(); - StreamPeerSSL(); + StreamPeerSSL() {} }; VARIANT_ENUM_CAST(StreamPeerSSL::Status); diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index f0c5816d73..cce728c30a 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -33,7 +33,6 @@ #include "core/project_settings.h" Error StreamPeerTCP::_poll_connection() { - ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED); Error err = _sock->connect_to_host(peer_host, peer_port); @@ -58,7 +57,6 @@ Error StreamPeerTCP::_poll_connection() { } void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port) { - _sock = p_sock; _sock->set_blocking_enabled(false); @@ -70,7 +68,6 @@ void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint } Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER); @@ -103,18 +100,14 @@ Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) } Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); if (status == STATUS_NONE || status == STATUS_ERROR) { - return FAILED; } if (status != STATUS_CONNECTED) { - if (_poll_connection() != OK) { - return FAILED; } @@ -124,8 +117,9 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool } } - if (!_sock->is_open()) + if (!_sock->is_open()) { return FAILED; + } Error err; int data_to_send = p_bytes; @@ -133,12 +127,10 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool int total_sent = 0; while (data_to_send) { - int sent_amount = 0; err = _sock->send(offset, data_to_send, sent_amount); if (err != OK) { - if (err != ERR_BUSY) { disconnect_from_host(); return FAILED; @@ -156,7 +148,6 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool return FAILED; } } else { - data_to_send -= sent_amount; offset += sent_amount; total_sent += sent_amount; @@ -169,16 +160,12 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool } Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) { - if (!is_connected_to_host()) { - return FAILED; } if (status == STATUS_CONNECTING) { - if (_poll_connection() != OK) { - return FAILED; } @@ -194,12 +181,10 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool r_received = 0; while (to_read) { - int read = 0; err = _sock->recv(p_buffer + total_read, to_read, read); if (err != OK) { - if (err != ERR_BUSY) { disconnect_from_host(); return FAILED; @@ -218,13 +203,11 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool } } else if (read == 0) { - disconnect_from_host(); r_received = total_read; return ERR_FILE_EOF; } else { - to_read -= read; total_read += read; @@ -241,18 +224,15 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool } void StreamPeerTCP::set_no_delay(bool p_enabled) { - ERR_FAIL_COND(!is_connected_to_host()); _sock->set_tcp_no_delay_enabled(p_enabled); } bool StreamPeerTCP::is_connected_to_host() const { - return _sock.is_valid() && _sock->is_open() && (status == STATUS_CONNECTED || status == STATUS_CONNECTING); } StreamPeerTCP::Status StreamPeerTCP::get_status() { - if (status == STATUS_CONNECTING) { _poll_connection(); } else if (status == STATUS_CONNECTED) { @@ -278,9 +258,9 @@ StreamPeerTCP::Status StreamPeerTCP::get_status() { } void StreamPeerTCP::disconnect_from_host() { - - if (_sock.is_valid() && _sock->is_open()) + if (_sock.is_valid() && _sock->is_open()) { _sock->close(); + } timeout = 0; status = STATUS_NONE; @@ -294,59 +274,51 @@ Error StreamPeerTCP::poll(NetSocket::PollType p_type, int timeout) { } Error StreamPeerTCP::put_data(const uint8_t *p_data, int p_bytes) { - int total; return write(p_data, p_bytes, total, true); } Error StreamPeerTCP::put_partial_data(const uint8_t *p_data, int p_bytes, int &r_sent) { - return write(p_data, p_bytes, r_sent, false); } Error StreamPeerTCP::get_data(uint8_t *p_buffer, int p_bytes) { - int total; return read(p_buffer, p_bytes, total, true); } Error StreamPeerTCP::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r_received) { - return read(p_buffer, p_bytes, r_received, false); } int StreamPeerTCP::get_available_bytes() const { - ERR_FAIL_COND_V(!_sock.is_valid(), -1); return _sock->get_available_bytes(); } IP_Address StreamPeerTCP::get_connected_host() const { - return peer_host; } uint16_t StreamPeerTCP::get_connected_port() const { - return peer_port; } Error StreamPeerTCP::_connect(const String &p_address, int p_port) { - IP_Address ip; if (p_address.is_valid_ip_address()) { ip = p_address; } else { ip = IP::get_singleton()->resolve_hostname(p_address); - if (!ip.is_valid()) + if (!ip.is_valid()) { return ERR_CANT_RESOLVE; + } } return connect_to_host(ip, p_port); } void StreamPeerTCP::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect); ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status); @@ -362,13 +334,9 @@ void StreamPeerTCP::_bind_methods() { } StreamPeerTCP::StreamPeerTCP() : - _sock(Ref<NetSocket>(NetSocket::create())), - timeout(0), - status(STATUS_NONE), - peer_port(0) { + _sock(Ref<NetSocket>(NetSocket::create())) { } StreamPeerTCP::~StreamPeerTCP() { - disconnect_from_host(); } diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 86df9ab8cf..ab98d494d6 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -37,7 +37,6 @@ #include "core/io/stream_peer.h" class StreamPeerTCP : public StreamPeer { - GDCLASS(StreamPeerTCP, StreamPeer); OBJ_CATEGORY("Networking"); @@ -52,10 +51,10 @@ public: protected: Ref<NetSocket> _sock; - uint64_t timeout; - Status status; + uint64_t timeout = 0; + Status status = STATUS_NONE; IP_Address peer_host; - uint16_t peer_port; + uint16_t peer_port = 0; Error _connect(const String &p_address, int p_port); Error _poll_connection(); diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index 69c2ba7943..d7061b6bf4 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -31,7 +31,6 @@ #include "tcp_server.h" void TCP_Server::_bind_methods() { - ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*")); ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available); ClassDB::bind_method(D_METHOD("is_listening"), &TCP_Server::is_listening); @@ -40,7 +39,6 @@ void TCP_Server::_bind_methods() { } Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -49,8 +47,9 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { IP::Type ip_type = IP::TYPE_ANY; // If the bind address is valid use its type as the socket type - if (p_bind_address.is_valid()) + if (p_bind_address.is_valid()) { ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + } err = _sock->open(NetSocket::TYPE_TCP, ip_type); @@ -62,7 +61,6 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) { err = _sock->bind(p_bind_address, p_port); if (err != OK) { - _sock->close(); return ERR_ALREADY_IN_USE; } @@ -83,18 +81,17 @@ bool TCP_Server::is_listening() const { } bool TCP_Server::is_connection_available() const { - ERR_FAIL_COND_V(!_sock.is_valid(), false); - if (!_sock->is_open()) + if (!_sock->is_open()) { return false; + } Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); return (err == OK); } Ref<StreamPeerTCP> TCP_Server::take_connection() { - Ref<StreamPeerTCP> conn; if (!is_connection_available()) { return conn; @@ -104,8 +101,9 @@ Ref<StreamPeerTCP> TCP_Server::take_connection() { IP_Address ip; uint16_t port = 0; ns = _sock->accept(ip, port); - if (!ns.is_valid()) + if (!ns.is_valid()) { return conn; + } conn = Ref<StreamPeerTCP>(memnew(StreamPeerTCP)); conn->accept_socket(ns, ip, port); @@ -113,7 +111,6 @@ Ref<StreamPeerTCP> TCP_Server::take_connection() { } void TCP_Server::stop() { - if (_sock.is_valid()) { _sock->close(); } @@ -124,6 +121,5 @@ TCP_Server::TCP_Server() : } TCP_Server::~TCP_Server() { - stop(); } diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index ca52b13ba1..eb715a745c 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -37,7 +37,6 @@ #include "core/io/stream_peer_tcp.h" class TCP_Server : public Reference { - GDCLASS(TCP_Server, Reference); protected: diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index 5da236d029..0e0a948953 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -34,7 +34,6 @@ #include "core/translation.h" RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { - enum Status { STATUS_NONE, @@ -48,8 +47,9 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { String msg_str; String config; - if (r_error) + if (r_error) { *r_error = ERR_FILE_CORRUPT; + } Ref<Translation> translation = Ref<Translation>(memnew(Translation)); int line = 1; @@ -58,13 +58,11 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { bool is_eof = false; while (!is_eof) { - String l = f->get_line().strip_edges(); is_eof = f->eof_reached(); // If we reached last line and it's not a content line, break, otherwise let processing that last loop if (is_eof && l.empty()) { - if (status == STATUS_READING_ID) { memdelete(f); ERR_FAIL_V_MSG(RES(), f->get_path() + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: "); @@ -74,18 +72,18 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { } if (l.begins_with("msgid")) { - if (status == STATUS_READING_ID) { - memdelete(f); ERR_FAIL_V_MSG(RES(), f->get_path() + ":" + itos(line) + " Unexpected 'msgid', was expecting 'msgstr' while parsing: "); } if (msg_id != "") { - if (!skip_this) + if (!skip_this) { translation->add_message(msg_id, msg_str); - } else if (config == "") + } + } else if (config == "") { config = msg_str; + } l = l.substr(5, l.length()).strip_edges(); status = STATUS_READING_ID; @@ -96,9 +94,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { } if (l.begins_with("msgstr")) { - if (status != STATUS_READING_ID) { - memdelete(f); ERR_FAIL_V_MSG(RES(), f->get_path() + ":" + itos(line) + " Unexpected 'msgstr', was expecting 'msgid' while parsing: "); } @@ -142,10 +138,11 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { l = l.substr(0, end_pos); l = l.c_unescape(); - if (status == STATUS_READING_ID) + if (status == STATUS_READING_ID) { msg_id += l; - else + } else { msg_str += l; + } line++; } @@ -154,23 +151,24 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { memdelete(f); if (status == STATUS_READING_STRING) { - if (msg_id != "") { - if (!skip_this) + if (!skip_this) { translation->add_message(msg_id, msg_str); - } else if (config == "") + } + } else if (config == "") { config = msg_str; + } } ERR_FAIL_COND_V_MSG(config == "", RES(), "No config found in file: " + f->get_path() + "."); Vector<String> configs = config.split("\n"); for (int i = 0; i < configs.size(); i++) { - String c = configs[i].strip_edges(); int p = c.find(":"); - if (p == -1) + if (p == -1) { continue; + } String prop = c.substr(0, p).strip_edges(); String value = c.substr(p + 1, c.length()).strip_edges(); @@ -179,16 +177,17 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { } } - if (r_error) + if (r_error) { *r_error = OK; + } return translation; } -RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) { - - if (r_error) +RES TranslationLoaderPO::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + if (r_error) { *r_error = ERR_CANT_OPEN; + } FileAccess *f = FileAccess::open(p_path, FileAccess::READ); ERR_FAIL_COND_V_MSG(!f, RES(), "Cannot open file '" + p_path + "'."); @@ -197,21 +196,17 @@ RES TranslationLoaderPO::load(const String &p_path, const String &p_original_pat } void TranslationLoaderPO::get_recognized_extensions(List<String> *p_extensions) const { - p_extensions->push_back("po"); //p_extensions->push_back("mo"); //mo in the future... } -bool TranslationLoaderPO::handles_type(const String &p_type) const { +bool TranslationLoaderPO::handles_type(const String &p_type) const { return (p_type == "Translation"); } String TranslationLoaderPO::get_resource_type(const String &p_path) const { - - if (p_path.get_extension().to_lower() == "po") + if (p_path.get_extension().to_lower() == "po") { return "Translation"; + } return ""; } - -TranslationLoaderPO::TranslationLoaderPO() { -} diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index 9d3117b630..a196a37dc0 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -38,12 +38,12 @@ class TranslationLoaderPO : public ResourceFormatLoader { public: static RES load_translation(FileAccess *f, Error *r_error = nullptr); - virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr); + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; virtual String get_resource_type(const String &p_path) const; - TranslationLoaderPO(); + TranslationLoaderPO() {} }; #endif // TRANSLATION_LOADER_PO_H diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp index 16b7863cdd..1d329daf8b 100644 --- a/core/io/udp_server.cpp +++ b/core/io/udp_server.cpp @@ -31,7 +31,6 @@ #include "udp_server.h" void UDPServer::_bind_methods() { - ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &UDPServer::listen, DEFVAL("*")); ClassDB::bind_method(D_METHOD("is_connection_available"), &UDPServer::is_connection_available); ClassDB::bind_method(D_METHOD("is_listening"), &UDPServer::is_listening); @@ -40,7 +39,6 @@ void UDPServer::_bind_methods() { } Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) { - ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER); @@ -48,13 +46,15 @@ Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) { Error err; IP::Type ip_type = IP::TYPE_ANY; - if (p_bind_address.is_valid()) + if (p_bind_address.is_valid()) { ip_type = p_bind_address.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6; + } err = _sock->open(NetSocket::TYPE_UDP, ip_type); - if (err != OK) + if (err != OK) { return ERR_CANT_CREATE; + } _sock->set_blocking_enabled(false); _sock->set_reuse_address_enabled(true); @@ -76,18 +76,17 @@ bool UDPServer::is_listening() const { } bool UDPServer::is_connection_available() const { - ERR_FAIL_COND_V(!_sock.is_valid(), false); - if (!_sock->is_open()) + if (!_sock->is_open()) { return false; + } Error err = _sock->poll(NetSocket::POLL_TYPE_IN, 0); return (err == OK); } Ref<PacketPeerUDP> UDPServer::take_connection() { - Ref<PacketPeerUDP> conn; if (!is_connection_available()) { return conn; @@ -101,7 +100,6 @@ Ref<PacketPeerUDP> UDPServer::take_connection() { } void UDPServer::stop() { - if (_sock.is_valid()) { _sock->close(); } @@ -114,6 +112,5 @@ UDPServer::UDPServer() : } UDPServer::~UDPServer() { - stop(); } diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index 9613ad3f10..b11267b60f 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -38,9 +38,11 @@ VARIANT_ENUM_CAST(XMLParser::NodeType); static bool _equalsn(const CharType *str1, const CharType *str2, int len) { int i; - for (i = 0; i < len && str1[i] && str2[i]; ++i) - if (str1[i] != str2[i]) + for (i = 0; i < len && str1[i] && str2[i]; ++i) { + if (str1[i] != str2[i]) { return false; + } + } // if one (or both) of the strings was smaller then they // are only equal if they have the same length @@ -48,12 +50,12 @@ static bool _equalsn(const CharType *str1, const CharType *str2, int len) { } String XMLParser::_replace_special_characters(const String &origstr) { - int pos = origstr.find("&"); int oldPos = 0; - if (pos == -1) + if (pos == -1) { return origstr; + } String newstr; @@ -84,8 +86,9 @@ String XMLParser::_replace_special_characters(const String &origstr) { pos = origstr.find("&", pos); } - if (oldPos < origstr.length() - 1) + if (oldPos < origstr.length() - 1) { newstr += (origstr.substr(oldPos, origstr.length() - oldPos)); + } return newstr; } @@ -100,12 +103,15 @@ bool XMLParser::_set_text(char *start, char *end) { // only white space, so that this text won't be reported if (end - start < 3) { char *p = start; - for (; p != end; ++p) - if (!_is_white_space(*p)) + for (; p != end; ++p) { + if (!_is_white_space(*p)) { break; + } + } - if (p == end) + if (p == end) { return false; + } } // set current text to the parsed text, and replace xml special characters @@ -126,8 +132,9 @@ void XMLParser::_parse_closing_xml_element() { ++P; const char *pBeginClose = P; - while (*P != '>') + while (*P != '>') { ++P; + } node_name = String::utf8(pBeginClose, (int)(P - pBeginClose)); #ifdef DEBUG_XML @@ -141,16 +148,17 @@ void XMLParser::_ignore_definition() { char *F = P; // move until end marked with '>' reached - while (*P != '>') + while (*P != '>') { ++P; + } node_name.parse_utf8(F, P - F); ++P; } bool XMLParser::_parse_cdata() { - - if (*(P + 1) != '[') + if (*(P + 1) != '[') { return false; + } node_type = NODE_CDATA; @@ -161,8 +169,9 @@ bool XMLParser::_parse_cdata() { ++count; } - if (!*P) + if (!*P) { return true; + } char *cDataBegin = P; char *cDataEnd = nullptr; @@ -178,10 +187,11 @@ bool XMLParser::_parse_cdata() { ++P; } - if (cDataEnd) + if (cDataEnd) { node_name = String::utf8(cDataBegin, (int)(cDataEnd - cDataBegin)); - else + } else { node_name = ""; + } #ifdef DEBUG_XML print_line("XML CDATA: " + node_name); #endif @@ -190,7 +200,6 @@ bool XMLParser::_parse_cdata() { } void XMLParser::_parse_comment() { - node_type = NODE_COMMENT; P += 1; @@ -200,10 +209,11 @@ void XMLParser::_parse_comment() { // move until end of comment reached while (count) { - if (*P == '>') + if (*P == '>') { --count; - else if (*P == '<') + } else if (*P == '<') { ++count; + } ++P; } @@ -217,7 +227,6 @@ void XMLParser::_parse_comment() { } void XMLParser::_parse_opening_xml_element() { - node_type = NODE_ELEMENT; node_empty = false; attributes.clear(); @@ -226,46 +235,52 @@ void XMLParser::_parse_opening_xml_element() { const char *startName = P; // find end of element - while (*P != '>' && !_is_white_space(*P)) + while (*P != '>' && !_is_white_space(*P)) { ++P; + } const char *endName = P; // find attributes while (*P != '>') { - if (_is_white_space(*P)) + if (_is_white_space(*P)) { ++P; - else { + } else { if (*P != '/') { // we've got an attribute // read the attribute names const char *attributeNameBegin = P; - while (!_is_white_space(*P) && *P != '=') + while (!_is_white_space(*P) && *P != '=') { ++P; + } const char *attributeNameEnd = P; ++P; // read the attribute value // check for quotes and single quotes, thx to murphy - while ((*P != '\"') && (*P != '\'') && *P) + while ((*P != '\"') && (*P != '\'') && *P) { ++P; + } - if (!*P) // malformatted xml file + if (!*P) { // malformatted xml file return; + } const char attributeQuoteChar = *P; ++P; const char *attributeValueBegin = P; - while (*P != attributeQuoteChar && *P) + while (*P != attributeQuoteChar && *P) { ++P; + } - if (!*P) // malformatted xml file + if (!*P) { // malformatted xml file return; + } const char *attributeValueEnd = P; ++P; @@ -304,21 +319,23 @@ void XMLParser::_parse_opening_xml_element() { } void XMLParser::_parse_current_node() { - char *start = P; node_offset = P - data; // more forward until '<' found - while (*P != '<' && *P) + while (*P != '<' && *P) { ++P; + } - if (!*P) + if (!*P) { return; + } if (P - start > 0) { // we found some text, store it - if (_set_text(start, P)) + if (_set_text(start, P)) { return; + } } ++P; @@ -332,8 +349,9 @@ void XMLParser::_parse_current_node() { _ignore_definition(); break; case '!': - if (!_parse_cdata()) + if (!_parse_cdata()) { _parse_comment(); + } break; default: _parse_opening_xml_element(); @@ -342,22 +360,19 @@ void XMLParser::_parse_current_node() { } uint64_t XMLParser::get_node_offset() const { - return node_offset; -}; +} Error XMLParser::seek(uint64_t p_pos) { - ERR_FAIL_COND_V(!data, ERR_FILE_EOF); ERR_FAIL_COND_V(p_pos >= length, ERR_FILE_EOF); P = data + p_pos; return read(); -}; +} void XMLParser::_bind_methods() { - ClassDB::bind_method(D_METHOD("read"), &XMLParser::read); ClassDB::bind_method(D_METHOD("get_node_type"), &XMLParser::get_node_type); ClassDB::bind_method(D_METHOD("get_node_name"), &XMLParser::get_node_name); @@ -383,10 +398,9 @@ void XMLParser::_bind_methods() { BIND_ENUM_CONSTANT(NODE_COMMENT); BIND_ENUM_CONSTANT(NODE_CDATA); BIND_ENUM_CONSTANT(NODE_UNKNOWN); -}; +} Error XMLParser::read() { - // if not end reached, parse the node if (P && (P - data) < (int64_t)length - 1 && *P != 0) { _parse_current_node(); @@ -397,11 +411,10 @@ Error XMLParser::read() { } XMLParser::NodeType XMLParser::get_node_type() { - return node_type; } -String XMLParser::get_node_data() const { +String XMLParser::get_node_data() const { ERR_FAIL_COND_V(node_type != NODE_TEXT, ""); return node_name; } @@ -410,31 +423,32 @@ String XMLParser::get_node_name() const { ERR_FAIL_COND_V(node_type == NODE_TEXT, ""); return node_name; } -int XMLParser::get_attribute_count() const { +int XMLParser::get_attribute_count() const { return attributes.size(); } -String XMLParser::get_attribute_name(int p_idx) const { +String XMLParser::get_attribute_name(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, attributes.size(), ""); return attributes[p_idx].name; } -String XMLParser::get_attribute_value(int p_idx) const { +String XMLParser::get_attribute_value(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, attributes.size(), ""); return attributes[p_idx].value; } -bool XMLParser::has_attribute(const String &p_name) const { +bool XMLParser::has_attribute(const String &p_name) const { for (int i = 0; i < attributes.size(); i++) { - if (attributes[i].name == p_name) + if (attributes[i].name == p_name) { return true; + } } return false; } -String XMLParser::get_attribute_value(const String &p_name) const { +String XMLParser::get_attribute_value(const String &p_name) const { int idx = -1; for (int i = 0; i < attributes.size(); i++) { if (attributes[i].name == p_name) { @@ -449,7 +463,6 @@ String XMLParser::get_attribute_value(const String &p_name) const { } String XMLParser::get_attribute_value_safe(const String &p_name) const { - int idx = -1; for (int i = 0; i < attributes.size(); i++) { if (attributes[i].name == p_name) { @@ -458,17 +471,17 @@ String XMLParser::get_attribute_value_safe(const String &p_name) const { } } - if (idx < 0) + if (idx < 0) { return ""; + } return attributes[idx].value; } -bool XMLParser::is_empty() const { +bool XMLParser::is_empty() const { return node_empty; } Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) { - ERR_FAIL_COND_V(p_buffer.size() == 0, ERR_INVALID_DATA); if (data) { @@ -484,7 +497,6 @@ Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) { } Error XMLParser::open(const String &p_path) { - Error err; FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err); @@ -508,10 +520,10 @@ Error XMLParser::open(const String &p_path) { } void XMLParser::skip_section() { - // skip if this element is empty anyway. - if (is_empty()) + if (is_empty()) { return; + } // read until we've reached the last element in this section int tagcount = 1; @@ -520,15 +532,16 @@ void XMLParser::skip_section() { if (get_node_type() == XMLParser::NODE_ELEMENT && !is_empty()) { ++tagcount; - } else if (get_node_type() == XMLParser::NODE_ELEMENT_END) + } else if (get_node_type() == XMLParser::NODE_ELEMENT_END) { --tagcount; + } } } void XMLParser::close() { - - if (data) + if (data) { memdelete_arr(data); + } data = nullptr; length = 0; P = nullptr; @@ -538,22 +551,19 @@ void XMLParser::close() { } int XMLParser::get_current_line() const { - return 0; } XMLParser::XMLParser() { - - data = nullptr; - close(); special_characters.push_back("&"); special_characters.push_back("<lt;"); special_characters.push_back(">gt;"); special_characters.push_back("\"quot;"); special_characters.push_back("'apos;"); } -XMLParser::~XMLParser() { - if (data) +XMLParser::~XMLParser() { + if (data) { memdelete_arr(data); + } } diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h index 26c3e6802f..ee2174d52c 100644 --- a/core/io/xml_parser.h +++ b/core/io/xml_parser.h @@ -41,7 +41,6 @@ */ class XMLParser : public Reference { - GDCLASS(XMLParser, Reference); public: @@ -66,15 +65,15 @@ public: }; private: - char *data; - char *P; - uint64_t length; + char *data = nullptr; + char *P = nullptr; + uint64_t length = 0; void unescape(String &p_str); Vector<String> special_characters; String node_name; - bool node_empty; - NodeType node_type; - uint64_t node_offset; + bool node_empty = false; + NodeType node_type = NODE_NONE; + uint64_t node_offset = 0; struct Attribute { String name; diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index 3a2a207d22..b8e7fd34d0 100644 --- a/core/io/zip_io.cpp +++ b/core/io/zip_io.cpp @@ -33,7 +33,6 @@ #include "core/os/copymem.h" void *zipio_open(void *data, const char *p_fname, int mode) { - FileAccess *&f = *(FileAccess **)data; String fname; @@ -42,42 +41,37 @@ void *zipio_open(void *data, const char *p_fname, int mode) { if (mode & ZLIB_FILEFUNC_MODE_WRITE) { f = FileAccess::open(fname, FileAccess::WRITE); } else { - f = FileAccess::open(fname, FileAccess::READ); } - if (!f) + if (!f) { return nullptr; + } return data; } uLong zipio_read(void *data, void *fdata, void *buf, uLong size) { - FileAccess *f = *(FileAccess **)data; return f->get_buffer((uint8_t *)buf, size); } uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) { - FileAccess *f = *(FileAccess **)opaque; f->store_buffer((uint8_t *)buf, size); return size; } long zipio_tell(voidpf opaque, voidpf stream) { - FileAccess *f = *(FileAccess **)opaque; return f->get_position(); } long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { - FileAccess *f = *(FileAccess **)opaque; int pos = offset; switch (origin) { - case ZLIB_FILEFUNC_SEEK_CUR: pos = f->get_position() + offset; break; @@ -86,14 +80,13 @@ long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) { break; default: break; - }; + } f->seek(pos); return 0; } int zipio_close(voidpf opaque, voidpf stream) { - FileAccess *&f = *(FileAccess **)opaque; if (f) { f->close(); @@ -104,25 +97,21 @@ int zipio_close(voidpf opaque, voidpf stream) { } int zipio_testerror(voidpf opaque, voidpf stream) { - FileAccess *f = *(FileAccess **)opaque; return (f && f->get_error() != OK) ? 1 : 0; } voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) { - voidpf ptr = memalloc(items * size); zeromem(ptr, items * size); return ptr; } void zipio_free(voidpf opaque, voidpf address) { - memfree(address); } zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) { - zlib_filefunc_def io; io.opaque = p_file; io.zopen_file = zipio_open; diff --git a/core/list.h b/core/list.h index be2dccd876..6052a619fb 100644 --- a/core/list.h +++ b/core/list.h @@ -49,127 +49,117 @@ class List { public: class Element { - private: friend class List<T, A>; T value; - Element *next_ptr; - Element *prev_ptr; - _Data *data; + Element *next_ptr = nullptr; + Element *prev_ptr = nullptr; + _Data *data = nullptr; public: /** * Get NEXT Element iterator, for constant lists. */ _FORCE_INLINE_ const Element *next() const { - return next_ptr; - }; + } /** * Get NEXT Element iterator, */ _FORCE_INLINE_ Element *next() { - return next_ptr; - }; + } /** * Get PREV Element iterator, for constant lists. */ _FORCE_INLINE_ const Element *prev() const { - return prev_ptr; - }; + } /** * Get PREV Element iterator, */ _FORCE_INLINE_ Element *prev() { - return prev_ptr; - }; + } /** * * operator, for using as *iterator, when iterators are defined on stack. */ _FORCE_INLINE_ const T &operator*() const { return value; - }; + } /** * operator->, for using as iterator->, when iterators are defined on stack, for constant lists. */ _FORCE_INLINE_ const T *operator->() const { - return &value; - }; + } /** * * operator, for using as *iterator, when iterators are defined on stack, */ _FORCE_INLINE_ T &operator*() { return value; - }; + } /** * operator->, for using as iterator->, when iterators are defined on stack, for constant lists. */ _FORCE_INLINE_ T *operator->() { return &value; - }; + } /** * get the value stored in this element. */ _FORCE_INLINE_ T &get() { return value; - }; + } /** * get the value stored in this element, for constant lists */ _FORCE_INLINE_ const T &get() const { return value; - }; + } /** * set the value stored in this element. */ _FORCE_INLINE_ void set(const T &p_value) { value = (T &)p_value; - }; + } void erase() { - data->erase(this); } - _FORCE_INLINE_ Element() { - next_ptr = 0; - prev_ptr = 0; - data = nullptr; - }; + _FORCE_INLINE_ Element() {} }; private: struct _Data { - Element *first; Element *last; int size_cache; bool erase(const Element *p_I) { - ERR_FAIL_COND_V(!p_I, false); ERR_FAIL_COND_V(p_I->data != this, false); if (first == p_I) { first = p_I->next_ptr; - }; + } - if (last == p_I) + if (last == p_I) { last = p_I->prev_ptr; + } - if (p_I->prev_ptr) + if (p_I->prev_ptr) { p_I->prev_ptr->next_ptr = p_I->next_ptr; + } - if (p_I->next_ptr) + if (p_I->next_ptr) { p_I->next_ptr->prev_ptr = p_I->prev_ptr; + } memdelete_allocator<Element, A>(const_cast<Element *>(p_I)); size_cache--; @@ -178,47 +168,42 @@ private: } }; - _Data *_data; + _Data *_data = nullptr; public: /** * return a const iterator to the beginning of the list. */ _FORCE_INLINE_ const Element *front() const { - - return _data ? _data->first : 0; - }; + return _data ? _data->first : nullptr; + } /** * return an iterator to the beginning of the list. */ _FORCE_INLINE_ Element *front() { - return _data ? _data->first : 0; - }; + return _data ? _data->first : nullptr; + } /** * return a const iterator to the last member of the list. */ _FORCE_INLINE_ const Element *back() const { - - return _data ? _data->last : 0; - }; + return _data ? _data->last : nullptr; + } /** * return an iterator to the last member of the list. */ _FORCE_INLINE_ Element *back() { - - return _data ? _data->last : 0; - }; + return _data ? _data->last : nullptr; + } /** * store a new element at the end of the list */ Element *push_back(const T &value) { - if (!_data) { - _data = memnew_allocator(_Data, A); _data->first = nullptr; _data->last = nullptr; @@ -229,37 +214,35 @@ public: n->value = (T &)value; n->prev_ptr = _data->last; - n->next_ptr = 0; + n->next_ptr = nullptr; n->data = _data; if (_data->last) { - _data->last->next_ptr = n; } _data->last = n; - if (!_data->first) + if (!_data->first) { _data->first = n; + } _data->size_cache++; return n; - }; + } void pop_back() { - - if (_data && _data->last) + if (_data && _data->last) { erase(_data->last); + } } /** * store a new element at the beginning of the list */ Element *push_front(const T &value) { - if (!_data) { - _data = memnew_allocator(_Data, A); _data->first = nullptr; _data->last = nullptr; @@ -268,29 +251,29 @@ public: Element *n = memnew_allocator(Element, A); n->value = (T &)value; - n->prev_ptr = 0; + n->prev_ptr = nullptr; n->next_ptr = _data->first; n->data = _data; if (_data->first) { - _data->first->prev_ptr = n; } _data->first = n; - if (!_data->last) + if (!_data->last) { _data->last = n; + } _data->size_cache++; return n; - }; + } void pop_front() { - - if (_data && _data->first) + if (_data && _data->first) { erase(_data->first); + } } Element *insert_after(Element *p_element, const T &p_value) { @@ -350,21 +333,21 @@ public: */ template <class T_v> Element *find(const T_v &p_val) { - Element *it = front(); while (it) { - if (it->value == p_val) return it; + if (it->value == p_val) { + return it; + } it = it->next(); - }; + } return nullptr; - }; + } /** * erase an element in the list, by iterator pointing to it. Return true if it was found/erased. */ bool erase(const Element *p_I) { - if (_data) { bool ret = _data->erase(p_I); @@ -377,22 +360,20 @@ public: } return false; - }; + } /** * erase the first element in the list, that contains value */ bool erase(const T &value) { - Element *I = find(value); return erase(I); - }; + } /** * return whether the list is empty */ _FORCE_INLINE_ bool empty() const { - return (!_data || !_data->size_cache); } @@ -400,19 +381,16 @@ public: * clear the list */ void clear() { - while (front()) { erase(front()); - }; - }; + } + } _FORCE_INLINE_ int size() const { - return _data ? _data->size_cache : 0; } void swap(Element *p_A, Element *p_B) { - ERR_FAIL_COND(!p_A || !p_B); ERR_FAIL_COND(p_A->data != _data); ERR_FAIL_COND(p_B->data != _data); @@ -426,32 +404,33 @@ public: p_B->next_ptr = A_next; p_B->prev_ptr = A_prev; - if (p_A->prev_ptr) + if (p_A->prev_ptr) { p_A->prev_ptr->next_ptr = p_A; - if (p_A->next_ptr) + } + if (p_A->next_ptr) { p_A->next_ptr->prev_ptr = p_A; + } - if (p_B->prev_ptr) + if (p_B->prev_ptr) { p_B->prev_ptr->next_ptr = p_B; - if (p_B->next_ptr) + } + if (p_B->next_ptr) { p_B->next_ptr->prev_ptr = p_B; + } } /** * copy the list */ void operator=(const List &p_list) { - clear(); const Element *it = p_list.front(); while (it) { - push_back(it->get()); it = it->next(); } } T &operator[](int p_index) { - CRASH_BAD_INDEX(p_index, size()); Element *I = front(); @@ -465,7 +444,6 @@ public: } const T &operator[](int p_index) const { - CRASH_BAD_INDEX(p_index, size()); const Element *I = front(); @@ -479,20 +457,22 @@ public: } void move_to_back(Element *p_I) { - ERR_FAIL_COND(p_I->data != _data); - if (!p_I->next_ptr) + if (!p_I->next_ptr) { return; + } if (_data->first == p_I) { _data->first = p_I->next_ptr; - }; + } - if (_data->last == p_I) + if (_data->last == p_I) { _data->last = p_I->prev_ptr; + } - if (p_I->prev_ptr) + if (p_I->prev_ptr) { p_I->prev_ptr->next_ptr = p_I->next_ptr; + } p_I->next_ptr->prev_ptr = p_I->prev_ptr; @@ -503,12 +483,10 @@ public: } void invert() { - int s = size() / 2; Element *F = front(); Element *B = back(); for (int i = 0; i < s; i++) { - SWAP(F->value, B->value); F = F->next(); B = B->prev(); @@ -516,22 +494,24 @@ public: } void move_to_front(Element *p_I) { - ERR_FAIL_COND(p_I->data != _data); - if (!p_I->prev_ptr) + if (!p_I->prev_ptr) { return; + } if (_data->first == p_I) { _data->first = p_I->next_ptr; - }; + } - if (_data->last == p_I) + if (_data->last == p_I) { _data->last = p_I->prev_ptr; + } p_I->prev_ptr->next_ptr = p_I->next_ptr; - if (p_I->next_ptr) + if (p_I->next_ptr) { p_I->next_ptr->prev_ptr = p_I->prev_ptr; + } _data->first->prev_ptr = p_I; p_I->next_ptr = _data->first; @@ -540,7 +520,6 @@ public: } void move_before(Element *value, Element *where) { - if (value->prev_ptr) { value->prev_ptr->next_ptr = value->next_ptr; } else { @@ -557,7 +536,7 @@ public: value->prev_ptr = _data->last; _data->last = value; return; - }; + } value->prev_ptr = where->prev_ptr; @@ -565,59 +544,56 @@ public: where->prev_ptr->next_ptr = value; } else { _data->first = value; - }; + } where->prev_ptr = value; - }; + } /** * simple insertion sort */ void sort() { - sort_custom<Comparator<T>>(); } template <class C> void sort_custom_inplace() { - - if (size() < 2) + if (size() < 2) { return; + } Element *from = front(); Element *current = from; Element *to = from; while (current) { - Element *next = current->next_ptr; if (from != current) { - current->prev_ptr = nullptr; current->next_ptr = from; Element *find = from; C less; while (find && less(find->value, current->value)) { - current->prev_ptr = find; current->next_ptr = find->next_ptr; find = find->next_ptr; } - if (current->prev_ptr) + if (current->prev_ptr) { current->prev_ptr->next_ptr = current; - else + } else { from = current; + } - if (current->next_ptr) + if (current->next_ptr) { current->next_ptr->prev_ptr = current; - else + } else { to = current; + } } else { - current->prev_ptr = nullptr; current->next_ptr = nullptr; } @@ -630,29 +606,26 @@ public: template <class C> struct AuxiliaryComparator { - C compare; _FORCE_INLINE_ bool operator()(const Element *a, const Element *b) const { - return compare(a->value, b->value); } }; template <class C> void sort_custom() { - //this version uses auxiliary memory for speed. //if you don't want to use auxiliary memory, use the in_place version int s = size(); - if (s < 2) + if (s < 2) { return; + } Element **aux_buffer = memnew_arr(Element *, s); int idx = 0; for (Element *E = front(); E; E = E->next_ptr) { - aux_buffer[idx] = E; idx++; } @@ -669,7 +642,6 @@ public: aux_buffer[s - 1]->next_ptr = nullptr; for (int i = 1; i < s - 1; i++) { - aux_buffer[i]->prev_ptr = aux_buffer[i - 1]; aux_buffer[i]->next_ptr = aux_buffer[i + 1]; } @@ -685,27 +657,22 @@ public: * copy constructor for the list */ List(const List &p_list) { - - _data = nullptr; const Element *it = p_list.front(); while (it) { - push_back(it->get()); it = it->next(); } } - List() { - _data = nullptr; - }; + List() {} + ~List() { clear(); if (_data) { - ERR_FAIL_COND(_data->size_cache); memdelete_allocator<_Data, A>(_data); } - }; + } }; #endif // LIST_H diff --git a/core/local_vector.h b/core/local_vector.h new file mode 100644 index 0000000000..7f96b25f8b --- /dev/null +++ b/core/local_vector.h @@ -0,0 +1,238 @@ +/*************************************************************************/ +/* local_vector.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LOCAL_VECTOR_H +#define LOCAL_VECTOR_H + +#include "core/error_macros.h" +#include "core/os/copymem.h" +#include "core/os/memory.h" +#include "core/sort_array.h" +#include "core/vector.h" + +template <class T, class U = uint32_t, bool force_trivial = false> +class LocalVector { +private: + U count = 0; + U capacity = 0; + T *data = nullptr; + +public: + _FORCE_INLINE_ void push_back(T p_elem) { + if (unlikely(count == capacity)) { + if (capacity == 0) { + capacity = 1; + } else { + capacity <<= 1; + } + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + + if (!__has_trivial_constructor(T) && !force_trivial) { + memnew_placement(&data[count++], T(p_elem)); + } else { + data[count++] = p_elem; + } + } + + void remove(U p_index) { + ERR_FAIL_UNSIGNED_INDEX(p_index, count); + for (U i = p_index; i < count; i++) { + data[i] = data[i + 1]; + } + count--; + if (!__has_trivial_destructor(T) && !force_trivial) { + data[count].~T(); + } + } + + void erase(const T &p_val) { + int64_t idx = find(p_val); + if (idx >= 0) { + remove(idx); + } + } + + void invert() { + for (U i = 0; i < count / 2; i++) { + SWAP(data[i], data[count - i - 1]); + } + } + + _FORCE_INLINE_ void clear() { resize(0); } + _FORCE_INLINE_ void reset() { + clear(); + if (data) { + memfree(data); + data = nullptr; + capacity = 0; + } + } + _FORCE_INLINE_ bool empty() const { return count == 0; } + _FORCE_INLINE_ void reserve(U p_size) { + p_size = nearest_power_of_2_templated(p_size); + if (p_size > capacity) { + capacity = p_size; + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + } + + _FORCE_INLINE_ U size() const { return count; } + void resize(U p_size) { + if (p_size < count) { + if (!__has_trivial_destructor(T) && !force_trivial) { + for (U i = p_size; i < count; i++) { + data[i].~T(); + } + } + count = p_size; + } else if (p_size > count) { + if (unlikely(p_size > capacity)) { + if (capacity == 0) { + capacity = 1; + } + while (capacity < p_size) { + capacity <<= 1; + } + data = (T *)memrealloc(data, capacity * sizeof(T)); + CRASH_COND_MSG(!data, "Out of memory"); + } + if (!__has_trivial_constructor(T) && !force_trivial) { + for (U i = count; i < p_size; i++) { + memnew_placement(&data[i], T); + } + } + count = p_size; + } + } + _FORCE_INLINE_ const T &operator[](U p_index) const { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + return data[p_index]; + } + _FORCE_INLINE_ T &operator[](U p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + return data[p_index]; + } + + void insert(U p_pos, T p_val) { + ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1); + if (p_pos == count) { + push_back(p_val); + } else { + resize(count + 1); + for (U i = count; i > p_pos; i--) { + data[i] = data[i - 1]; + } + data[p_pos] = p_val; + } + } + + int64_t find(const T &p_val, U p_from = 0) const { + for (U i = 0; i < count; i++) { + if (data[i] == p_val) { + return int64_t(i); + } + } + return -1; + } + + template <class C> + void sort_custom() { + U len = count; + if (len == 0) { + return; + } + + SortArray<T, C> sorter; + sorter.sort(data, len); + } + + void sort() { + sort_custom<_DefaultComparator<T>>(); + } + + void ordered_insert(T p_val) { + U i; + for (i = 0; i < count; i++) { + if (p_val < data[i]) { + break; + } + } + insert(i, p_val); + } + + operator Vector<T>() const { + Vector<T> ret; + ret.resize(size()); + T *w = ret.ptrw(); + copymem(w, data, sizeof(T) * count); + return ret; + } + + Vector<uint8_t> to_byte_array() const { //useful to pass stuff to gpu or variant + Vector<uint8_t> ret; + ret.resize(count * sizeof(T)); + uint8_t *w = ret.ptrw(); + copymem(w, data, sizeof(T) * count); + return ret; + } + + _FORCE_INLINE_ LocalVector() {} + _FORCE_INLINE_ LocalVector(const LocalVector &p_from) { + resize(p_from.size()); + for (U i = 0; i < p_from.count; i++) { + data[i] = p_from.data[i]; + } + } + inline LocalVector &operator=(const LocalVector &p_from) { + resize(p_from.size()); + for (U i = 0; i < p_from.count; i++) { + data[i] = p_from.data[i]; + } + return *this; + } + inline LocalVector &operator=(const Vector<T> &p_from) { + resize(p_from.size()); + for (U i = 0; i < count; i++) { + data[i] = p_from[i]; + } + return *this; + } + + _FORCE_INLINE_ ~LocalVector() { + if (data) { + reset(); + } + } +}; + +#endif // LOCAL_VECTOR_H diff --git a/core/make_binders.py b/core/make_binders.py index 94bee95bfb..7d0d08cde6 100644 --- a/core/make_binders.py +++ b/core/make_binders.py @@ -75,7 +75,7 @@ public: #endif $ifret _set_returns(true); $ - }; + } }; template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> @@ -170,7 +170,7 @@ public: $ifret _set_returns(true); $ - }; + } }; template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> @@ -266,7 +266,7 @@ public: #endif $ifret _set_returns(true); $ - }; + } }; template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> diff --git a/core/map.h b/core/map.h index 6b9dff51de..fd4f500556 100644 --- a/core/map.h +++ b/core/map.h @@ -39,7 +39,6 @@ template <class K, class V, class C = Comparator<K>, class A = DefaultAllocator> class Map { - enum Color { RED, BLACK @@ -48,67 +47,54 @@ class Map { public: class Element { - private: friend class Map<K, V, C, A>; - int color; - Element *right; - Element *left; - Element *parent; - Element *_next; - Element *_prev; + int color = RED; + Element *right = nullptr; + Element *left = nullptr; + Element *parent = nullptr; + Element *_next = nullptr; + Element *_prev = nullptr; K _key; V _value; //_Data *data; public: const Element *next() const { - return _next; } Element *next() { - return _next; } const Element *prev() const { - return _prev; } Element *prev() { - return _prev; } const K &key() const { return _key; - }; + } V &value() { return _value; - }; + } const V &value() const { return _value; - }; + } V &get() { return _value; - }; + } const V &get() const { return _value; - }; - Element() { - color = RED; - right = nullptr; - left = nullptr; - parent = nullptr; - _next = nullptr; - _prev = nullptr; - }; + } + Element() {} }; private: struct _Data { - - Element *_root; + Element *_root = nullptr; Element *_nil; - int size_cache; + int size_cache = 0; _FORCE_INLINE_ _Data() { #ifdef GLOBALNIL_DISABLED @@ -118,19 +104,15 @@ private: #else _nil = (Element *)&_GlobalNilClass::_nil; #endif - _root = nullptr; - size_cache = 0; } void _create_root() { - _root = memnew_allocator(Element, A); _root->parent = _root->left = _root->right = _nil; _root->color = BLACK; } void _free_root() { - if (_root) { memdelete_allocator<Element, A>(_root); _root = nullptr; @@ -138,7 +120,6 @@ private: } ~_Data() { - _free_root(); #ifdef GLOBALNIL_DISABLED @@ -150,62 +131,61 @@ private: _Data _data; inline void _set_color(Element *p_node, int p_color) { - 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; p_node->right = r->left; - if (r->left != _data._nil) + if (r->left != _data._nil) { r->left->parent = p_node; + } r->parent = p_node->parent; - if (p_node == p_node->parent->left) + if (p_node == p_node->parent->left) { p_node->parent->left = r; - else + } else { p_node->parent->right = r; + } r->left = p_node; p_node->parent = r; } inline void _rotate_right(Element *p_node) { - Element *l = p_node->left; p_node->left = l->right; - if (l->right != _data._nil) + if (l->right != _data._nil) { l->right->parent = p_node; + } l->parent = p_node->parent; - if (p_node == p_node->parent->right) + if (p_node == p_node->parent->right) { p_node->parent->right = l; - else + } else { p_node->parent->left = l; + } l->right = p_node; p_node->parent = l; } inline Element *_successor(Element *p_node) const { - Element *node = p_node; if (node->right != _data._nil) { - node = node->right; while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */ node = node->left; } return node; } else { - while (node == node->parent->right) { node = node->parent; } - if (node->parent == _data._root) + if (node->parent == _data._root) { return nullptr; // No successor, as p_node = last node + } return node->parent; } } @@ -214,43 +194,41 @@ private: Element *node = p_node; if (node->left != _data._nil) { - node = node->left; while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */ node = node->right; } return node; } else { - while (node == node->parent->left) { node = node->parent; } - if (node == _data._root) + if (node == _data._root) { return nullptr; // No predecessor, as p_node = first node + } return node->parent; } } Element *_find(const K &p_key) const { - Element *node = _data._root->left; C less; while (node != _data._nil) { - if (less(p_key, node->_key)) + if (less(p_key, node->_key)) { node = node->left; - else if (less(node->_key, p_key)) + } else if (less(node->_key, p_key)) { node = node->right; - else + } else { return node; // found + } } return nullptr; } Element *_find_closest(const K &p_key) const { - Element *node = _data._root->left; Element *prev = nullptr; C less; @@ -258,25 +236,27 @@ private: while (node != _data._nil) { prev = node; - if (less(p_key, node->_key)) + if (less(p_key, node->_key)) { node = node->left; - else if (less(node->_key, p_key)) + } else if (less(node->_key, p_key)) { node = node->right; - else + } else { return node; // found + } } - if (prev == nullptr) + if (prev == nullptr) { return nullptr; // tree empty + } - if (less(p_key, prev->_key)) + if (less(p_key, prev->_key)) { prev = prev->_prev; + } return prev; } void _insert_rb_fix(Element *p_new_node) { - Element *node = p_new_node; Element *nparent = node->parent; Element *ngrand_parent; @@ -325,20 +305,18 @@ private: } Element *_insert(const K &p_key, const V &p_value) { - Element *new_parent = _data._root; Element *node = _data._root->left; C less; while (node != _data._nil) { - new_parent = node; - if (less(p_key, node->_key)) + if (less(p_key, node->_key)) { node = node->left; - else if (less(node->_key, p_key)) + } else if (less(node->_key, p_key)) { node = node->right; - else { + } else { node->_value = p_value; return node; // Return existing node with new value } @@ -360,10 +338,12 @@ private: new_node->_next = _successor(new_node); new_node->_prev = _predecessor(new_node); - if (new_node->_next) + if (new_node->_next) { new_node->_next->_prev = new_node; - if (new_node->_prev) + } + if (new_node->_prev) { new_node->_prev->_next = new_node; + } _data.size_cache++; _insert_rb_fix(new_node); @@ -371,7 +351,6 @@ private: } void _erase_fix_rb(Element *p_node) { - Element *root = _data._root->left; Element *node = _data._nil; Element *sibling = p_node; @@ -433,7 +412,6 @@ private: } void _erase(Element *p_node) { - 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; @@ -454,17 +432,18 @@ private: } if (rp != p_node) { - ERR_FAIL_COND(rp == _data._nil); rp->left = p_node->left; rp->right = p_node->right; rp->parent = p_node->parent; rp->color = p_node->color; - if (p_node->left != _data._nil) + if (p_node->left != _data._nil) { p_node->left->parent = rp; - if (p_node->right != _data._nil) + } + if (p_node->right != _data._nil) { p_node->right->parent = rp; + } if (p_node == p_node->parent->left) { p_node->parent->left = rp; @@ -473,10 +452,12 @@ private: } } - if (p_node->_next) + if (p_node->_next) { p_node->_next->_prev = p_node->_prev; - if (p_node->_prev) + } + if (p_node->_prev) { p_node->_prev->_next = p_node->_next; + } memdelete_allocator<Element, A>(p_node); _data.size_cache--; @@ -484,21 +465,22 @@ 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) + if (d > max_d) { max_d = d; + } } void _cleanup_tree(Element *p_element) { - - if (p_element == _data._nil) + if (p_element == _data._nil) { return; + } _cleanup_tree(p_element->left); _cleanup_tree(p_element->right); @@ -506,91 +488,90 @@ private: } void _copy_from(const Map &p_map) { - clear(); // not the fastest way, but safeset to write. for (Element *I = p_map.front(); I; I = I->next()) { - insert(I->key(), I->value()); } } public: const Element *find(const K &p_key) const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } const Element *res = _find(p_key); return res; } Element *find(const K &p_key) { - - if (!_data._root) + if (!_data._root) { return nullptr; + } Element *res = _find(p_key); return res; } const Element *find_closest(const K &p_key) const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } const Element *res = _find_closest(p_key); return res; } Element *find_closest(const K &p_key) { - - if (!_data._root) + if (!_data._root) { return nullptr; + } Element *res = _find_closest(p_key); return res; } bool has(const K &p_key) const { - return find(p_key) != nullptr; } Element *insert(const K &p_key, const V &p_value) { - - if (!_data._root) + if (!_data._root) { _data._create_root(); + } return _insert(p_key, p_value); } void erase(Element *p_element) { - - if (!_data._root || !p_element) + if (!_data._root || !p_element) { return; + } _erase(p_element); - if (_data.size_cache == 0 && _data._root) + if (_data.size_cache == 0 && _data._root) { _data._free_root(); + } } bool erase(const K &p_key) { - - if (!_data._root) + if (!_data._root) { return false; + } Element *e = find(p_key); - if (!e) + if (!e) { return false; + } _erase(e); - if (_data.size_cache == 0 && _data._root) + if (_data.size_cache == 0 && _data._root) { _data._free_root(); + } return true; } const V &operator[](const K &p_key) const { - CRASH_COND(!_data._root); const Element *e = find(p_key); CRASH_COND(!e); @@ -598,43 +579,48 @@ public: } V &operator[](const K &p_key) { - - if (!_data._root) + if (!_data._root) { _data._create_root(); + } Element *e = find(p_key); - if (!e) + if (!e) { e = insert(p_key, V()); + } return e->_value; } Element *front() const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } Element *e = _data._root->left; - if (e == _data._nil) + if (e == _data._nil) { return nullptr; + } - while (e->left != _data._nil) + while (e->left != _data._nil) { e = e->left; + } return e; } Element *back() const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } Element *e = _data._root->left; - if (e == _data._nil) + if (e == _data._nil) { return nullptr; + } - while (e->right != _data._nil) + while (e->right != _data._nil) { e = e->right; + } return e; } @@ -644,8 +630,9 @@ public: int calculate_depth() const { // used for debug mostly - if (!_data._root) + if (!_data._root) { return 0; + } int max_d = 0; _calculate_depth(_data._root->left, max_d, 0); @@ -653,9 +640,9 @@ public: } void clear() { - - if (!_data._root) + if (!_data._root) { return; + } _cleanup_tree(_data._root->left); _data._root->left = _data._nil; @@ -664,20 +651,16 @@ public: } void operator=(const Map &p_map) { - _copy_from(p_map); } Map(const Map &p_map) { - _copy_from(p_map); } - _FORCE_INLINE_ Map() { - } + _FORCE_INLINE_ Map() {} ~Map() { - clear(); } }; diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 3e3e6c50a7..30f712b2c3 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -30,12 +30,11 @@ #include "a_star.h" -#include "core/math/geometry.h" +#include "core/math/geometry_3d.h" #include "core/script_language.h" #include "scene/scene_string_names.h" int AStar::get_available_point_id() const { - if (points.empty()) { return 1; } @@ -54,7 +53,6 @@ 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); @@ -78,7 +76,6 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) { } Vector3 AStar::get_point_position(int p_id) const { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V(!p_exists, Vector3()); @@ -87,7 +84,6 @@ Vector3 AStar::get_point_position(int p_id) const { } void AStar::set_point_position(int p_id, const Vector3 &p_pos) { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND(!p_exists); @@ -96,7 +92,6 @@ void AStar::set_point_position(int p_id, const Vector3 &p_pos) { } real_t AStar::get_point_weight_scale(int p_id) const { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V(!p_exists, 0); @@ -105,7 +100,6 @@ real_t AStar::get_point_weight_scale(int p_id) const { } void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND(!p_exists); @@ -115,13 +109,11 @@ void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) { } void AStar::remove_point(int p_id) { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND(!p_exists); for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { - Segment s(p_id, (*it.key)); segments.erase(s); @@ -130,7 +122,6 @@ void AStar::remove_point(int p_id) { } for (OAHashMap<int, Point *>::Iterator it = p->unlinked_neighbours.iter(); it.valid; it = p->unlinked_neighbours.next_iter(it)) { - Segment s(p_id, (*it.key)); segments.erase(s); @@ -144,7 +135,6 @@ void AStar::remove_point(int p_id) { } void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { - ERR_FAIL_COND(p_id == p_with_id); Point *a; @@ -164,7 +154,9 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { } Segment s(p_id, p_with_id); - if (bidirectional) s.direction = Segment::BIDIRECTIONAL; + if (bidirectional) { + s.direction = Segment::BIDIRECTIONAL; + } Set<Segment>::Element *element = segments.find(s); if (element != nullptr) { @@ -181,7 +173,6 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { } void AStar::disconnect_points(int p_id, int p_with_id, bool bidirectional) { - Point *a; bool a_exists = points.lookup(p_id, a); ERR_FAIL_COND(!a_exists); @@ -207,25 +198,25 @@ void AStar::disconnect_points(int p_id, int p_with_id, bool bidirectional) { b->unlinked_neighbours.remove(a->id); } } else { - if (s.direction == Segment::NONE) + if (s.direction == Segment::NONE) { b->unlinked_neighbours.remove(a->id); - else + } else { a->unlinked_neighbours.set(b->id, b); + } } segments.erase(element); - if (s.direction != Segment::NONE) + if (s.direction != Segment::NONE) { segments.insert(s); + } } } bool AStar::has_point(int p_id) const { - return points.has(p_id); } Array AStar::get_points() { - Array point_list; for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { @@ -236,7 +227,6 @@ Array AStar::get_points() { } Vector<int> AStar::get_point_connections(int p_id) { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V(!p_exists, Vector<int>()); @@ -251,7 +241,6 @@ Vector<int> AStar::get_point_connections(int p_id) { } bool AStar::are_points_connected(int p_id, int p_with_id, bool bidirectional) const { - Segment s(p_id, p_with_id); const Set<Segment>::Element *element = segments.find(s); @@ -260,7 +249,6 @@ bool AStar::are_points_connected(int p_id, int p_with_id, bool bidirectional) co } void AStar::clear() { - last_free_id = 0; for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { memdelete(*(it.value)); @@ -284,18 +272,24 @@ void AStar::reserve_space(int p_num_nodes) { } int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) const { - int closest_id = -1; real_t closest_dist = 1e20; for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { + if (!p_include_disabled && !(*it.value)->enabled) { + continue; // Disabled points should not be considered. + } - if (!p_include_disabled && !(*it.value)->enabled) continue; // Disabled points should not be considered. - + // Keep the closest point's ID, and in case of multiple closest IDs, + // the smallest one (makes it deterministic). real_t d = p_point.distance_squared_to((*it.value)->pos); - if (closest_id < 0 || d < closest_dist) { + int id = *(it.key); + if (d <= closest_dist) { + if (d == closest_dist && id > closest_id) { // Keep lowest ID. + continue; + } closest_dist = d; - closest_id = *(it.key); + closest_id = id; } } @@ -303,13 +297,10 @@ int AStar::get_closest_point(const Vector3 &p_point, bool p_include_disabled) co } Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const { - - bool found = false; real_t closest_dist = 1e20; Vector3 closest_point; for (const Set<Segment>::Element *E = segments.front(); E; E = E->next()) { - Point *from_point = nullptr, *to_point = nullptr; points.lookup(E->get().u, from_point); points.lookup(E->get().v, to_point); @@ -323,13 +314,11 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const { to_point->pos, }; - Vector3 p = Geometry::get_closest_point_to_segment(p_point, segment); + Vector3 p = Geometry3D::get_closest_point_to_segment(p_point, segment); real_t d = p_point.distance_squared_to(p); - if (!found || d < closest_dist) { - + if (d < closest_dist) { closest_point = p; closest_dist = d; - found = true; } } @@ -337,10 +326,11 @@ Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const { } bool AStar::_solve(Point *begin_point, Point *end_point) { - pass++; - if (!end_point->enabled) return false; + if (!end_point->enabled) { + return false; + } bool found_route = false; @@ -352,7 +342,6 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { open_list.push_back(begin_point); while (!open_list.empty()) { - Point *p = open_list[0]; // The currently processed point if (p == end_point) { @@ -365,7 +354,6 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { p->closed_pass = pass; // Mark the point as closed for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { - Point *e = *(it.value); // The neighbour point if (!e->enabled || e->closed_pass == pass) { @@ -400,9 +388,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { } real_t 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)) + 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); + } Point *from_point; bool from_exists = points.lookup(p_from_id, from_point); @@ -416,9 +404,9 @@ real_t AStar::_estimate_cost(int p_from_id, int p_to_id) { } real_t 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)) + 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); + } Point *from_point; bool from_exists = points.lookup(p_from_id, from_point); @@ -432,7 +420,6 @@ real_t AStar::_compute_cost(int p_from_id, int p_to_id) { } Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { - Point *a; bool from_exists = points.lookup(p_from_id, a); ERR_FAIL_COND_V(!from_exists, Vector<Vector3>()); @@ -451,7 +438,9 @@ Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<Vector3>(); + if (!found_route) { + return Vector<Vector3>(); + } Point *p = end_point; int pc = 1; // Begin point @@ -480,7 +469,6 @@ Vector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { } Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) { - Point *a; bool from_exists = points.lookup(p_from_id, a); ERR_FAIL_COND_V(!from_exists, Vector<int>()); @@ -499,7 +487,9 @@ Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<int>(); + if (!found_route) { + return Vector<int>(); + } Point *p = end_point; int pc = 1; // Begin point @@ -528,7 +518,6 @@ Vector<int> AStar::get_id_path(int p_from_id, int p_to_id) { } void AStar::set_point_disabled(int p_id, bool p_disabled) { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND(!p_exists); @@ -537,7 +526,6 @@ void AStar::set_point_disabled(int p_id, bool p_disabled) { } bool AStar::is_point_disabled(int p_id) const { - Point *p; bool p_exists = points.lookup(p_id, p); ERR_FAIL_COND_V(!p_exists, false); @@ -546,7 +534,6 @@ bool AStar::is_point_disabled(int p_id) const { } 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", "position", "weight_scale"), &AStar::add_point, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar::get_point_position); @@ -580,11 +567,6 @@ void AStar::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); } -AStar::AStar() { - last_free_id = 0; - pass = 1; -} - AStar::~AStar() { clear(); } @@ -678,9 +660,9 @@ Vector2 AStar2D::get_closest_position_in_segment(const Vector2 &p_point) const { } real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) { - - if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) + 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); + } AStar::Point *from_point; bool from_exists = astar.points.lookup(p_from_id, from_point); @@ -694,9 +676,9 @@ real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) { } real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) { - - if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) + 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); + } AStar::Point *from_point; bool from_exists = astar.points.lookup(p_from_id, from_point); @@ -710,7 +692,6 @@ real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) { } Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { - AStar::Point *a; bool from_exists = astar.points.lookup(p_from_id, a); ERR_FAIL_COND_V(!from_exists, Vector<Vector2>()); @@ -729,7 +710,9 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { AStar::Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<Vector2>(); + if (!found_route) { + return Vector<Vector2>(); + } AStar::Point *p = end_point; int pc = 1; // Begin point @@ -758,7 +741,6 @@ Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { } Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { - AStar::Point *a; bool from_exists = astar.points.lookup(p_from_id, a); ERR_FAIL_COND_V(!from_exists, Vector<int>()); @@ -777,7 +759,9 @@ Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { AStar::Point *end_point = b; bool found_route = _solve(begin_point, end_point); - if (!found_route) return Vector<int>(); + if (!found_route) { + return Vector<int>(); + } AStar::Point *p = end_point; int pc = 1; // Begin point @@ -806,10 +790,11 @@ Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { } bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { - astar.pass++; - if (!end_point->enabled) return false; + if (!end_point->enabled) { + return false; + } bool found_route = false; @@ -821,7 +806,6 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { open_list.push_back(begin_point); while (!open_list.empty()) { - AStar::Point *p = open_list[0]; // The currently processed point if (p == end_point) { @@ -834,7 +818,6 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { p->closed_pass = astar.pass; // Mark the point as closed for (OAHashMap<int, AStar::Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { - AStar::Point *e = *(it.value); // The neighbour point if (!e->enabled || e->closed_pass == astar.pass) { @@ -869,7 +852,6 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { } void AStar2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_available_point_id"), &AStar2D::get_available_point_id); ClassDB::bind_method(D_METHOD("add_point", "id", "position", "weight_scale"), &AStar2D::add_point, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar2D::get_point_position); @@ -902,9 +884,3 @@ void AStar2D::_bind_methods() { BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); } - -AStar2D::AStar2D() { -} - -AStar2D::~AStar2D() { -} diff --git a/core/math/a_star.h b/core/math/a_star.h index 8c10ace33c..ba1c3033b8 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -41,23 +41,19 @@ */ class AStar : public Reference { - GDCLASS(AStar, Reference); friend class AStar2D; struct Point { - - Point() : - neighbours(4u), - unlinked_neighbours(4u) {} + Point() {} int id; Vector3 pos; real_t weight_scale; bool enabled; - OAHashMap<int, Point *> neighbours; - OAHashMap<int, Point *> unlinked_neighbours; + OAHashMap<int, Point *> neighbours = 4u; + OAHashMap<int, Point *> unlinked_neighbours = 4u; // Used for pathfinding. Point *prev_point; @@ -85,7 +81,7 @@ class AStar : public Reference { int32_t u; int32_t v; }; - uint64_t key; + uint64_t key = 0; }; enum { @@ -94,13 +90,11 @@ class AStar : public Reference { BACKWARD = 2, BIDIRECTIONAL = FORWARD | BACKWARD }; - unsigned char direction; + unsigned char direction = NONE; bool operator<(const Segment &p_s) const { return key < p_s.key; } - Segment() { - key = 0; - direction = NONE; - } + + Segment() {} Segment(int p_from, int p_to) { if (p_from < p_to) { u = p_from; @@ -114,8 +108,8 @@ class AStar : public Reference { } }; - int last_free_id; - uint64_t pass; + int last_free_id = 0; + uint64_t pass = 1; OAHashMap<int, Point *> points; Set<Segment> segments; @@ -159,7 +153,7 @@ public: Vector<Vector3> get_point_path(int p_from_id, int p_to_id); Vector<int> get_id_path(int p_from_id, int p_to_id); - AStar(); + AStar() {} ~AStar(); }; @@ -206,8 +200,8 @@ public: Vector<Vector2> get_point_path(int p_from_id, int p_to_id); Vector<int> get_id_path(int p_from_id, int p_to_id); - AStar2D(); - ~AStar2D(); + AStar2D() {} + ~AStar2D() {} }; #endif // A_STAR_H diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index 19d60fea72..f5c667dab0 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -33,21 +33,18 @@ #include "core/print_string.h" real_t AABB::get_area() const { - return size.x * size.y * size.z; } bool AABB::operator==(const AABB &p_rval) const { - return ((position == p_rval.position) && (size == p_rval.size)); } -bool AABB::operator!=(const AABB &p_rval) const { +bool AABB::operator!=(const AABB &p_rval) const { return ((position != p_rval.position) || (size != p_rval.size)); } void AABB::merge_with(const AABB &p_aabb) { - Vector3 beg_1, beg_2; Vector3 end_1, end_2; Vector3 min, max; @@ -70,12 +67,10 @@ void AABB::merge_with(const AABB &p_aabb) { } bool AABB::is_equal_approx(const AABB &p_aabb) const { - return position.is_equal_approx(p_aabb.position) && size.is_equal_approx(p_aabb.size); } AABB AABB::intersection(const AABB &p_aabb) const { - Vector3 src_min = position; Vector3 src_max = position + size; Vector3 dst_min = p_aabb.position; @@ -83,26 +78,23 @@ AABB AABB::intersection(const AABB &p_aabb) const { Vector3 min, max; - if (src_min.x > dst_max.x || src_max.x < dst_min.x) + if (src_min.x > dst_max.x || src_max.x < dst_min.x) { return AABB(); - else { - + } else { min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x; max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x; } - if (src_min.y > dst_max.y || src_max.y < dst_min.y) + if (src_min.y > dst_max.y || src_max.y < dst_min.y) { return AABB(); - else { - + } else { min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y; max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y; } - if (src_min.z > dst_max.z || src_max.z < dst_min.z) + if (src_min.z > dst_max.z || src_max.z < dst_min.z) { return AABB(); - else { - + } else { min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z; max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z; } @@ -111,7 +103,6 @@ AABB AABB::intersection(const AABB &p_aabb) const { } bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const { - Vector3 c1, c2; Vector3 end = position + size; real_t near = -1e20; @@ -143,8 +134,9 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 * } } - if (r_clip) + if (r_clip) { *r_clip = c1; + } if (r_normal) { *r_normal = Vector3(); (*r_normal)[axis] = p_dir[axis] ? -1 : 1; @@ -154,7 +146,6 @@ bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 * } bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const { - real_t min = 0, max = 1; int axis = 0; real_t sign = 0; @@ -168,18 +159,18 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector real_t csign; if (seg_from < seg_to) { - - if (seg_from > box_end || seg_to < box_begin) + if (seg_from > box_end || seg_to < box_begin) { return false; + } real_t length = seg_to - seg_from; cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0; cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1; csign = -1.0; } else { - - if (seg_to > box_end || seg_from < box_begin) + if (seg_to > box_end || seg_from < box_begin) { return false; + } real_t length = seg_to - seg_from; cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0; cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1; @@ -191,10 +182,12 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector axis = i; sign = csign; } - if (cmax < max) + if (cmax < max) { max = cmax; - if (max < min) + } + if (max < min) { return false; + } } Vector3 rel = p_to - p_from; @@ -205,14 +198,14 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector *r_normal = normal; } - if (r_clip) + if (r_clip) { *r_clip = p_from + rel * min; + } return true; } bool AABB::intersects_plane(const Plane &p_plane) const { - Vector3 points[8] = { Vector3(position.x, position.y, position.z), Vector3(position.x, position.y, position.z + size.z), @@ -228,18 +221,17 @@ bool AABB::intersects_plane(const Plane &p_plane) const { bool under = false; for (int i = 0; i < 8; i++) { - - if (p_plane.distance_to(points[i]) > 0) + if (p_plane.distance_to(points[i]) > 0) { over = true; - else + } else { under = true; + } } return under && over; } Vector3 AABB::get_longest_axis() const { - Vector3 axis(1, 0, 0); real_t max_size = size.x; @@ -254,8 +246,8 @@ Vector3 AABB::get_longest_axis() const { return axis; } -int AABB::get_longest_axis_index() const { +int AABB::get_longest_axis_index() const { int axis = 0; real_t max_size = size.x; @@ -272,7 +264,6 @@ int AABB::get_longest_axis_index() const { } Vector3 AABB::get_shortest_axis() const { - Vector3 axis(1, 0, 0); real_t max_size = size.x; @@ -287,8 +278,8 @@ Vector3 AABB::get_shortest_axis() const { return axis; } -int AABB::get_shortest_axis_index() const { +int AABB::get_shortest_axis_index() const { int axis = 0; real_t max_size = size.x; @@ -305,35 +296,31 @@ int AABB::get_shortest_axis_index() const { } AABB AABB::merge(const AABB &p_with) const { - AABB aabb = *this; aabb.merge_with(p_with); return aabb; } + AABB AABB::expand(const Vector3 &p_vector) const { AABB aabb = *this; aabb.expand_to(p_vector); return aabb; } -AABB AABB::grow(real_t p_by) const { +AABB AABB::grow(real_t p_by) const { AABB aabb = *this; aabb.grow_by(p_by); return aabb; } void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const { - ERR_FAIL_INDEX(p_edge, 12); switch (p_edge) { - case 0: { - r_from = Vector3(position.x + size.x, position.y, position.z); r_to = Vector3(position.x, position.y, position.z); } break; case 1: { - r_from = Vector3(position.x + size.x, position.y, position.z + size.z); r_to = Vector3(position.x + size.x, position.y, position.z); } break; @@ -343,18 +330,15 @@ void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const { } break; case 3: { - r_from = Vector3(position.x, position.y, position.z); r_to = Vector3(position.x, position.y, position.z + size.z); } break; case 4: { - r_from = Vector3(position.x, position.y + size.y, position.z); r_to = Vector3(position.x + size.x, position.y + size.y, position.z); } break; case 5: { - r_from = Vector3(position.x + size.x, position.y + size.y, position.z); r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z); } break; @@ -364,31 +348,26 @@ void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const { } break; case 7: { - r_from = Vector3(position.x, position.y + size.y, position.z + size.z); r_to = Vector3(position.x, position.y + size.y, position.z); } break; case 8: { - r_from = Vector3(position.x, position.y, position.z + size.z); r_to = Vector3(position.x, position.y + size.y, position.z + size.z); } break; case 9: { - r_from = Vector3(position.x, position.y, position.z); r_to = Vector3(position.x, position.y + size.y, position.z); } break; case 10: { - r_from = Vector3(position.x + size.x, position.y, position.z); r_to = Vector3(position.x + size.x, position.y + size.y, position.z); } break; case 11: { - r_from = Vector3(position.x + size.x, position.y, position.z + size.z); r_to = Vector3(position.x + size.x, position.y + size.y, position.z + size.z); @@ -397,6 +376,5 @@ void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const { } AABB::operator String() const { - return String() + position + " - " + size; } diff --git a/core/math/aabb.h b/core/math/aabb.h index eca74e6755..4106fbb93c 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -47,12 +47,10 @@ public: real_t get_area() const; /// get area _FORCE_INLINE_ bool has_no_area() const { - return (size.x <= 0 || size.y <= 0 || size.z <= 0); } _FORCE_INLINE_ bool has_no_surface() const { - return (size.x <= 0 && size.y <= 0 && size.z <= 0); } @@ -76,7 +74,7 @@ public: bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const; - _FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count) const; + _FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const; _FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const; bool intersects_plane(const Plane &p_plane) const; @@ -111,43 +109,52 @@ public: }; inline bool AABB::intersects(const AABB &p_aabb) const { - - if (position.x >= (p_aabb.position.x + p_aabb.size.x)) + if (position.x >= (p_aabb.position.x + p_aabb.size.x)) { return false; - if ((position.x + size.x) <= p_aabb.position.x) + } + if ((position.x + size.x) <= p_aabb.position.x) { return false; - if (position.y >= (p_aabb.position.y + p_aabb.size.y)) + } + if (position.y >= (p_aabb.position.y + p_aabb.size.y)) { return false; - if ((position.y + size.y) <= p_aabb.position.y) + } + if ((position.y + size.y) <= p_aabb.position.y) { return false; - if (position.z >= (p_aabb.position.z + p_aabb.size.z)) + } + if (position.z >= (p_aabb.position.z + p_aabb.size.z)) { return false; - if ((position.z + size.z) <= p_aabb.position.z) + } + if ((position.z + size.z) <= p_aabb.position.z) { return false; + } return true; } inline bool AABB::intersects_inclusive(const AABB &p_aabb) const { - - if (position.x > (p_aabb.position.x + p_aabb.size.x)) + if (position.x > (p_aabb.position.x + p_aabb.size.x)) { return false; - if ((position.x + size.x) < p_aabb.position.x) + } + if ((position.x + size.x) < p_aabb.position.x) { return false; - if (position.y > (p_aabb.position.y + p_aabb.size.y)) + } + if (position.y > (p_aabb.position.y + p_aabb.size.y)) { return false; - if ((position.y + size.y) < p_aabb.position.y) + } + if ((position.y + size.y) < p_aabb.position.y) { return false; - if (position.z > (p_aabb.position.z + p_aabb.size.z)) + } + if (position.z > (p_aabb.position.z + p_aabb.size.z)) { return false; - if ((position.z + size.z) < p_aabb.position.z) + } + if ((position.z + size.z) < p_aabb.position.z) { return false; + } return true; } inline bool AABB::encloses(const AABB &p_aabb) const { - Vector3 src_min = position; Vector3 src_max = position + size; Vector3 dst_min = p_aabb.position; @@ -163,7 +170,6 @@ inline bool AABB::encloses(const AABB &p_aabb) const { } Vector3 AABB::get_support(const Vector3 &p_normal) const { - Vector3 half_extents = size * 0.5; Vector3 ofs = position + half_extents; @@ -175,23 +181,29 @@ Vector3 AABB::get_support(const Vector3 &p_normal) const { } Vector3 AABB::get_endpoint(int p_point) const { - switch (p_point) { - case 0: return Vector3(position.x, position.y, position.z); - case 1: return Vector3(position.x, position.y, position.z + size.z); - case 2: return Vector3(position.x, position.y + size.y, position.z); - case 3: return Vector3(position.x, position.y + size.y, position.z + size.z); - case 4: return Vector3(position.x + size.x, position.y, position.z); - case 5: return Vector3(position.x + size.x, position.y, position.z + size.z); - case 6: return Vector3(position.x + size.x, position.y + size.y, position.z); - case 7: return Vector3(position.x + size.x, position.y + size.y, position.z + size.z); - }; + case 0: + return Vector3(position.x, position.y, position.z); + case 1: + return Vector3(position.x, position.y, position.z + size.z); + case 2: + return Vector3(position.x, position.y + size.y, position.z); + case 3: + return Vector3(position.x, position.y + size.y, position.z + size.z); + case 4: + return Vector3(position.x + size.x, position.y, position.z); + case 5: + return Vector3(position.x + size.x, position.y, position.z + size.z); + case 6: + return Vector3(position.x + size.x, position.y + size.y, position.z); + case 7: + return Vector3(position.x + size.x, position.y + size.y, position.z + size.z); + } ERR_FAIL_V(Vector3()); } -bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const { - +bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const { Vector3 half_extents = size * 0.5; Vector3 ofs = position + half_extents; @@ -202,15 +214,38 @@ bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) con (p.normal.y > 0) ? -half_extents.y : half_extents.y, (p.normal.z > 0) ? -half_extents.z : half_extents.z); point += ofs; - if (p.is_point_over(point)) + if (p.is_point_over(point)) { + return false; + } + } + + // Make sure all points in the shape aren't fully separated from the AABB on + // each axis. + int bad_point_counts_positive[3] = { 0 }; + int bad_point_counts_negative[3] = { 0 }; + + for (int k = 0; k < 3; k++) { + for (int i = 0; i < p_point_count; i++) { + if (p_points[i].coord[k] > ofs.coord[k] + half_extents.coord[k]) { + bad_point_counts_positive[k]++; + } + if (p_points[i].coord[k] < ofs.coord[k] - half_extents.coord[k]) { + bad_point_counts_negative[k]++; + } + } + + if (bad_point_counts_negative[k] == p_point_count) { + return false; + } + if (bad_point_counts_positive[k] == p_point_count) { return false; + } } return true; } bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const { - Vector3 half_extents = size * 0.5; Vector3 ofs = position + half_extents; @@ -221,56 +256,66 @@ bool AABB::inside_convex_shape(const Plane *p_planes, int p_plane_count) const { (p.normal.y < 0) ? -half_extents.y : half_extents.y, (p.normal.z < 0) ? -half_extents.z : half_extents.z); point += ofs; - if (p.is_point_over(point)) + if (p.is_point_over(point)) { return false; + } } return true; } bool AABB::has_point(const Vector3 &p_point) const { - - if (p_point.x < position.x) + if (p_point.x < position.x) { return false; - if (p_point.y < position.y) + } + if (p_point.y < position.y) { return false; - if (p_point.z < position.z) + } + if (p_point.z < position.z) { return false; - if (p_point.x > position.x + size.x) + } + if (p_point.x > position.x + size.x) { return false; - if (p_point.y > position.y + size.y) + } + if (p_point.y > position.y + size.y) { return false; - if (p_point.z > position.z + size.z) + } + if (p_point.z > position.z + size.z) { return false; + } return true; } inline void AABB::expand_to(const Vector3 &p_vector) { - Vector3 begin = position; Vector3 end = position + size; - if (p_vector.x < begin.x) + if (p_vector.x < begin.x) { begin.x = p_vector.x; - if (p_vector.y < begin.y) + } + if (p_vector.y < begin.y) { begin.y = p_vector.y; - if (p_vector.z < begin.z) + } + if (p_vector.z < begin.z) { begin.z = p_vector.z; + } - if (p_vector.x > end.x) + if (p_vector.x > end.x) { end.x = p_vector.x; - if (p_vector.y > end.y) + } + if (p_vector.y > end.y) { end.y = p_vector.y; - if (p_vector.z > end.z) + } + if (p_vector.z > end.z) { end.z = p_vector.z; + } position = begin; size = end - begin; } void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r_max) const { - Vector3 half_extents(size.x * 0.5, size.y * 0.5, size.z * 0.5); Vector3 center(position.x + half_extents.x, position.y + half_extents.y, position.z + half_extents.z); @@ -281,7 +326,6 @@ void AABB::project_range_in_plane(const Plane &p_plane, real_t &r_min, real_t &r } inline real_t AABB::get_longest_axis_size() const { - real_t max_size = size.x; if (size.y > max_size) { @@ -296,7 +340,6 @@ inline real_t AABB::get_longest_axis_size() const { } inline real_t AABB::get_shortest_axis_size() const { - real_t max_size = size.x; if (size.y < max_size) { @@ -311,7 +354,6 @@ inline real_t AABB::get_shortest_axis_size() const { } bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const { - real_t divx = 1.0 / p_dir.x; real_t divy = 1.0 / p_dir.y; real_t divz = 1.0 / p_dir.z; @@ -332,12 +374,15 @@ bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real tymin = (upbound.y - p_from.y) * divy; tymax = (position.y - p_from.y) * divy; } - if ((tmin > tymax) || (tymin > tmax)) + if ((tmin > tymax) || (tymin > tmax)) { return false; - if (tymin > tmin) + } + if (tymin > tmin) { tmin = tymin; - if (tymax < tmax) + } + if (tymax < tmax) { tmax = tymax; + } if (p_dir.z >= 0) { tzmin = (position.z - p_from.z) * divz; tzmax = (upbound.z - p_from.z) * divz; @@ -345,17 +390,19 @@ bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real tzmin = (upbound.z - p_from.z) * divz; tzmax = (position.z - p_from.z) * divz; } - if ((tmin > tzmax) || (tzmin > tmax)) + if ((tmin > tzmax) || (tzmin > tmax)) { return false; - if (tzmin > tmin) + } + if (tzmin > tmin) { tmin = tzmin; - if (tzmax < tmax) + } + if (tzmax < tmax) { tmax = tzmax; + } return ((tmin < t1) && (tmax > t0)); } void AABB::grow_by(real_t p_amount) { - position.x -= p_amount; position.y -= p_amount; position.z -= p_amount; diff --git a/core/math/audio_frame.cpp b/core/math/audio_frame.cpp deleted file mode 100644 index c565ea9b13..0000000000 --- a/core/math/audio_frame.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************/ -/* audio_frame.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "audio_frame.h" diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index e1dbb385e4..91f533eafb 100644 --- a/core/math/audio_frame.h +++ b/core/math/audio_frame.h @@ -48,7 +48,6 @@ static inline float undenormalise(volatile float f) { } struct AudioFrame { - //left and right samples float l, r; @@ -104,8 +103,7 @@ struct AudioFrame { r = ::undenormalise(r); } - _FORCE_INLINE_ AudioFrame linear_interpolate(const AudioFrame &p_b, float p_t) const { - + _FORCE_INLINE_ AudioFrame lerp(const AudioFrame &p_b, float p_t) const { AudioFrame res = *this; res.l += (p_t * (p_b.l - l)); diff --git a/core/math/basis.cpp b/core/math/basis.cpp index 0f519a20d8..df5199b0f9 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -38,16 +38,13 @@ (elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1]) void Basis::from_z(const Vector3 &p_z) { - if (Math::abs(p_z.z) > Math_SQRT12) { - // choose p in y-z plane real_t a = p_z[1] * p_z[1] + p_z[2] * p_z[2]; real_t k = 1.0 / Math::sqrt(a); elements[0] = Vector3(0, -p_z[2] * k, p_z[1] * k); elements[1] = Vector3(a * k, -p_z[0] * elements[0][2], p_z[0] * elements[0][1]); } else { - // choose p in x-y plane real_t a = p_z.x * p_z.x + p_z.y * p_z.y; real_t k = 1.0 / Math::sqrt(a); @@ -58,7 +55,6 @@ void Basis::from_z(const Vector3 &p_z) { } void Basis::invert() { - real_t co[3] = { cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1) }; @@ -76,7 +72,6 @@ void Basis::invert() { } void Basis::orthonormalize() { - // Gram-Schmidt Process Vector3 x = get_axis(0); @@ -95,7 +90,6 @@ void Basis::orthonormalize() { } Basis Basis::orthonormalized() const { - Basis c = *this; c.orthonormalize(); return c; @@ -120,19 +114,20 @@ bool Basis::is_rotation() const { } bool Basis::is_symmetric() const { - - if (!Math::is_equal_approx_ratio(elements[0][1], elements[1][0], UNIT_EPSILON)) + if (!Math::is_equal_approx_ratio(elements[0][1], elements[1][0], UNIT_EPSILON)) { return false; - if (!Math::is_equal_approx_ratio(elements[0][2], elements[2][0], UNIT_EPSILON)) + } + if (!Math::is_equal_approx_ratio(elements[0][2], elements[2][0], UNIT_EPSILON)) { return false; - if (!Math::is_equal_approx_ratio(elements[1][2], elements[2][1], UNIT_EPSILON)) + } + if (!Math::is_equal_approx_ratio(elements[1][2], elements[2][1], UNIT_EPSILON)) { return false; + } return true; } Basis Basis::diagonalize() { - //NOTE: only implemented for symmetric matrices //with the Jacobi iterative method method #ifdef MATH_CHECKS @@ -193,21 +188,18 @@ Basis Basis::diagonalize() { } Basis Basis::inverse() const { - Basis inv = *this; inv.invert(); return inv; } void Basis::transpose() { - SWAP(elements[0][1], elements[1][0]); SWAP(elements[0][2], elements[2][0]); SWAP(elements[1][2], elements[2][1]); } Basis Basis::transposed() const { - Basis tr = *this; tr.transpose(); return tr; @@ -216,7 +208,6 @@ Basis Basis::transposed() const { // Multiplies the matrix from left by the scaling matrix: M -> S.M // See the comment for Basis::rotated for further explanation. void Basis::scale(const Vector3 &p_scale) { - elements[0][0] *= p_scale.x; elements[0][1] *= p_scale.x; elements[0][2] *= p_scale.x; @@ -260,7 +251,6 @@ Basis Basis::scaled_local(const Vector3 &p_scale) const { } Vector3 Basis::get_scale_abs() 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(), @@ -340,8 +330,8 @@ void Basis::rotate_local(const Vector3 &p_axis, real_t p_phi) { // M -> (M.R.Minv).M = M.R. *this = rotated_local(p_axis, p_phi); } -Basis Basis::rotated_local(const Vector3 &p_axis, real_t p_phi) const { +Basis Basis::rotated_local(const Vector3 &p_axis, real_t p_phi) const { return (*this) * Basis(p_axis, p_phi); } @@ -430,7 +420,6 @@ void Basis::get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) cons // the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates // around the z-axis by a and so on. Vector3 Basis::get_euler_xyz() const { - // Euler angles in XYZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -439,12 +428,9 @@ Vector3 Basis::get_euler_xyz() const { // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy Vector3 euler; -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(!is_rotation(), euler); -#endif real_t sy = elements[0][2]; - if (sy < 1.0) { - if (sy > -1.0) { + if (sy < (1.0 - CMP_EPSILON)) { + if (sy > -(1.0 - CMP_EPSILON)) { // 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 (human friendlier in editor and scripts) @@ -457,12 +443,12 @@ Vector3 Basis::get_euler_xyz() const { euler.z = Math::atan2(-elements[0][1], elements[0][0]); } } else { - euler.x = -Math::atan2(elements[0][1], elements[1][1]); + euler.x = Math::atan2(elements[2][1], elements[1][1]); euler.y = -Math_PI / 2.0; euler.z = 0.0; } } else { - euler.x = Math::atan2(elements[0][1], elements[1][1]); + euler.x = Math::atan2(elements[2][1], elements[1][1]); euler.y = Math_PI / 2.0; euler.z = 0.0; } @@ -474,7 +460,6 @@ Vector3 Basis::get_euler_xyz() const { // and similar for other axes. // The current implementation uses XYZ convention (Z is the first rotation). void Basis::set_euler_xyz(const Vector3 &p_euler) { - real_t c, s; c = Math::cos(p_euler.x); @@ -493,16 +478,106 @@ void Basis::set_euler_xyz(const Vector3 &p_euler) { *this = xmat * (ymat * zmat); } +Vector3 Basis::get_euler_xzy() const { + // Euler angles in XZY convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cz*cy -sz cz*sy + // sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx + // cy*sx*sz cz*sx cx*cy+sx*sz*sy + + Vector3 euler; + real_t sz = elements[0][1]; + if (sz < (1.0 - CMP_EPSILON)) { + if (sz > -(1.0 - CMP_EPSILON)) { + euler.x = Math::atan2(elements[2][1], elements[1][1]); + euler.y = Math::atan2(elements[0][2], elements[0][0]); + euler.z = Math::asin(-sz); + } else { + // It's -1 + euler.x = -Math::atan2(elements[1][2], elements[2][2]); + euler.y = 0.0; + euler.z = Math_PI / 2.0; + } + } else { + // It's 1 + euler.x = -Math::atan2(elements[1][2], elements[2][2]); + euler.y = 0.0; + euler.z = -Math_PI / 2.0; + } + return euler; +} + +void Basis::set_euler_xzy(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = xmat * zmat * ymat; +} + +Vector3 Basis::get_euler_yzx() const { + // Euler angles in YZX convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx + // sz cz*cx -cz*sx + // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx + + Vector3 euler; + real_t sz = elements[1][0]; + if (sz < (1.0 - CMP_EPSILON)) { + if (sz > -(1.0 - CMP_EPSILON)) { + euler.x = Math::atan2(-elements[1][2], elements[1][1]); + euler.y = Math::atan2(-elements[2][0], elements[0][0]); + euler.z = Math::asin(sz); + } else { + // It's -1 + euler.x = Math::atan2(elements[2][1], elements[2][2]); + euler.y = 0.0; + euler.z = -Math_PI / 2.0; + } + } else { + // It's 1 + euler.x = Math::atan2(elements[2][1], elements[2][2]); + euler.y = 0.0; + euler.z = Math_PI / 2.0; + } + return euler; +} + +void Basis::set_euler_yzx(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = ymat * zmat * xmat; +} + // get_euler_yxz returns a vector containing the Euler angles in the YXZ convention, // as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned // as the x, y, and z components of a Vector3 respectively. Vector3 Basis::get_euler_yxz() const { - - /* checking this is a bad idea, because obtaining from scaled transform is a valid use case -#ifdef MATH_CHECKS - ERR_FAIL_COND(!is_rotation()); -#endif -*/ // Euler angles in YXZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -514,8 +589,8 @@ Vector3 Basis::get_euler_yxz() const { real_t m12 = elements[1][2]; - if (m12 < 1) { - if (m12 > -1) { + if (m12 < (1 - CMP_EPSILON)) { + if (m12 > -(1 - CMP_EPSILON)) { // 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 (human friendlier in editor and scripts) @@ -529,12 +604,12 @@ Vector3 Basis::get_euler_yxz() const { } } else { // m12 == -1 euler.x = Math_PI * 0.5; - euler.y = -atan2(-elements[0][1], elements[0][0]); + euler.y = atan2(elements[0][1], elements[0][0]); euler.z = 0; } } else { // m12 == 1 euler.x = -Math_PI * 0.5; - euler.y = -atan2(-elements[0][1], elements[0][0]); + euler.y = -atan2(elements[0][1], elements[0][0]); euler.z = 0; } @@ -546,7 +621,6 @@ Vector3 Basis::get_euler_yxz() const { // and similar for other axes. // The current implementation uses YXZ convention (Z is the first rotation). void Basis::set_euler_yxz(const Vector3 &p_euler) { - real_t c, s; c = Math::cos(p_euler.x); @@ -565,17 +639,110 @@ void Basis::set_euler_yxz(const Vector3 &p_euler) { *this = ymat * xmat * zmat; } -bool Basis::is_equal_approx(const Basis &p_basis) const { +Vector3 Basis::get_euler_zxy() const { + // Euler angles in ZXY convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx + // cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx + // -cx*sy sx cx*cy + Vector3 euler; + real_t sx = elements[2][1]; + if (sx < (1.0 - CMP_EPSILON)) { + if (sx > -(1.0 - CMP_EPSILON)) { + euler.x = Math::asin(sx); + euler.y = Math::atan2(-elements[2][0], elements[2][2]); + euler.z = Math::atan2(-elements[0][1], elements[1][1]); + } else { + // It's -1 + euler.x = -Math_PI / 2.0; + euler.y = Math::atan2(elements[0][2], elements[0][0]); + euler.z = 0; + } + } else { + // It's 1 + euler.x = Math_PI / 2.0; + euler.y = Math::atan2(elements[0][2], elements[0][0]); + euler.z = 0; + } + return euler; +} + +void Basis::set_euler_zxy(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = zmat * xmat * ymat; +} + +Vector3 Basis::get_euler_zyx() const { + // Euler angles in ZYX convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy + // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx + // -sy cy*sx cy*cx + Vector3 euler; + real_t sy = elements[2][0]; + if (sy < (1.0 - CMP_EPSILON)) { + if (sy > -(1.0 - CMP_EPSILON)) { + euler.x = Math::atan2(elements[2][1], elements[2][2]); + euler.y = Math::asin(-sy); + euler.z = Math::atan2(elements[1][0], elements[0][0]); + } else { + // It's -1 + euler.x = 0; + euler.y = Math_PI / 2.0; + euler.z = -Math::atan2(elements[0][1], elements[1][1]); + } + } else { + // It's 1 + euler.x = 0; + euler.y = -Math_PI / 2.0; + euler.z = -Math::atan2(elements[0][1], elements[1][1]); + } + return euler; +} + +void Basis::set_euler_zyx(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = zmat * ymat * xmat; +} + +bool Basis::is_equal_approx(const Basis &p_basis) const { return elements[0].is_equal_approx(p_basis.elements[0]) && elements[1].is_equal_approx(p_basis.elements[1]) && elements[2].is_equal_approx(p_basis.elements[2]); } bool Basis::is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsilon) const { - for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], p_epsilon)) + if (!Math::is_equal_approx_ratio(a.elements[i][j], b.elements[i][j], p_epsilon)) { return false; + } } } @@ -583,11 +750,11 @@ bool Basis::is_equal_approx_ratio(const Basis &a, const Basis &b, real_t p_epsil } bool Basis::operator==(const Basis &p_matrix) const { - for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - if (elements[i][j] != p_matrix.elements[i][j]) + if (elements[i][j] != p_matrix.elements[i][j]) { return false; + } } } @@ -595,19 +762,16 @@ bool Basis::operator==(const Basis &p_matrix) const { } bool Basis::operator!=(const Basis &p_matrix) const { - return (!(*this == p_matrix)); } Basis::operator String() const { - String mtx; for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - - if (i != 0 || j != 0) + if (i != 0 || j != 0) { mtx += ", "; + } mtx += rtos(elements[i][j]); } @@ -617,7 +781,6 @@ Basis::operator String() const { } Quat Basis::get_quat() const { - #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_rotation(), Quat(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quat() or call orthonormalized() instead."); #endif @@ -681,35 +844,33 @@ static const Basis _ortho_bases[24] = { }; int Basis::get_orthogonal_index() const { - //could be sped up if i come up with a way Basis orth = *this; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - real_t v = orth[i][j]; - if (v > 0.5) + if (v > 0.5) { v = 1.0; - else if (v < -0.5) + } else if (v < -0.5) { v = -1.0; - else + } else { v = 0; + } orth[i][j] = v; } } for (int i = 0; i < 24; i++) { - - if (_ortho_bases[i] == orth) + if (_ortho_bases[i] == orth) { return i; + } } return 0; } void Basis::set_orthogonal_index(int p_index) { - //there only exist 24 orthogonal bases in r3 ERR_FAIL_INDEX(p_index, 24); @@ -783,7 +944,9 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { real_t s = Math::sqrt((elements[1][2] - elements[2][1]) * (elements[1][2] - elements[2][1]) + (elements[2][0] - elements[0][2]) * (elements[2][0] - elements[0][2]) + (elements[0][1] - elements[1][0]) * (elements[0][1] - elements[1][0])); // s=|axis||sin(angle)|, used to normalise angle = Math::acos((elements[0][0] + elements[1][1] + elements[2][2] - 1) / 2); - if (angle < 0) s = -s; + if (angle < 0) { + s = -s; + } x = (elements[2][1] - elements[1][2]) / s; y = (elements[0][2] - elements[2][0]) / s; z = (elements[1][0] - elements[0][1]) / s; @@ -793,7 +956,6 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { } void Basis::set_quat(const Quat &p_quat) { - real_t d = p_quat.length_squared(); real_t s = 2.0 / d; real_t xs = p_quat.x * s, ys = p_quat.y * s, zs = p_quat.z * s; @@ -865,7 +1027,6 @@ void Basis::set_diagonal(const Vector3 &p_diag) { } Basis Basis::slerp(const Basis &target, const real_t &t) const { - //consider scale Quat from(*this); Quat to(target); @@ -877,3 +1038,113 @@ Basis Basis::slerp(const Basis &target, const real_t &t) const { return b; } + +void Basis::rotate_sh(real_t *p_values) { + // code by John Hable + // http://filmicworlds.com/blog/simple-and-fast-spherical-harmonic-rotation/ + // this code is Public Domain + + const static real_t s_c3 = 0.94617469575; // (3*sqrt(5))/(4*sqrt(pi)) + const static real_t s_c4 = -0.31539156525; // (-sqrt(5))/(4*sqrt(pi)) + const static real_t s_c5 = 0.54627421529; // (sqrt(15))/(4*sqrt(pi)) + + const static real_t s_c_scale = 1.0 / 0.91529123286551084; + const static real_t s_c_scale_inv = 0.91529123286551084; + + const static real_t s_rc2 = 1.5853309190550713 * s_c_scale; + const static real_t s_c4_div_c3 = s_c4 / s_c3; + const static real_t s_c4_div_c3_x2 = (s_c4 / s_c3) * 2.0; + + const static real_t s_scale_dst2 = s_c3 * s_c_scale_inv; + const static real_t s_scale_dst4 = s_c5 * s_c_scale_inv; + + real_t src[9] = { p_values[0], p_values[1], p_values[2], p_values[3], p_values[4], p_values[5], p_values[6], p_values[7], p_values[8] }; + + real_t m00 = elements[0][0]; + real_t m01 = elements[0][1]; + real_t m02 = elements[0][2]; + real_t m10 = elements[1][0]; + real_t m11 = elements[1][1]; + real_t m12 = elements[1][2]; + real_t m20 = elements[2][0]; + real_t m21 = elements[2][1]; + real_t m22 = elements[2][2]; + + p_values[0] = src[0]; + p_values[1] = m11 * src[1] - m12 * src[2] + m10 * src[3]; + p_values[2] = -m21 * src[1] + m22 * src[2] - m20 * src[3]; + p_values[3] = m01 * src[1] - m02 * src[2] + m00 * src[3]; + + real_t sh0 = src[7] + src[8] + src[8] - src[5]; + real_t sh1 = src[4] + s_rc2 * src[6] + src[7] + src[8]; + real_t sh2 = src[4]; + real_t sh3 = -src[7]; + real_t sh4 = -src[5]; + + // Rotations. R0 and R1 just use the raw matrix columns + real_t r2x = m00 + m01; + real_t r2y = m10 + m11; + real_t r2z = m20 + m21; + + real_t r3x = m00 + m02; + real_t r3y = m10 + m12; + real_t r3z = m20 + m22; + + real_t r4x = m01 + m02; + real_t r4y = m11 + m12; + real_t r4z = m21 + m22; + + // dense matrix multiplication one column at a time + + // column 0 + real_t sh0_x = sh0 * m00; + real_t sh0_y = sh0 * m10; + real_t d0 = sh0_x * m10; + real_t d1 = sh0_y * m20; + real_t d2 = sh0 * (m20 * m20 + s_c4_div_c3); + real_t d3 = sh0_x * m20; + real_t d4 = sh0_x * m00 - sh0_y * m10; + + // column 1 + real_t sh1_x = sh1 * m02; + real_t sh1_y = sh1 * m12; + d0 += sh1_x * m12; + d1 += sh1_y * m22; + d2 += sh1 * (m22 * m22 + s_c4_div_c3); + d3 += sh1_x * m22; + d4 += sh1_x * m02 - sh1_y * m12; + + // column 2 + real_t sh2_x = sh2 * r2x; + real_t sh2_y = sh2 * r2y; + d0 += sh2_x * r2y; + d1 += sh2_y * r2z; + d2 += sh2 * (r2z * r2z + s_c4_div_c3_x2); + d3 += sh2_x * r2z; + d4 += sh2_x * r2x - sh2_y * r2y; + + // column 3 + real_t sh3_x = sh3 * r3x; + real_t sh3_y = sh3 * r3y; + d0 += sh3_x * r3y; + d1 += sh3_y * r3z; + d2 += sh3 * (r3z * r3z + s_c4_div_c3_x2); + d3 += sh3_x * r3z; + d4 += sh3_x * r3x - sh3_y * r3y; + + // column 4 + real_t sh4_x = sh4 * r4x; + real_t sh4_y = sh4 * r4y; + d0 += sh4_x * r4y; + d1 += sh4_y * r4z; + d2 += sh4 * (r4z * r4z + s_c4_div_c3_x2); + d3 += sh4_x * r4z; + d4 += sh4_x * r4x - sh4_y * r4y; + + // extra multipliers + p_values[4] = d0; + p_values[5] = -d1; + p_values[6] = d2 * s_scale_dst2; + p_values[7] = -d3; + p_values[8] = d4 * s_scale_dst4; +} diff --git a/core/math/basis.h b/core/math/basis.h index 0261cf67c6..985fb0e44f 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -39,11 +39,9 @@ public: Vector3 elements[3]; _FORCE_INLINE_ const Vector3 &operator[](int axis) const { - return elements[axis]; } _FORCE_INLINE_ Vector3 &operator[](int axis) { - return elements[axis]; } @@ -90,9 +88,22 @@ public: Vector3 get_euler_xyz() const; void set_euler_xyz(const Vector3 &p_euler); + + Vector3 get_euler_xzy() const; + void set_euler_xzy(const Vector3 &p_euler); + + Vector3 get_euler_yzx() const; + void set_euler_yzx(const Vector3 &p_euler); + Vector3 get_euler_yxz() const; void set_euler_yxz(const Vector3 &p_euler); + Vector3 get_euler_zxy() const; + void set_euler_zxy(const Vector3 &p_euler); + + Vector3 get_euler_zyx() const; + void set_euler_zyx(const Vector3 &p_euler); + Quat get_quat() const; void set_quat(const Quat &p_quat); @@ -159,13 +170,13 @@ public: bool is_rotation() const; Basis slerp(const Basis &target, const real_t &t) const; + void rotate_sh(real_t *p_values); operator String() const; /* create / set */ _FORCE_INLINE_ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { - elements[0][0] = xx; elements[0][1] = xy; elements[0][2] = xz; @@ -177,18 +188,15 @@ public: elements[2][2] = zz; } _FORCE_INLINE_ void set(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) { - set_axis(0, p_x); set_axis(1, p_y); set_axis(2, p_z); } _FORCE_INLINE_ Vector3 get_column(int i) const { - return Vector3(elements[0][i], elements[1][i], elements[2][i]); } _FORCE_INLINE_ Vector3 get_row(int i) const { - return Vector3(elements[i][0], elements[i][1], elements[i][2]); } _FORCE_INLINE_ Vector3 get_main_diagonal() const { @@ -220,7 +228,6 @@ public: elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z); } Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { - set(xx, xy, xz, yx, yy, yz, zx, zy, zz); } @@ -248,7 +255,6 @@ public: } _FORCE_INLINE_ Basis() { - elements[0][0] = 1; elements[0][1] = 0; elements[0][2] = 0; @@ -262,7 +268,6 @@ public: }; _FORCE_INLINE_ void Basis::operator*=(const Basis &p_matrix) { - set( p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]), p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]), @@ -270,7 +275,6 @@ _FORCE_INLINE_ void Basis::operator*=(const Basis &p_matrix) { } _FORCE_INLINE_ Basis Basis::operator*(const Basis &p_matrix) const { - return Basis( p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]), p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]), @@ -278,49 +282,42 @@ _FORCE_INLINE_ Basis Basis::operator*(const Basis &p_matrix) const { } _FORCE_INLINE_ void Basis::operator+=(const Basis &p_matrix) { - elements[0] += p_matrix.elements[0]; elements[1] += p_matrix.elements[1]; elements[2] += p_matrix.elements[2]; } _FORCE_INLINE_ Basis Basis::operator+(const Basis &p_matrix) const { - Basis ret(*this); ret += p_matrix; return ret; } _FORCE_INLINE_ void Basis::operator-=(const Basis &p_matrix) { - elements[0] -= p_matrix.elements[0]; elements[1] -= p_matrix.elements[1]; elements[2] -= p_matrix.elements[2]; } _FORCE_INLINE_ Basis Basis::operator-(const Basis &p_matrix) const { - Basis ret(*this); ret -= p_matrix; return ret; } _FORCE_INLINE_ void Basis::operator*=(real_t p_val) { - elements[0] *= p_val; elements[1] *= p_val; elements[2] *= p_val; } _FORCE_INLINE_ Basis Basis::operator*(real_t p_val) const { - Basis ret(*this); ret *= p_val; return ret; } Vector3 Basis::xform(const Vector3 &p_vector) const { - return Vector3( elements[0].dot(p_vector), elements[1].dot(p_vector), @@ -328,7 +325,6 @@ Vector3 Basis::xform(const Vector3 &p_vector) const { } Vector3 Basis::xform_inv(const Vector3 &p_vector) const { - return Vector3( (elements[0][0] * p_vector.x) + (elements[1][0] * p_vector.y) + (elements[2][0] * p_vector.z), (elements[0][1] * p_vector.x) + (elements[1][1] * p_vector.y) + (elements[2][1] * p_vector.z), @@ -336,7 +332,6 @@ Vector3 Basis::xform_inv(const Vector3 &p_vector) const { } real_t Basis::determinant() const { - return elements[0][0] * (elements[1][1] * elements[2][2] - elements[2][1] * elements[1][2]) - elements[1][0] * (elements[0][1] * elements[2][2] - elements[2][1] * elements[0][2]) + elements[2][0] * (elements[0][1] * elements[1][2] - elements[1][1] * elements[0][2]); diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index c36070e47f..22ab83f358 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -33,30 +33,38 @@ #include "core/math/math_funcs.h" #include "core/print_string.h" -void CameraMatrix::set_identity() { +float CameraMatrix::determinant() const { + return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] - + matrix[0][3] * matrix[1][1] * matrix[2][2] * matrix[3][0] + matrix[0][1] * matrix[1][3] * matrix[2][2] * matrix[3][0] + + matrix[0][2] * matrix[1][1] * matrix[2][3] * matrix[3][0] - matrix[0][1] * matrix[1][2] * matrix[2][3] * matrix[3][0] - + matrix[0][3] * matrix[1][2] * matrix[2][0] * matrix[3][1] + matrix[0][2] * matrix[1][3] * matrix[2][0] * matrix[3][1] + + matrix[0][3] * matrix[1][0] * matrix[2][2] * matrix[3][1] - matrix[0][0] * matrix[1][3] * matrix[2][2] * matrix[3][1] - + matrix[0][2] * matrix[1][0] * matrix[2][3] * matrix[3][1] + matrix[0][0] * matrix[1][2] * matrix[2][3] * matrix[3][1] + + matrix[0][3] * matrix[1][1] * matrix[2][0] * matrix[3][2] - matrix[0][1] * matrix[1][3] * matrix[2][0] * matrix[3][2] - + matrix[0][3] * matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[0][0] * matrix[1][3] * matrix[2][1] * matrix[3][2] + + matrix[0][1] * matrix[1][0] * matrix[2][3] * matrix[3][2] - matrix[0][0] * matrix[1][1] * matrix[2][3] * matrix[3][2] - + matrix[0][2] * matrix[1][1] * matrix[2][0] * matrix[3][3] + matrix[0][1] * matrix[1][2] * matrix[2][0] * matrix[3][3] + + matrix[0][2] * matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[0][0] * matrix[1][2] * matrix[2][1] * matrix[3][3] - + matrix[0][1] * matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[0][0] * matrix[1][1] * matrix[2][2] * matrix[3][3]; +} +void CameraMatrix::set_identity() { for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - matrix[i][j] = (i == j) ? 1 : 0; } } } void CameraMatrix::set_zero() { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - matrix[i][j] = 0; } } } Plane CameraMatrix::xform4(const Plane &p_vec4) const { - Plane ret; ret.normal.x = matrix[0][0] * p_vec4.normal.x + matrix[1][0] * p_vec4.normal.y + matrix[2][0] * p_vec4.normal.z + matrix[3][0] * p_vec4.d; @@ -67,7 +75,6 @@ Plane CameraMatrix::xform4(const Plane &p_vec4) const { } void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov) { - if (p_flip_fov) { p_fovy_degrees = get_fovy(p_fovy_degrees, 1.0 / p_aspect); } @@ -109,18 +116,18 @@ void CameraMatrix::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_ left = -xmax + frustumshift; right = xmax + frustumshift; modeltranslation = p_intraocular_dist / 2.0; - }; break; + } break; case 2: { // right eye left = -xmax - frustumshift; right = xmax - frustumshift; modeltranslation = -p_intraocular_dist / 2.0; - }; break; + } break; default: { // mono, should give the same result as set_perspective(p_fovy_degrees,p_aspect,p_z_near,p_z_far,p_flip_fov) left = -xmax; right = xmax; modeltranslation = 0.0; - }; break; - }; + } break; + } set_frustum(left, right, -ymax, ymax, p_z_near, p_z_far); @@ -150,17 +157,16 @@ void CameraMatrix::set_for_hmd(int p_eye, real_t p_aspect, real_t p_intraocular_ switch (p_eye) { case 1: { // left eye set_frustum(-f2 * p_z_near, f1 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far); - }; break; + } break; case 2: { // right eye set_frustum(-f1 * p_z_near, f2 * p_z_near, -f3 * p_z_near, f3 * p_z_near, p_z_near, p_z_far); - }; break; + } break; default: { // mono, does not apply here! - }; break; - }; -}; + } break; + } +} void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar) { - set_identity(); matrix[0][0] = 2.0 / (p_right - p_left); @@ -173,7 +179,6 @@ void CameraMatrix::set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom } void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov) { - if (!p_flip_fov) { p_size *= p_aspect; } @@ -182,7 +187,6 @@ void CameraMatrix::set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear } void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far) { - ERR_FAIL_COND(p_right <= p_left); ERR_FAIL_COND(p_top <= p_bottom); ERR_FAIL_COND(p_far <= p_near); @@ -223,7 +227,6 @@ void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, } real_t CameraMatrix::get_z_far() const { - const real_t *matrix = (const real_t *)this->matrix; Plane new_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], @@ -235,8 +238,8 @@ real_t CameraMatrix::get_z_far() const { return new_plane.d; } -real_t CameraMatrix::get_z_near() const { +real_t CameraMatrix::get_z_near() const { const real_t *matrix = (const real_t *)this->matrix; Plane new_plane = Plane(matrix[3] + matrix[2], matrix[7] + matrix[6], @@ -248,7 +251,6 @@ real_t CameraMatrix::get_z_near() const { } Vector2 CameraMatrix::get_viewport_half_extents() const { - const real_t *matrix = (const real_t *)this->matrix; ///////--- Near Plane ---/////// Plane near_plane = Plane(matrix[3] + matrix[2], @@ -277,7 +279,6 @@ Vector2 CameraMatrix::get_viewport_half_extents() const { } void CameraMatrix::get_far_plane_size(real_t &r_width, real_t &r_height) const { - const real_t *matrix = (const real_t *)this->matrix; ///////--- Far Plane ---/////// Plane far_plane = Plane(matrix[3] - matrix[2], @@ -307,7 +308,6 @@ void CameraMatrix::get_far_plane_size(real_t &r_width, real_t &r_height) const { } bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8points) const { - Vector<Plane> planes = get_projection_planes(Transform()); const Planes intersections[8][3] = { { PLANE_FAR, PLANE_LEFT, PLANE_TOP }, @@ -321,7 +321,6 @@ bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8point }; for (int i = 0; i < 8; i++) { - 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); @@ -332,7 +331,6 @@ bool CameraMatrix::get_endpoints(const Transform &p_transform, Vector3 *p_8point } Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) const { - /** Fast Plane Extraction from combined modelview/projection matrices. * References: * https://web.archive.org/web/20011221205252/http://www.markmorley.com/opengl/frustumculling.html @@ -415,14 +413,12 @@ Vector<Plane> CameraMatrix::get_projection_planes(const Transform &p_transform) } CameraMatrix CameraMatrix::inverse() const { - CameraMatrix cm = *this; cm.invert(); return cm; } void CameraMatrix::invert() { - int i, j, k; int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */ real_t pvt_val; /* Value of current pivot element */ @@ -473,20 +469,26 @@ void CameraMatrix::invert() { /** Divide column by minus pivot value **/ for (i = 0; i < 4; i++) { - if (i != k) matrix[i][k] /= (-pvt_val); + if (i != k) { + matrix[i][k] /= (-pvt_val); + } } /** Reduce the matrix **/ for (i = 0; i < 4; i++) { hold = matrix[i][k]; for (j = 0; j < 4; j++) { - if (i != k && j != k) matrix[i][j] += hold * matrix[k][j]; + if (i != k && j != k) { + matrix[i][j] += hold * matrix[k][j]; + } } } /** Divide row by pivot **/ for (j = 0; j < 4; j++) { - if (j != k) matrix[k][j] /= pvt_val; + if (j != k) { + matrix[k][j] /= pvt_val; + } } /** Replace pivot by reciprocal (at last we can touch it). **/ @@ -506,12 +508,13 @@ void CameraMatrix::invert() { } j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */ - if (j != k) /* If columns are different */ + if (j != k) { /* If columns are different */ for (i = 0; i < 4; i++) { hold = matrix[i][k]; matrix[i][k] = -matrix[i][j]; matrix[i][j] = hold; } + } } } @@ -522,19 +525,18 @@ void CameraMatrix::flip_y() { } CameraMatrix::CameraMatrix() { - set_identity(); } CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const { - CameraMatrix new_matrix; for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { real_t ab = 0; - for (int k = 0; k < 4; k++) + for (int k = 0; k < 4; k++) { ab += matrix[k][i] * p_matrix.matrix[j][k]; + } new_matrix.matrix[j][i] = ab; } } @@ -543,7 +545,6 @@ CameraMatrix CameraMatrix::operator*(const CameraMatrix &p_matrix) const { } void CameraMatrix::set_depth_correction(bool p_flip_y) { - real_t *m = &matrix[0][0]; m[0] = 1; @@ -565,7 +566,6 @@ void CameraMatrix::set_depth_correction(bool p_flip_y) { } void CameraMatrix::set_light_bias() { - real_t *m = &matrix[0][0]; m[0] = 0.5; @@ -587,7 +587,6 @@ void CameraMatrix::set_light_bias() { } void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) { - real_t *m = &matrix[0][0]; m[0] = p_rect.size.width; @@ -609,30 +608,28 @@ void CameraMatrix::set_light_atlas_rect(const Rect2 &p_rect) { } CameraMatrix::operator String() const { - String str; - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { str += String((j > 0) ? ", " : "\n") + rtos(matrix[i][j]); + } + } return str; } real_t CameraMatrix::get_aspect() const { - Vector2 vp_he = get_viewport_half_extents(); return vp_he.x / vp_he.y; } int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const { - Vector3 result = xform(Vector3(1, 0, -1)); return int((result.x * 0.5 + 0.5) * p_for_pixel_width); } bool CameraMatrix::is_orthogonal() const { - return matrix[3][3] == 1.0; } @@ -660,7 +657,6 @@ real_t CameraMatrix::get_fov() const { } void CameraMatrix::make_scale(const Vector3 &p_scale) { - set_identity(); matrix[0][0] = p_scale.x; matrix[1][1] = p_scale.y; @@ -668,7 +664,6 @@ void CameraMatrix::make_scale(const Vector3 &p_scale) { } void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) { - Vector3 min = p_aabb.position; Vector3 max = p_aabb.position + p_aabb.size; @@ -694,7 +689,6 @@ void CameraMatrix::scale_translate_to_fit(const AABB &p_aabb) { } CameraMatrix::operator Transform() const { - Transform tr; const real_t *m = &matrix[0][0]; @@ -718,7 +712,6 @@ CameraMatrix::operator Transform() const { } CameraMatrix::CameraMatrix(const Transform &p_transform) { - const Transform &tr = p_transform; real_t *m = &matrix[0][0]; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index c10193bc84..49fdecae02 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -35,7 +35,6 @@ #include "core/math/transform.h" struct CameraMatrix { - enum Planes { PLANE_NEAR, PLANE_FAR, @@ -47,6 +46,7 @@ struct CameraMatrix { real_t matrix[4][4]; + float determinant() const; void set_identity(); void set_zero(); void set_light_bias(); @@ -61,7 +61,6 @@ struct CameraMatrix { void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false); static real_t get_fovy(real_t p_fovx, real_t p_aspect) { - return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0); } @@ -115,7 +114,6 @@ struct CameraMatrix { }; Vector3 CameraMatrix::xform(const Vector3 &p_vec3) const { - Vector3 ret; ret.x = matrix[0][0] * p_vec3.x + matrix[1][0] * p_vec3.y + matrix[2][0] * p_vec3.z + matrix[3][0]; ret.y = matrix[0][1] * p_vec3.x + matrix[1][1] * p_vec3.y + matrix[2][1] * p_vec3.z + matrix[3][1]; diff --git a/core/math/delaunay.h b/core/math/delaunay_2d.h index 29f84210d2..d637671686 100644 --- a/core/math/delaunay.h +++ b/core/math/delaunay_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* delaunay.h */ +/* delaunay_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,39 +28,35 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef DELAUNAY_H -#define DELAUNAY_H +#ifndef DELAUNAY_2D_H +#define DELAUNAY_2D_H #include "core/math/rect2.h" class Delaunay2D { public: struct Triangle { - int points[3]; - bool bad; - Triangle() { bad = false; } + bool bad = false; + Triangle() {} Triangle(int p_a, int p_b, int p_c) { points[0] = p_a; points[1] = p_b; points[2] = p_c; - bad = false; } }; struct Edge { int edge[2]; - bool bad; - Edge() { bad = false; } + bool bad = false; + Edge() {} Edge(int p_a, int p_b) { - bad = false; edge[0] = p_a; edge[1] = p_b; } }; static bool circum_circle_contains(const Vector<Vector2> &p_vertices, const Triangle &p_triangle, int p_vertex) { - Vector2 p1 = p_vertices[p_triangle.points[0]]; Vector2 p2 = p_vertices[p_triangle.points[1]]; Vector2 p3 = p_vertices[p_triangle.points[2]]; @@ -92,7 +88,6 @@ public: } static Vector<Triangle> triangulate(const Vector<Vector2> &p_points) { - Vector<Vector2> points = p_points; Vector<Triangle> triangles; @@ -115,9 +110,6 @@ public: triangles.push_back(Triangle(p_points.size() + 0, p_points.size() + 1, p_points.size() + 2)); for (int i = 0; i < p_points.size(); i++) { - //std::cout << "Traitement du point " << *p << std::endl; - //std::cout << "_triangles contains " << _triangles.size() << " elements" << std::endl; - Vector<Edge> polygon; for (int j = 0; j < triangles.size(); j++) { @@ -146,7 +138,6 @@ public: } for (int j = 0; j < polygon.size(); j++) { - if (polygon[j].bad) { continue; } @@ -172,4 +163,4 @@ public: } }; -#endif // DELAUNAY_H +#endif // DELAUNAY_2D_H diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h new file mode 100644 index 0000000000..014b4c4621 --- /dev/null +++ b/core/math/delaunay_3d.h @@ -0,0 +1,408 @@ +/*************************************************************************/ +/* delaunay_3d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DELAUNAY_3D_H +#define DELAUNAY_3D_H + +#include "core/local_vector.h" +#include "core/math/aabb.h" +#include "core/math/camera_matrix.h" +#include "core/math/vector3.h" +#include "core/oa_hash_map.h" +#include "core/os/file_access.h" +#include "core/print_string.h" +#include "core/variant.h" +#include "core/vector.h" + +#include "thirdparty/misc/r128.h" + +class Delaunay3D { + struct Simplex; + + enum { + ACCEL_GRID_SIZE = 16 + }; + struct GridPos { + Vector3i pos; + List<Simplex *>::Element *E = nullptr; + }; + + struct Simplex { + uint32_t points[4]; + R128 circum_center_x; + R128 circum_center_y; + R128 circum_center_z; + R128 circum_r2; + LocalVector<GridPos> grid_positions; + List<Simplex *>::Element *SE = nullptr; + + _FORCE_INLINE_ Simplex() {} + _FORCE_INLINE_ Simplex(uint32_t p_a, uint32_t p_b, uint32_t p_c, uint32_t p_d) { + points[0] = p_a; + points[1] = p_b; + points[2] = p_c; + points[3] = p_d; + } + }; + + struct Triangle { + uint32_t triangle[3]; + bool bad = false; + _FORCE_INLINE_ bool operator==(const Triangle &p_triangle) const { + return triangle[0] == p_triangle.triangle[0] && triangle[1] == p_triangle.triangle[1] && triangle[2] == p_triangle.triangle[2]; + } + + _FORCE_INLINE_ Triangle() {} + _FORCE_INLINE_ Triangle(uint32_t p_a, uint32_t p_b, uint32_t p_c) { + if (p_a > p_b) { + SWAP(p_a, p_b); + } + if (p_b > p_c) { + SWAP(p_b, p_c); + } + if (p_a > p_b) { + SWAP(p_a, p_b); + } + + triangle[0] = p_a; + triangle[1] = p_b; + triangle[2] = p_c; + } + }; + + struct TriangleHasher { + _FORCE_INLINE_ static uint32_t hash(const Triangle &p_triangle) { + uint32_t h = hash_djb2_one_32(p_triangle.triangle[0]); + h = hash_djb2_one_32(p_triangle.triangle[1], h); + return hash_djb2_one_32(p_triangle.triangle[2], h); + } + }; + + _FORCE_INLINE_ static void circum_sphere_compute(const Vector3 *p_points, Simplex *p_simplex) { + // the only part in the algorithm where there may be precision errors is this one, so ensure that + // we do it as maximum precision as possible + + R128 v0_x = p_points[p_simplex->points[0]].x; + R128 v0_y = p_points[p_simplex->points[0]].y; + R128 v0_z = p_points[p_simplex->points[0]].z; + R128 v1_x = p_points[p_simplex->points[1]].x; + R128 v1_y = p_points[p_simplex->points[1]].y; + R128 v1_z = p_points[p_simplex->points[1]].z; + R128 v2_x = p_points[p_simplex->points[2]].x; + R128 v2_y = p_points[p_simplex->points[2]].y; + R128 v2_z = p_points[p_simplex->points[2]].z; + R128 v3_x = p_points[p_simplex->points[3]].x; + R128 v3_y = p_points[p_simplex->points[3]].y; + R128 v3_z = p_points[p_simplex->points[3]].z; + + //Create the rows of our "unrolled" 3x3 matrix + R128 row1_x = v1_x - v0_x; + R128 row1_y = v1_y - v0_y; + R128 row1_z = v1_z - v0_z; + + R128 row2_x = v2_x - v0_x; + R128 row2_y = v2_y - v0_y; + R128 row2_z = v2_z - v0_z; + + R128 row3_x = v3_x - v0_x; + R128 row3_y = v3_y - v0_y; + R128 row3_z = v3_z - v0_z; + + R128 sq_lenght1 = row1_x * row1_x + row1_y * row1_y + row1_z * row1_z; + R128 sq_lenght2 = row2_x * row2_x + row2_y * row2_y + row2_z * row2_z; + R128 sq_lenght3 = row3_x * row3_x + row3_y * row3_y + row3_z * row3_z; + + //Compute the determinant of said matrix + R128 determinant = row1_x * (row2_y * row3_z - row3_y * row2_z) - row2_x * (row1_y * row3_z - row3_y * row1_z) + row3_x * (row1_y * row2_z - row2_y * row1_z); + + // Compute the volume of the tetrahedron, and precompute a scalar quantity for re-use in the formula + R128 volume = determinant / R128(6.f); + R128 i12volume = R128(1.f) / (volume * R128(12.f)); + + R128 center_x = v0_x + i12volume * ((row2_y * row3_z - row3_y * row2_z) * sq_lenght1 - (row1_y * row3_z - row3_y * row1_z) * sq_lenght2 + (row1_y * row2_z - row2_y * row1_z) * sq_lenght3); + R128 center_y = v0_y + i12volume * (-(row2_x * row3_z - row3_x * row2_z) * sq_lenght1 + (row1_x * row3_z - row3_x * row1_z) * sq_lenght2 - (row1_x * row2_z - row2_x * row1_z) * sq_lenght3); + R128 center_z = v0_z + i12volume * ((row2_x * row3_y - row3_x * row2_y) * sq_lenght1 - (row1_x * row3_y - row3_x * row1_y) * sq_lenght2 + (row1_x * row2_y - row2_x * row1_y) * sq_lenght3); + + //Once we know the center, the radius is clearly the distance to any vertex + + R128 rel1_x = center_x - v0_x; + R128 rel1_y = center_y - v0_y; + R128 rel1_z = center_z - v0_z; + + R128 radius1 = rel1_x * rel1_x + rel1_y * rel1_y + rel1_z * rel1_z; + + p_simplex->circum_center_x = center_x; + p_simplex->circum_center_y = center_y; + p_simplex->circum_center_z = center_z; + p_simplex->circum_r2 = radius1; + } + + _FORCE_INLINE_ static bool simplex_contains(const Vector3 *p_points, const Simplex &p_simplex, uint32_t p_vertex) { + R128 v_x = p_points[p_vertex].x; + R128 v_y = p_points[p_vertex].y; + R128 v_z = p_points[p_vertex].z; + + R128 rel2_x = p_simplex.circum_center_x - v_x; + R128 rel2_y = p_simplex.circum_center_y - v_y; + R128 rel2_z = p_simplex.circum_center_z - v_z; + + R128 radius2 = rel2_x * rel2_x + rel2_y * rel2_y + rel2_z * rel2_z; + + return radius2 < (p_simplex.circum_r2 - R128(0.00001)); + } + + static bool simplex_is_coplanar(const Vector3 *p_points, const Simplex &p_simplex) { + Plane p(p_points[p_simplex.points[0]], p_points[p_simplex.points[1]], p_points[p_simplex.points[2]]); + if (ABS(p.distance_to(p_points[p_simplex.points[3]])) < CMP_EPSILON) { + return true; + } + + CameraMatrix cm; + + cm.matrix[0][0] = p_points[p_simplex.points[0]].x; + cm.matrix[0][1] = p_points[p_simplex.points[1]].x; + cm.matrix[0][2] = p_points[p_simplex.points[2]].x; + cm.matrix[0][3] = p_points[p_simplex.points[3]].x; + + cm.matrix[1][0] = p_points[p_simplex.points[0]].y; + cm.matrix[1][1] = p_points[p_simplex.points[1]].y; + cm.matrix[1][2] = p_points[p_simplex.points[2]].y; + cm.matrix[1][3] = p_points[p_simplex.points[3]].y; + + cm.matrix[2][0] = p_points[p_simplex.points[0]].z; + cm.matrix[2][1] = p_points[p_simplex.points[1]].z; + cm.matrix[2][2] = p_points[p_simplex.points[2]].z; + cm.matrix[2][3] = p_points[p_simplex.points[3]].z; + + cm.matrix[3][0] = 1.0; + cm.matrix[3][1] = 1.0; + cm.matrix[3][2] = 1.0; + cm.matrix[3][3] = 1.0; + + return ABS(cm.determinant()) <= CMP_EPSILON; + } + +public: + struct OutputSimplex { + uint32_t points[4]; + }; + + static Vector<OutputSimplex> tetrahedralize(const Vector<Vector3> &p_points) { + uint32_t point_count = p_points.size(); + Vector3 *points = (Vector3 *)memalloc(sizeof(Vector3) * (point_count + 4)); + + { + const Vector3 *src_points = p_points.ptr(); + AABB rect; + for (uint32_t i = 0; i < point_count; i++) { + Vector3 point = src_points[i]; + if (i == 0) { + rect.position = point; + } else { + rect.expand_to(point); + } + points[i] = point; + } + + for (uint32_t i = 0; i < point_count; i++) { + points[i] = (points[i] - rect.position) / rect.size; + } + + float delta_max = Math::sqrt(2.0) * 20.0; + Vector3 center = Vector3(0.5, 0.5, 0.5); + + // any simplex that contains everything is good + points[point_count + 0] = center + Vector3(0, 1, 0) * delta_max; + points[point_count + 1] = center + Vector3(0, -1, 1) * delta_max; + points[point_count + 2] = center + Vector3(1, -1, -1) * delta_max; + points[point_count + 3] = center + Vector3(-1, -1, -1) * delta_max; + } + + List<Simplex *> acceleration_grid[ACCEL_GRID_SIZE][ACCEL_GRID_SIZE][ACCEL_GRID_SIZE]; + + List<Simplex *> simplex_list; + { + //create root simplex + Simplex *root = memnew(Simplex(point_count + 0, point_count + 1, point_count + 2, point_count + 3)); + root->SE = simplex_list.push_back(root); + + for (uint32_t i = 0; i < ACCEL_GRID_SIZE; i++) { + for (uint32_t j = 0; j < ACCEL_GRID_SIZE; j++) { + for (uint32_t k = 0; k < ACCEL_GRID_SIZE; k++) { + GridPos gp; + gp.E = acceleration_grid[i][j][k].push_back(root); + gp.pos = Vector3i(i, j, k); + root->grid_positions.push_back(gp); + } + } + } + + circum_sphere_compute(points, root); + } + + OAHashMap<Triangle, uint32_t, TriangleHasher> triangles_inserted; + LocalVector<Triangle> triangles; + + for (uint32_t i = 0; i < point_count; i++) { + bool unique = true; + for (uint32_t j = i + 1; j < point_count; j++) { + if (points[i].is_equal_approx(points[j])) { + unique = false; + break; + } + } + if (!unique) { + continue; + } + + Vector3i grid_pos = Vector3i(points[i] * ACCEL_GRID_SIZE); + grid_pos.x = CLAMP(grid_pos.x, 0, ACCEL_GRID_SIZE - 1); + grid_pos.y = CLAMP(grid_pos.y, 0, ACCEL_GRID_SIZE - 1); + grid_pos.z = CLAMP(grid_pos.z, 0, ACCEL_GRID_SIZE - 1); + + for (List<Simplex *>::Element *E = acceleration_grid[grid_pos.x][grid_pos.y][grid_pos.z].front(); E;) { + List<Simplex *>::Element *N = E->next(); //may be deleted + + Simplex *simplex = E->get(); + + if (simplex_contains(points, *simplex, i)) { + static const uint32_t triangle_order[4][3] = { + { 0, 1, 2 }, + { 0, 1, 3 }, + { 0, 2, 3 }, + { 1, 2, 3 }, + }; + + for (uint32_t k = 0; k < 4; k++) { + Triangle t = Triangle(simplex->points[triangle_order[k][0]], simplex->points[triangle_order[k][1]], simplex->points[triangle_order[k][2]]); + uint32_t *p = triangles_inserted.lookup_ptr(t); + if (p) { + triangles[*p].bad = true; + } else { + triangles_inserted.insert(t, triangles.size()); + triangles.push_back(t); + } + } + + //remove simplex and continue + simplex_list.erase(simplex->SE); + + for (uint32_t k = 0; k < simplex->grid_positions.size(); k++) { + Vector3i p = simplex->grid_positions[k].pos; + acceleration_grid[p.x][p.y][p.z].erase(simplex->grid_positions[k].E); + } + memdelete(simplex); + } + E = N; + } + + uint32_t good_triangles = 0; + for (uint32_t j = 0; j < triangles.size(); j++) { + if (triangles[j].bad) { + continue; + } + Simplex *new_simplex = memnew(Simplex(triangles[j].triangle[0], triangles[j].triangle[1], triangles[j].triangle[2], i)); + circum_sphere_compute(points, new_simplex); + new_simplex->SE = simplex_list.push_back(new_simplex); + { + Vector3 center; + center.x = double(new_simplex->circum_center_x); + center.y = double(new_simplex->circum_center_y); + center.z = double(new_simplex->circum_center_z); + + float radius2 = Math::sqrt(double(new_simplex->circum_r2)); + radius2 += 0.0001; // + Vector3 extents = Vector3(radius2, radius2, radius2); + Vector3i from = Vector3i((center - extents) * ACCEL_GRID_SIZE); + Vector3i to = Vector3i((center + extents) * ACCEL_GRID_SIZE); + from.x = CLAMP(from.x, 0, ACCEL_GRID_SIZE - 1); + from.y = CLAMP(from.y, 0, ACCEL_GRID_SIZE - 1); + from.z = CLAMP(from.z, 0, ACCEL_GRID_SIZE - 1); + to.x = CLAMP(to.x, 0, ACCEL_GRID_SIZE - 1); + to.y = CLAMP(to.y, 0, ACCEL_GRID_SIZE - 1); + to.z = CLAMP(to.z, 0, ACCEL_GRID_SIZE - 1); + + for (int32_t x = from.x; x <= to.x; x++) { + for (int32_t y = from.y; y <= to.y; y++) { + for (int32_t z = from.z; z <= to.z; z++) { + GridPos gp; + gp.pos = Vector3(x, y, z); + gp.E = acceleration_grid[x][y][z].push_back(new_simplex); + new_simplex->grid_positions.push_back(gp); + } + } + } + } + + good_triangles++; + } + + //print_line("at point " + itos(i) + "/" + itos(point_count) + " simplices added " + itos(good_triangles) + "/" + itos(simplex_list.size()) + " - triangles: " + itos(triangles.size())); + triangles.clear(); + triangles_inserted.clear(); + } + + //print_line("end with simplices: " + itos(simplex_list.size())); + Vector<OutputSimplex> ret_simplices; + ret_simplices.resize(simplex_list.size()); + OutputSimplex *ret_simplicesw = ret_simplices.ptrw(); + uint32_t simplices_written = 0; + + for (List<Simplex *>::Element *E = simplex_list.front(); E; E = E->next()) { + Simplex *simplex = E->get(); + bool invalid = false; + for (int j = 0; j < 4; j++) { + if (simplex->points[j] >= point_count) { + invalid = true; + break; + } + } + if (invalid || simplex_is_coplanar(points, *simplex)) { + memdelete(simplex); + continue; + } + + ret_simplicesw[simplices_written].points[0] = simplex->points[0]; + ret_simplicesw[simplices_written].points[1] = simplex->points[1]; + ret_simplicesw[simplices_written].points[2] = simplex->points[2]; + ret_simplicesw[simplices_written].points[3] = simplex->points[3]; + simplices_written++; + memdelete(simplex); + } + + ret_simplices.resize(simplices_written); + + memfree(points); + + return ret_simplices; + } +}; + +#endif // DELAUNAY_3D_H diff --git a/core/math/disjoint_set.cpp b/core/math/disjoint_set.cpp deleted file mode 100644 index a508151ad3..0000000000 --- a/core/math/disjoint_set.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************/ -/* disjoint_set.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "disjoint_set.h" diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h index 32b9875e4c..198f46e111 100644 --- a/core/math/disjoint_set.h +++ b/core/math/disjoint_set.h @@ -41,7 +41,6 @@ /* This DisjointSet class uses Find with path compression and Union by rank */ template <typename T, class C = Comparator<T>, class AL = DefaultAllocator> class DisjointSet { - struct Element { T object; Element *parent = nullptr; @@ -103,7 +102,6 @@ typename DisjointSet<T, C, AL>::Element *DisjointSet<T, C, AL>::insert_or_get(T template <typename T, class C, class AL> void DisjointSet<T, C, AL>::create_union(T a, T b) { - Element *x = insert_or_get(a); Element *y = insert_or_get(b); @@ -111,8 +109,9 @@ void DisjointSet<T, C, AL>::create_union(T a, T b) { Element *y_root = get_parent(y); // Already in the same set - if (x_root == y_root) + if (x_root == y_root) { return; + } // Not in the same set, merge if (x_root->rank < y_root->rank) { diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 859b9be8c5..6421606ca2 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -110,25 +110,22 @@ const char *Expression::func_name[Expression::FUNC_MAX] = { }; Expression::BuiltinFunc Expression::find_function(const String &p_string) { - for (int i = 0; i < FUNC_MAX; i++) { - if (p_string == func_name[i]) + if (p_string == func_name[i]) { return BuiltinFunc(i); + } } return FUNC_MAX; } String Expression::get_func_name(BuiltinFunc p_func) { - ERR_FAIL_INDEX_V(p_func, FUNC_MAX, String()); return func_name[p_func]; } int Expression::get_func_argument_count(BuiltinFunc p_func) { - switch (p_func) { - case MATH_RANDOMIZE: case MATH_RAND: case MATH_RANDF: @@ -220,194 +217,157 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant r_error.error = Callable::CallError::CALL_OK; switch (p_func) { case MATH_SIN: { - VALIDATE_ARG_NUM(0); *r_return = Math::sin((double)*p_inputs[0]); } break; case MATH_COS: { - VALIDATE_ARG_NUM(0); *r_return = Math::cos((double)*p_inputs[0]); } break; case MATH_TAN: { - VALIDATE_ARG_NUM(0); *r_return = Math::tan((double)*p_inputs[0]); } break; case MATH_SINH: { - VALIDATE_ARG_NUM(0); *r_return = Math::sinh((double)*p_inputs[0]); } break; case MATH_COSH: { - VALIDATE_ARG_NUM(0); *r_return = Math::cosh((double)*p_inputs[0]); } break; case MATH_TANH: { - VALIDATE_ARG_NUM(0); *r_return = Math::tanh((double)*p_inputs[0]); } break; case MATH_ASIN: { - VALIDATE_ARG_NUM(0); *r_return = Math::asin((double)*p_inputs[0]); } break; case MATH_ACOS: { - VALIDATE_ARG_NUM(0); *r_return = Math::acos((double)*p_inputs[0]); } break; case MATH_ATAN: { - VALIDATE_ARG_NUM(0); *r_return = Math::atan((double)*p_inputs[0]); } break; case MATH_ATAN2: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::atan2((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_SQRT: { - VALIDATE_ARG_NUM(0); *r_return = Math::sqrt((double)*p_inputs[0]); } break; case MATH_FMOD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::fmod((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_FPOSMOD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_POSMOD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]); } break; case MATH_FLOOR: { - VALIDATE_ARG_NUM(0); *r_return = Math::floor((double)*p_inputs[0]); } break; case MATH_CEIL: { - VALIDATE_ARG_NUM(0); *r_return = Math::ceil((double)*p_inputs[0]); } break; case MATH_ROUND: { - VALIDATE_ARG_NUM(0); *r_return = Math::round((double)*p_inputs[0]); } break; case MATH_ABS: { - if (p_inputs[0]->get_type() == Variant::INT) { - int64_t i = *p_inputs[0]; *r_return = ABS(i); } else if (p_inputs[0]->get_type() == Variant::FLOAT) { - real_t r = *p_inputs[0]; *r_return = Math::abs(r); } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::FLOAT; } } break; case MATH_SIGN: { - if (p_inputs[0]->get_type() == Variant::INT) { - int64_t i = *p_inputs[0]; *r_return = i < 0 ? -1 : (i > 0 ? +1 : 0); } else if (p_inputs[0]->get_type() == Variant::FLOAT) { - real_t r = *p_inputs[0]; *r_return = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0); } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::FLOAT; } } break; case MATH_POW: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::pow((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_LOG: { - VALIDATE_ARG_NUM(0); *r_return = Math::log((double)*p_inputs[0]); } break; case MATH_EXP: { - VALIDATE_ARG_NUM(0); *r_return = Math::exp((double)*p_inputs[0]); } break; case MATH_ISNAN: { - VALIDATE_ARG_NUM(0); *r_return = Math::is_nan((double)*p_inputs[0]); } break; case MATH_ISINF: { - VALIDATE_ARG_NUM(0); *r_return = Math::is_inf((double)*p_inputs[0]); } break; case MATH_EASE: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_STEP_DECIMALS: { - VALIDATE_ARG_NUM(0); *r_return = Math::step_decimals((double)*p_inputs[0]); } break; case MATH_STEPIFY: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_LERP: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case MATH_LERP_ANGLE: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case MATH_INVERSE_LERP: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case MATH_RANGE_LERP: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); @@ -422,14 +382,12 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case MATH_MOVE_TOWARD: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case MATH_DECTIME: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); VALIDATE_ARG_NUM(2); @@ -446,20 +404,17 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return = Math::randf(); } break; case MATH_RANDOM: { - VALIDATE_ARG_NUM(0); VALIDATE_ARG_NUM(1); *r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]); } break; case MATH_SEED: { - VALIDATE_ARG_NUM(0); uint64_t seed = *p_inputs[0]; Math::seed(seed); } break; case MATH_RANDSEED: { - VALIDATE_ARG_NUM(0); uint64_t seed = *p_inputs[0]; int ret = Math::rand_from_seed(&seed); @@ -470,22 +425,18 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case MATH_DEG2RAD: { - VALIDATE_ARG_NUM(0); *r_return = Math::deg2rad((double)*p_inputs[0]); } break; case MATH_RAD2DEG: { - VALIDATE_ARG_NUM(0); *r_return = Math::rad2deg((double)*p_inputs[0]); } break; case MATH_LINEAR2DB: { - VALIDATE_ARG_NUM(0); *r_return = Math::linear2db((double)*p_inputs[0]); } break; case MATH_DB2LINEAR: { - VALIDATE_ARG_NUM(0); *r_return = Math::db2linear((double)*p_inputs[0]); } break; @@ -516,9 +467,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); } break; case LOGIC_MAX: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; *r_return = MAX(a, b); @@ -534,9 +483,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case LOGIC_MIN: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; *r_return = MIN(a, b); @@ -551,9 +498,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } } break; case LOGIC_CLAMP: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT && p_inputs[2]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; int64_t b = *p_inputs[1]; int64_t c = *p_inputs[2]; @@ -571,15 +516,12 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } } break; case LOGIC_NEAREST_PO2: { - VALIDATE_ARG_NUM(0); int64_t num = *p_inputs[0]; *r_return = next_power_of_2(num); } break; case OBJ_WEAKREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -588,10 +530,8 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } if (p_inputs[0]->is_ref()) { - REF r = *p_inputs[0]; if (!r.is_valid()) { - return; } @@ -601,7 +541,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } else { Object *obj = *p_inputs[0]; if (!obj) { - return; } Ref<WeakRef> wref = memnew(WeakRef); @@ -611,9 +550,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case FUNC_FUNCREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::OBJECT; @@ -621,7 +558,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant return; } if (p_inputs[1]->get_type() != Variant::STRING && p_inputs[1]->get_type() != Variant::NODE_PATH) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::STRING; @@ -638,11 +574,9 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case TYPE_CONVERT: { - VALIDATE_ARG_NUM(1); int type = *p_inputs[1]; if (type < 0 || type >= Variant::VARIANT_MAX) { - r_error_str = RTR("Invalid type argument to convert(), use TYPE_* constants."); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -650,31 +584,25 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant return; } else { - *r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error); } } break; case TYPE_OF: { - *r_return = p_inputs[0]->get_type(); } break; case TYPE_EXISTS: { - *r_return = ClassDB::class_exists(*p_inputs[0]); } break; case TEXT_CHAR: { - CharType result[2] = { *p_inputs[0], 0 }; *r_return = String(result); } break; case TEXT_ORD: { - if (p_inputs[0]->get_type() != Variant::STRING) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::STRING; @@ -685,7 +613,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant String str = *p_inputs[0]; if (str.length() != 1) { - r_error_str = RTR("Expected a string of length 1 (a character)."); r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -698,39 +625,33 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case TEXT_STR: { - String str = *p_inputs[0]; *r_return = str; } break; case TEXT_PRINT: { - String str = *p_inputs[0]; print_line(str); } break; case TEXT_PRINTERR: { - String str = *p_inputs[0]; print_error(str); } break; case TEXT_PRINTRAW: { - String str = *p_inputs[0]; OS::get_singleton()->print("%s", str.utf8().get_data()); } break; case VAR_TO_STR: { - String vars; VariantWriter::write_to_string(*p_inputs[0], vars); *r_return = vars; } break; case STR_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::STRING) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -756,7 +677,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case VAR_TO_BYTES: { - PackedByteArray barr; bool full_objects = *p_inputs[1]; int len; @@ -777,7 +697,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return = barr; } break; case BYTES_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; @@ -805,7 +724,6 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case COLORN: { - VALIDATE_ARG_NUM(1); Color color = Color::named(*p_inputs[0]); @@ -826,60 +744,49 @@ static bool _is_number(CharType c) { } Error Expression::_get_token(Token &r_token) { - while (true) { #define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++]) CharType cchar = GET_CHAR(); switch (cchar) { - case 0: { r_token.type = TK_EOF; return OK; - }; + } case '{': { - r_token.type = TK_CURLY_BRACKET_OPEN; return OK; - }; + } case '}': { - r_token.type = TK_CURLY_BRACKET_CLOSE; return OK; - }; + } case '[': { - r_token.type = TK_BRACKET_OPEN; return OK; - }; + } case ']': { - r_token.type = TK_BRACKET_CLOSE; return OK; - }; + } case '(': { - r_token.type = TK_PARENTHESIS_OPEN; return OK; - }; + } case ')': { - r_token.type = TK_PARENTHESIS_CLOSE; return OK; - }; + } case ',': { - r_token.type = TK_COMMA; return OK; - }; + } case ':': { - r_token.type = TK_COLON; return OK; - }; + } case '$': { - r_token.type = TK_INPUT; int index = 0; do { @@ -896,9 +803,8 @@ Error Expression::_get_token(Token &r_token) { r_token.value = index; return OK; - }; + } case '=': { - cchar = GET_CHAR(); if (cchar == '=') { r_token.type = TK_OP_EQUAL; @@ -908,9 +814,8 @@ Error Expression::_get_token(Token &r_token) { return ERR_PARSE_ERROR; } return OK; - }; + } case '!': { - if (expression[str_ofs] == '=') { r_token.type = TK_OP_NOT_EQUAL; str_ofs++; @@ -918,9 +823,8 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_OP_NOT; } return OK; - }; + } case '>': { - if (expression[str_ofs] == '=') { r_token.type = TK_OP_GREATER_EQUAL; str_ofs++; @@ -931,9 +835,8 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_OP_GREATER; } return OK; - }; + } case '<': { - if (expression[str_ofs] == '=') { r_token.type = TK_OP_LESS_EQUAL; str_ofs++; @@ -944,29 +847,28 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_OP_LESS; } return OK; - }; + } case '+': { r_token.type = TK_OP_ADD; return OK; - }; + } case '-': { r_token.type = TK_OP_SUB; return OK; - }; + } case '/': { r_token.type = TK_OP_DIV; return OK; - }; + } case '*': { r_token.type = TK_OP_MUL; return OK; - }; + } case '%': { r_token.type = TK_OP_MOD; return OK; - }; + } case '&': { - if (expression[str_ofs] == '&') { r_token.type = TK_OP_AND; str_ofs++; @@ -974,9 +876,8 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_OP_BIT_AND; } return OK; - }; + } case '|': { - if (expression[str_ofs] == '|') { r_token.type = TK_OP_OR; str_ofs++; @@ -984,31 +885,29 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_OP_BIT_OR; } return OK; - }; + } case '^': { - r_token.type = TK_OP_BIT_XOR; return OK; - }; + } case '~': { - r_token.type = TK_OP_BIT_INVERT; return OK; - }; + } + case '\'': case '"': { - String str; while (true) { - CharType ch = GET_CHAR(); if (ch == 0) { _set_error("Unterminated String"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; - } else if (ch == '"') { + } else if (ch == cchar) { + // cchar contain a corresponding quote symbol break; } else if (ch == '\\') { //escaped characters... @@ -1022,12 +921,21 @@ Error Expression::_get_token(Token &r_token) { CharType res = 0; switch (next) { - - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { // hex number for (int j = 0; j < 4; j++) { @@ -1039,7 +947,6 @@ Error Expression::_get_token(Token &r_token) { return ERR_PARSE_ERROR; } if (!(_is_number(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { - _set_error("Malformed hex constant in string"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; @@ -1081,7 +988,6 @@ Error Expression::_get_token(Token &r_token) { } break; default: { - if (cchar <= 32) { break; } @@ -1104,10 +1010,8 @@ Error Expression::_get_token(Token &r_token) { bool is_float = false; while (true) { - switch (reading) { case READING_INT: { - if (_is_number(c)) { //pass } else if (c == '.') { @@ -1121,9 +1025,7 @@ Error Expression::_get_token(Token &r_token) { } break; case READING_DEC: { - if (_is_number(c)) { - } else if (c == 'e') { reading = READING_EXP; @@ -1133,13 +1035,13 @@ Error Expression::_get_token(Token &r_token) { } break; case READING_EXP: { - if (_is_number(c)) { exp_beg = true; } else if ((c == '-' || c == '+') && !exp_sign && !exp_beg) { - if (c == '-') + if (c == '-') { is_float = true; + } exp_sign = true; } else { @@ -1148,8 +1050,9 @@ Error Expression::_get_token(Token &r_token) { } break; } - if (reading == READING_DONE) + if (reading == READING_DONE) { break; + } num += String::chr(c); c = GET_CHAR(); } @@ -1158,19 +1061,18 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_CONSTANT; - if (is_float) + if (is_float) { r_token.value = num.to_double(); - else + } else { r_token.value = num.to_int64(); + } return OK; } else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') { - String id; bool first = true; while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && _is_number(cchar))) { - id += String::chr(cchar); cchar = GET_CHAR(); first = false; @@ -1210,7 +1112,6 @@ Error Expression::_get_token(Token &r_token) { } else if (id == "self") { r_token.type = TK_SELF; } else { - for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (id == Variant::get_type_name(Variant::Type(i))) { r_token.type = TK_BASIC_TYPE; @@ -1293,7 +1194,6 @@ const char *Expression::token_name[TK_MAX] = { }; Expression::ENode *Expression::_parse_expression() { - Vector<ExpressionNode> expression; while (true) { @@ -1302,8 +1202,9 @@ Expression::ENode *Expression::_parse_expression() { Token tk; _get_token(tk); - if (error_set) + if (error_set) { return nullptr; + } switch (tk.type) { case TK_CURLY_BRACKET_OPEN: { @@ -1311,7 +1212,6 @@ Expression::ENode *Expression::_parse_expression() { DictionaryNode *dn = alloc_node<DictionaryNode>(); while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_CURLY_BRACKET_CLOSE) { @@ -1320,8 +1220,9 @@ Expression::ENode *Expression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } dn->dict.push_back(subexpr); _get_token(tk); @@ -1331,8 +1232,9 @@ Expression::ENode *Expression::_parse_expression() { } subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } dn->dict.push_back(subexpr); @@ -1355,7 +1257,6 @@ Expression::ENode *Expression::_parse_expression() { ArrayNode *an = alloc_node<ArrayNode>(); while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_BRACKET_CLOSE) { @@ -1364,8 +1265,9 @@ Expression::ENode *Expression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } an->array.push_back(subexpr); cofs = str_ofs; @@ -1384,8 +1286,9 @@ Expression::ENode *Expression::_parse_expression() { case TK_PARENTHESIS_OPEN: { //a suexpression ENode *e = _parse_expression(); - if (error_set) + if (error_set) { return nullptr; + } _get_token(tk); if (tk.type != TK_PARENTHESIS_CLOSE) { _set_error("Expected ')'"); @@ -1396,7 +1299,6 @@ Expression::ENode *Expression::_parse_expression() { } break; case TK_IDENTIFIER: { - String identifier = tk.value; int cofs = str_ofs; @@ -1409,7 +1311,6 @@ Expression::ENode *Expression::_parse_expression() { func_call->base = self_node; while (true) { - int cofs2 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -1418,8 +1319,9 @@ Expression::ENode *Expression::_parse_expression() { str_ofs = cofs2; //revert //parse an expression ENode *subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } func_call->arguments.push_back(subexpr); @@ -1452,7 +1354,6 @@ Expression::ENode *Expression::_parse_expression() { input->index = input_index; expr = input; } else { - NamedIndexNode *index = alloc_node<NamedIndexNode>(); SelfNode *self_node = alloc_node<SelfNode>(); index->base = self_node; @@ -1462,13 +1363,11 @@ Expression::ENode *Expression::_parse_expression() { } } break; case TK_INPUT: { - InputNode *input = alloc_node<InputNode>(); input->index = tk.value; expr = input; } break; case TK_SELF: { - SelfNode *self = alloc_node<SelfNode>(); expr = self; } break; @@ -1491,7 +1390,6 @@ Expression::ENode *Expression::_parse_expression() { constructor->data_type = bt; while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -1500,8 +1398,9 @@ Expression::ENode *Expression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } constructor->arguments.push_back(subexpr); @@ -1532,7 +1431,6 @@ Expression::ENode *Expression::_parse_expression() { bifunc->func = BuiltinFunc(int(tk.value)); while (true) { - int cofs = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -1541,8 +1439,9 @@ Expression::ENode *Expression::_parse_expression() { str_ofs = cofs; //revert //parse an expression ENode *subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } bifunc->arguments.push_back(subexpr); @@ -1566,7 +1465,6 @@ Expression::ENode *Expression::_parse_expression() { } break; case TK_OP_SUB: { - ExpressionNode e; e.is_op = true; e.op = Variant::OP_NEGATE; @@ -1574,7 +1472,6 @@ Expression::ENode *Expression::_parse_expression() { continue; } break; case TK_OP_NOT: { - ExpressionNode e; e.is_op = true; e.op = Variant::OP_NOT; @@ -1593,8 +1490,9 @@ Expression::ENode *Expression::_parse_expression() { while (true) { int cofs2 = str_ofs; _get_token(tk); - if (error_set) + if (error_set) { return nullptr; + } bool done = false; @@ -1606,8 +1504,9 @@ Expression::ENode *Expression::_parse_expression() { index->base = expr; ENode *what = _parse_expression(); - if (!what) + if (!what) { return nullptr; + } index->index = what; @@ -1638,7 +1537,6 @@ Expression::ENode *Expression::_parse_expression() { func_call->base = expr; while (true) { - int cofs3 = str_ofs; _get_token(tk); if (tk.type == TK_PARENTHESIS_CLOSE) { @@ -1647,8 +1545,9 @@ Expression::ENode *Expression::_parse_expression() { str_ofs = cofs3; //revert //parse an expression ENode *subexpr = _parse_expression(); - if (!subexpr) + if (!subexpr) { return nullptr; + } func_call->arguments.push_back(subexpr); @@ -1681,8 +1580,9 @@ Expression::ENode *Expression::_parse_expression() { } break; } - if (done) + if (done) { break; + } } //push expression @@ -1697,35 +1597,78 @@ Expression::ENode *Expression::_parse_expression() { int cofs = str_ofs; _get_token(tk); - if (error_set) + if (error_set) { return nullptr; + } Variant::Operator op = Variant::OP_MAX; switch (tk.type) { - case TK_OP_IN: op = Variant::OP_IN; break; - case TK_OP_EQUAL: op = Variant::OP_EQUAL; break; - case TK_OP_NOT_EQUAL: op = Variant::OP_NOT_EQUAL; break; - case TK_OP_LESS: op = Variant::OP_LESS; break; - case TK_OP_LESS_EQUAL: op = Variant::OP_LESS_EQUAL; break; - case TK_OP_GREATER: op = Variant::OP_GREATER; break; - case TK_OP_GREATER_EQUAL: op = Variant::OP_GREATER_EQUAL; break; - case TK_OP_AND: op = Variant::OP_AND; break; - case TK_OP_OR: op = Variant::OP_OR; break; - case TK_OP_NOT: op = Variant::OP_NOT; break; - case TK_OP_ADD: op = Variant::OP_ADD; break; - case TK_OP_SUB: op = Variant::OP_SUBTRACT; break; - case TK_OP_MUL: op = Variant::OP_MULTIPLY; break; - case TK_OP_DIV: op = Variant::OP_DIVIDE; break; - case TK_OP_MOD: op = Variant::OP_MODULE; break; - case TK_OP_SHIFT_LEFT: op = Variant::OP_SHIFT_LEFT; break; - case TK_OP_SHIFT_RIGHT: op = Variant::OP_SHIFT_RIGHT; break; - case TK_OP_BIT_AND: op = Variant::OP_BIT_AND; break; - case TK_OP_BIT_OR: op = Variant::OP_BIT_OR; break; - case TK_OP_BIT_XOR: op = Variant::OP_BIT_XOR; break; - case TK_OP_BIT_INVERT: op = Variant::OP_BIT_NEGATE; break; + case TK_OP_IN: + op = Variant::OP_IN; + break; + case TK_OP_EQUAL: + op = Variant::OP_EQUAL; + break; + case TK_OP_NOT_EQUAL: + op = Variant::OP_NOT_EQUAL; + break; + case TK_OP_LESS: + op = Variant::OP_LESS; + break; + case TK_OP_LESS_EQUAL: + op = Variant::OP_LESS_EQUAL; + break; + case TK_OP_GREATER: + op = Variant::OP_GREATER; + break; + case TK_OP_GREATER_EQUAL: + op = Variant::OP_GREATER_EQUAL; + break; + case TK_OP_AND: + op = Variant::OP_AND; + break; + case TK_OP_OR: + op = Variant::OP_OR; + break; + case TK_OP_NOT: + op = Variant::OP_NOT; + break; + case TK_OP_ADD: + op = Variant::OP_ADD; + break; + case TK_OP_SUB: + op = Variant::OP_SUBTRACT; + break; + case TK_OP_MUL: + op = Variant::OP_MULTIPLY; + break; + case TK_OP_DIV: + op = Variant::OP_DIVIDE; + break; + case TK_OP_MOD: + op = Variant::OP_MODULE; + break; + case TK_OP_SHIFT_LEFT: + op = Variant::OP_SHIFT_LEFT; + break; + case TK_OP_SHIFT_RIGHT: + op = Variant::OP_SHIFT_RIGHT; + break; + case TK_OP_BIT_AND: + op = Variant::OP_BIT_AND; + break; + case TK_OP_BIT_OR: + op = Variant::OP_BIT_OR; + break; + case TK_OP_BIT_XOR: + op = Variant::OP_BIT_XOR; + break; + case TK_OP_BIT_INVERT: + op = Variant::OP_BIT_NEGATE; + break; default: { - }; + } } if (op == Variant::OP_MAX) { //stop appending stuff @@ -1745,15 +1688,12 @@ Expression::ENode *Expression::_parse_expression() { /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ while (expression.size() > 1) { - int next_op = -1; int min_priority = 0xFFFFF; bool is_unary = false; for (int i = 0; i < expression.size(); i++) { - if (!expression[i].is_op) { - continue; } @@ -1762,7 +1702,6 @@ Expression::ENode *Expression::_parse_expression() { bool unary = false; switch (expression[i].op) { - case Variant::OP_BIT_NEGATE: priority = 0; unary = true; @@ -1772,36 +1711,74 @@ Expression::ENode *Expression::_parse_expression() { unary = true; break; - case Variant::OP_MULTIPLY: priority = 2; break; - case Variant::OP_DIVIDE: priority = 2; break; - case Variant::OP_MODULE: priority = 2; break; + case Variant::OP_MULTIPLY: + priority = 2; + break; + case Variant::OP_DIVIDE: + priority = 2; + break; + case Variant::OP_MODULE: + priority = 2; + break; - case Variant::OP_ADD: priority = 3; break; - case Variant::OP_SUBTRACT: priority = 3; break; + case Variant::OP_ADD: + priority = 3; + break; + case Variant::OP_SUBTRACT: + priority = 3; + break; - case Variant::OP_SHIFT_LEFT: priority = 4; break; - case Variant::OP_SHIFT_RIGHT: priority = 4; break; + case Variant::OP_SHIFT_LEFT: + priority = 4; + break; + case Variant::OP_SHIFT_RIGHT: + priority = 4; + break; - case Variant::OP_BIT_AND: priority = 5; break; - case Variant::OP_BIT_XOR: priority = 6; break; - case Variant::OP_BIT_OR: priority = 7; break; + case Variant::OP_BIT_AND: + priority = 5; + break; + case Variant::OP_BIT_XOR: + priority = 6; + break; + case Variant::OP_BIT_OR: + priority = 7; + break; - case Variant::OP_LESS: priority = 8; break; - case Variant::OP_LESS_EQUAL: priority = 8; break; - case Variant::OP_GREATER: priority = 8; break; - case Variant::OP_GREATER_EQUAL: priority = 8; break; + case Variant::OP_LESS: + priority = 8; + break; + case Variant::OP_LESS_EQUAL: + priority = 8; + break; + case Variant::OP_GREATER: + priority = 8; + break; + case Variant::OP_GREATER_EQUAL: + priority = 8; + break; - case Variant::OP_EQUAL: priority = 8; break; - case Variant::OP_NOT_EQUAL: priority = 8; break; + case Variant::OP_EQUAL: + priority = 8; + break; + case Variant::OP_NOT_EQUAL: + priority = 8; + break; - case Variant::OP_IN: priority = 10; break; + case Variant::OP_IN: + priority = 10; + break; case Variant::OP_NOT: priority = 11; unary = true; break; - case Variant::OP_AND: priority = 12; break; - case Variant::OP_OR: priority = 13; break; + case Variant::OP_AND: + priority = 12; + break; + case Variant::OP_OR: + priority = 13; + break; default: { _set_error("Parser bug, invalid operator in expression: " + itos(expression[i].op)); @@ -1820,17 +1797,14 @@ Expression::ENode *Expression::_parse_expression() { } if (next_op == -1) { - _set_error("Yet another parser bug...."); ERR_FAIL_V(nullptr); } // OK! create operator.. if (is_unary) { - int expr_pos = next_op; while (expression[expr_pos].is_op) { - expr_pos++; if (expr_pos == expression.size()) { //can happen.. @@ -1841,7 +1815,6 @@ Expression::ENode *Expression::_parse_expression() { //consecutively do unary operators for (int i = expr_pos - 1; i >= next_op; i--) { - OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; op->nodes[0] = expression[i + 1].node; @@ -1852,7 +1825,6 @@ Expression::ENode *Expression::_parse_expression() { } } else { - if (next_op < 1 || next_op >= (expression.size() - 1)) { _set_error("Parser bug..."); ERR_FAIL_V(nullptr); @@ -1862,7 +1834,6 @@ Expression::ENode *Expression::_parse_expression() { op->op = expression[next_op].op; if (expression[next_op - 1].is_op) { - _set_error("Parser bug..."); ERR_FAIL_V(nullptr); } @@ -1891,9 +1862,9 @@ Expression::ENode *Expression::_parse_expression() { } bool Expression::_compile_expression() { - - if (!expression_dirty) + if (!expression_dirty) { return error_set; + } if (nodes) { memdelete(nodes); @@ -1921,10 +1892,8 @@ bool Expression::_compile_expression() { } bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression::ENode *p_node, Variant &r_ret, String &r_error_str) { - switch (p_node->type) { case Expression::ENode::TYPE_INPUT: { - const Expression::InputNode *in = static_cast<const Expression::InputNode *>(p_node); if (in->index < 0 || in->index >= p_inputs.size()) { r_error_str = vformat(RTR("Invalid input %i (not passed) in expression"), in->index); @@ -1933,13 +1902,11 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: r_ret = p_inputs[in->index]; } break; case Expression::ENode::TYPE_CONSTANT: { - const Expression::ConstantNode *c = static_cast<const Expression::ConstantNode *>(p_node); r_ret = c->value; } break; case Expression::ENode::TYPE_SELF: { - if (!p_instance) { r_error_str = RTR("self can't be used because instance is null (not passed)"); return true; @@ -1947,20 +1914,21 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: r_ret = p_instance; } break; case Expression::ENode::TYPE_OPERATOR: { - const Expression::OperatorNode *op = static_cast<const Expression::OperatorNode *>(p_node); Variant a; bool ret = _execute(p_inputs, p_instance, op->nodes[0], a, r_error_str); - if (ret) + if (ret) { return true; + } Variant b; if (op->nodes[1]) { ret = _execute(p_inputs, p_instance, op->nodes[1], b, r_error_str); - if (ret) + if (ret) { return true; + } } bool valid = true; @@ -1972,19 +1940,20 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } break; case Expression::ENode::TYPE_INDEX: { - const Expression::IndexNode *index = static_cast<const Expression::IndexNode *>(p_node); Variant base; bool ret = _execute(p_inputs, p_instance, index->base, base, r_error_str); - if (ret) + if (ret) { return true; + } Variant idx; ret = _execute(p_inputs, p_instance, index->index, idx, r_error_str); - if (ret) + if (ret) { return true; + } bool valid; r_ret = base.get(idx, &valid); @@ -1995,13 +1964,13 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } break; case Expression::ENode::TYPE_NAMED_INDEX: { - const Expression::NamedIndexNode *index = static_cast<const Expression::NamedIndexNode *>(p_node); Variant base; bool ret = _execute(p_inputs, p_instance, index->base, base, r_error_str); - if (ret) + if (ret) { return true; + } bool valid; r_ret = base.get_named(index->name, &valid); @@ -2017,12 +1986,12 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: Array arr; arr.resize(array->array.size()); for (int i = 0; i < array->array.size(); i++) { - Variant value; bool ret = _execute(p_inputs, p_instance, array->array[i], value, r_error_str); - if (ret) + if (ret) { return true; + } arr[i] = value; } @@ -2034,17 +2003,18 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: Dictionary d; for (int i = 0; i < dictionary->dict.size(); i += 2) { - Variant key; bool ret = _execute(p_inputs, p_instance, dictionary->dict[i + 0], key, r_error_str); - if (ret) + if (ret) { return true; + } Variant value; ret = _execute(p_inputs, p_instance, dictionary->dict[i + 1], value, r_error_str); - if (ret) + if (ret) { return true; + } d[key] = value; } @@ -2052,7 +2022,6 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: r_ret = d; } break; case Expression::ENode::TYPE_CONSTRUCTOR: { - const Expression::ConstructorNode *constructor = static_cast<const Expression::ConstructorNode *>(p_node); Vector<Variant> arr; @@ -2061,12 +2030,12 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: argp.resize(constructor->arguments.size()); for (int i = 0; i < constructor->arguments.size(); i++) { - Variant value; bool ret = _execute(p_inputs, p_instance, constructor->arguments[i], value, r_error_str); - if (ret) + if (ret) { return true; + } arr.write[i] = value; argp.write[i] = &arr[i]; } @@ -2081,7 +2050,6 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } break; case Expression::ENode::TYPE_BUILTIN_FUNC: { - const Expression::BuiltinFuncNode *bifunc = static_cast<const Expression::BuiltinFuncNode *>(p_node); Vector<Variant> arr; @@ -2090,11 +2058,11 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: argp.resize(bifunc->arguments.size()); for (int i = 0; i < bifunc->arguments.size(); i++) { - Variant value; bool ret = _execute(p_inputs, p_instance, bifunc->arguments[i], value, r_error_str); - if (ret) + if (ret) { return true; + } arr.write[i] = value; argp.write[i] = &arr[i]; } @@ -2109,14 +2077,14 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } break; case Expression::ENode::TYPE_CALL: { - const Expression::CallNode *call = static_cast<const Expression::CallNode *>(p_node); Variant base; bool ret = _execute(p_inputs, p_instance, call->base, base, r_error_str); - if (ret) + if (ret) { return true; + } Vector<Variant> arr; Vector<const Variant *> argp; @@ -2124,12 +2092,12 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: argp.resize(call->arguments.size()); for (int i = 0; i < call->arguments.size(); i++) { - Variant value; ret = _execute(p_inputs, p_instance, call->arguments[i], value, r_error_str); - if (ret) + if (ret) { return true; + } arr.write[i] = value; argp.write[i] = &arr[i]; } @@ -2148,7 +2116,6 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } Error Expression::parse(const String &p_expression, const Vector<String> &p_input_names) { - if (nodes) { memdelete(nodes); nodes = nullptr; @@ -2176,7 +2143,6 @@ Error Expression::parse(const String &p_expression, const Vector<String> &p_inpu } Variant Expression::execute(Array p_inputs, Object *p_base, bool p_show_error) { - ERR_FAIL_COND_V_MSG(error_set, Variant(), "There was previously a parse error: " + error_str + "."); execution_error = false; @@ -2201,26 +2167,13 @@ String Expression::get_error_text() const { } void Expression::_bind_methods() { - ClassDB::bind_method(D_METHOD("parse", "expression", "input_names"), &Expression::parse, DEFVAL(Vector<String>())); ClassDB::bind_method(D_METHOD("execute", "inputs", "base_instance", "show_error"), &Expression::execute, DEFVAL(Array()), DEFVAL(Variant()), DEFVAL(true)); ClassDB::bind_method(D_METHOD("has_execute_failed"), &Expression::has_execute_failed); ClassDB::bind_method(D_METHOD("get_error_text"), &Expression::get_error_text); } -Expression::Expression() : - output_type(Variant::NIL), - sequenced(false), - error_set(true), - root(nullptr), - nodes(nullptr), - execution_error(false) { - str_ofs = 0; - expression_dirty = false; -} - Expression::~Expression() { - if (nodes) { memdelete(nodes); } diff --git a/core/math/expression.h b/core/math/expression.h index 78de225ebf..59a9a2f4ed 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -118,23 +118,20 @@ private: static const char *func_name[FUNC_MAX]; struct Input { - - Variant::Type type; + Variant::Type type = Variant::NIL; String name; - Input() : - type(Variant::NIL) { - } + Input() {} }; Vector<Input> inputs; - Variant::Type output_type; + Variant::Type output_type = Variant::NIL; String expression; - bool sequenced; - int str_ofs; - bool expression_dirty; + bool sequenced = false; + int str_ofs = 0; + bool expression_dirty = false; bool _compile_expression(); @@ -182,14 +179,14 @@ private: static const char *token_name[TK_MAX]; struct Token { - TokenType type; Variant value; }; void _set_error(const String &p_err) { - if (error_set) + if (error_set) { return; + } error_str = p_err; error_set = true; } @@ -197,10 +194,9 @@ private: Error _get_token(Token &r_token); String error_str; - bool error_set; + bool error_set = true; struct ENode { - enum Type { TYPE_INPUT, TYPE_CONSTANT, @@ -215,11 +211,11 @@ private: TYPE_CALL }; - ENode *next; + ENode *next = nullptr; Type type; - ENode() { next = nullptr; } + ENode() {} virtual ~ENode() { if (next) { memdelete(next); @@ -228,7 +224,6 @@ private: }; struct ExpressionNode { - bool is_op; union { Variant::Operator op; @@ -239,7 +234,6 @@ private: ENode *_parse_expression(); struct InputNode : public ENode { - int index; InputNode() { type = TYPE_INPUT; @@ -247,7 +241,6 @@ private: }; struct ConstantNode : public ENode { - Variant value; ConstantNode() { type = TYPE_CONSTANT; @@ -255,7 +248,6 @@ private: }; struct OperatorNode : public ENode { - Variant::Operator op; ENode *nodes[2]; @@ -266,7 +258,6 @@ private: }; struct SelfNode : public ENode { - SelfNode() { type = TYPE_SELF; } @@ -339,12 +330,12 @@ private: return node; } - ENode *root; - ENode *nodes; + ENode *root = nullptr; + ENode *nodes = nullptr; Vector<String> input_names; - bool execution_error; + bool execution_error = false; bool _execute(const Array &p_inputs, Object *p_instance, Expression::ENode *p_node, Variant &r_ret, String &r_error_str); protected: @@ -356,7 +347,7 @@ public: bool has_execute_failed() const; String get_error_text() const; - Expression(); + Expression() {} ~Expression(); }; diff --git a/core/math/face3.cpp b/core/math/face3.cpp index 74331b391f..db2bfaa58b 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -30,10 +30,9 @@ #include "face3.h" -#include "core/math/geometry.h" +#include "core/math/geometry_3d.h" int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_over[3]) const { - ERR_FAIL_COND_V(is_degenerate(), 0); Vector3 above[4]; @@ -43,7 +42,6 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_ int below_count = 0; for (int i = 0; i < 3; i++) { - if (p_plane.has_point(vertex[i], CMP_EPSILON)) { // point is in plane ERR_FAIL_COND_V(above_count >= 4, 0); @@ -52,7 +50,6 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_ below[below_count++] = vertex[i]; } else { - if (p_plane.is_point_over(vertex[i])) { //Point is over ERR_FAIL_COND_V(above_count >= 4, 0); @@ -67,8 +64,9 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_ /* Check for Intersection between this and the next vertex*/ Vector3 inters; - if (!p_plane.intersects_segment(vertex[i], vertex[(i + 1) % 3], &inters)) + if (!p_plane.intersects_segment(vertex[i], vertex[(i + 1) % 3], &inters)) { continue; + } /* Intersection goes to both */ ERR_FAIL_COND_V(above_count >= 4, 0); @@ -83,13 +81,11 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_ ERR_FAIL_COND_V(above_count >= 4 && below_count >= 4, 0); //bug in the algo if (above_count >= 3) { - p_res[polygons_created] = Face3(above[0], above[1], above[2]); p_is_point_over[polygons_created] = true; polygons_created++; if (above_count == 4) { - p_res[polygons_created] = Face3(above[2], above[3], above[0]); p_is_point_over[polygons_created] = true; polygons_created++; @@ -97,13 +93,11 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_ } if (below_count >= 3) { - p_res[polygons_created] = Face3(below[0], below[1], below[2]); p_is_point_over[polygons_created] = false; polygons_created++; if (below_count == 4) { - p_res[polygons_created] = Face3(below[2], below[3], below[0]); p_is_point_over[polygons_created] = false; polygons_created++; @@ -114,52 +108,49 @@ int Face3::split_by_plane(const Plane &p_plane, Face3 p_res[3], bool p_is_point_ } bool Face3::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const { - - return Geometry::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection); + return Geometry3D::ray_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection); } bool Face3::intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const { - - return Geometry::segment_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection); + return Geometry3D::segment_intersects_triangle(p_from, p_dir, vertex[0], vertex[1], vertex[2], p_intersection); } bool Face3::is_degenerate() const { - Vector3 normal = vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]); return (normal.length_squared() < CMP_EPSILON2); } Face3::Side Face3::get_side_of(const Face3 &p_face, ClockDirection p_clock_dir) const { - int over = 0, under = 0; Plane plane = get_plane(p_clock_dir); for (int i = 0; i < 3; i++) { - const Vector3 &v = p_face.vertex[i]; - if (plane.has_point(v)) //coplanar, don't bother + if (plane.has_point(v)) { //coplanar, don't bother continue; + } - if (plane.is_point_over(v)) + if (plane.is_point_over(v)) { over++; - else + } else { under++; + } } - if (over > 0 && under == 0) + if (over > 0 && under == 0) { return SIDE_OVER; - else if (under > 0 && over == 0) + } else if (under > 0 && over == 0) { return SIDE_UNDER; - else if (under == 0 && over == 0) + } else if (under == 0 && over == 0) { return SIDE_COPLANAR; - else + } else { return SIDE_SPANNING; + } } Vector3 Face3::get_random_point_inside() const { - real_t a = Math::random(0, 1); real_t b = Math::random(0, 1); if (a > b) { @@ -170,32 +161,28 @@ Vector3 Face3::get_random_point_inside() const { } Plane Face3::get_plane(ClockDirection p_dir) const { - return Plane(vertex[0], vertex[1], vertex[2], p_dir); } Vector3 Face3::get_median_point() const { - return (vertex[0] + vertex[1] + vertex[2]) / 3.0; } real_t Face3::get_area() const { - return vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]).length(); } ClockDirection Face3::get_clock_dir() const { - Vector3 normal = vec3_cross(vertex[0] - vertex[1], vertex[0] - vertex[2]); //printf("normal is %g,%g,%g x %g,%g,%g- wtfu is %g\n",tofloat(normal.x),tofloat(normal.y),tofloat(normal.z),tofloat(vertex[0].x),tofloat(vertex[0].y),tofloat(vertex[0].z),tofloat( normal.dot( vertex[0] ) ) ); return (normal.dot(vertex[0]) >= 0) ? CLOCKWISE : COUNTERCLOCKWISE; } bool Face3::intersects_aabb(const AABB &p_aabb) const { - /** TEST PLANE **/ - if (!p_aabb.intersects_plane(get_plane())) + if (!p_aabb.intersects_plane(get_plane())) { return false; + } #define TEST_AXIS(m_ax) \ /** TEST FACE AXIS */ \ @@ -228,7 +215,6 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const { }; for (int i = 0; i < 12; i++) { - Vector3 from, to; p_aabb.get_edge(i, from, to); Vector3 e1 = from - to; @@ -237,58 +223,57 @@ bool Face3::intersects_aabb(const AABB &p_aabb) const { Vector3 axis = vec3_cross(e1, e2); - if (axis.length_squared() < 0.0001) + if (axis.length_squared() < 0.0001) { continue; // coplanar + } axis.normalize(); real_t minA, maxA, minB, maxB; p_aabb.project_range_in_plane(Plane(axis, 0), minA, maxA); project_range(axis, Transform(), minB, maxB); - if (maxA < minB || maxB < minA) + if (maxA < minB || maxB < minA) { return false; + } } } return true; } Face3::operator String() const { - return String() + vertex[0] + ", " + vertex[1] + ", " + vertex[2]; } void Face3::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - for (int i = 0; i < 3; i++) { - Vector3 v = p_transform.xform(vertex[i]); real_t d = p_normal.dot(v); - if (i == 0 || d > r_max) + if (i == 0 || d > r_max) { r_max = d; + } - if (i == 0 || d < r_min) + if (i == 0 || d < r_min) { r_min = d; + } } } void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, Vector3 *p_vertices, int *p_count, int p_max) const { - #define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.98 #define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.05 - if (p_max <= 0) + if (p_max <= 0) { return; + } Vector3 n = p_transform.basis.xform_inv(p_normal); /** TEST FACE AS SUPPORT **/ if (get_plane().normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { - *p_count = MIN(3, p_max); for (int i = 0; i < *p_count; i++) { - p_vertices[i] = p_transform.xform(vertex[i]); } @@ -301,7 +286,6 @@ void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, V real_t support_max = 0; for (int i = 0; i < 3; i++) { - real_t d = n.dot(vertex[i]); if (i == 0 || d > support_max) { @@ -313,19 +297,19 @@ void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, V /** TEST EDGES AS SUPPORT **/ for (int i = 0; i < 3; i++) { - - if (i != vert_support_idx && i + 1 != vert_support_idx) + if (i != vert_support_idx && i + 1 != vert_support_idx) { continue; + } // check if edge is valid as a support real_t dot = (vertex[i] - vertex[(i + 1) % 3]).normalized().dot(n); dot = ABS(dot); if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { - *p_count = MIN(2, p_max); - for (int j = 0; j < *p_count; j++) + for (int j = 0; j < *p_count; j++) { p_vertices[j] = p_transform.xform(vertex[(j + i) % 3]); + } return; } @@ -336,7 +320,6 @@ void Face3::get_support(const Vector3 &p_normal, const Transform &p_transform, V } Vector3 Face3::get_closest_point_to(const Vector3 &p_point) const { - Vector3 edge0 = vertex[1] - vertex[0]; Vector3 edge1 = vertex[2] - vertex[0]; Vector3 v0 = vertex[0] - p_point; diff --git a/core/math/face3.h b/core/math/face3.h index f4b8721caa..fb40e8ab9e 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -69,8 +69,8 @@ public: Vector3 get_median_point() const; Vector3 get_closest_point_to(const Vector3 &p_point) const; - bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = 0) const; - bool intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = 0) const; + bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const; + bool intersects_segment(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection = nullptr) const; ClockDirection get_clock_dir() const; ///< todo, test if this is returning the proper clockwisity @@ -78,7 +78,6 @@ public: void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; AABB get_aabb() const { - AABB aabb(vertex[0], Vector3()); aabb.expand_to(vertex[1]); aabb.expand_to(vertex[2]); @@ -98,7 +97,6 @@ public: }; bool Face3::intersects_aabb2(const AABB &p_aabb) const { - Vector3 perp = (vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]); Vector3 half_extents = p_aabb.size * 0.5; @@ -113,8 +111,9 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { real_t dist_a = perp.dot(ofs + sup) - d; real_t dist_b = perp.dot(ofs - sup) - d; - if (dist_a * dist_b > 0) + if (dist_a * dist_b > 0) { return false; //does not intersect the plane + } #define TEST_AXIS(m_ax) \ { \ @@ -145,17 +144,13 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { }; for (int i = 0; i < 12; i++) { - Vector3 from, to; switch (i) { - case 0: { - from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z); to = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z); } break; case 1: { - from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z); to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z); } break; @@ -165,18 +160,15 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { } break; case 3: { - from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z); to = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z); } break; case 4: { - from = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z); to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z); } break; case 5: { - from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z); to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z); } break; @@ -186,31 +178,26 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { } break; case 7: { - from = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z); to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z); } break; case 8: { - from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z); to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z); } break; case 9: { - from = Vector3(p_aabb.position.x, p_aabb.position.y, p_aabb.position.z); to = Vector3(p_aabb.position.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z); } break; case 10: { - from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z); to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z); } break; case 11: { - from = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y, p_aabb.position.z + p_aabb.size.z); to = Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z); @@ -223,8 +210,9 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { Vector3 axis = vec3_cross(e1, e2); - if (axis.length_squared() < 0.0001) + if (axis.length_squared() < 0.0001) { continue; // coplanar + } //axis.normalize(); Vector3 sup2 = Vector3( @@ -240,18 +228,20 @@ bool Face3::intersects_aabb2(const AABB &p_aabb) const { real_t minT = 1e20, maxT = -1e20; for (int k = 0; k < 3; k++) { - real_t vert_d = axis.dot(vertex[k]); - if (vert_d > maxT) + if (vert_d > maxT) { maxT = vert_d; + } - if (vert_d < minT) + if (vert_d < minT) { minT = vert_d; + } } - if (maxB < minT || maxT < minB) + if (maxB < minT || maxT < minB) { return false; + } } } return true; diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp new file mode 100644 index 0000000000..7d8fde8bcc --- /dev/null +++ b/core/math/geometry_2d.cpp @@ -0,0 +1,384 @@ +/*************************************************************************/ +/* geometry.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "geometry_2d.h" + +#include "thirdparty/misc/clipper.hpp" +#include "thirdparty/misc/triangulator.h" +#define STB_RECT_PACK_IMPLEMENTATION +#include "thirdparty/misc/stb_rect_pack.h" + +#define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON. + +Vector<Vector<Vector2>> Geometry2D::decompose_polygon_in_convex(Vector<Point2> polygon) { + Vector<Vector<Vector2>> decomp; + List<TriangulatorPoly> in_poly, out_poly; + + TriangulatorPoly inp; + inp.Init(polygon.size()); + for (int i = 0; i < polygon.size(); i++) { + inp.GetPoint(i) = polygon[i]; + } + inp.SetOrientation(TRIANGULATOR_CCW); + in_poly.push_back(inp); + TriangulatorPartition tpart; + if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { // Failed. + ERR_PRINT("Convex decomposing failed!"); + return decomp; + } + + decomp.resize(out_poly.size()); + int idx = 0; + for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) { + TriangulatorPoly &tp = I->get(); + + decomp.write[idx].resize(tp.GetNumPoints()); + + for (int64_t i = 0; i < tp.GetNumPoints(); i++) { + decomp.write[idx].write[i] = tp.GetPoint(i); + } + + idx++; + } + + return decomp; +} + +struct _AtlasWorkRect { + Size2i s; + Point2i p; + int idx; + _FORCE_INLINE_ bool operator<(const _AtlasWorkRect &p_r) const { return s.width > p_r.s.width; }; +}; + +struct _AtlasWorkRectResult { + Vector<_AtlasWorkRect> result; + int max_w; + int max_h; +}; + +void Geometry2D::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) { + // Super simple, almost brute force scanline stacking fitter. + // It's pretty basic for now, but it tries to make sure that the aspect ratio of the + // resulting atlas is somehow square. This is necessary because video cards have limits. + // On texture size (usually 2048 or 4096), so the more square a texture, the more chances. + // It will work in every hardware. + // For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a + // 256x8192 atlas (won't work anywhere). + + ERR_FAIL_COND(p_rects.size() == 0); + + Vector<_AtlasWorkRect> wrects; + wrects.resize(p_rects.size()); + for (int i = 0; i < p_rects.size(); i++) { + wrects.write[i].s = p_rects[i]; + wrects.write[i].idx = i; + } + wrects.sort(); + int widest = wrects[0].s.width; + + Vector<_AtlasWorkRectResult> results; + + for (int i = 0; i <= 12; i++) { + int w = 1 << i; + int max_h = 0; + int max_w = 0; + if (w < widest) { + continue; + } + + Vector<int> hmax; + hmax.resize(w); + for (int j = 0; j < w; j++) { + hmax.write[j] = 0; + } + + // Place them. + int ofs = 0; + int limit_h = 0; + for (int j = 0; j < wrects.size(); j++) { + if (ofs + wrects[j].s.width > w) { + ofs = 0; + } + + int from_y = 0; + for (int k = 0; k < wrects[j].s.width; k++) { + if (hmax[ofs + k] > from_y) { + from_y = hmax[ofs + k]; + } + } + + wrects.write[j].p.x = ofs; + wrects.write[j].p.y = from_y; + int end_h = from_y + wrects[j].s.height; + int end_w = ofs + wrects[j].s.width; + if (ofs == 0) { + limit_h = end_h; + } + + for (int k = 0; k < wrects[j].s.width; k++) { + hmax.write[ofs + k] = end_h; + } + + if (end_h > max_h) { + max_h = end_h; + } + + if (end_w > max_w) { + max_w = end_w; + } + + if (ofs == 0 || end_h > limit_h) { // While h limit not reached, keep stacking. + ofs += wrects[j].s.width; + } + } + + _AtlasWorkRectResult result; + result.result = wrects; + result.max_h = max_h; + result.max_w = max_w; + results.push_back(result); + } + + // Find the result with the best aspect ratio. + + int best = -1; + real_t best_aspect = 1e20; + + for (int i = 0; i < results.size(); i++) { + real_t h = next_power_of_2(results[i].max_h); + real_t w = next_power_of_2(results[i].max_w); + real_t aspect = h > w ? h / w : w / h; + if (aspect < best_aspect) { + best = i; + best_aspect = aspect; + } + } + + r_result.resize(p_rects.size()); + + for (int i = 0; i < p_rects.size(); i++) { + r_result.write[results[best].result[i].idx] = results[best].result[i].p; + } + + r_size = Size2(results[best].max_w, results[best].max_h); +} + +Vector<Vector<Point2>> Geometry2D::_polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open) { + using namespace ClipperLib; + + ClipType op = ctUnion; + + switch (p_op) { + case OPERATION_UNION: + op = ctUnion; + break; + case OPERATION_DIFFERENCE: + op = ctDifference; + break; + case OPERATION_INTERSECTION: + op = ctIntersection; + break; + case OPERATION_XOR: + op = ctXor; + break; + } + Path path_a, path_b; + + // Need to scale points (Clipper's requirement for robust computation). + for (int i = 0; i != p_polypath_a.size(); ++i) { + path_a << IntPoint(p_polypath_a[i].x * SCALE_FACTOR, p_polypath_a[i].y * SCALE_FACTOR); + } + for (int i = 0; i != p_polypath_b.size(); ++i) { + path_b << IntPoint(p_polypath_b[i].x * SCALE_FACTOR, p_polypath_b[i].y * SCALE_FACTOR); + } + Clipper clp; + clp.AddPath(path_a, ptSubject, !is_a_open); // Forward compatible with Clipper 10.0.0. + clp.AddPath(path_b, ptClip, true); // Polylines cannot be set as clip. + + Paths paths; + + if (is_a_open) { + PolyTree tree; // Needed to populate polylines. + clp.Execute(op, tree); + OpenPathsFromPolyTree(tree, paths); + } else { + clp.Execute(op, paths); // Works on closed polygons only. + } + // Have to scale points down now. + Vector<Vector<Point2>> polypaths; + + for (Paths::size_type i = 0; i < paths.size(); ++i) { + Vector<Vector2> polypath; + + const Path &scaled_path = paths[i]; + + for (Paths::size_type j = 0; j < scaled_path.size(); ++j) { + polypath.push_back(Point2( + static_cast<real_t>(scaled_path[j].X) / SCALE_FACTOR, + static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR)); + } + polypaths.push_back(polypath); + } + return polypaths; +} + +Vector<Vector<Point2>> Geometry2D::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { + using namespace ClipperLib; + + JoinType jt = jtSquare; + + switch (p_join_type) { + case JOIN_SQUARE: + jt = jtSquare; + break; + case JOIN_ROUND: + jt = jtRound; + break; + case JOIN_MITER: + jt = jtMiter; + break; + } + + EndType et = etClosedPolygon; + + switch (p_end_type) { + case END_POLYGON: + et = etClosedPolygon; + break; + case END_JOINED: + et = etClosedLine; + break; + case END_BUTT: + et = etOpenButt; + break; + case END_SQUARE: + et = etOpenSquare; + break; + case END_ROUND: + et = etOpenRound; + break; + } + ClipperOffset co(2.0, 0.25 * SCALE_FACTOR); // Defaults from ClipperOffset. + Path path; + + // Need to scale points (Clipper's requirement for robust computation). + for (int i = 0; i != p_polypath.size(); ++i) { + path << IntPoint(p_polypath[i].x * SCALE_FACTOR, p_polypath[i].y * SCALE_FACTOR); + } + co.AddPath(path, jt, et); + + Paths paths; + co.Execute(paths, p_delta * SCALE_FACTOR); // Inflate/deflate. + + // Have to scale points down now. + Vector<Vector<Point2>> polypaths; + + for (Paths::size_type i = 0; i < paths.size(); ++i) { + Vector<Vector2> polypath; + + const Path &scaled_path = paths[i]; + + for (Paths::size_type j = 0; j < scaled_path.size(); ++j) { + polypath.push_back(Point2( + static_cast<real_t>(scaled_path[j].X) / SCALE_FACTOR, + static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR)); + } + polypaths.push_back(polypath); + } + return polypaths; +} + +Vector<Point2i> Geometry2D::pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size) { + Vector<stbrp_node> nodes; + nodes.resize(p_atlas_size.width); + + stbrp_context context; + stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width); + + Vector<stbrp_rect> rects; + rects.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + rects.write[i].id = 0; + rects.write[i].w = p_sizes[i].width; + rects.write[i].h = p_sizes[i].height; + rects.write[i].x = 0; + rects.write[i].y = 0; + rects.write[i].was_packed = 0; + } + + int res = stbrp_pack_rects(&context, rects.ptrw(), rects.size()); + if (res == 0) { //pack failed + return Vector<Point2i>(); + } + + Vector<Point2i> ret; + ret.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + Point2i r(rects[i].x, rects[i].y); + ret.write[i] = r; + } + + return ret; +} + +Vector<Vector3i> Geometry2D::partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size) { + Vector<stbrp_node> nodes; + nodes.resize(p_atlas_size.width); + zeromem(nodes.ptrw(), sizeof(stbrp_node) * nodes.size()); + + stbrp_context context; + stbrp_init_target(&context, p_atlas_size.width, p_atlas_size.height, nodes.ptrw(), p_atlas_size.width); + + Vector<stbrp_rect> rects; + rects.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + rects.write[i].id = i; + rects.write[i].w = p_sizes[i].width; + rects.write[i].h = p_sizes[i].height; + rects.write[i].x = 0; + rects.write[i].y = 0; + rects.write[i].was_packed = 0; + } + + stbrp_pack_rects(&context, rects.ptrw(), rects.size()); + + Vector<Vector3i> ret; + ret.resize(p_sizes.size()); + + for (int i = 0; i < p_sizes.size(); i++) { + ret.write[rects[i].id] = Vector3i(rects[i].x, rects[i].y, rects[i].was_packed != 0 ? 1 : 0); + } + + return ret; +} diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h new file mode 100644 index 0000000000..cfd7abfacb --- /dev/null +++ b/core/math/geometry_2d.h @@ -0,0 +1,398 @@ +/*************************************************************************/ +/* geometry_2d.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GEOMETRY_2D_H +#define GEOMETRY_2D_H + +#include "core/math/delaunay_2d.h" +#include "core/math/rect2.h" +#include "core/math/triangulate.h" +#include "core/object.h" +#include "core/vector.h" + +class Geometry2D { + Geometry2D(); + +public: + static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) { + Vector2 d1 = q1 - p1; // Direction vector of segment S1. + Vector2 d2 = q2 - p2; // Direction vector of segment S2. + Vector2 r = p1 - p2; + real_t a = d1.dot(d1); // Squared length of segment S1, always nonnegative. + real_t e = d2.dot(d2); // Squared length of segment S2, always nonnegative. + real_t f = d2.dot(r); + real_t s, t; + // Check if either or both segments degenerate into points. + if (a <= CMP_EPSILON && e <= CMP_EPSILON) { + // Both segments degenerate into points. + c1 = p1; + c2 = p2; + return Math::sqrt((c1 - c2).dot(c1 - c2)); + } + if (a <= CMP_EPSILON) { + // First segment degenerates into a point. + s = 0.0; + t = f / e; // s = 0 => t = (b*s + f) / e = f / e + t = CLAMP(t, 0.0, 1.0); + } else { + real_t c = d1.dot(r); + if (e <= CMP_EPSILON) { + // Second segment degenerates into a point. + t = 0.0; + s = CLAMP(-c / a, 0.0, 1.0); // t = 0 => s = (b*t - c) / a = -c / a + } else { + // The general nondegenerate case starts here. + real_t b = d1.dot(d2); + real_t denom = a * e - b * b; // Always nonnegative. + // If segments not parallel, compute closest point on L1 to L2 and + // clamp to segment S1. Else pick arbitrary s (here 0). + if (denom != 0.0) { + s = CLAMP((b * f - c * e) / denom, 0.0, 1.0); + } else { + s = 0.0; + } + // Compute point on L2 closest to S1(s) using + // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e + t = (b * s + f) / e; + + //If t in [0,1] done. Else clamp t, recompute s for the new value + // of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a + // and clamp s to [0, 1]. + if (t < 0.0) { + t = 0.0; + s = CLAMP(-c / a, 0.0, 1.0); + } else if (t > 1.0) { + t = 1.0; + s = CLAMP((b - c) / a, 0.0, 1.0); + } + } + } + c1 = p1 + d1 * s; + c2 = p2 + d2 * t; + return Math::sqrt((c1 - c2).dot(c1 - c2)); + } + + static Vector2 get_closest_point_to_segment(const Vector2 &p_point, const Vector2 *p_segment) { + Vector2 p = p_point - p_segment[0]; + Vector2 n = p_segment[1] - p_segment[0]; + real_t l2 = n.length_squared(); + if (l2 < 1e-20) { + return p_segment[0]; // Both points are the same, just give any. + } + + real_t d = n.dot(p) / l2; + + if (d <= 0.0) { + return p_segment[0]; // Before first point. + } else if (d >= 1.0) { + return p_segment[1]; // After first point. + } else { + return p_segment[0] + n * d; // Inside. + } + } + + static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) { + Vector2 an = a - s; + Vector2 bn = b - s; + Vector2 cn = c - s; + + bool orientation = an.cross(bn) > 0; + + if ((bn.cross(cn) > 0) != orientation) { + return false; + } + + return (cn.cross(an) > 0) == orientation; + } + + static Vector2 get_closest_point_to_segment_uncapped(const Vector2 &p_point, const Vector2 *p_segment) { + Vector2 p = p_point - p_segment[0]; + Vector2 n = p_segment[1] - p_segment[0]; + real_t l2 = n.length_squared(); + if (l2 < 1e-20) { + return p_segment[0]; // Both points are the same, just give any. + } + + real_t d = n.dot(p) / l2; + + return p_segment[0] + n * d; // Inside. + } + + static bool line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b, Vector2 &r_result) { + // See http://paulbourke.net/geometry/pointlineplane/ + + const real_t denom = p_dir_b.y * p_dir_a.x - p_dir_b.x * p_dir_a.y; + if (Math::is_zero_approx(denom)) { // Parallel? + return false; + } + + const Vector2 v = p_from_a - p_from_b; + const real_t t = (p_dir_b.x * v.y - p_dir_b.y * v.x) / denom; + r_result = p_from_a + t * p_dir_a; + return true; + } + + static bool segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b, Vector2 *r_result) { + Vector2 B = p_to_a - p_from_a; + Vector2 C = p_from_b - p_from_a; + Vector2 D = p_to_b - p_from_a; + + real_t ABlen = B.dot(B); + if (ABlen <= 0) { + return false; + } + Vector2 Bn = B / ABlen; + C = Vector2(C.x * Bn.x + C.y * Bn.y, C.y * Bn.x - C.x * Bn.y); + D = Vector2(D.x * Bn.x + D.y * Bn.y, D.y * Bn.x - D.x * Bn.y); + + if ((C.y < 0 && D.y < 0) || (C.y >= 0 && D.y >= 0)) { + return false; + } + + real_t ABpos = D.x + (C.x - D.x) * D.y / (D.y - C.y); + + // Fail if segment C-D crosses line A-B outside of segment A-B. + if (ABpos < 0 || ABpos > 1.0) { + return false; + } + + // (4) Apply the discovered position to line A-B in the original coordinate system. + if (r_result) { + *r_result = p_from_a + B * ABpos; + } + + return true; + } + + static inline bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) { + return p_point.distance_squared_to(p_circle_pos) <= p_circle_radius * p_circle_radius; + } + + static real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) { + Vector2 line_vec = p_to - p_from; + Vector2 vec_to_line = p_from - p_circle_pos; + + // Create a quadratic formula of the form ax^2 + bx + c = 0 + real_t a, b, c; + + a = line_vec.dot(line_vec); + b = 2 * vec_to_line.dot(line_vec); + c = vec_to_line.dot(vec_to_line) - p_circle_radius * p_circle_radius; + + // Solve for t. + real_t sqrtterm = b * b - 4 * a * c; + + // If the term we intend to square root is less than 0 then the answer won't be real, + // so it definitely won't be t in the range 0 to 1. + if (sqrtterm < 0) { + return -1; + } + + // If we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection) + // then the following can be skipped and we can just return the equivalent of res1. + sqrtterm = Math::sqrt(sqrtterm); + real_t res1 = (-b - sqrtterm) / (2 * a); + real_t res2 = (-b + sqrtterm) / (2 * a); + + if (res1 >= 0 && res1 <= 1) { + return res1; + } + if (res2 >= 0 && res2 <= 1) { + return res2; + } + return -1; + } + + enum PolyBooleanOperation { + OPERATION_UNION, + OPERATION_DIFFERENCE, + OPERATION_INTERSECTION, + OPERATION_XOR + }; + enum PolyJoinType { + JOIN_SQUARE, + JOIN_ROUND, + JOIN_MITER + }; + enum PolyEndType { + END_POLYGON, + END_JOINED, + END_BUTT, + END_SQUARE, + END_ROUND + }; + + static Vector<Vector<Point2>> merge_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { + return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b); + } + + static Vector<Vector<Point2>> clip_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { + return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polygon_a, p_polygon_b); + } + + static Vector<Vector<Point2>> intersect_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { + return _polypaths_do_operation(OPERATION_INTERSECTION, p_polygon_a, p_polygon_b); + } + + static Vector<Vector<Point2>> exclude_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { + return _polypaths_do_operation(OPERATION_XOR, p_polygon_a, p_polygon_b); + } + + static Vector<Vector<Point2>> clip_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { + return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polyline, p_polygon, true); + } + + static Vector<Vector<Point2>> intersect_polyline_with_polygon(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { + return _polypaths_do_operation(OPERATION_INTERSECTION, p_polyline, p_polygon, true); + } + + static Vector<Vector<Point2>> offset_polygon(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { + return _polypath_offset(p_polygon, p_delta, p_join_type, END_POLYGON); + } + + static Vector<Vector<Point2>> offset_polyline(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { + ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2>>(), "Attempt to offset a polyline like a polygon (use offset_polygon instead)."); + + return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type); + } + + static Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points) { + Vector<Delaunay2D::Triangle> tr = Delaunay2D::triangulate(p_points); + Vector<int> triangles; + + for (int i = 0; i < tr.size(); i++) { + triangles.push_back(tr[i].points[0]); + triangles.push_back(tr[i].points[1]); + triangles.push_back(tr[i].points[2]); + } + return triangles; + } + + static Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon) { + Vector<int> triangles; + if (!Triangulate::triangulate(p_polygon, triangles)) { + return Vector<int>(); //fail + } + return triangles; + } + + static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) { + int c = p_polygon.size(); + if (c < 3) { + return false; + } + const Vector2 *p = p_polygon.ptr(); + real_t sum = 0; + for (int i = 0; i < c; i++) { + const Vector2 &v1 = p[i]; + const Vector2 &v2 = p[(i + 1) % c]; + sum += (v2.x - v1.x) * (v2.y + v1.y); + } + + return sum > 0.0f; + } + + // Alternate implementation that should be faster. + static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { + int c = p_polygon.size(); + if (c < 3) { + return false; + } + const Vector2 *p = p_polygon.ptr(); + Vector2 further_away(-1e20, -1e20); + Vector2 further_away_opposite(1e20, 1e20); + + for (int i = 0; i < c; i++) { + further_away.x = MAX(p[i].x, further_away.x); + further_away.y = MAX(p[i].y, further_away.y); + further_away_opposite.x = MIN(p[i].x, further_away_opposite.x); + further_away_opposite.y = MIN(p[i].y, further_away_opposite.y); + } + + // Make point outside that won't intersect with points in segment from p_point. + further_away += (further_away - further_away_opposite) * Vector2(1.221313, 1.512312); + + int intersections = 0; + for (int i = 0; i < c; i++) { + const Vector2 &v1 = p[i]; + const Vector2 &v2 = p[(i + 1) % c]; + if (segment_intersects_segment(v1, v2, p_point, further_away, nullptr)) { + intersections++; + } + } + + return (intersections & 1); + } + + static real_t vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B) { + return (real_t)(A.x - O.x) * (B.y - O.y) - (real_t)(A.y - O.y) * (B.x - O.x); + } + + // Returns a list of points on the convex hull in counter-clockwise order. + // Note: the last point in the returned list is the same as the first one. + static Vector<Point2> convex_hull(Vector<Point2> P) { + int n = P.size(), k = 0; + Vector<Point2> H; + H.resize(2 * n); + + // Sort points lexicographically. + P.sort(); + + // Build lower hull. + for (int i = 0; i < n; ++i) { + while (k >= 2 && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) { + k--; + } + H.write[k++] = P[i]; + } + + // Build upper hull. + for (int i = n - 2, t = k + 1; i >= 0; i--) { + while (k >= t && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) { + k--; + } + H.write[k++] = P[i]; + } + + H.resize(k); + return H; + } + static Vector<Vector<Vector2>> decompose_polygon_in_convex(Vector<Point2> polygon); + + static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size); + static Vector<Point2i> pack_rects(const Vector<Size2i> &p_sizes, const Size2i &p_atlas_size); + static Vector<Vector3i> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size); + +private: + static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open = false); + static Vector<Vector<Point2>> _polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type); +}; + +#endif // GEOMETRY_2D_H diff --git a/core/math/geometry.cpp b/core/math/geometry_3d.cpp index 3e07e9253e..3b30f4b1fe 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry_3d.cpp @@ -28,36 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "geometry.h" +#include "geometry_3d.h" #include "core/print_string.h" + #include "thirdparty/misc/clipper.hpp" #include "thirdparty/misc/triangulator.h" -#define SCALE_FACTOR 100000.0 // Based on CMP_EPSILON. - -// This implementation is very inefficient, commenting unless bugs happen. See the other one. -/* -bool Geometry::is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { - - Vector<int> indices = Geometry::triangulate_polygon(p_polygon); - for (int j = 0; j + 3 <= indices.size(); j += 3) { - int i1 = indices[j], i2 = indices[j + 1], i3 = indices[j + 2]; - if (Geometry::is_point_in_triangle(p_point, p_polygon[i1], p_polygon[i2], p_polygon[i3])) - return true; - } - return false; -} -*/ - -void Geometry::MeshData::optimize_vertices() { - +void Geometry3D::MeshData::optimize_vertices() { Map<int, int> vtx_remap; for (int i = 0; i < faces.size(); i++) { - for (int j = 0; j < faces[i].indices.size(); j++) { - int idx = faces[i].indices[j]; if (!vtx_remap.has(idx)) { int ni = vtx_remap.size(); @@ -69,7 +51,6 @@ void Geometry::MeshData::optimize_vertices() { } for (int i = 0; i < edges.size(); i++) { - int a = edges[i].a; int b = edges[i].b; @@ -90,36 +71,28 @@ void Geometry::MeshData::optimize_vertices() { new_vertices.resize(vtx_remap.size()); for (int i = 0; i < vertices.size(); i++) { - - if (vtx_remap.has(i)) + if (vtx_remap.has(i)) { new_vertices.write[vtx_remap[i]] = vertices[i]; + } } vertices = new_vertices; } struct _FaceClassify { - struct _Link { - - int face; - int edge; + int face = -1; + int edge = -1; void clear() { face = -1; edge = -1; } - _Link() { - face = -1; - edge = -1; - } + _Link() {} }; - bool valid; - int group; + bool valid = false; + int group = -1; _Link links[3]; Face3 face; - _FaceClassify() { - group = -1; - valid = false; - }; + _FaceClassify() {} }; static bool _connect_faces(_FaceClassify *p_faces, int len, int p_group) { @@ -129,42 +102,36 @@ static bool _connect_faces(_FaceClassify *p_faces, int len, int p_group) { bool error = false; for (int i = 0; i < len; i++) { - for (int j = 0; j < 3; j++) { - p_faces[i].links[j].clear(); } } for (int i = 0; i < len; i++) { - - if (p_faces[i].group != p_group) + if (p_faces[i].group != p_group) { continue; + } for (int j = i + 1; j < len; j++) { - - if (p_faces[j].group != p_group) + if (p_faces[j].group != p_group) { continue; + } for (int k = 0; k < 3; k++) { - Vector3 vi1 = p_faces[i].face.vertex[k]; Vector3 vi2 = p_faces[i].face.vertex[(k + 1) % 3]; for (int l = 0; l < 3; l++) { - Vector3 vj2 = p_faces[j].face.vertex[l]; Vector3 vj1 = p_faces[j].face.vertex[(l + 1) % 3]; if (vi1.distance_to(vj1) < 0.00001 && vi2.distance_to(vj2) < 0.00001) { if (p_faces[i].links[k].face != -1) { - ERR_PRINT("already linked\n"); error = true; break; } if (p_faces[j].links[l].face != -1) { - ERR_PRINT("already linked\n"); error = true; break; @@ -176,37 +143,38 @@ static bool _connect_faces(_FaceClassify *p_faces, int len, int p_group) { p_faces[j].links[l].edge = k; } } - if (error) + if (error) { break; + } } - if (error) + if (error) { break; + } } - if (error) + if (error) { break; + } } for (int i = 0; i < len; i++) { - p_faces[i].valid = true; for (int j = 0; j < 3; j++) { - - if (p_faces[i].links[j].face == -1) + if (p_faces[i].links[j].face == -1) { p_faces[i].valid = false; + } } } return error; } static bool _group_face(_FaceClassify *p_faces, int len, int p_index, int p_group) { - - if (p_faces[p_index].group >= 0) + if (p_faces[p_index].group >= 0) { return false; + } p_faces[p_index].group = p_group; for (int i = 0; i < 3; i++) { - ERR_FAIL_INDEX_V(p_faces[p_index].links[i].face, len, true); _group_face(p_faces, len, p_faces[p_index].links[i].face, p_group); } @@ -214,8 +182,7 @@ static bool _group_face(_FaceClassify *p_faces, int len, int p_index, int p_grou return true; } -Vector<Vector<Face3>> Geometry::separate_objects(Vector<Face3> p_array) { - +Vector<Vector<Face3>> Geometry3D::separate_objects(Vector<Face3> p_array) { Vector<Vector<Face3>> objects; int len = p_array.size(); @@ -229,7 +196,6 @@ Vector<Vector<Face3>> Geometry::separate_objects(Vector<Face3> p_array) { _FaceClassify *_fcptr = fc.ptrw(); for (int i = 0; i < len; i++) { - _fcptr[i].face = arrayptr[i]; } @@ -241,9 +207,9 @@ Vector<Vector<Face3>> Geometry::separate_objects(Vector<Face3> p_array) { int group = 0; for (int i = 0; i < len; i++) { - - if (!_fcptr[i].valid) + if (!_fcptr[i].valid) { continue; + } if (_group_face(_fcptr, len, i, group)) { group++; } @@ -252,20 +218,18 @@ Vector<Vector<Face3>> Geometry::separate_objects(Vector<Face3> p_array) { // Group connected faces in separate objects. for (int i = 0; i < len; i++) { - _fcptr[i].face = arrayptr[i]; } if (group >= 0) { - objects.resize(group); Vector<Face3> *group_faces = objects.ptrw(); for (int i = 0; i < len; i++) { - if (!_fcptr[i].valid) + if (!_fcptr[i].valid) { continue; + } if (_fcptr[i].group >= 0 && _fcptr[i].group < group) { - group_faces[_fcptr[i].group].push_back(_fcptr[i].face); } } @@ -302,16 +266,15 @@ enum _CellFlags { }; static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, const Vector3 &voxelsize, const Face3 &p_face) { - AABB aabb(Vector3(x, y, z), Vector3(len_x, len_y, len_z)); aabb.position = aabb.position * voxelsize; aabb.size = aabb.size * voxelsize; - if (!p_face.intersects_aabb(aabb)) + if (!p_face.intersects_aabb(aabb)) { return; + } if (len_x == 1 && len_y == 1 && len_z == 1) { - p_cell_status[x][y][z] = _CELL_SOLID; return; } @@ -340,15 +303,12 @@ static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int int new_len_z; for (int i = 0; i < div_x; i++) { - _SPLIT(i, div_x, x, len_x, new_x, new_len_x); for (int j = 0; j < div_y; j++) { - _SPLIT(j, div_y, y, len_y, new_y, new_len_y); for (int k = 0; k < div_z; k++) { - _SPLIT(k, div_z, z, len_z, new_z, new_len_z); _plot_face(p_cell_status, new_x, new_y, new_z, new_len_x, new_len_y, new_len_z, voxelsize, p_face); @@ -358,14 +318,13 @@ static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int } static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z) { - - if (p_cell_status[x][y][z] & 3) + if (p_cell_status[x][y][z] & 3) { return; // Nothing to do, already used and/or visited. + } p_cell_status[x][y][z] = _CELL_PREV_FIRST; while (true) { - uint8_t &c = p_cell_status[x][y][z]; if ((c & _CELL_STEP_MASK) == _CELL_STEP_NONE) { @@ -419,9 +378,7 @@ static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, uint8_t prev = 0; switch (c & _CELL_STEP_MASK) { - case _CELL_STEP_Y_POS: { - next_y++; prev = _CELL_PREV_Y_NEG; } break; @@ -445,18 +402,23 @@ static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, next_z--; prev = _CELL_PREV_Z_POS; } break; - default: ERR_FAIL(); + default: + ERR_FAIL(); } - if (next_x < 0 || next_x >= len_x) + if (next_x < 0 || next_x >= len_x) { continue; - if (next_y < 0 || next_y >= len_y) + } + if (next_y < 0 || next_y >= len_y) { continue; - if (next_z < 0 || next_z >= len_z) + } + if (next_z < 0 || next_z >= len_z) { continue; + } - if (p_cell_status[next_x][next_y][next_z] & 3) + if (p_cell_status[next_x][next_y][next_z] & 3) { continue; + } x = next_x; y = next_y; @@ -466,13 +428,13 @@ static inline void _mark_outside(uint8_t ***p_cell_status, int x, int y, int z, } static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, Vector<Face3> &p_faces) { - ERR_FAIL_INDEX(x, len_x); ERR_FAIL_INDEX(y, len_y); ERR_FAIL_INDEX(z, len_z); - if (p_cell_status[x][y][z] & _CELL_EXTERIOR) + if (p_cell_status[x][y][z] & _CELL_EXTERIOR) { return; + } #define vert(m_idx) Vector3(((m_idx)&4) >> 2, ((m_idx)&2) >> 1, (m_idx)&1) @@ -487,7 +449,6 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i }; for (int i = 0; i < 6; i++) { - Vector3 face_points[4]; int disp_x = x + ((i % 3) == 0 ? ((i < 3) ? 1 : -1) : 0); int disp_y = y + (((i - 1) % 3) == 0 ? ((i < 3) ? 1 : -1) : 0); @@ -495,21 +456,27 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i bool plot = false; - if (disp_x < 0 || disp_x >= len_x) + if (disp_x < 0 || disp_x >= len_x) { plot = true; - if (disp_y < 0 || disp_y >= len_y) + } + if (disp_y < 0 || disp_y >= len_y) { plot = true; - if (disp_z < 0 || disp_z >= len_z) + } + if (disp_z < 0 || disp_z >= len_z) { plot = true; + } - if (!plot && (p_cell_status[disp_x][disp_y][disp_z] & _CELL_EXTERIOR)) + if (!plot && (p_cell_status[disp_x][disp_y][disp_z] & _CELL_EXTERIOR)) { plot = true; + } - if (!plot) + if (!plot) { continue; + } - for (int j = 0; j < 4; j++) + for (int j = 0; j < 4; j++) { face_points[j] = vert(indices[i][j]) + Vector3(x, y, z); + } p_faces.push_back( Face3( @@ -525,8 +492,7 @@ static inline void _build_faces(uint8_t ***p_cell_status, int x, int y, int z, i } } -Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { - +Vector<Face3> Geometry3D::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { #define _MIN_SIZE 1.0 #define _MAX_LENGTH 20 @@ -536,12 +502,9 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { AABB global_aabb; for (int i = 0; i < face_count; i++) { - if (i == 0) { - global_aabb = faces[i].get_aabb(); } else { - global_aabb.merge_with(faces[i].get_aabb()); } } @@ -551,20 +514,23 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { // Determine amount of cells in grid axis. int div_x, div_y, div_z; - if (global_aabb.size.x / _MIN_SIZE < _MAX_LENGTH) + if (global_aabb.size.x / _MIN_SIZE < _MAX_LENGTH) { div_x = (int)(global_aabb.size.x / _MIN_SIZE) + 1; - else + } else { div_x = _MAX_LENGTH; + } - if (global_aabb.size.y / _MIN_SIZE < _MAX_LENGTH) + if (global_aabb.size.y / _MIN_SIZE < _MAX_LENGTH) { div_y = (int)(global_aabb.size.y / _MIN_SIZE) + 1; - else + } else { div_y = _MAX_LENGTH; + } - if (global_aabb.size.z / _MIN_SIZE < _MAX_LENGTH) + if (global_aabb.size.z / _MIN_SIZE < _MAX_LENGTH) { div_z = (int)(global_aabb.size.z / _MIN_SIZE) + 1; - else + } else { div_z = _MAX_LENGTH; + } Vector3 voxelsize = global_aabb.size; voxelsize.x /= div_x; @@ -575,15 +541,12 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { uint8_t ***cell_status = memnew_arr(uint8_t **, div_x); for (int i = 0; i < div_x; i++) { - cell_status[i] = memnew_arr(uint8_t *, div_y); for (int j = 0; j < div_y; j++) { - cell_status[i][j] = memnew_arr(uint8_t, div_z); for (int k = 0; k < div_z; k++) { - cell_status[i][j][k] = 0; } } @@ -592,10 +555,8 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { // Plot faces into cells. for (int i = 0; i < face_count; i++) { - Face3 f = faces[i]; for (int j = 0; j < 3; j++) { - f.vertex[j] -= global_aabb.position; } _plot_face(cell_status, 0, 0, 0, div_x, div_y, div_z, voxelsize, f); @@ -604,27 +565,21 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { // Determine which cells connect to the outside by traversing the outside and recursively flood-fill marking. for (int i = 0; i < div_x; i++) { - for (int j = 0; j < div_y; j++) { - _mark_outside(cell_status, i, j, 0, div_x, div_y, div_z); _mark_outside(cell_status, i, j, div_z - 1, div_x, div_y, div_z); } } for (int i = 0; i < div_z; i++) { - for (int j = 0; j < div_y; j++) { - _mark_outside(cell_status, 0, j, i, div_x, div_y, div_z); _mark_outside(cell_status, div_x - 1, j, i, div_x, div_y, div_z); } } for (int i = 0; i < div_x; i++) { - for (int j = 0; j < div_z; j++) { - _mark_outside(cell_status, i, 0, j, div_x, div_y, div_z); _mark_outside(cell_status, i, div_y - 1, j, div_x, div_y, div_z); } @@ -635,11 +590,8 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { Vector<Face3> wrapped_faces; for (int i = 0; i < div_x; i++) { - for (int j = 0; j < div_y; j++) { - for (int k = 0; k < div_z; k++) { - _build_faces(cell_status, i, j, k, div_x, div_y, div_z, wrapped_faces); } } @@ -651,9 +603,7 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { Face3 *wrapped_faces_ptr = wrapped_faces.ptrw(); for (int i = 0; i < wrapped_faces_count; i++) { - for (int j = 0; j < 3; j++) { - Vector3 &v = wrapped_faces_ptr[i].vertex[j]; v = v * voxelsize; v += global_aabb.position; @@ -663,9 +613,7 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { // clean up grid for (int i = 0; i < div_x; i++) { - for (int j = 0; j < div_y; j++) { - memdelete_arr(cell_status[i][j]); } @@ -673,61 +621,27 @@ Vector<Face3> Geometry::wrap_geometry(Vector<Face3> p_array, real_t *p_error) { } memdelete_arr(cell_status); - if (p_error) + if (p_error) { *p_error = voxelsize.length(); - - return wrapped_faces; -} - -Vector<Vector<Vector2>> Geometry::decompose_polygon_in_convex(Vector<Point2> polygon) { - Vector<Vector<Vector2>> decomp; - List<TriangulatorPoly> in_poly, out_poly; - - TriangulatorPoly inp; - inp.Init(polygon.size()); - for (int i = 0; i < polygon.size(); i++) { - inp.GetPoint(i) = polygon[i]; - } - inp.SetOrientation(TRIANGULATOR_CCW); - in_poly.push_back(inp); - TriangulatorPartition tpart; - if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { // Failed. - ERR_PRINT("Convex decomposing failed!"); - return decomp; - } - - decomp.resize(out_poly.size()); - int idx = 0; - for (List<TriangulatorPoly>::Element *I = out_poly.front(); I; I = I->next()) { - TriangulatorPoly &tp = I->get(); - - decomp.write[idx].resize(tp.GetNumPoints()); - - for (int64_t i = 0; i < tp.GetNumPoints(); i++) { - decomp.write[idx].write[i] = tp.GetPoint(i); - } - - idx++; } - return decomp; + return wrapped_faces; } -Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { - +Geometry3D::MeshData Geometry3D::build_convex_mesh(const Vector<Plane> &p_planes) { MeshData mesh; #define SUBPLANE_SIZE 1024.0 real_t subplane_size = 1024.0; // Should compute this from the actual plane. for (int i = 0; i < p_planes.size(); i++) { - Plane p = p_planes[i]; Vector3 ref = Vector3(0.0, 1.0, 0.0); - if (ABS(p.normal.dot(ref)) > 0.95) + if (ABS(p.normal.dot(ref)) > 0.95) { ref = Vector3(0.0, 0.0, 1.0); // Change axis. + } Vector3 right = p.normal.cross(ref).normalized(); Vector3 up = p.normal.cross(right).normalized(); @@ -742,21 +656,22 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { vertices.push_back(center + up * subplane_size + right * subplane_size); for (int j = 0; j < p_planes.size(); j++) { - - if (j == i) + if (j == i) { continue; + } Vector<Vector3> new_vertices; Plane clip = p_planes[j]; - if (clip.normal.dot(p.normal) > 0.95) + if (clip.normal.dot(p.normal) > 0.95) { continue; + } - if (vertices.size() < 3) + if (vertices.size() < 3) { break; + } for (int k = 0; k < vertices.size(); k++) { - int k_n = (k + 1) % vertices.size(); Vector3 edge0_A = vertices[k]; @@ -772,13 +687,13 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { // Check for different sides and non coplanar. if ((dist0 * dist1) < 0) { - // Calculate intersection. Vector3 rel = edge1_A - edge0_A; real_t den = clip.normal.dot(rel); - if (Math::is_zero_approx(den)) + if (Math::is_zero_approx(den)) { continue; // Point too short. + } real_t dist = -(clip.normal.dot(edge0_A) - clip.d) / den; Vector3 inters = edge0_A + rel * dist; @@ -789,8 +704,9 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { vertices = new_vertices; } - if (vertices.size() < 3) + if (vertices.size() < 3) { continue; + } // Result is a clockwise face. @@ -798,19 +714,15 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { // Add face indices. for (int j = 0; j < vertices.size(); j++) { - int idx = -1; for (int k = 0; k < mesh.vertices.size(); k++) { - if (mesh.vertices[k].distance_to(vertices[j]) < 0.001) { - idx = k; break; } } if (idx == -1) { - idx = mesh.vertices.size(); mesh.vertices.push_back(vertices[j]); } @@ -823,13 +735,11 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { // Add edge. for (int j = 0; j < face.indices.size(); j++) { - int a = face.indices[j]; int b = face.indices[(j + 1) % face.indices.size()]; bool found = false; for (int k = 0; k < mesh.edges.size(); k++) { - if (mesh.edges[k].a == a && mesh.edges[k].b == b) { found = true; break; @@ -840,8 +750,9 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { } } - if (found) + if (found) { continue; + } MeshData::Edge edge; edge.a = a; edge.b = b; @@ -852,8 +763,7 @@ Geometry::MeshData Geometry::build_convex_mesh(const Vector<Plane> &p_planes) { return mesh; } -Vector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) { - +Vector<Plane> Geometry3D::build_box_planes(const Vector3 &p_extents) { Vector<Plane> planes; planes.push_back(Plane(Vector3(1, 0, 0), p_extents.x)); @@ -866,12 +776,10 @@ Vector<Plane> Geometry::build_box_planes(const Vector3 &p_extents) { return planes; } -Vector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) { - +Vector<Plane> Geometry3D::build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis) { Vector<Plane> planes; for (int i = 0; i < p_sides; i++) { - Vector3 normal; normal[(p_axis + 1) % 3] = Math::cos(i * (2.0 * Math_PI) / p_sides); normal[(p_axis + 2) % 3] = Math::sin(i * (2.0 * Math_PI) / p_sides); @@ -888,8 +796,7 @@ Vector<Plane> Geometry::build_cylinder_planes(real_t p_radius, real_t p_height, return planes; } -Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) { - +Vector<Plane> Geometry3D::build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis) { Vector<Plane> planes; Vector3 axis; @@ -901,7 +808,6 @@ Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_l axis_neg[p_axis] = -1.0; for (int i = 0; i < p_lons; i++) { - Vector3 normal; normal[(p_axis + 1) % 3] = Math::cos(i * (2.0 * Math_PI) / p_lons); normal[(p_axis + 2) % 3] = Math::sin(i * (2.0 * Math_PI) / p_lons); @@ -909,9 +815,8 @@ Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_l planes.push_back(Plane(normal, p_radius)); for (int j = 1; j <= p_lats; j++) { - // FIXME: This is stupid. - Vector3 angle = normal.linear_interpolate(axis, j / (real_t)p_lats).normalized(); + Vector3 angle = normal.lerp(axis, j / (real_t)p_lats).normalized(); Vector3 pos = angle * p_radius; planes.push_back(Plane(pos, angle)); planes.push_back(Plane(pos * axis_neg, angle * axis_neg)); @@ -921,8 +826,7 @@ Vector<Plane> Geometry::build_sphere_planes(real_t p_radius, int p_lats, int p_l return planes; } -Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { - +Vector<Plane> Geometry3D::build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { Vector<Plane> planes; Vector3 axis; @@ -934,7 +838,6 @@ Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, i axis_neg[p_axis] = -1.0; for (int i = 0; i < p_sides; i++) { - Vector3 normal; normal[(p_axis + 1) % 3] = Math::cos(i * (2.0 * Math_PI) / p_sides); normal[(p_axis + 2) % 3] = Math::sin(i * (2.0 * Math_PI) / p_sides); @@ -942,8 +845,7 @@ Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, i planes.push_back(Plane(normal, p_radius)); for (int j = 1; j <= p_lats; j++) { - - Vector3 angle = normal.linear_interpolate(axis, j / (real_t)p_lats).normalized(); + Vector3 angle = normal.lerp(axis, j / (real_t)p_lats).normalized(); Vector3 pos = axis * p_height * 0.5 + angle * p_radius; planes.push_back(Plane(pos, angle)); planes.push_back(Plane(pos * axis_neg, angle * axis_neg)); @@ -953,228 +855,159 @@ Vector<Plane> Geometry::build_capsule_planes(real_t p_radius, real_t p_height, i return planes; } -struct _AtlasWorkRect { - - Size2i s; - Point2i p; - int idx; - _FORCE_INLINE_ bool operator<(const _AtlasWorkRect &p_r) const { return s.width > p_r.s.width; }; -}; - -struct _AtlasWorkRectResult { - - Vector<_AtlasWorkRect> result; - int max_w; - int max_h; -}; - -void Geometry::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) { - - // Super simple, almost brute force scanline stacking fitter. - // It's pretty basic for now, but it tries to make sure that the aspect ratio of the - // resulting atlas is somehow square. This is necessary because video cards have limits. - // On texture size (usually 2048 or 4096), so the more square a texture, the more chances. - // It will work in every hardware. - // For example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a - // 256x8192 atlas (won't work anywhere). - - ERR_FAIL_COND(p_rects.size() == 0); - - Vector<_AtlasWorkRect> wrects; - wrects.resize(p_rects.size()); - for (int i = 0; i < p_rects.size(); i++) { - wrects.write[i].s = p_rects[i]; - wrects.write[i].idx = i; - } - wrects.sort(); - int widest = wrects[0].s.width; - - Vector<_AtlasWorkRectResult> results; - - for (int i = 0; i <= 12; i++) { - - int w = 1 << i; - int max_h = 0; - int max_w = 0; - if (w < widest) - continue; - - Vector<int> hmax; - hmax.resize(w); - for (int j = 0; j < w; j++) - hmax.write[j] = 0; - - // Place them. - int ofs = 0; - int limit_h = 0; - for (int j = 0; j < wrects.size(); j++) { - - if (ofs + wrects[j].s.width > w) { - - ofs = 0; - } - - int from_y = 0; - for (int k = 0; k < wrects[j].s.width; k++) { +Vector<Vector3> Geometry3D::compute_convex_mesh_points(const Plane *p_planes, int p_plane_count) { + Vector<Vector3> points; + + // Iterate through every unique combination of any three planes. + for (int i = p_plane_count - 1; i >= 0; i--) { + for (int j = i - 1; j >= 0; j--) { + for (int k = j - 1; k >= 0; k--) { + // Find the point where these planes all cross over (if they + // do at all). + Vector3 convex_shape_point; + if (p_planes[i].intersect_3(p_planes[j], p_planes[k], &convex_shape_point)) { + // See if any *other* plane excludes this point because it's + // on the wrong side. + bool excluded = false; + for (int n = 0; n < p_plane_count; n++) { + if (n != i && n != j && n != k) { + real_t dp = p_planes[n].normal.dot(convex_shape_point); + if (dp - p_planes[n].d > CMP_EPSILON) { + excluded = true; + break; + } + } + } - if (hmax[ofs + k] > from_y) - from_y = hmax[ofs + k]; + // Only add the point if it passed all tests. + if (!excluded) { + points.push_back(convex_shape_point); + } + } } + } + } - wrects.write[j].p.x = ofs; - wrects.write[j].p.y = from_y; - int end_h = from_y + wrects[j].s.height; - int end_w = ofs + wrects[j].s.width; - if (ofs == 0) - limit_h = end_h; - - for (int k = 0; k < wrects[j].s.width; k++) { - - hmax.write[ofs + k] = end_h; - } + return points; +} - if (end_h > max_h) - max_h = end_h; +#define square(m_s) ((m_s) * (m_s)) +#define INF 1e20 - if (end_w > max_w) - max_w = end_w; +/* dt of 1d function using squared distance */ +static void edt(float *f, int stride, int n) { + float *d = (float *)alloca(sizeof(float) * n + sizeof(int) * n + sizeof(float) * (n + 1)); + int *v = (int *)&(d[n]); + float *z = (float *)&v[n]; - if (ofs == 0 || end_h > limit_h) // While h limit not reached, keep stacking. - ofs += wrects[j].s.width; + int k = 0; + v[0] = 0; + z[0] = -INF; + z[1] = +INF; + for (int q = 1; q <= n - 1; q++) { + float s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]); + while (s <= z[k]) { + k--; + s = ((f[q * stride] + square(q)) - (f[v[k] * stride] + square(v[k]))) / (2 * q - 2 * v[k]); } + k++; + v[k] = q; - _AtlasWorkRectResult result; - result.result = wrects; - result.max_h = max_h; - result.max_w = max_w; - results.push_back(result); + z[k] = s; + z[k + 1] = +INF; } - // Find the result with the best aspect ratio. - - int best = -1; - real_t best_aspect = 1e20; - - for (int i = 0; i < results.size(); i++) { - - real_t h = next_power_of_2(results[i].max_h); - real_t w = next_power_of_2(results[i].max_w); - real_t aspect = h > w ? h / w : w / h; - if (aspect < best_aspect) { - best = i; - best_aspect = aspect; + k = 0; + for (int q = 0; q <= n - 1; q++) { + while (z[k + 1] < q) { + k++; } + d[q] = square(q - v[k]) + f[v[k] * stride]; } - r_result.resize(p_rects.size()); - - for (int i = 0; i < p_rects.size(); i++) { - - r_result.write[results[best].result[i].idx] = results[best].result[i].p; + for (int i = 0; i < n; i++) { + f[i * stride] = d[i]; } - - r_size = Size2(results[best].max_w, results[best].max_h); } -Vector<Vector<Point2>> Geometry::_polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open) { - - using namespace ClipperLib; +#undef square - ClipType op = ctUnion; +Vector<uint32_t> Geometry3D::generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative) { + uint32_t float_count = p_size.x * p_size.y * p_size.z; - switch (p_op) { - case OPERATION_UNION: op = ctUnion; break; - case OPERATION_DIFFERENCE: op = ctDifference; break; - case OPERATION_INTERSECTION: op = ctIntersection; break; - case OPERATION_XOR: op = ctXor; break; - } - Path path_a, path_b; + ERR_FAIL_COND_V((uint32_t)p_voxels.size() != float_count, Vector<uint32_t>()); - // Need to scale points (Clipper's requirement for robust computation). - for (int i = 0; i != p_polypath_a.size(); ++i) { - path_a << IntPoint(p_polypath_a[i].x * SCALE_FACTOR, p_polypath_a[i].y * SCALE_FACTOR); - } - for (int i = 0; i != p_polypath_b.size(); ++i) { - path_b << IntPoint(p_polypath_b[i].x * SCALE_FACTOR, p_polypath_b[i].y * SCALE_FACTOR); + float *work_memory = memnew_arr(float, float_count); + for (uint32_t i = 0; i < float_count; i++) { + work_memory[i] = INF; } - Clipper clp; - clp.AddPath(path_a, ptSubject, !is_a_open); // Forward compatible with Clipper 10.0.0. - clp.AddPath(path_b, ptClip, true); // Polylines cannot be set as clip. - Paths paths; + uint32_t y_mult = p_size.x; + uint32_t z_mult = y_mult * p_size.y; - if (is_a_open) { - PolyTree tree; // Needed to populate polylines. - clp.Execute(op, tree); - OpenPathsFromPolyTree(tree, paths); - } else { - clp.Execute(op, paths); // Works on closed polygons only. + //plot solid cells + { + const bool *voxr = p_voxels.ptr(); + for (uint32_t i = 0; i < float_count; i++) { + bool plot = voxr[i]; + if (p_negative) { + plot = !plot; + } + if (plot) { + work_memory[i] = 0; + } + } } - // Have to scale points down now. - Vector<Vector<Point2>> polypaths; - for (Paths::size_type i = 0; i < paths.size(); ++i) { - Vector<Vector2> polypath; + //process in each direction - const Path &scaled_path = paths[i]; + //xy->z - for (Paths::size_type j = 0; j < scaled_path.size(); ++j) { - polypath.push_back(Point2( - static_cast<real_t>(scaled_path[j].X) / SCALE_FACTOR, - static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR)); + for (int i = 0; i < p_size.x; i++) { + for (int j = 0; j < p_size.y; j++) { + edt(&work_memory[i + j * y_mult], z_mult, p_size.z); } - polypaths.push_back(polypath); } - return polypaths; -} - -Vector<Vector<Point2>> Geometry::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { - - using namespace ClipperLib; - JoinType jt = jtSquare; + //xz->y - switch (p_join_type) { - case JOIN_SQUARE: jt = jtSquare; break; - case JOIN_ROUND: jt = jtRound; break; - case JOIN_MITER: jt = jtMiter; break; + for (int i = 0; i < p_size.x; i++) { + for (int j = 0; j < p_size.z; j++) { + edt(&work_memory[i + j * z_mult], y_mult, p_size.y); + } } - EndType et = etClosedPolygon; - - switch (p_end_type) { - case END_POLYGON: et = etClosedPolygon; break; - case END_JOINED: et = etClosedLine; break; - case END_BUTT: et = etOpenButt; break; - case END_SQUARE: et = etOpenSquare; break; - case END_ROUND: et = etOpenRound; break; + //yz->x + for (int i = 0; i < p_size.y; i++) { + for (int j = 0; j < p_size.z; j++) { + edt(&work_memory[i * y_mult + j * z_mult], 1, p_size.x); + } } - ClipperOffset co(2.0, 0.25 * SCALE_FACTOR); // Defaults from ClipperOffset. - Path path; - // Need to scale points (Clipper's requirement for robust computation). - for (int i = 0; i != p_polypath.size(); ++i) { - path << IntPoint(p_polypath[i].x * SCALE_FACTOR, p_polypath[i].y * SCALE_FACTOR); + Vector<uint32_t> ret; + ret.resize(float_count); + { + uint32_t *w = ret.ptrw(); + for (uint32_t i = 0; i < float_count; i++) { + w[i] = uint32_t(Math::sqrt(work_memory[i])); + } } - co.AddPath(path, jt, et); - - Paths paths; - co.Execute(paths, p_delta * SCALE_FACTOR); // Inflate/deflate. - - // Have to scale points down now. - Vector<Vector<Point2>> polypaths; - for (Paths::size_type i = 0; i < paths.size(); ++i) { - Vector<Vector2> polypath; + return ret; +} - const Path &scaled_path = paths[i]; +Vector<int8_t> Geometry3D::generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative) { + ERR_FAIL_COND_V(p_positive.size() != p_negative.size(), Vector<int8_t>()); + Vector<int8_t> sdf8; + int s = p_positive.size(); + sdf8.resize(s); - for (Paths::size_type j = 0; j < scaled_path.size(); ++j) { - polypath.push_back(Point2( - static_cast<real_t>(scaled_path[j].X) / SCALE_FACTOR, - static_cast<real_t>(scaled_path[j].Y) / SCALE_FACTOR)); - } - polypaths.push_back(polypath); + const uint32_t *rpos = p_positive.ptr(); + const uint32_t *rneg = p_negative.ptr(); + int8_t *wsdf = sdf8.ptrw(); + for (int i = 0; i < s; i++) { + int32_t diff = int32_t(rpos[i]) - int32_t(rneg[i]); + wsdf[i] = CLAMP(diff, -128, 127); } - return polypaths; + return sdf8; } diff --git a/core/math/geometry.h b/core/math/geometry_3d.h index e47d18b056..64cd34892e 100644 --- a/core/math/geometry.h +++ b/core/math/geometry_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* geometry.h */ +/* geometry_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,83 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GEOMETRY_H -#define GEOMETRY_H +#ifndef GEOMETRY_3D_H +#define GEOMETRY_3D_H -#include "core/math/delaunay.h" #include "core/math/face3.h" -#include "core/math/rect2.h" -#include "core/math/triangulate.h" -#include "core/math/vector3.h" #include "core/object.h" - -#include "core/print_string.h" #include "core/vector.h" -class Geometry { - Geometry(); +class Geometry3D { + Geometry3D(); public: - static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) { - - Vector2 d1 = q1 - p1; // Direction vector of segment S1. - Vector2 d2 = q2 - p2; // Direction vector of segment S2. - Vector2 r = p1 - p2; - real_t a = d1.dot(d1); // Squared length of segment S1, always nonnegative. - real_t e = d2.dot(d2); // Squared length of segment S2, always nonnegative. - real_t f = d2.dot(r); - real_t s, t; - // Check if either or both segments degenerate into points. - if (a <= CMP_EPSILON && e <= CMP_EPSILON) { - // Both segments degenerate into points. - c1 = p1; - c2 = p2; - return Math::sqrt((c1 - c2).dot(c1 - c2)); - } - if (a <= CMP_EPSILON) { - // First segment degenerates into a point. - s = 0.0; - t = f / e; // s = 0 => t = (b*s + f) / e = f / e - t = CLAMP(t, 0.0, 1.0); - } else { - real_t c = d1.dot(r); - if (e <= CMP_EPSILON) { - // Second segment degenerates into a point. - t = 0.0; - s = CLAMP(-c / a, 0.0, 1.0); // t = 0 => s = (b*t - c) / a = -c / a - } else { - // The general nondegenerate case starts here. - real_t b = d1.dot(d2); - real_t denom = a * e - b * b; // Always nonnegative. - // If segments not parallel, compute closest point on L1 to L2 and - // clamp to segment S1. Else pick arbitrary s (here 0). - if (denom != 0.0) { - s = CLAMP((b * f - c * e) / denom, 0.0, 1.0); - } else - s = 0.0; - // Compute point on L2 closest to S1(s) using - // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e - t = (b * s + f) / e; - - //If t in [0,1] done. Else clamp t, recompute s for the new value - // of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a - // and clamp s to [0, 1]. - if (t < 0.0) { - t = 0.0; - s = CLAMP(-c / a, 0.0, 1.0); - } else if (t > 1.0) { - t = 1.0; - s = CLAMP((b - c) / a, 0.0, 1.0); - } - } - } - c1 = p1 + d1 * s; - c2 = p2 + d2 * t; - return Math::sqrt((c1 - c2).dot(c1 - c2)); - } - static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) { - // Do the function 'd' as defined by pb. I think is is dot product of some sort. #define d_of(m, n, o, p) ((m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z)) @@ -113,12 +48,20 @@ public: real_t mub = (d_of(p1, q1, q2, q1) + mua * d_of(q2, q1, p2, p1)) / d_of(q2, q1, q2, q1); // Clip the value between [0..1] constraining the solution to lie on the original curves. - if (mua < 0) mua = 0; - if (mub < 0) mub = 0; - if (mua > 1) mua = 1; - if (mub > 1) mub = 1; - c1 = p1.linear_interpolate(p2, mua); - c2 = q1.linear_interpolate(q2, mub); + if (mua < 0) { + mua = 0; + } + if (mub < 0) { + mub = 0; + } + if (mua > 1) { + mua = 1; + } + if (mub > 1) { + mub = 1; + } + c1 = p1.lerp(p2, mua); + c2 = q1.lerp(q2, mub); } static real_t get_closest_distance_between_segments(const Vector3 &p_from_a, const Vector3 &p_to_a, const Vector3 &p_from_b, const Vector3 &p_to_b) { @@ -157,22 +100,22 @@ public: if (tN < 0.0) { // tc < 0 => the t=0 edge is visible. tN = 0.0; // Recompute sc for this edge. - if (-d < 0.0) + if (-d < 0.0) { sN = 0.0; - else if (-d > a) + } else if (-d > a) { sN = sD; - else { + } else { sN = -d; sD = a; } } else if (tN > tD) { // tc > 1 => the t=1 edge is visible. tN = tD; // Recompute sc for this edge. - if ((-d + b) < 0.0) + if ((-d + b) < 0.0) { sN = 0; - else if ((-d + b) > a) + } else if ((-d + b) > a) { sN = sD; - else { + } else { sN = (-d + b); sD = a; } @@ -187,120 +130,134 @@ public: return dP.length(); // Return the closest distance. } - static inline bool ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2, Vector3 *r_res = 0) { + static inline bool ray_intersects_triangle(const Vector3 &p_from, const Vector3 &p_dir, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2, Vector3 *r_res = nullptr) { Vector3 e1 = p_v1 - p_v0; Vector3 e2 = p_v2 - p_v0; Vector3 h = p_dir.cross(e2); real_t a = e1.dot(h); - if (Math::is_zero_approx(a)) // Parallel test. + if (Math::is_zero_approx(a)) { // Parallel test. return false; + } real_t f = 1.0 / a; Vector3 s = p_from - p_v0; real_t u = f * s.dot(h); - if (u < 0.0 || u > 1.0) + if (u < 0.0 || u > 1.0) { return false; + } Vector3 q = s.cross(e1); real_t v = f * p_dir.dot(q); - if (v < 0.0 || u + v > 1.0) + if (v < 0.0 || u + v > 1.0) { return false; + } // At this stage we can compute t to find out where // the intersection point is on the line. real_t t = f * e2.dot(q); if (t > 0.00001) { // ray intersection - if (r_res) + if (r_res) { *r_res = p_from + p_dir * t; + } return true; - } else // This means that there is a line intersection but not a ray intersection. + } else { // This means that there is a line intersection but not a ray intersection. return false; + } } - static inline bool segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2, Vector3 *r_res = 0) { - + static inline bool segment_intersects_triangle(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_v0, const Vector3 &p_v1, const Vector3 &p_v2, Vector3 *r_res = nullptr) { Vector3 rel = p_to - p_from; Vector3 e1 = p_v1 - p_v0; Vector3 e2 = p_v2 - p_v0; Vector3 h = rel.cross(e2); real_t a = e1.dot(h); - if (Math::is_zero_approx(a)) // Parallel test. + if (Math::is_zero_approx(a)) { // Parallel test. return false; + } real_t f = 1.0 / a; Vector3 s = p_from - p_v0; real_t u = f * s.dot(h); - if (u < 0.0 || u > 1.0) + if (u < 0.0 || u > 1.0) { return false; + } Vector3 q = s.cross(e1); real_t v = f * rel.dot(q); - if (v < 0.0 || u + v > 1.0) + if (v < 0.0 || u + v > 1.0) { return false; + } // At this stage we can compute t to find out where // the intersection point is on the line. real_t t = f * e2.dot(q); if (t > CMP_EPSILON && t <= 1.0) { // Ray intersection. - if (r_res) + if (r_res) { *r_res = p_from + rel * t; + } return true; - } else // This means that there is a line intersection but not a ray intersection. + } else { // This means that there is a line intersection but not a ray intersection. return false; + } } - static inline bool segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius, Vector3 *r_res = 0, Vector3 *r_norm = 0) { - + static inline bool segment_intersects_sphere(const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_sphere_pos, real_t p_sphere_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr) { Vector3 sphere_pos = p_sphere_pos - p_from; Vector3 rel = (p_to - p_from); real_t rel_l = rel.length(); - if (rel_l < CMP_EPSILON) + if (rel_l < CMP_EPSILON) { return false; // Both points are the same. + } Vector3 normal = rel / rel_l; real_t sphere_d = normal.dot(sphere_pos); real_t ray_distance = sphere_pos.distance_to(normal * sphere_d); - if (ray_distance >= p_sphere_radius) + if (ray_distance >= p_sphere_radius) { return false; + } real_t inters_d2 = p_sphere_radius * p_sphere_radius - ray_distance * ray_distance; real_t inters_d = sphere_d; - if (inters_d2 >= CMP_EPSILON) + if (inters_d2 >= CMP_EPSILON) { inters_d -= Math::sqrt(inters_d2); + } // Check in segment. - if (inters_d < 0 || inters_d > rel_l) + if (inters_d < 0 || inters_d > rel_l) { return false; + } Vector3 result = p_from + normal * inters_d; - if (r_res) + if (r_res) { *r_res = result; - if (r_norm) + } + if (r_norm) { *r_norm = (result - p_sphere_pos).normalized(); + } return true; } - static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = 0, Vector3 *r_norm = 0) { - + static inline bool segment_intersects_cylinder(const Vector3 &p_from, const Vector3 &p_to, real_t p_height, real_t p_radius, Vector3 *r_res = nullptr, Vector3 *r_norm = nullptr) { Vector3 rel = (p_to - p_from); real_t rel_l = rel.length(); - if (rel_l < CMP_EPSILON) + if (rel_l < CMP_EPSILON) { return false; // Both points are the same. + } // First check if they are parallel. Vector3 normal = (rel / rel_l); @@ -317,13 +274,15 @@ public: real_t dist = z_dir.dot(p_from); - if (dist >= p_radius) + if (dist >= p_radius) { return false; // Too far away. + } // Convert to 2D. real_t w2 = p_radius * p_radius - dist * dist; - if (w2 < CMP_EPSILON) + if (w2 < CMP_EPSILON) { return false; // Avoid numerical error. + } Size2 size(Math::sqrt(w2), p_height * 0.5); Vector3 x_dir = z_dir.cross(Vector3(0, 0, 1)).normalized(); @@ -336,7 +295,6 @@ public: int axis = -1; for (int i = 0; i < 2; i++) { - real_t seg_from = from2D[i]; real_t seg_to = to2D[i]; real_t box_begin = -size[i]; @@ -344,17 +302,17 @@ public: real_t cmin, cmax; if (seg_from < seg_to) { - - if (seg_from > box_end || seg_to < box_begin) + if (seg_from > box_end || seg_to < box_begin) { return false; + } real_t length = seg_to - seg_from; cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0; cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1; } else { - - if (seg_to > box_end || seg_from < box_begin) + if (seg_to > box_end || seg_from < box_begin) { return false; + } real_t length = seg_to - seg_from; cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0; cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1; @@ -364,10 +322,12 @@ public: min = cmin; axis = i; } - if (cmax < max) + if (cmax < max) { max = cmax; - if (max < min) + } + if (max < min) { return false; + } } // Convert to 3D again. @@ -383,45 +343,47 @@ public: res_normal.normalize(); - if (r_res) + if (r_res) { *r_res = result; - if (r_norm) + } + if (r_norm) { *r_norm = res_normal; + } return true; } static bool segment_intersects_convex(const Vector3 &p_from, const Vector3 &p_to, const Plane *p_planes, int p_plane_count, Vector3 *p_res, Vector3 *p_norm) { - real_t min = -1e20, max = 1e20; Vector3 rel = p_to - p_from; real_t rel_l = rel.length(); - if (rel_l < CMP_EPSILON) + if (rel_l < CMP_EPSILON) { return false; + } Vector3 dir = rel / rel_l; int min_index = -1; for (int i = 0; i < p_plane_count; i++) { - const Plane &p = p_planes[i]; real_t den = p.normal.dot(dir); - if (Math::abs(den) <= CMP_EPSILON) + if (Math::abs(den) <= CMP_EPSILON) { continue; // Ignore parallel plane. + } real_t dist = -p.distance_to(p_from) / den; if (den > 0) { // Backwards facing plane. - if (dist < max) + if (dist < max) { max = dist; + } } else { - // Front facing plane. if (dist > min) { min = dist; @@ -430,169 +392,89 @@ public: } } - if (max <= min || min < 0 || min > rel_l || min_index == -1) // Exit conditions. + if (max <= min || min < 0 || min > rel_l || min_index == -1) { // Exit conditions. return false; // No intersection. + } - if (p_res) + if (p_res) { *p_res = p_from + dir * min; - if (p_norm) + } + if (p_norm) { *p_norm = p_planes[min_index].normal; + } return true; } static Vector3 get_closest_point_to_segment(const Vector3 &p_point, const Vector3 *p_segment) { - Vector3 p = p_point - p_segment[0]; Vector3 n = p_segment[1] - p_segment[0]; real_t l2 = n.length_squared(); - if (l2 < 1e-20) + if (l2 < 1e-20) { return p_segment[0]; // Both points are the same, just give any. + } real_t d = n.dot(p) / l2; - if (d <= 0.0) + if (d <= 0.0) { return p_segment[0]; // Before first point. - else if (d >= 1.0) + } else if (d >= 1.0) { return p_segment[1]; // After first point. - else + } else { return p_segment[0] + n * d; // Inside. + } } static Vector3 get_closest_point_to_segment_uncapped(const Vector3 &p_point, const Vector3 *p_segment) { - Vector3 p = p_point - p_segment[0]; Vector3 n = p_segment[1] - p_segment[0]; real_t l2 = n.length_squared(); - if (l2 < 1e-20) - return p_segment[0]; // Both points are the same, just give any. - - real_t d = n.dot(p) / l2; - - return p_segment[0] + n * d; // Inside. - } - - static Vector2 get_closest_point_to_segment_2d(const Vector2 &p_point, const Vector2 *p_segment) { - - Vector2 p = p_point - p_segment[0]; - Vector2 n = p_segment[1] - p_segment[0]; - real_t l2 = n.length_squared(); - if (l2 < 1e-20) - return p_segment[0]; // Both points are the same, just give any. - - real_t d = n.dot(p) / l2; - - if (d <= 0.0) - return p_segment[0]; // Before first point. - else if (d >= 1.0) - return p_segment[1]; // After first point. - else - return p_segment[0] + n * d; // Inside. - } - - static bool is_point_in_triangle(const Vector2 &s, const Vector2 &a, const Vector2 &b, const Vector2 &c) { - Vector2 an = a - s; - Vector2 bn = b - s; - Vector2 cn = c - s; - - bool orientation = an.cross(bn) > 0; - - if ((bn.cross(cn) > 0) != orientation) return false; - - return (cn.cross(an) > 0) == orientation; - } - - static Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2 &p_point, const Vector2 *p_segment) { - - Vector2 p = p_point - p_segment[0]; - Vector2 n = p_segment[1] - p_segment[0]; - real_t l2 = n.length_squared(); - if (l2 < 1e-20) + if (l2 < 1e-20) { return p_segment[0]; // Both points are the same, just give any. + } real_t d = n.dot(p) / l2; return p_segment[0] + n * d; // Inside. } - static bool line_intersects_line_2d(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b, Vector2 &r_result) { - - // See http://paulbourke.net/geometry/pointlineplane/ - - const real_t denom = p_dir_b.y * p_dir_a.x - p_dir_b.x * p_dir_a.y; - if (Math::is_zero_approx(denom)) { // Parallel? - return false; - } - - const Vector2 v = p_from_a - p_from_b; - const real_t t = (p_dir_b.x * v.y - p_dir_b.y * v.x) / denom; - r_result = p_from_a + t * p_dir_a; - return true; - } - - static bool segment_intersects_segment_2d(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b, Vector2 *r_result) { - - Vector2 B = p_to_a - p_from_a; - Vector2 C = p_from_b - p_from_a; - Vector2 D = p_to_b - p_from_a; - - real_t ABlen = B.dot(B); - if (ABlen <= 0) - return false; - Vector2 Bn = B / ABlen; - C = Vector2(C.x * Bn.x + C.y * Bn.y, C.y * Bn.x - C.x * Bn.y); - D = Vector2(D.x * Bn.x + D.y * Bn.y, D.y * Bn.x - D.x * Bn.y); - - if ((C.y < 0 && D.y < 0) || (C.y >= 0 && D.y >= 0)) - return false; - - real_t ABpos = D.x + (C.x - D.x) * D.y / (D.y - C.y); - - // Fail if segment C-D crosses line A-B outside of segment A-B. - if (ABpos < 0 || ABpos > 1.0) - return false; - - // (4) Apply the discovered position to line A-B in the original coordinate system. - if (r_result) - *r_result = p_from_a + B * ABpos; - - return true; - } - static inline bool point_in_projected_triangle(const Vector3 &p_point, const Vector3 &p_v1, const Vector3 &p_v2, const Vector3 &p_v3) { - Vector3 face_n = (p_v1 - p_v3).cross(p_v1 - p_v2); Vector3 n1 = (p_point - p_v3).cross(p_point - p_v2); - if (face_n.dot(n1) < 0) + if (face_n.dot(n1) < 0) { return false; + } Vector3 n2 = (p_v1 - p_v3).cross(p_v1 - p_point); - if (face_n.dot(n2) < 0) + if (face_n.dot(n2) < 0) { return false; + } Vector3 n3 = (p_v1 - p_point).cross(p_v1 - p_v2); - if (face_n.dot(n3) < 0) + if (face_n.dot(n3) < 0) { return false; + } return true; } static inline bool triangle_sphere_intersection_test(const Vector3 *p_triangle, const Vector3 &p_normal, const Vector3 &p_sphere_pos, real_t p_sphere_radius, Vector3 &r_triangle_contact, Vector3 &r_sphere_contact) { - real_t d = p_normal.dot(p_sphere_pos) - p_normal.dot(p_triangle[0]); - if (d > p_sphere_radius || d < -p_sphere_radius) // Not touching the plane of the face, return. + if (d > p_sphere_radius || d < -p_sphere_radius) { + // Not touching the plane of the face, return. return false; + } Vector3 contact = p_sphere_pos - (p_normal * d); /** 2nd) TEST INSIDE TRIANGLE **/ - if (Geometry::point_in_projected_triangle(contact, p_triangle[0], p_triangle[1], p_triangle[2])) { + if (Geometry3D::point_in_projected_triangle(contact, p_triangle[0], p_triangle[1], p_triangle[2])) { r_triangle_contact = contact; r_sphere_contact = p_sphere_pos - p_normal * p_sphere_radius; //printf("solved inside triangle\n"); @@ -604,7 +486,6 @@ public: const Vector3 verts[4] = { p_triangle[0], p_triangle[1], p_triangle[2], p_triangle[0] }; // for() friendly for (int i = 0; i < 3; i++) { - // Check edge cylinder. Vector3 n1 = verts[i] - verts[i + 1]; @@ -629,7 +510,6 @@ public: real_t sphere_at = n1.dot(n2); if (sphere_at >= 0 && sphere_at < n1.dot(n1)) { - r_triangle_contact = p_sphere_pos - axis * (axis.dot(n2)); r_sphere_contact = p_sphere_pos - axis * p_sphere_radius; // Point inside here. @@ -639,7 +519,6 @@ public: real_t r2 = p_sphere_radius * p_sphere_radius; if (n2.length_squared() < r2) { - Vector3 n = (p_sphere_pos - verts[i + 1]).normalized(); r_triangle_contact = verts[i + 1]; @@ -661,51 +540,16 @@ public: return false; } - static inline bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius) { - - return p_point.distance_squared_to(p_circle_pos) <= p_circle_radius * p_circle_radius; - } - - static real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius) { - - Vector2 line_vec = p_to - p_from; - Vector2 vec_to_line = p_from - p_circle_pos; - - // Create a quadratic formula of the form ax^2 + bx + c = 0 - real_t a, b, c; - - a = line_vec.dot(line_vec); - b = 2 * vec_to_line.dot(line_vec); - c = vec_to_line.dot(vec_to_line) - p_circle_radius * p_circle_radius; - - // Solve for t. - real_t sqrtterm = b * b - 4 * a * c; - - // If the term we intend to square root is less than 0 then the answer won't be real, - // so it definitely won't be t in the range 0 to 1. - if (sqrtterm < 0) return -1; - - // If we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection) - // then the following can be skipped and we can just return the equivalent of res1. - sqrtterm = Math::sqrt(sqrtterm); - real_t res1 = (-b - sqrtterm) / (2 * a); - real_t res2 = (-b + sqrtterm) / (2 * a); - - if (res1 >= 0 && res1 <= 1) return res1; - if (res2 >= 0 && res2 <= 1) return res2; - return -1; - } - static inline Vector<Vector3> clip_polygon(const Vector<Vector3> &polygon, const Plane &p_plane) { - enum LocationCache { LOC_INSIDE = 1, LOC_BOUNDARY = 0, LOC_OUTSIDE = -1 }; - if (polygon.size() == 0) + if (polygon.size() == 0) { return polygon; + } int *location_cache = (int *)alloca(sizeof(int) * polygon.size()); int inside_count = 0; @@ -727,11 +571,8 @@ public: } if (outside_count == 0) { - return polygon; // No changes. - } else if (inside_count == 0) { - return Vector<Vector3>(); // Empty. } @@ -771,141 +612,12 @@ public: return clipped; } - enum PolyBooleanOperation { - OPERATION_UNION, - OPERATION_DIFFERENCE, - OPERATION_INTERSECTION, - OPERATION_XOR - }; - enum PolyJoinType { - JOIN_SQUARE, - JOIN_ROUND, - JOIN_MITER - }; - enum PolyEndType { - END_POLYGON, - END_JOINED, - END_BUTT, - END_SQUARE, - END_ROUND - }; - - static Vector<Vector<Point2>> merge_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { - - return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b); - } - - static Vector<Vector<Point2>> clip_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { - - return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polygon_a, p_polygon_b); - } - - static Vector<Vector<Point2>> intersect_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { - - return _polypaths_do_operation(OPERATION_INTERSECTION, p_polygon_a, p_polygon_b); - } - - static Vector<Vector<Point2>> exclude_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { - - return _polypaths_do_operation(OPERATION_XOR, p_polygon_a, p_polygon_b); - } - - static Vector<Vector<Point2>> clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { - - return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polyline, p_polygon, true); - } - - static Vector<Vector<Point2>> intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { - - return _polypaths_do_operation(OPERATION_INTERSECTION, p_polyline, p_polygon, true); - } - - static Vector<Vector<Point2>> offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { - - return _polypath_offset(p_polygon, p_delta, p_join_type, END_POLYGON); - } - - static Vector<Vector<Point2>> offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { - - ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2>>(), "Attempt to offset a polyline like a polygon (use offset_polygon_2d instead)."); - - return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type); - } - - static Vector<int> triangulate_delaunay_2d(const Vector<Vector2> &p_points) { - - Vector<Delaunay2D::Triangle> tr = Delaunay2D::triangulate(p_points); - Vector<int> triangles; - - for (int i = 0; i < tr.size(); i++) { - triangles.push_back(tr[i].points[0]); - triangles.push_back(tr[i].points[1]); - triangles.push_back(tr[i].points[2]); - } - return triangles; - } - - static Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon) { - - Vector<int> triangles; - if (!Triangulate::triangulate(p_polygon, triangles)) - return Vector<int>(); //fail - return triangles; - } - - static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) { - int c = p_polygon.size(); - if (c < 3) - return false; - const Vector2 *p = p_polygon.ptr(); - real_t sum = 0; - for (int i = 0; i < c; i++) { - const Vector2 &v1 = p[i]; - const Vector2 &v2 = p[(i + 1) % c]; - sum += (v2.x - v1.x) * (v2.y + v1.y); - } - - return sum > 0.0f; - } - - // Alternate implementation that should be faster. - static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { - int c = p_polygon.size(); - if (c < 3) - return false; - const Vector2 *p = p_polygon.ptr(); - Vector2 further_away(-1e20, -1e20); - Vector2 further_away_opposite(1e20, 1e20); - - for (int i = 0; i < c; i++) { - further_away.x = MAX(p[i].x, further_away.x); - further_away.y = MAX(p[i].y, further_away.y); - further_away_opposite.x = MIN(p[i].x, further_away_opposite.x); - further_away_opposite.y = MIN(p[i].y, further_away_opposite.y); - } - - // Make point outside that won't intersect with points in segment from p_point. - further_away += (further_away - further_away_opposite) * Vector2(1.221313, 1.512312); - - int intersections = 0; - for (int i = 0; i < c; i++) { - const Vector2 &v1 = p[i]; - const Vector2 &v2 = p[(i + 1) % c]; - if (segment_intersects_segment_2d(v1, v2, p_point, further_away, nullptr)) { - intersections++; - } - } - - return (intersections & 1); - } - static Vector<Vector<Face3>> separate_objects(Vector<Face3> p_array); // Create a "wrap" that encloses the given geometry. static Vector<Face3> wrap_geometry(Vector<Face3> p_array, real_t *p_error = nullptr); struct MeshData { - struct Face { Plane plane; Vector<int> indices; @@ -914,7 +626,6 @@ public: Vector<Face> faces; struct Edge { - int a, b; }; @@ -926,7 +637,6 @@ public: }; _FORCE_INLINE_ static int get_uv84_normal_bit(const Vector3 &p_vector) { - int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0, 1, 0))) * 4.0 / Math_PI + 0.5)); if (lat == 0) { @@ -941,82 +651,300 @@ public: } _FORCE_INLINE_ static int get_uv84_normal_bit_neighbors(int p_idx) { - if (p_idx == 24) { return 1 | 2 | 4 | 8; } else if (p_idx == 25) { return (1 << 23) | (1 << 22) | (1 << 21) | (1 << 20); } else { - int ret = 0; - if ((p_idx % 8) == 0) + if ((p_idx % 8) == 0) { ret |= (1 << (p_idx + 7)); - else + } else { ret |= (1 << (p_idx - 1)); - if ((p_idx % 8) == 7) + } + if ((p_idx % 8) == 7) { ret |= (1 << (p_idx - 7)); - else + } else { ret |= (1 << (p_idx + 1)); + } int mask = ret | (1 << p_idx); - if (p_idx < 8) + if (p_idx < 8) { ret |= 24; - else + } else { ret |= mask >> 8; + } - if (p_idx >= 16) + if (p_idx >= 16) { ret |= 25; - else + } else { ret |= mask << 8; + } return ret; } } + static MeshData build_convex_mesh(const Vector<Plane> &p_planes); + static Vector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); + static Vector<Plane> build_box_planes(const Vector3 &p_extents); + static Vector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); + static Vector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); - static real_t vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B) { - return (real_t)(A.x - O.x) * (B.y - O.y) - (real_t)(A.y - O.y) * (B.x - O.x); - } + static Vector<Vector3> compute_convex_mesh_points(const Plane *p_planes, int p_plane_count); + +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if (x1 < min) { \ + min = x1; \ + } \ + if (x1 > max) { \ + max = x1; \ + } \ + if (x2 < min) { \ + min = x2; \ + } \ + if (x2 > max) { \ + max = x2; \ + } + + _FORCE_INLINE_ static bool planeBoxOverlap(Vector3 normal, float d, Vector3 maxbox) { + int q; + Vector3 vmin, vmax; + for (q = 0; q <= 2; q++) { + if (normal[q] > 0.0f) { + vmin[q] = -maxbox[q]; + vmax[q] = maxbox[q]; + } else { + vmin[q] = maxbox[q]; + vmax[q] = -maxbox[q]; + } + } + if (normal.dot(vmin) + d > 0.0f) { + return false; + } + if (normal.dot(vmax) + d >= 0.0f) { + return true; + } - // Returns a list of points on the convex hull in counter-clockwise order. - // Note: the last point in the returned list is the same as the first one. - static Vector<Point2> convex_hull_2d(Vector<Point2> P) { - int n = P.size(), k = 0; - Vector<Point2> H; - H.resize(2 * n); + return false; + } - // Sort points lexicographically. - P.sort(); +/*======================== X-tests ========================*/ +#define AXISTEST_X01(a, b, fa, fb) \ + p0 = a * v0.y - b * v0.z; \ + p2 = a * v2.y - b * v2.z; \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) { \ + return false; \ + } + +#define AXISTEST_X2(a, b, fa, fb) \ + p0 = a * v0.y - b * v0.z; \ + p1 = a * v1.y - b * v1.z; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) { \ + return false; \ + } + +/*======================== Y-tests ========================*/ +#define AXISTEST_Y02(a, b, fa, fb) \ + p0 = -a * v0.x + b * v0.z; \ + p2 = -a * v2.x + b * v2.z; \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) { \ + return false; \ + } + +#define AXISTEST_Y1(a, b, fa, fb) \ + p0 = -a * v0.x + b * v0.z; \ + p1 = -a * v1.x + b * v1.z; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.z; \ + if (min > rad || max < -rad) { \ + return false; \ + } + + /*======================== Z-tests ========================*/ + +#define AXISTEST_Z12(a, b, fa, fb) \ + p1 = a * v1.x - b * v1.y; \ + p2 = a * v2.x - b * v2.y; \ + if (p2 < p1) { \ + min = p2; \ + max = p1; \ + } else { \ + min = p1; \ + max = p2; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ + if (min > rad || max < -rad) { \ + return false; \ + } + +#define AXISTEST_Z0(a, b, fa, fb) \ + p0 = a * v0.x - b * v0.y; \ + p1 = a * v1.x - b * v1.y; \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x + fb * boxhalfsize.y; \ + if (min > rad || max < -rad) { \ + return false; \ + } + + _FORCE_INLINE_ static bool triangle_box_overlap(const Vector3 &boxcenter, const Vector3 boxhalfsize, const Vector3 *triverts) { + /* use separating axis theorem to test overlap between triangle and box */ + /* need to test for overlap in these directions: */ + /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ + /* we do not even need to test these) */ + /* 2) normal of the triangle */ + /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ + /* this gives 3x3=9 more tests */ + Vector3 v0, v1, v2; + float min, max, d, p0, p1, p2, rad, fex, fey, fez; + Vector3 normal, e0, e1, e2; + + /* This is the fastest branch on Sun */ + /* move everything so that the boxcenter is in (0,0,0) */ + + v0 = triverts[0] - boxcenter; + v1 = triverts[1] - boxcenter; + v2 = triverts[2] - boxcenter; + + /* compute triangle edges */ + e0 = v1 - v0; /* tri edge 0 */ + e1 = v2 - v1; /* tri edge 1 */ + e2 = v0 - v2; /* tri edge 2 */ + + /* Bullet 3: */ + /* test the 9 tests first (this was faster) */ + fex = Math::abs(e0.x); + fey = Math::abs(e0.y); + fez = Math::abs(e0.z); + AXISTEST_X01(e0.z, e0.y, fez, fey); + AXISTEST_Y02(e0.z, e0.x, fez, fex); + AXISTEST_Z12(e0.y, e0.x, fey, fex); + + fex = Math::abs(e1.x); + fey = Math::abs(e1.y); + fez = Math::abs(e1.z); + AXISTEST_X01(e1.z, e1.y, fez, fey); + AXISTEST_Y02(e1.z, e1.x, fez, fex); + AXISTEST_Z0(e1.y, e1.x, fey, fex); + + fex = Math::abs(e2.x); + fey = Math::abs(e2.y); + fez = Math::abs(e2.z); + AXISTEST_X2(e2.z, e2.y, fez, fey); + AXISTEST_Y1(e2.z, e2.x, fez, fex); + AXISTEST_Z12(e2.y, e2.x, fey, fex); + + /* Bullet 1: */ + /* first test overlap in the {x,y,z}-directions */ + /* find min, max of the triangle each direction, and test for overlap in */ + /* that direction -- this is equivalent to testing a minimal AABB around */ + /* the triangle against the AABB */ + + /* test in X-direction */ + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if (min > boxhalfsize.x || max < -boxhalfsize.x) { + return false; + } - // Build lower hull. - for (int i = 0; i < n; ++i) { - while (k >= 2 && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) - k--; - H.write[k++] = P[i]; + /* test in Y-direction */ + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if (min > boxhalfsize.y || max < -boxhalfsize.y) { + return false; } - // Build upper hull. - for (int i = n - 2, t = k + 1; i >= 0; i--) { - while (k >= t && vec2_cross(H[k - 2], H[k - 1], P[i]) <= 0) - k--; - H.write[k++] = P[i]; + /* test in Z-direction */ + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if (min > boxhalfsize.z || max < -boxhalfsize.z) { + return false; } - H.resize(k); - return H; + /* Bullet 2: */ + /* test if the box intersects the plane of the triangle */ + /* compute plane equation of triangle: normal*x+d=0 */ + normal = e0.cross(e1); + d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ + return planeBoxOverlap(normal, d, boxhalfsize); /* if true, box and triangle overlaps */ + } + + static Vector<uint32_t> generate_edf(const Vector<bool> &p_voxels, const Vector3i &p_size, bool p_negative); + static Vector<int8_t> generate_sdf8(const Vector<uint32_t> &p_positive, const Vector<uint32_t> &p_negative); + + static Vector3 triangle_get_barycentric_coords(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, const Vector3 &p_pos) { + Vector3 v0 = p_b - p_a; + Vector3 v1 = p_c - p_a; + Vector3 v2 = p_pos - p_a; + + float d00 = v0.dot(v0); + float d01 = v0.dot(v1); + float d11 = v1.dot(v1); + float d20 = v2.dot(v0); + float d21 = v2.dot(v1); + float denom = (d00 * d11 - d01 * d01); + if (denom == 0) { + return Vector3(); //invalid triangle, return empty + } + float v = (d11 * d20 - d01 * d21) / denom; + float w = (d00 * d21 - d01 * d20) / denom; + float u = 1.0f - v - w; + return Vector3(u, v, w); + } + + static Color tetrahedron_get_barycentric_coords(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_c, const Vector3 &p_d, const Vector3 &p_pos) { + Vector3 vap = p_pos - p_a; + Vector3 vbp = p_pos - p_b; + + Vector3 vab = p_b - p_a; + Vector3 vac = p_c - p_a; + Vector3 vad = p_d - p_a; + + Vector3 vbc = p_c - p_b; + Vector3 vbd = p_d - p_b; + // ScTP computes the scalar triple product +#define STP(m_a, m_b, m_c) ((m_a).dot((m_b).cross((m_c)))) + float va6 = STP(vbp, vbd, vbc); + float vb6 = STP(vap, vac, vad); + float vc6 = STP(vap, vad, vab); + float vd6 = STP(vap, vab, vac); + float v6 = 1 / STP(vab, vac, vad); + return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6); +#undef STP } - static Vector<Vector<Vector2>> decompose_polygon_in_convex(Vector<Point2> polygon); - - static MeshData build_convex_mesh(const Vector<Plane> &p_planes); - static Vector<Plane> build_sphere_planes(real_t p_radius, int p_lats, int p_lons, Vector3::Axis p_axis = Vector3::AXIS_Z); - static Vector<Plane> build_box_planes(const Vector3 &p_extents); - static Vector<Plane> build_cylinder_planes(real_t p_radius, real_t p_height, int p_sides, Vector3::Axis p_axis = Vector3::AXIS_Z); - static Vector<Plane> build_capsule_planes(real_t p_radius, real_t p_height, int p_sides, int p_lats, Vector3::Axis p_axis = Vector3::AXIS_Z); - - static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size); - -private: - static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open = false); - static Vector<Vector<Point2>> _polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type); }; -#endif // GEOMETRY_H +#endif // GEOMETRY_3D_H diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp index a47d4ef7ad..ef2a0c5339 100644 --- a/core/math/math_fieldwise.cpp +++ b/core/math/math_fieldwise.cpp @@ -41,7 +41,6 @@ } Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const String &p_field) { - ERR_FAIL_COND_V(p_target.get_type() != p_source.get_type(), p_target); /* clang-format makes a mess of this macro usage */ diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 7417e64ac1..1585c96b38 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -94,16 +94,18 @@ double Math::dectime(double p_value, double p_amount, double p_step) { double sgn = p_value < 0 ? -1.0 : 1.0; double val = Math::abs(p_value); val -= p_amount * p_step; - if (val < 0.0) + if (val < 0.0) { val = 0.0; + } return val * sgn; } double Math::ease(double p_x, double p_c) { - if (p_x < 0) + if (p_x < 0) { p_x = 0; - else if (p_x > 1.0) + } else if (p_x > 1.0) { p_x = 1.0; + } if (p_c > 0) { if (p_c < 1.0) { return 1.0 - Math::pow(1.0 - p_x, 1.0 / p_c); @@ -118,8 +120,9 @@ double Math::ease(double p_x, double p_c) { } else { return (1.0 - Math::pow(1.0 - (p_x - 0.5) * 2.0, -p_c)) * 0.5 + 0.5; } - } else + } else { return 0; // no ease (raw) + } } double Math::stepify(double p_value, double p_step) { @@ -130,7 +133,6 @@ double Math::stepify(double p_value, double p_step) { } uint32_t Math::larger_prime(uint32_t p_val) { - static const uint32_t primes[] = { 5, 13, @@ -166,10 +168,10 @@ uint32_t Math::larger_prime(uint32_t p_val) { int idx = 0; while (true) { - ERR_FAIL_COND_V(primes[idx] == 0, 0); - if (primes[idx] > p_val) + if (primes[idx] > p_val) { return primes[idx]; + } idx++; } } diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 3e1eb14a6a..7a9fd60e23 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -41,7 +41,6 @@ #include <math.h> class Math { - static RandomPCG default_rand; public: @@ -233,12 +232,16 @@ public: static _ALWAYS_INLINE_ float range_lerp(float p_value, float p_istart, float p_istop, float p_ostart, float p_ostop) { return Math::lerp(p_ostart, p_ostop, Math::inverse_lerp(p_istart, p_istop, p_value)); } static _ALWAYS_INLINE_ double smoothstep(double p_from, double p_to, double p_weight) { - if (is_equal_approx(p_from, p_to)) return p_from; + if (is_equal_approx(p_from, p_to)) { + return p_from; + } double x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0, 1.0); return x * x * (3.0 - 2.0 * x); } static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_weight) { - if (is_equal_approx(p_from, p_to)) return p_from; + if (is_equal_approx(p_from, p_to)) { + return p_from; + } float x = CLAMP((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f); return x * x * (3.0f - 2.0f * x); } @@ -326,7 +329,6 @@ public: } static _ALWAYS_INLINE_ float absf(float g) { - union { float f; uint32_t i; @@ -338,7 +340,6 @@ public: } static _ALWAYS_INLINE_ double absd(double g) { - union { double d; uint64_t i; @@ -350,7 +351,6 @@ public: //this function should be as fast as possible and rounding mode should not matter static _ALWAYS_INLINE_ int fast_ftoi(float a) { - static int b; #if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603) || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP // windows 8 phone? @@ -405,7 +405,6 @@ public: } static _ALWAYS_INLINE_ float halfptr_to_float(const uint16_t *h) { - union { uint32_t u32; float f32; @@ -420,7 +419,6 @@ public: } static _ALWAYS_INLINE_ uint16_t make_half_float(float f) { - union { float fv; uint32_t ui; @@ -451,7 +449,6 @@ public: } // check if exponent is <= -15 else if (exp <= 0x38000000) { - /*// store a denorm half-float value or zero exp = (0x38000000 - exp) >> 23; mantissa >>= (14 + exp); @@ -476,10 +473,11 @@ public: 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) + if (p_target >= 0) { b -= p_separation; - else + } else { b += p_step; + } return (Math::abs(p_target - a) < Math::abs(p_target - b)) ? a : b; } return p_target; diff --git a/core/math/octree.h b/core/math/octree.h index 5225fbecb4..5d9688d442 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -34,6 +34,7 @@ #include "core/list.h" #include "core/map.h" #include "core/math/aabb.h" +#include "core/math/geometry_3d.h" #include "core/math/vector3.h" #include "core/print_string.h" #include "core/variant.h" @@ -51,7 +52,6 @@ public: private: enum { - NEG = 0, POS = 1, }; @@ -68,7 +68,6 @@ private: }; struct PairKey { - union { struct { OctreeElementID A; @@ -78,18 +77,14 @@ private: }; _FORCE_INLINE_ bool operator<(const PairKey &p_pair) const { - return key < p_pair.key; } _FORCE_INLINE_ PairKey(OctreeElementID p_A, OctreeElementID p_B) { - if (p_A < p_B) { - A = p_A; B = p_B; } else { - B = p_A; A = p_B; } @@ -101,53 +96,37 @@ private: struct Element; struct Octant { - // cached for FAST plane check AABB aabb; - uint64_t last_pass; - Octant *parent; - Octant *children[8]; + uint64_t last_pass = 0; + Octant *parent = nullptr; + Octant *children[8] = { nullptr }; - int children_count; // cache for amount of childrens (fast check for removal) - int parent_index; // cache for parent index (fast check for removal) + int children_count = 0; // cache for amount of childrens (fast check for removal) + int parent_index = -1; // cache for parent index (fast check for removal) List<Element *, AL> pairable_elements; List<Element *, AL> elements; - Octant() { - children_count = 0; - parent_index = -1; - last_pass = 0; - parent = nullptr; - for (int i = 0; i < 8; i++) - children[i] = nullptr; - } - - ~Octant() { - - /* - for (int i=0;i<8;i++) - memdelete_notnull(children[i]); - */ - } + Octant() {} + ~Octant() {} }; struct PairData; struct Element { + Octree *octree = nullptr; - Octree *octree; - - T *userdata; - int subindex; - bool pairable; - uint32_t pairable_mask; - uint32_t pairable_type; + T *userdata = nullptr; + int subindex = 0; + bool pairable = false; + uint32_t pairable_mask = 0; + uint32_t pairable_type = 0; - uint64_t last_pass; - OctreeElementID _id; - Octant *common_parent; + uint64_t last_pass = 0; + OctreeElementID _id = 0; + Octant *common_parent = nullptr; AABB aabb; AABB container_aabb; @@ -155,28 +134,16 @@ private: List<PairData *, AL> pair_list; struct OctantOwner { - Octant *octant; typename List<Element *, AL>::Element *E; }; // an element can be in max 8 octants List<OctantOwner, AL> octant_owners; - Element() { - last_pass = 0; - _id = 0; - pairable = false; - subindex = 0; - userdata = 0; - octree = 0; - pairable_mask = 0; - pairable_type = 0; - common_parent = nullptr; - } + Element() {} }; struct PairData { - int refcount; bool intersect; Element *A, *B; @@ -203,19 +170,15 @@ private: int pair_count; _FORCE_INLINE_ void _pair_check(PairData *p_pair) { - bool intersect = p_pair->A->aabb.intersects_inclusive(p_pair->B->aabb); if (intersect != p_pair->intersect) { - if (intersect) { - if (pair_callback) { p_pair->ud = pair_callback(pair_callback_userdata, p_pair->A->_id, p_pair->A->userdata, p_pair->A->subindex, p_pair->B->_id, p_pair->B->userdata, p_pair->B->subindex); } pair_count++; } else { - if (unpair_callback) { unpair_callback(pair_callback_userdata, p_pair->A->_id, p_pair->A->userdata, p_pair->A->subindex, p_pair->B->_id, p_pair->B->userdata, p_pair->B->subindex, p_pair->ud); } @@ -227,19 +190,19 @@ private: } _FORCE_INLINE_ void _pair_reference(Element *p_A, Element *p_B) { - - if (p_A == p_B || (p_A->userdata == p_B->userdata && p_A->userdata)) + if (p_A == p_B || (p_A->userdata == p_B->userdata && p_A->userdata)) { return; + } if (!(p_A->pairable_type & p_B->pairable_mask) && - !(p_B->pairable_type & p_A->pairable_mask)) + !(p_B->pairable_type & p_A->pairable_mask)) { return; // none can pair with none + } PairKey key(p_A->_id, p_B->_id); typename PairMap::Element *E = pair_map.find(key); if (!E) { - PairData pdata; pdata.refcount = 1; pdata.A = p_A; @@ -254,15 +217,14 @@ private: pair_callback(pair_callback_userdata,p_A->userdata,p_B->userdata); */ } else { - E->get().refcount++; } } _FORCE_INLINE_ void _pair_unreference(Element *p_A, Element *p_B) { - - if (p_A == p_B) + if (p_A == p_B) { return; + } PairKey key(p_A->_id, p_B->_id); typename PairMap::Element *E = pair_map.find(key); @@ -295,24 +257,18 @@ private: } _FORCE_INLINE_ void _element_check_pairs(Element *p_element) { - typename List<PairData *, AL>::Element *E = p_element->pair_list.front(); while (E) { - _pair_check(E->get()); E = E->next(); } } _FORCE_INLINE_ void _optimize() { - while (root && root->children_count < 2 && !root->elements.size() && !(use_pairs && root->pairable_elements.size())) { - Octant *new_root = nullptr; if (root->children_count == 1) { - for (int i = 0; i < 8; i++) { - if (root->children[i]) { new_root = root->children[i]; root->children[i] = nullptr; @@ -338,9 +294,10 @@ private: void _unpair_element(Element *p_element, Octant *p_octant); struct _CullConvexData { - const Plane *planes; int plane_count; + const Vector3 *points; + int point_count; T **result_array; int *result_idx; int result_max; @@ -353,14 +310,14 @@ private: void _cull_point(Octant *p_octant, const Vector3 &p_point, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask); void _remove_tree(Octant *p_octant) { - - if (!p_octant) + if (!p_octant) { return; + } for (int i = 0; i < 8; i++) { - - if (p_octant->children[i]) + if (p_octant->children[i]) { _remove_tree(p_octant->children[i]); + } } memdelete_allocator<Octant, AL>(p_octant); @@ -402,7 +359,6 @@ T *Octree<T, use_pairs, AL>::get(OctreeElementID p_id) const { template <class T, bool use_pairs, class AL> bool Octree<T, use_pairs, AL>::is_pairable(OctreeElementID p_id) const { - const typename ElementMap::Element *E = element_map.find(p_id); ERR_FAIL_COND_V(!E, false); return E->get().pairable; @@ -410,7 +366,6 @@ bool Octree<T, use_pairs, AL>::is_pairable(OctreeElementID p_id) const { template <class T, bool use_pairs, class AL> int Octree<T, use_pairs, AL>::get_subindex(OctreeElementID p_id) const { - const typename ElementMap::Element *E = element_map.find(p_id); ERR_FAIL_COND_V(!E, -1); return E->get().subindex; @@ -420,7 +375,6 @@ int Octree<T, use_pairs, AL>::get_subindex(OctreeElementID p_id) const { template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_octant) { - real_t element_size = p_element->aabb.get_longest_axis_size() * 1.01; // avoid precision issues if (p_octant->aabb.size.x / OCTREE_DIVISOR < element_size) { @@ -431,11 +385,9 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct owner.octant = p_octant; if (use_pairs && p_element->pairable) { - p_octant->pairable_elements.push_back(p_element); owner.E = p_octant->pairable_elements.back(); } else { - p_octant->elements.push_back(p_element); owner.E = p_octant->elements.back(); } @@ -450,11 +402,9 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct } if (use_pairs && p_octant->children_count > 0) { - pass++; //elements below this only get ONE reference added for (int i = 0; i < 8; i++) { - if (p_octant->children[i]) { _pair_element(p_element, p_octant->children[i]); } @@ -466,7 +416,6 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct bool candidate = p_element->common_parent == nullptr; for (int i = 0; i < 8; i++) { - if (p_octant->children[i]) { /* element exists, go straight to it */ if (p_octant->children[i]->aabb.intersects_inclusive(p_element->aabb)) { @@ -479,12 +428,15 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct AABB aabb = p_octant->aabb; aabb.size *= 0.5; - if (i & 1) + if (i & 1) { aabb.position.x += aabb.size.x; - if (i & 2) + } + if (i & 2) { aabb.position.y += aabb.size.y; - if (i & 4) + } + if (i & 4) { aabb.position.z += aabb.size.z; + } if (aabb.intersects_inclusive(p_element->aabb)) { /* if actually intersects, create the child */ @@ -506,13 +458,11 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct } if (candidate && splits > 1) { - p_element->common_parent = p_octant; } } if (use_pairs) { - typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front(); while (E) { @@ -533,14 +483,12 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_ensure_valid_root(const AABB &p_aabb) { - if (!root) { // octre is empty AABB base(Vector3(), Vector3(1.0, 1.0, 1.0) * unit_size); while (!base.encloses(p_aabb)) { - if (ABS(base.position.x + base.size.x) <= ABS(base.position.x)) { /* grow towards positive */ base.size *= 2.0; @@ -559,11 +507,9 @@ void Octree<T, use_pairs, AL>::_ensure_valid_root(const AABB &p_aabb) { octant_count++; } else { - AABB base = root->aabb; while (!base.encloses(p_aabb)) { - ERR_FAIL_COND_MSG(base.size.x > OCTREE_SIZE_LIMIT, "Octree upper size limit reached, does the AABB supplied contain NAN?"); Octant *gp = memnew_allocator(Octant, AL); @@ -592,15 +538,14 @@ void Octree<T, use_pairs, AL>::_ensure_valid_root(const AABB &p_aabb) { template <class T, bool use_pairs, class AL> bool Octree<T, use_pairs, AL>::_remove_element_from_octant(Element *p_element, Octant *p_octant, Octant *p_limit) { - bool octant_removed = false; while (true) { - // check all exit conditions - if (p_octant == p_limit) // reached limit, nothing to erase, exit + if (p_octant == p_limit) { // reached limit, nothing to erase, exit return octant_removed; + } bool unpaired = false; @@ -629,7 +574,6 @@ bool Octree<T, use_pairs, AL>::_remove_element_from_octant(Element *p_element, O Octant *parent = p_octant->parent; if (p_octant->children_count == 0 && p_octant->elements.empty() && p_octant->pairable_elements.empty()) { - // erase octant if (p_octant == root) { // won't have a parent, just erase @@ -648,8 +592,9 @@ bool Octree<T, use_pairs, AL>::_remove_element_from_octant(Element *p_element, O octant_removed = true; } - if (!removed && !unpaired) + if (!removed && !unpaired) { return octant_removed; // no reason to keep going up anymore! was already visited and was not removed + } p_octant = parent; } @@ -659,7 +604,6 @@ bool Octree<T, use_pairs, AL>::_remove_element_from_octant(Element *p_element, O template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_unpair_element(Element *p_element, Octant *p_octant) { - // always test pairable typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front(); while (E) { @@ -684,25 +628,24 @@ void Octree<T, use_pairs, AL>::_unpair_element(Element *p_element, Octant *p_oct p_octant->last_pass = pass; - if (p_octant->children_count == 0) + if (p_octant->children_count == 0) { return; // small optimization for leafs + } for (int i = 0; i < 8; i++) { - - if (p_octant->children[i]) + if (p_octant->children[i]) { _unpair_element(p_element, p_octant->children[i]); + } } } template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_pair_element(Element *p_element, Octant *p_octant) { - // always test pairable typename List<Element *, AL>::Element *E = p_octant->pairable_elements.front(); while (E) { - if (E->get()->last_pass != pass) { // only get ONE reference _pair_reference(p_element, E->get()); E->get()->last_pass = pass; @@ -723,30 +666,30 @@ void Octree<T, use_pairs, AL>::_pair_element(Element *p_element, Octant *p_octan } p_octant->last_pass = pass; - if (p_octant->children_count == 0) + if (p_octant->children_count == 0) { return; // small optimization for leafs + } for (int i = 0; i < 8; i++) { - - if (p_octant->children[i]) + if (p_octant->children[i]) { _pair_element(p_element, p_octant->children[i]); + } } } template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_remove_element(Element *p_element) { - pass++; // will do a new pass for this typename List<typename Element::OctantOwner, AL>::Element *I = p_element->octant_owners.front(); /* FIRST remove going up normally */ for (; I; I = I->next()) { - Octant *o = I->get().octant; - if (!use_pairs) // small speedup + if (!use_pairs) { // small speedup o->elements.erase(I->get().E); + } _remove_element_from_octant(p_element, o); } @@ -756,30 +699,28 @@ void Octree<T, use_pairs, AL>::_remove_element(Element *p_element) { I = p_element->octant_owners.front(); if (use_pairs) { - for (; I; I = I->next()) { - Octant *o = I->get().octant; // erase children pairs, they are erased ONCE even if repeated pass++; for (int i = 0; i < 8; i++) { - - if (o->children[i]) + if (o->children[i]) { _unpair_element(p_element, o->children[i]); + } } - if (p_element->pairable) + if (p_element->pairable) { o->pairable_elements.erase(I->get().E); - else + } else { o->elements.erase(I->get().E); + } } } p_element->octant_owners.clear(); if (use_pairs) { - int remaining = p_element->pair_list.size(); //p_element->pair_list.clear(); ERR_FAIL_COND(remaining); @@ -788,7 +729,6 @@ void Octree<T, use_pairs, AL>::_remove_element(Element *p_element) { template <class T, bool use_pairs, class AL> OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const AABB &p_aabb, int p_subindex, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) { - // check for AABB validity #ifdef DEBUG_ENABLED ERR_FAIL_COND_V(p_aabb.position.x > 1e15 || p_aabb.position.x < -1e15, 0); @@ -819,8 +759,9 @@ OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const AABB &p_aa if (!e.aabb.has_no_surface()) { _ensure_valid_root(p_aabb); _insert_element(&e, root); - if (use_pairs) + if (use_pairs) { _element_check_pairs(&e); + } } return last_element_id - 1; @@ -828,7 +769,6 @@ OctreeElementID Octree<T, use_pairs, AL>::create(T *p_userdata, const AABB &p_aa template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { - #ifdef DEBUG_ENABLED // check for AABB validity ERR_FAIL_COND(p_aabb.position.x > 1e15 || p_aabb.position.x < -1e15); @@ -849,7 +789,6 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { bool new_has_surf = !p_aabb.has_no_surface(); if (old_has_surf != new_has_surf) { - if (old_has_surf) { _remove_element(&e); // removing e.common_parent = nullptr; @@ -860,22 +799,24 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { e.common_parent = nullptr; e.aabb = p_aabb; _insert_element(&e, root); - if (use_pairs) + if (use_pairs) { _element_check_pairs(&e); + } } return; } - if (!old_has_surf) // doing nothing + if (!old_has_surf) { // doing nothing return; + } // it still is enclosed in the same AABB it was assigned to if (e.container_aabb.encloses(p_aabb)) { - e.aabb = p_aabb; - if (use_pairs) + if (use_pairs) { _element_check_pairs(&e); // must check pairs anyway + } return; } @@ -895,8 +836,9 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { //src is now the place towards where insertion is going to happen pass++; - while (common_parent && !common_parent->aabb.encloses(p_aabb)) + while (common_parent && !common_parent->aabb.encloses(p_aabb)) { common_parent = common_parent->parent; + } ERR_FAIL_COND(!common_parent); @@ -910,7 +852,6 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { pass++; for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F;) { - Octant *o = F->get().octant; typename List<typename Element::OctantOwner, AL>::Element *N = F->next(); @@ -919,13 +860,13 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { o->elements.erase( F->get().E ); */ - if (use_pairs && e.pairable) + if (use_pairs && e.pairable) { o->pairable_elements.erase(F->get().E); - else + } else { o->elements.erase(F->get().E); + } if (_remove_element_from_octant(&e, o, common_parent->parent)) { - owners.erase(F); } @@ -935,15 +876,14 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { if (use_pairs) { //unpair child elements in anything that survived for (typename List<typename Element::OctantOwner, AL>::Element *F = owners.front(); F; F = F->next()) { - Octant *o = F->get().octant; // erase children pairs, unref ONCE pass++; for (int i = 0; i < 8; i++) { - - if (o->children[i]) + if (o->children[i]) { _unpair_element(&e, o->children[i]); + } } } @@ -955,14 +895,14 @@ void Octree<T, use_pairs, AL>::move(OctreeElementID p_id, const AABB &p_aabb) { template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::set_pairable(OctreeElementID p_id, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask) { - typename ElementMap::Element *E = element_map.find(p_id); ERR_FAIL_COND(!E); Element &e = E->get(); - if (p_pairable == e.pairable && e.pairable_type == p_pairable_type && e.pairable_mask == p_pairable_mask) + if (p_pairable == e.pairable && e.pairable_type == p_pairable_type && e.pairable_mask == p_pairable_mask) { return; // no changes, return + } if (!e.aabb.has_no_surface()) { _remove_element(&e); @@ -976,21 +916,20 @@ void Octree<T, use_pairs, AL>::set_pairable(OctreeElementID p_id, bool p_pairabl if (!e.aabb.has_no_surface()) { _ensure_valid_root(e.aabb); _insert_element(&e, root); - if (use_pairs) + if (use_pairs) { _element_check_pairs(&e); + } } } template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::erase(OctreeElementID p_id) { - typename ElementMap::Element *E = element_map.find(p_id); ERR_FAIL_COND(!E); Element &e = E->get(); if (!e.aabb.has_no_surface()) { - _remove_element(&e); } @@ -1000,30 +939,27 @@ void Octree<T, use_pairs, AL>::erase(OctreeElementID p_id) { template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p_cull) { - - if (*p_cull->result_idx == p_cull->result_max) + if (*p_cull->result_idx == p_cull->result_max) { return; //pointless + } if (!p_octant->elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_cull->mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_cull->mask))) { continue; + } e->last_pass = pass; - if (e->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count)) { - + if (e->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count, p_cull->points, p_cull->point_count)) { if (*p_cull->result_idx < p_cull->result_max) { p_cull->result_array[*p_cull->result_idx] = e->userdata; (*p_cull->result_idx)++; } else { - return; // pointless to continue } } @@ -1031,26 +967,22 @@ void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p } if (use_pairs && !p_octant->pairable_elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_cull->mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_cull->mask))) { continue; + } e->last_pass = pass; - if (e->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count)) { - + if (e->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count, p_cull->points, p_cull->point_count)) { if (*p_cull->result_idx < p_cull->result_max) { - p_cull->result_array[*p_cull->result_idx] = e->userdata; (*p_cull->result_idx)++; } else { - return; // pointless to continue } } @@ -1058,8 +990,7 @@ void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p } for (int i = 0; i < 8; i++) { - - if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count)) { + if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_convex_shape(p_cull->planes, p_cull->plane_count, p_cull->points, p_cull->point_count)) { _cull_convex(p_octant->children[i], p_cull); } } @@ -1067,33 +998,30 @@ void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) { - - if (*p_result_idx == p_result_max) + if (*p_result_idx == p_result_max) { return; //pointless + } if (!p_octant->elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) { continue; + } e->last_pass = pass; if (p_aabb.intersects_inclusive(e->aabb)) { - if (*p_result_idx < p_result_max) { - p_result_array[*p_result_idx] = e->userdata; - if (p_subindex_array) + if (p_subindex_array) { p_subindex_array[*p_result_idx] = e->subindex; + } (*p_result_idx)++; } else { - return; // pointless to continue } } @@ -1101,27 +1029,24 @@ void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, } if (use_pairs && !p_octant->pairable_elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) { continue; + } e->last_pass = pass; if (p_aabb.intersects_inclusive(e->aabb)) { - if (*p_result_idx < p_result_max) { - p_result_array[*p_result_idx] = e->userdata; - if (p_subindex_array) + if (p_subindex_array) { p_subindex_array[*p_result_idx] = e->subindex; + } (*p_result_idx)++; } else { - return; // pointless to continue } } @@ -1129,7 +1054,6 @@ void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, } for (int i = 0; i < 8; i++) { - if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_inclusive(p_aabb)) { _cull_aabb(p_octant->children[i], p_aabb, p_result_array, p_result_idx, p_result_max, p_subindex_array, p_mask); } @@ -1138,33 +1062,30 @@ void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) { - - if (*p_result_idx == p_result_max) + if (*p_result_idx == p_result_max) { return; //pointless + } if (!p_octant->elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) { continue; + } e->last_pass = pass; if (e->aabb.intersects_segment(p_from, p_to)) { - if (*p_result_idx < p_result_max) { - p_result_array[*p_result_idx] = e->userdata; - if (p_subindex_array) + if (p_subindex_array) { p_subindex_array[*p_result_idx] = e->subindex; + } (*p_result_idx)++; } else { - return; // pointless to continue } } @@ -1172,30 +1093,27 @@ void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_ } if (use_pairs && !p_octant->pairable_elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) { continue; + } e->last_pass = pass; if (e->aabb.intersects_segment(p_from, p_to)) { - if (*p_result_idx < p_result_max) { - p_result_array[*p_result_idx] = e->userdata; - if (p_subindex_array) + if (p_subindex_array) { p_subindex_array[*p_result_idx] = e->subindex; + } (*p_result_idx)++; } else { - return; // pointless to continue } } @@ -1203,7 +1121,6 @@ void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_ } for (int i = 0; i < 8; i++) { - if (p_octant->children[i] && p_octant->children[i]->aabb.intersects_segment(p_from, p_to)) { _cull_segment(p_octant->children[i], p_from, p_to, p_result_array, p_result_idx, p_result_max, p_subindex_array, p_mask); } @@ -1212,33 +1129,30 @@ void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_ template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_point, T **p_result_array, int *p_result_idx, int p_result_max, int *p_subindex_array, uint32_t p_mask) { - - if (*p_result_idx == p_result_max) + if (*p_result_idx == p_result_max) { return; //pointless + } if (!p_octant->elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) { continue; + } e->last_pass = pass; if (e->aabb.has_point(p_point)) { - if (*p_result_idx < p_result_max) { - p_result_array[*p_result_idx] = e->userdata; - if (p_subindex_array) + if (p_subindex_array) { p_subindex_array[*p_result_idx] = e->subindex; + } (*p_result_idx)++; } else { - return; // pointless to continue } } @@ -1246,30 +1160,27 @@ void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_po } if (use_pairs && !p_octant->pairable_elements.empty()) { - typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { - Element *e = I->get(); - if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) + if (e->last_pass == pass || (use_pairs && !(e->pairable_type & p_mask))) { continue; + } e->last_pass = pass; if (e->aabb.has_point(p_point)) { - if (*p_result_idx < p_result_max) { - p_result_array[*p_result_idx] = e->userdata; - if (p_subindex_array) + if (p_subindex_array) { p_subindex_array[*p_result_idx] = e->subindex; + } (*p_result_idx)++; } else { - return; // pointless to continue } } @@ -1277,7 +1188,6 @@ void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_po } for (int i = 0; i < 8; i++) { - //could be optimized.. if (p_octant->children[i] && p_octant->children[i]->aabb.has_point(p_point)) { _cull_point(p_octant->children[i], p_point, p_result_array, p_result_idx, p_result_max, p_subindex_array, p_mask); @@ -1287,15 +1197,22 @@ void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_po template <class T, bool use_pairs, class AL> int Octree<T, use_pairs, AL>::cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask) { + if (!root || p_convex.size() == 0) { + return 0; + } - if (!root) + Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(&p_convex[0], p_convex.size()); + if (convex_points.size() == 0) { return 0; + } int result_count = 0; pass++; _CullConvexData cdata; cdata.planes = &p_convex[0]; cdata.plane_count = p_convex.size(); + cdata.points = &convex_points[0]; + cdata.point_count = convex_points.size(); cdata.result_array = p_result_array; cdata.result_max = p_result_max; cdata.result_idx = &result_count; @@ -1308,9 +1225,9 @@ int Octree<T, use_pairs, AL>::cull_convex(const Vector<Plane> &p_convex, T **p_r template <class T, bool use_pairs, class AL> int Octree<T, use_pairs, AL>::cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) { - - if (!root) + if (!root) { return 0; + } int result_count = 0; pass++; @@ -1321,9 +1238,9 @@ int Octree<T, use_pairs, AL>::cull_aabb(const AABB &p_aabb, T **p_result_array, template <class T, bool use_pairs, class AL> int Octree<T, use_pairs, AL>::cull_segment(const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) { - - if (!root) + if (!root) { return 0; + } int result_count = 0; pass++; @@ -1334,9 +1251,9 @@ int Octree<T, use_pairs, AL>::cull_segment(const Vector3 &p_from, const Vector3 template <class T, bool use_pairs, class AL> int Octree<T, use_pairs, AL>::cull_point(const Vector3 &p_point, T **p_result_array, int p_result_max, int *p_subindex_array, uint32_t p_mask) { - - if (!root) + if (!root) { return 0; + } int result_count = 0; pass++; @@ -1347,20 +1264,18 @@ int Octree<T, use_pairs, AL>::cull_point(const Vector3 &p_point, T **p_result_ar template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::set_pair_callback(PairCallback p_callback, void *p_userdata) { - pair_callback = p_callback; pair_callback_userdata = p_userdata; } + template <class T, bool use_pairs, class AL> void Octree<T, use_pairs, AL>::set_unpair_callback(UnpairCallback p_callback, void *p_userdata) { - unpair_callback = p_callback; unpair_callback_userdata = p_userdata; } template <class T, bool use_pairs, class AL> Octree<T, use_pairs, AL>::Octree(real_t p_unit_size) { - last_element_id = 1; pass = 1; unit_size = p_unit_size; diff --git a/core/math/plane.cpp b/core/math/plane.cpp index a3818698bc..df37ceb0e5 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -33,12 +33,10 @@ #include "core/math/math_funcs.h" void Plane::set_normal(const Vector3 &p_normal) { - normal = p_normal; } void Plane::normalize() { - real_t l = normal.length(); if (l == 0) { *this = Plane(0, 0, 0, 0); @@ -49,27 +47,25 @@ void Plane::normalize() { } Plane Plane::normalized() const { - Plane p = *this; p.normalize(); return p; } Vector3 Plane::get_any_point() const { - return get_normal() * d; } Vector3 Plane::get_any_perpendicular_normal() const { - static const Vector3 p1 = Vector3(1, 0, 0); static const Vector3 p2 = Vector3(0, 1, 0); Vector3 p; - if (ABS(normal.dot(p1)) > 0.99) // if too similar to p1 + if (ABS(normal.dot(p1)) > 0.99) { // if too similar to p1 p = p2; // use p2 - else + } else { p = p1; // use p1 + } p -= normal * normal.dot(p); p.normalize(); @@ -80,7 +76,6 @@ Vector3 Plane::get_any_perpendicular_normal() const { /* intersections */ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result) const { - const Plane &p_plane0 = *this; Vector3 normal0 = p_plane0.normal; Vector3 normal1 = p_plane1.normal; @@ -88,8 +83,9 @@ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r real_t denom = vec3_cross(normal0, normal1).dot(normal2); - if (Math::is_zero_approx(denom)) + if (Math::is_zero_approx(denom)) { return false; + } if (r_result) { *r_result = ((vec3_cross(normal1, normal2) * p_plane0.d) + @@ -102,13 +98,11 @@ bool Plane::intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r } bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const { - Vector3 segment = p_dir; real_t den = normal.dot(segment); //printf("den is %i\n",den); if (Math::is_zero_approx(den)) { - return false; } @@ -127,13 +121,11 @@ bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 } bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const { - Vector3 segment = p_begin - p_end; real_t den = normal.dot(segment); //printf("den is %i\n",den); if (Math::is_zero_approx(den)) { - return false; } @@ -141,7 +133,6 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec //printf("dist is %i\n",dist); if (dist < -CMP_EPSILON || dist > (1.0 + CMP_EPSILON)) { - return false; } @@ -153,12 +144,14 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec /* misc */ -bool Plane::is_equal_approx(const Plane &p_plane) const { +bool Plane::is_equal_approx_any_side(const Plane &p_plane) const { + return (normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d)) || (normal.is_equal_approx(-p_plane.normal) && Math::is_equal_approx(d, -p_plane.d)); +} +bool Plane::is_equal_approx(const Plane &p_plane) const { return normal.is_equal_approx(p_plane.normal) && Math::is_equal_approx(d, p_plane.d); } Plane::operator String() const { - return normal.operator String() + ", " + rtos(d); } diff --git a/core/math/plane.h b/core/math/plane.h index 771c8fc705..9a3e5a485f 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -36,7 +36,7 @@ class Plane { public: Vector3 normal; - real_t d; + real_t d = 0; void set_normal(const Vector3 &p_normal); _FORCE_INLINE_ Vector3 get_normal() const { return normal; }; ///Point is coplanar, CMP_EPSILON for precision @@ -56,12 +56,11 @@ public: /* intersections */ - bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result = 0) const; + bool intersect_3(const Plane &p_plane1, const Plane &p_plane2, Vector3 *r_result = nullptr) const; bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const; bool intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const; _FORCE_INLINE_ Vector3 project(const Vector3 &p_point) const { - return p_point - normal * distance_to(p_point); } @@ -69,13 +68,13 @@ public: Plane operator-() const { return Plane(-normal, -d); } bool is_equal_approx(const Plane &p_plane) const; + bool is_equal_approx_any_side(const Plane &p_plane) const; _FORCE_INLINE_ bool operator==(const Plane &p_plane) const; _FORCE_INLINE_ bool operator!=(const Plane &p_plane) const; operator String() const; - _FORCE_INLINE_ Plane() : - d(0) {} + _FORCE_INLINE_ Plane() {} _FORCE_INLINE_ Plane(real_t p_a, real_t p_b, real_t p_c, real_t p_d) : normal(p_a, p_b, p_c), d(p_d) {} @@ -86,17 +85,14 @@ public: }; bool Plane::is_point_over(const Vector3 &p_point) const { - return (normal.dot(p_point) > d); } real_t Plane::distance_to(const Vector3 &p_point) const { - return (normal.dot(p_point) - d); } bool Plane::has_point(const Vector3 &p_point, real_t _epsilon) const { - real_t dist = normal.dot(p_point) - d; dist = ABS(dist); return (dist <= _epsilon); @@ -113,23 +109,21 @@ Plane::Plane(const Vector3 &p_point, const Vector3 &p_normal) : } Plane::Plane(const Vector3 &p_point1, const Vector3 &p_point2, const Vector3 &p_point3, ClockDirection p_dir) { - - if (p_dir == CLOCKWISE) + if (p_dir == CLOCKWISE) { normal = (p_point1 - p_point3).cross(p_point1 - p_point2); - else + } else { normal = (p_point1 - p_point2).cross(p_point1 - p_point3); + } normal.normalize(); d = normal.dot(p_point1); } bool Plane::operator==(const Plane &p_plane) const { - return normal == p_plane.normal && d == p_plane.d; } bool Plane::operator!=(const Plane &p_plane) const { - return normal != p_plane.normal || d != p_plane.d; } diff --git a/core/math/quat.cpp b/core/math/quat.cpp index 61cd41b23d..c10f5da494 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -107,7 +107,6 @@ Vector3 Quat::get_euler_yxz() const { } void Quat::operator*=(const Quat &q) { - set(w * q.x + x * q.w + y * q.z - z * q.y, w * q.y + y * q.w + z * q.x - x * q.z, w * q.z + z * q.w + x * q.y - y * q.x, @@ -115,19 +114,16 @@ void Quat::operator*=(const Quat &q) { } Quat Quat::operator*(const Quat &q) const { - Quat r = *this; r *= q; return r; } bool Quat::is_equal_approx(const Quat &p_quat) const { - return Math::is_equal_approx(x, p_quat.x) && Math::is_equal_approx(y, p_quat.y) && Math::is_equal_approx(z, p_quat.z) && Math::is_equal_approx(w, p_quat.w); } real_t Quat::length() const { - return Math::sqrt(length_squared()); } @@ -206,7 +202,9 @@ Quat Quat::slerpni(const Quat &q, const real_t &t) const { real_t dot = from.dot(q); - if (Math::absf(dot) > 0.9999) return from; + if (Math::absf(dot) > 0.9999) { + return from; + } real_t theta = Math::acos(dot), sinT = 1.0 / Math::sin(theta), @@ -232,7 +230,6 @@ Quat Quat::cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const } Quat::operator String() const { - return String::num(x) + ", " + String::num(y) + ", " + String::num(z) + ", " + String::num(w); } @@ -241,9 +238,9 @@ void Quat::set_axis_angle(const Vector3 &axis, const real_t &angle) { ERR_FAIL_COND_MSG(!axis.is_normalized(), "The axis Vector3 must be normalized."); #endif real_t d = axis.length(); - if (d == 0) + if (d == 0) { set(0, 0, 0, 0); - else { + } else { real_t sin_angle = Math::sin(angle * 0.5); real_t cos_angle = Math::cos(angle * 0.5); real_t s = sin_angle / d; diff --git a/core/math/quat.h b/core/math/quat.h index b3135ad1ca..64d0f00912 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -40,7 +40,7 @@ class Quat { public: - real_t x, y, z, w; + real_t x = 0, y = 0, z = 0, w = 1; _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Quat &p_quat) const; @@ -112,7 +112,9 @@ public: z = p_z; w = p_w; } - inline Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : + + _FORCE_INLINE_ Quat() {} + _FORCE_INLINE_ Quat(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : x(p_x), y(p_y), z(p_z), @@ -147,7 +149,6 @@ public: z = 0; w = 0; } else { - real_t s = Math::sqrt((1.0 + d) * 2.0); real_t rs = 1.0 / s; @@ -157,13 +158,6 @@ public: w = s * 0.5; } } - - inline Quat() : - x(0), - y(0), - z(0), - w(1) { - } }; real_t Quat::dot(const Quat &q) const { @@ -196,7 +190,6 @@ void Quat::operator*=(const real_t &s) { } void Quat::operator/=(const real_t &s) { - *this *= 1.0 / s; } diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 7fbb26c377..8ba1ba9286 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -34,13 +34,11 @@ uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF; -Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) { - +Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_mesh) { /* CREATE AABB VOLUME */ AABB aabb; for (int i = 0; i < p_points.size(); i++) { - if (i == 0) { aabb.position = p_points[i]; } else { @@ -57,7 +55,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me Set<Vector3> valid_cache; for (int i = 0; i < p_points.size(); i++) { - Vector3 sp = p_points[i].snapped(Vector3(0.0001, 0.0001, 0.0001)); if (valid_cache.has(sp)) { valid_points.write[i] = false; @@ -78,12 +75,11 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me real_t max = 0, min = 0; for (int i = 0; i < p_points.size(); i++) { - - if (!valid_points[i]) + if (!valid_points[i]) { continue; + } real_t d = p_points[i][longest_axis]; if (i == 0 || d < min) { - simplex[0] = i; min = d; } @@ -102,15 +98,14 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me Vector3 rel12 = p_points[simplex[0]] - p_points[simplex[1]]; for (int i = 0; i < p_points.size(); i++) { - - if (!valid_points[i]) + if (!valid_points[i]) { continue; + } Vector3 n = rel12.cross(p_points[simplex[0]] - p_points[i]).cross(rel12).normalized(); real_t d = Math::abs(n.dot(p_points[simplex[0]]) - n.dot(p_points[i])); if (i == 0 || d > maxd) { - maxd = d; simplex[2] = i; } @@ -124,14 +119,13 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me Plane p(p_points[simplex[0]], p_points[simplex[1]], p_points[simplex[2]]); for (int i = 0; i < p_points.size(); i++) { - - if (!valid_points[i]) + if (!valid_points[i]) { continue; + } real_t d = Math::abs(p.distance_to(p_points[i])); if (i == 0 || d > maxd) { - maxd = d; simplex[3] = i; } @@ -152,7 +146,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me List<Face> faces; for (int i = 0; i < 4; i++) { - static const int face_order[4][3] = { { 0, 1, 2 }, { 0, 1, 3 }, @@ -183,22 +176,24 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me /* COMPUTE AVAILABLE VERTICES */ for (int i = 0; i < p_points.size(); i++) { - - if (i == simplex[0]) + if (i == simplex[0]) { continue; - if (i == simplex[1]) + } + if (i == simplex[1]) { continue; - if (i == simplex[2]) + } + if (i == simplex[2]) { continue; - if (i == simplex[3]) + } + if (i == simplex[3]) { continue; - if (!valid_points[i]) + } + if (!valid_points[i]) { continue; + } for (List<Face>::Element *E = faces.front(); E; E = E->next()) { - if (E->get().plane.distance_to(p_points[i]) > over_tolerance) { - E->get().points_over.push_back(i); break; } @@ -219,7 +214,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me uint32_t debug_stop = debug_stop_after; while (debug_stop > 0 && faces.back()->get().points_over.size()) { - debug_stop--; Face &f = faces.back()->get(); @@ -228,7 +222,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me real_t next_d = 0; for (int i = 0; i < f.points_over.size(); i++) { - real_t d = f.plane.distance_to(p_points[f.points_over[i]]); if (d > next_d) { @@ -247,9 +240,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me Map<Edge, FaceConnect> lit_edges; //create this on the flight, should not be that bad for performance and simplifies code a lot for (List<Face>::Element *E = faces.front(); E; E = E->next()) { - if (E->get().plane.distance_to(v) > 0) { - lit_faces.push_back(E); for (int i = 0; i < 3; i++) { @@ -265,7 +256,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //left F->get().left = E; } else { - F->get().right = E; } } @@ -276,7 +266,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me List<List<Face>::Element *> new_faces; //new faces for (Map<Edge, FaceConnect>::Element *E = lit_edges.front(); E; E = E->next()) { - FaceConnect &fc = E->get(); if (fc.left && fc.right) { continue; //edge is uninteresting, not on horizont @@ -304,17 +293,15 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //distribute points into new faces for (List<List<Face>::Element *>::Element *F = lit_faces.front(); F; F = F->next()) { - Face &lf = F->get()->get(); for (int i = 0; i < lf.points_over.size(); i++) { - - if (lf.points_over[i] == f.points_over[next]) //do not add current one + if (lf.points_over[i] == f.points_over[next]) { //do not add current one continue; + } Vector3 p = p_points[lf.points_over[i]]; for (List<List<Face>::Element *>::Element *E = new_faces.front(); E; E = E->next()) { - Face &f2 = E->get()->get(); if (f2.plane.distance_to(p) > over_tolerance) { f2.points_over.push_back(lf.points_over[i]); @@ -327,7 +314,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //erase lit faces while (lit_faces.size()) { - faces.erase(lit_faces.front()->get()); lit_faces.pop_front(); } @@ -335,7 +321,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //put faces that contain no points on the front for (List<List<Face>::Element *>::Element *E = new_faces.front(); E; E = E->next()) { - Face &f2 = E->get()->get(); if (f2.points_over.size() == 0) { faces.move_to_front(E->get()); @@ -349,21 +334,19 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //make a map of edges again Map<Edge, RetFaceConnect> ret_edges; - List<Geometry::MeshData::Face> ret_faces; + List<Geometry3D::MeshData::Face> ret_faces; for (List<Face>::Element *E = faces.front(); E; E = E->next()) { - - Geometry::MeshData::Face f; + Geometry3D::MeshData::Face f; f.plane = E->get().plane; for (int i = 0; i < 3; i++) { f.indices.push_back(E->get().vertices[i]); } - List<Geometry::MeshData::Face>::Element *F = ret_faces.push_back(f); + List<Geometry3D::MeshData::Face>::Element *F = ret_faces.push_back(f); for (int i = 0; i < 3; i++) { - uint32_t a = E->get().vertices[i]; uint32_t b = E->get().vertices[(i + 1) % 3]; Edge e(a, b); @@ -376,7 +359,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //left G->get().left = F; } else { - G->get().right = F; } } @@ -384,12 +366,10 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me //fill faces - for (List<Geometry::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) { - - Geometry::MeshData::Face &f = E->get(); + for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) { + Geometry3D::MeshData::Face &f = E->get(); for (int i = 0; i < f.indices.size(); i++) { - int a = E->get().indices[i]; int b = E->get().indices[(i + 1) % f.indices.size()]; Edge e(a, b); @@ -397,7 +377,7 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me Map<Edge, RetFaceConnect>::Element *F = ret_edges.find(e); ERR_CONTINUE(!F); - List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left; + List<Geometry3D::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left; ERR_CONTINUE(O == E); ERR_CONTINUE(O == nullptr); @@ -411,7 +391,6 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me if (O->get().indices[j] == a) { //append the rest for (int k = 0; k < ois; k++) { - int idx = O->get().indices[(k + j) % ois]; int idxn = O->get().indices[(k + j + 1) % ois]; if (idx == b && idxn == a) { //already have b! @@ -427,10 +406,11 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me Map<Edge, RetFaceConnect>::Element *F2 = ret_edges.find(e2); ERR_CONTINUE(!F2); //change faceconnect, point to this face instead - if (F2->get().left == O) + if (F2->get().left == O) { F2->get().left = E; - else if (F2->get().right == O) + } else if (F2->get().right == O) { F2->get().right = E; + } } break; @@ -439,11 +419,13 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me // remove all edge connections to this face for (Map<Edge, RetFaceConnect>::Element *G = ret_edges.front(); G; G = G->next()) { - if (G->get().left == O) + if (G->get().left == O) { G->get().left = nullptr; + } - if (G->get().right == O) + if (G->get().right == O) { G->get().right = nullptr; + } } ret_edges.erase(F); //remove the edge @@ -457,14 +439,13 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me r_mesh.faces.resize(ret_faces.size()); int idx = 0; - for (List<Geometry::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) { + for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) { r_mesh.faces.write[idx++] = E->get(); } r_mesh.edges.resize(ret_edges.size()); idx = 0; for (Map<Edge, RetFaceConnect>::Element *E = ret_edges.front(); E; E = E->next()) { - - Geometry::MeshData::Edge e; + Geometry3D::MeshData::Edge e; e.a = E->key().vertices[0]; e.b = E->key().vertices[1]; r_mesh.edges.write[idx++] = e; diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h index 173f919a73..cac8e58d23 100644 --- a/core/math/quick_hull.h +++ b/core/math/quick_hull.h @@ -33,14 +33,12 @@ #include "core/list.h" #include "core/math/aabb.h" -#include "core/math/geometry.h" +#include "core/math/geometry_3d.h" #include "core/set.h" class QuickHull { - public: struct Edge { - union { uint32_t vertices[2]; uint64_t id; @@ -51,7 +49,6 @@ public: } Edge(int p_vtx_a = 0, int p_vtx_b = 0) { - if (p_vtx_a > p_vtx_b) { SWAP(p_vtx_a, p_vtx_b); } @@ -62,36 +59,28 @@ public: }; struct Face { - Plane plane; uint32_t vertices[3]; Vector<int> points_over; bool operator<(const Face &p_face) const { - return points_over.size() < p_face.points_over.size(); } }; private: struct FaceConnect { - List<Face>::Element *left, *right; - FaceConnect() { - left = nullptr; - right = nullptr; - } + List<Face>::Element *left, *right = nullptr; + FaceConnect() {} }; struct RetFaceConnect { - List<Geometry::MeshData::Face>::Element *left, *right; - RetFaceConnect() { - left = nullptr; - right = nullptr; - } + List<Geometry3D::MeshData::Face>::Element *left, *right = nullptr; + RetFaceConnect() {} }; public: static uint32_t debug_stop_after; - static Error build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh); + static Error build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_mesh); }; #endif // QUICK_HULL_H diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp index 1a1bffb562..67f4c0b14a 100644 --- a/core/math/random_number_generator.cpp +++ b/core/math/random_number_generator.cpp @@ -30,8 +30,6 @@ #include "random_number_generator.h" -RandomNumberGenerator::RandomNumberGenerator() {} - void RandomNumberGenerator::_bind_methods() { ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed); ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed); diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h index e7f188bb42..920308e597 100644 --- a/core/math/random_number_generator.h +++ b/core/math/random_number_generator.h @@ -59,13 +59,14 @@ public: _FORCE_INLINE_ int randi_range(int from, int to) { unsigned int ret = randbase.rand(); - if (to < from) + if (to < from) { return ret % (from - to + 1) + to; - else + } else { return ret % (to - from + 1) + from; + } } - RandomNumberGenerator(); + RandomNumberGenerator() {} }; #endif // RANDOM_NUMBER_GENERATOR_H diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp index 12b9904c88..0cc3c4ca0f 100644 --- a/core/math/rect2.cpp +++ b/core/math/rect2.cpp @@ -31,12 +31,10 @@ #include "core/math/transform_2d.h" // Includes rect2.h but Rect2 needs Transform2D bool Rect2::is_equal_approx(const Rect2 &p_rect) const { - return position.is_equal_approx(p_rect.position) && size.is_equal_approx(p_rect.size); } bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos, Point2 *r_normal) const { - real_t min = 0, max = 1; int axis = 0; real_t sign = 0; @@ -50,18 +48,18 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 real_t csign; if (seg_from < seg_to) { - - if (seg_from > box_end || seg_to < box_begin) + if (seg_from > box_end || seg_to < box_begin) { return false; + } real_t length = seg_to - seg_from; cmin = (seg_from < box_begin) ? ((box_begin - seg_from) / length) : 0; cmax = (seg_to > box_end) ? ((box_end - seg_from) / length) : 1; csign = -1.0; } else { - - if (seg_to > box_end || seg_from < box_begin) + if (seg_to > box_end || seg_from < box_begin) { return false; + } real_t length = seg_to - seg_from; cmin = (seg_from > box_end) ? (box_end - seg_from) / length : 0; cmax = (seg_to < box_begin) ? (box_begin - seg_from) / length : 1; @@ -73,10 +71,12 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 axis = i; sign = csign; } - if (cmax < max) + if (cmax < max) { max = cmax; - if (max < min) + } + if (max < min) { return false; + } } Vector2 rel = p_to - p_from; @@ -87,14 +87,14 @@ bool Rect2::intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_normal = normal; } - if (r_pos) + if (r_pos) { *r_pos = p_from + rel * min; + } return true; } bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const { - //SAT intersection between local and transformed rect2 Vector2 xf_points[4] = { @@ -108,14 +108,18 @@ bool Rect2::intersects_transformed(const Transform2D &p_xform, const Rect2 &p_re //base rect2 first (faster) - if (xf_points[0].y > position.y) + if (xf_points[0].y > position.y) { goto next1; - if (xf_points[1].y > position.y) + } + if (xf_points[1].y > position.y) { goto next1; - if (xf_points[2].y > position.y) + } + if (xf_points[2].y > position.y) { goto next1; - if (xf_points[3].y > position.y) + } + if (xf_points[3].y > position.y) { goto next1; + } return false; @@ -123,27 +127,35 @@ next1: low_limit = position.y + size.y; - if (xf_points[0].y < low_limit) + if (xf_points[0].y < low_limit) { goto next2; - if (xf_points[1].y < low_limit) + } + if (xf_points[1].y < low_limit) { goto next2; - if (xf_points[2].y < low_limit) + } + if (xf_points[2].y < low_limit) { goto next2; - if (xf_points[3].y < low_limit) + } + if (xf_points[3].y < low_limit) { goto next2; + } return false; next2: - if (xf_points[0].x > position.x) + if (xf_points[0].x > position.x) { goto next3; - if (xf_points[1].x > position.x) + } + if (xf_points[1].x > position.x) { goto next3; - if (xf_points[2].x > position.x) + } + if (xf_points[2].x > position.x) { goto next3; - if (xf_points[3].x > position.x) + } + if (xf_points[3].x > position.x) { goto next3; + } return false; @@ -151,14 +163,18 @@ next3: low_limit = position.x + size.x; - if (xf_points[0].x < low_limit) + if (xf_points[0].x < low_limit) { goto next4; - if (xf_points[1].x < low_limit) + } + if (xf_points[1].x < low_limit) { goto next4; - if (xf_points[2].x < low_limit) + } + if (xf_points[2].x < low_limit) { goto next4; - if (xf_points[3].x < low_limit) + } + if (xf_points[3].x < low_limit) { goto next4; + } return false; @@ -201,10 +217,12 @@ next4: maxb = MAX(dp, maxb); minb = MIN(dp, minb); - if (mina > maxb) + if (mina > maxb) { return false; - if (minb > maxa) + } + if (minb > maxa) { return false; + } maxa = p_xform.elements[1].dot(xf_points2[0]); mina = maxa; @@ -236,10 +254,12 @@ next4: maxb = MAX(dp, maxb); minb = MIN(dp, minb); - if (mina > maxb) + if (mina > maxb) { return false; - if (minb > maxa) + } + if (minb > maxa) { return false; + } return true; } diff --git a/core/math/rect2.h b/core/math/rect2.h index 30dbfdbbe5..14393325ec 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -36,7 +36,6 @@ struct Transform2D; struct Rect2 { - Point2 position; Size2 size; @@ -49,30 +48,37 @@ struct Rect2 { inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const { if (p_include_borders) { - if (position.x > (p_rect.position.x + p_rect.size.width)) + if (position.x > (p_rect.position.x + p_rect.size.width)) { return false; - if ((position.x + size.width) < p_rect.position.x) + } + if ((position.x + size.width) < p_rect.position.x) { return false; - if (position.y > (p_rect.position.y + p_rect.size.height)) + } + if (position.y > (p_rect.position.y + p_rect.size.height)) { return false; - if ((position.y + size.height) < p_rect.position.y) + } + if ((position.y + size.height) < p_rect.position.y) { return false; + } } else { - if (position.x >= (p_rect.position.x + p_rect.size.width)) + if (position.x >= (p_rect.position.x + p_rect.size.width)) { return false; - if ((position.x + size.width) <= p_rect.position.x) + } + if ((position.x + size.width) <= p_rect.position.x) { return false; - if (position.y >= (p_rect.position.y + p_rect.size.height)) + } + if (position.y >= (p_rect.position.y + p_rect.size.height)) { return false; - if ((position.y + size.height) <= p_rect.position.y) + } + if ((position.y + size.height) <= p_rect.position.y) { return false; + } } return true; } inline real_t distance_to(const Vector2 &p_point) const { - real_t dist = 0.0; bool inside = true; @@ -97,10 +103,11 @@ struct Rect2 { inside = false; } - if (inside) + if (inside) { return 0; - else + } else { return dist; + } } bool intersects_transformed(const Transform2D &p_xform, const Rect2 &p_rect) const; @@ -108,22 +115,21 @@ struct Rect2 { bool intersects_segment(const Point2 &p_from, const Point2 &p_to, Point2 *r_pos = nullptr, Point2 *r_normal = nullptr) const; inline bool encloses(const Rect2 &p_rect) const { - return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && ((p_rect.position.x + p_rect.size.x) <= (position.x + size.x)) && ((p_rect.position.y + p_rect.size.y) <= (position.y + size.y)); } _FORCE_INLINE_ bool has_no_area() const { - return (size.x <= 0 || size.y <= 0); } inline Rect2 clip(const Rect2 &p_rect) const { /// return a clipped rect Rect2 new_rect = p_rect; - if (!intersects(new_rect)) + if (!intersects(new_rect)) { return Rect2(); + } new_rect.position.x = MAX(p_rect.position.x, position.x); new_rect.position.y = MAX(p_rect.position.y, position.y); @@ -150,17 +156,21 @@ struct Rect2 { new_rect.size = new_rect.size - new_rect.position; //make relative again return new_rect; - }; + } inline bool has_point(const Point2 &p_point) const { - if (p_point.x < position.x) + if (p_point.x < position.x) { return false; - if (p_point.y < position.y) + } + if (p_point.y < position.y) { return false; + } - if (p_point.x >= (position.x + size.x)) + if (p_point.x >= (position.x + size.x)) { return false; - if (p_point.y >= (position.y + size.y)) + } + if (p_point.y >= (position.y + size.y)) { return false; + } return true; } @@ -170,7 +180,6 @@ struct Rect2 { bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } inline Rect2 grow(real_t p_by) const { - Rect2 g = *this; g.position.x -= p_by; g.position.y -= p_by; @@ -189,7 +198,6 @@ struct Rect2 { } inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { - Rect2 g = *this; g.position.x -= p_left; g.position.y -= p_top; @@ -200,7 +208,6 @@ struct Rect2 { } _FORCE_INLINE_ Rect2 expand(const Vector2 &p_vector) const { - Rect2 r = *this; r.expand_to(p_vector); return r; @@ -211,22 +218,25 @@ struct Rect2 { Vector2 begin = position; Vector2 end = position + size; - if (p_vector.x < begin.x) + if (p_vector.x < begin.x) { begin.x = p_vector.x; - if (p_vector.y < begin.y) + } + if (p_vector.y < begin.y) { begin.y = p_vector.y; + } - if (p_vector.x > end.x) + if (p_vector.x > end.x) { end.x = p_vector.x; - if (p_vector.y > end.y) + } + if (p_vector.y > end.y) { end.y = p_vector.y; + } position = begin; size = end - begin; } _FORCE_INLINE_ Rect2 abs() const { - return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); } @@ -244,7 +254,6 @@ struct Rect2 { }; struct Rect2i { - Point2i position; Size2i size; @@ -256,35 +265,38 @@ struct Rect2i { int get_area() const { return size.width * size.height; } inline bool intersects(const Rect2i &p_rect) const { - if (position.x > (p_rect.position.x + p_rect.size.width)) + if (position.x > (p_rect.position.x + p_rect.size.width)) { return false; - if ((position.x + size.width) < p_rect.position.x) + } + if ((position.x + size.width) < p_rect.position.x) { return false; - if (position.y > (p_rect.position.y + p_rect.size.height)) + } + if (position.y > (p_rect.position.y + p_rect.size.height)) { return false; - if ((position.y + size.height) < p_rect.position.y) + } + if ((position.y + size.height) < p_rect.position.y) { return false; + } return true; } inline bool encloses(const Rect2i &p_rect) const { - return (p_rect.position.x >= position.x) && (p_rect.position.y >= position.y) && ((p_rect.position.x + p_rect.size.x) < (position.x + size.x)) && ((p_rect.position.y + p_rect.size.y) < (position.y + size.y)); } _FORCE_INLINE_ bool has_no_area() const { - return (size.x <= 0 || size.y <= 0); } inline Rect2i clip(const Rect2i &p_rect) const { /// return a clipped rect Rect2i new_rect = p_rect; - if (!intersects(new_rect)) + if (!intersects(new_rect)) { return Rect2i(); + } new_rect.position.x = MAX(p_rect.position.x, position.x); new_rect.position.y = MAX(p_rect.position.y, position.y); @@ -311,17 +323,21 @@ struct Rect2i { new_rect.size = new_rect.size - new_rect.position; //make relative again return new_rect; - }; + } bool has_point(const Point2 &p_point) const { - if (p_point.x < position.x) + if (p_point.x < position.x) { return false; - if (p_point.y < position.y) + } + if (p_point.y < position.y) { return false; + } - if (p_point.x >= (position.x + size.x)) + if (p_point.x >= (position.x + size.x)) { return false; - if (p_point.y >= (position.y + size.y)) + } + if (p_point.y >= (position.y + size.y)) { return false; + } return true; } @@ -330,7 +346,6 @@ struct Rect2i { bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } Rect2i grow(int p_by) const { - Rect2i g = *this; g.position.x -= p_by; g.position.y -= p_by; @@ -349,7 +364,6 @@ struct Rect2i { } inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const { - Rect2i g = *this; g.position.x -= p_left; g.position.y -= p_top; @@ -360,44 +374,46 @@ struct Rect2i { } _FORCE_INLINE_ Rect2i expand(const Vector2i &p_vector) const { - Rect2i r = *this; r.expand_to(p_vector); return r; } inline void expand_to(const Point2i &p_vector) { - Point2i begin = position; Point2i end = position + size; - if (p_vector.x < begin.x) + if (p_vector.x < begin.x) { begin.x = p_vector.x; - if (p_vector.y < begin.y) + } + if (p_vector.y < begin.y) { begin.y = p_vector.y; + } - if (p_vector.x > end.x) + if (p_vector.x > end.x) { end.x = p_vector.x; - if (p_vector.y > end.y) + } + if (p_vector.y > end.y) { end.y = p_vector.y; + } position = begin; size = end - begin; } _FORCE_INLINE_ Rect2i abs() const { - return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); } operator String() const { return String(position) + ", " + String(size); } operator Rect2() const { return Rect2(position, size); } + + Rect2i() {} Rect2i(const Rect2 &p_r2) : position(p_r2.position), size(p_r2.size) { } - Rect2i() {} Rect2i(int p_x, int p_y, int p_width, int p_height) : position(Point2(p_x, p_y)), size(Size2(p_width, p_height)) { diff --git a/core/math/transform.cpp b/core/math/transform.cpp index 9dad3262d2..0274dd18af 100644 --- a/core/math/transform.cpp +++ b/core/math/transform.cpp @@ -35,20 +35,17 @@ #include "core/print_string.h" void Transform::affine_invert() { - basis.invert(); origin = basis.xform(-origin); } Transform Transform::affine_inverse() const { - Transform ret = *this; ret.affine_invert(); return ret; } void Transform::invert() { - basis.transpose(); origin = basis.xform(-origin); } @@ -62,22 +59,18 @@ Transform Transform::inverse() const { } void Transform::rotate(const Vector3 &p_axis, real_t p_phi) { - *this = rotated(p_axis, p_phi); } Transform Transform::rotated(const Vector3 &p_axis, real_t p_phi) const { - return Transform(Basis(p_axis, p_phi), Vector3()) * (*this); } void Transform::rotate_basis(const Vector3 &p_axis, real_t p_phi) { - basis.rotate(p_axis, p_phi); } Transform Transform::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { - Transform t = *this; t.set_look_at(origin, p_target, p_up); return t; @@ -117,7 +110,6 @@ void Transform::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const } Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) const { - /* not sure if very "efficient" but good enough? */ Vector3 src_scale = basis.get_scale(); @@ -129,88 +121,77 @@ Transform Transform::interpolate_with(const Transform &p_transform, real_t p_c) Vector3 dst_loc = p_transform.origin; Transform interp; - interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.linear_interpolate(dst_scale, p_c)); - interp.origin = src_loc.linear_interpolate(dst_loc, p_c); + interp.basis.set_quat_scale(src_rot.slerp(dst_rot, p_c).normalized(), src_scale.lerp(dst_scale, p_c)); + interp.origin = src_loc.lerp(dst_loc, p_c); return interp; } void Transform::scale(const Vector3 &p_scale) { - basis.scale(p_scale); origin *= p_scale; } Transform Transform::scaled(const Vector3 &p_scale) const { - Transform t = *this; t.scale(p_scale); return t; } void Transform::scale_basis(const Vector3 &p_scale) { - basis.scale(p_scale); } void Transform::translate(real_t p_tx, real_t p_ty, real_t p_tz) { translate(Vector3(p_tx, p_ty, p_tz)); } -void Transform::translate(const Vector3 &p_translation) { +void Transform::translate(const Vector3 &p_translation) { for (int i = 0; i < 3; i++) { origin[i] += basis[i].dot(p_translation); } } Transform Transform::translated(const Vector3 &p_translation) const { - Transform t = *this; t.translate(p_translation); return t; } void Transform::orthonormalize() { - basis.orthonormalize(); } Transform Transform::orthonormalized() const { - Transform _copy = *this; _copy.orthonormalize(); return _copy; } bool Transform::is_equal_approx(const Transform &p_transform) const { - return basis.is_equal_approx(p_transform.basis) && origin.is_equal_approx(p_transform.origin); } bool Transform::operator==(const Transform &p_transform) const { - return (basis == p_transform.basis && origin == p_transform.origin); } -bool Transform::operator!=(const Transform &p_transform) const { +bool Transform::operator!=(const Transform &p_transform) const { return (basis != p_transform.basis || origin != p_transform.origin); } void Transform::operator*=(const Transform &p_transform) { - origin = xform(p_transform.origin); basis *= p_transform.basis; } Transform Transform::operator*(const Transform &p_transform) const { - Transform t = *this; t *= p_transform; return t; } Transform::operator String() const { - return basis.operator String() + " - " + origin.operator String(); } diff --git a/core/math/transform.h b/core/math/transform.h index c6e3be4c70..71847d36ac 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -92,14 +92,12 @@ public: Transform interpolate_with(const Transform &p_transform, real_t p_c) const; _FORCE_INLINE_ Transform inverse_xform(const Transform &t) const { - Vector3 v = t.origin - origin; return Transform(basis.transpose_xform(t.basis), basis.xform(v)); } void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) { - basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz); origin.x = tx; origin.y = ty; @@ -114,14 +112,13 @@ public: }; _FORCE_INLINE_ Vector3 Transform::xform(const Vector3 &p_vector) const { - return Vector3( basis[0].dot(p_vector) + origin.x, basis[1].dot(p_vector) + origin.y, basis[2].dot(p_vector) + origin.z); } -_FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const { +_FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const { Vector3 v = p_vector - origin; return Vector3( @@ -131,7 +128,6 @@ _FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const { } _FORCE_INLINE_ Plane Transform::xform(const Plane &p_plane) const { - Vector3 point = p_plane.normal * p_plane.d; Vector3 point_dir = point + p_plane.normal; point = xform(point); @@ -143,8 +139,8 @@ _FORCE_INLINE_ Plane Transform::xform(const Plane &p_plane) const { return Plane(normal, d); } -_FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const { +_FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const { Vector3 point = p_plane.normal * p_plane.d; Vector3 point_dir = point + p_plane.normal; xform_inv(point); @@ -158,7 +154,6 @@ _FORCE_INLINE_ Plane Transform::xform_inv(const Plane &p_plane) const { } _FORCE_INLINE_ AABB Transform::xform(const AABB &p_aabb) const { - /* http://dev.theomader.com/transform-bounding-boxes/ */ Vector3 min = p_aabb.position; Vector3 max = p_aabb.position + p_aabb.size; @@ -184,7 +179,6 @@ _FORCE_INLINE_ AABB Transform::xform(const AABB &p_aabb) const { } _FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const { - /* define vertices */ Vector3 vertices[8] = { Vector3(p_aabb.position.x + p_aabb.size.x, p_aabb.position.y + p_aabb.size.y, p_aabb.position.z + p_aabb.size.z), @@ -202,7 +196,6 @@ _FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const { ret.position = xform_inv(vertices[0]); for (int i = 1; i < 8; i++) { - ret.expand_to(xform_inv(vertices[i])); } @@ -210,7 +203,6 @@ _FORCE_INLINE_ AABB Transform::xform_inv(const AABB &p_aabb) const { } Vector<Vector3> Transform::xform(const Vector<Vector3> &p_array) const { - Vector<Vector3> array; array.resize(p_array.size()); @@ -224,7 +216,6 @@ Vector<Vector3> Transform::xform(const Vector<Vector3> &p_array) const { } Vector<Vector3> Transform::xform_inv(const Vector<Vector3> &p_array) const { - Vector<Vector3> array; array.resize(p_array.size()); diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index f28b664e46..dee1b3b23e 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -38,14 +38,12 @@ void Transform2D::invert() { } Transform2D Transform2D::inverse() const { - Transform2D inv = *this; inv.invert(); return inv; } void Transform2D::affine_invert() { - real_t det = basis_determinant(); #ifdef MATH_CHECKS ERR_FAIL_COND(det == 0); @@ -60,7 +58,6 @@ void Transform2D::affine_invert() { } Transform2D Transform2D::affine_inverse() const { - Transform2D inv = *this; inv.affine_invert(); return inv; @@ -70,6 +67,16 @@ void Transform2D::rotate(real_t p_phi) { *this = Transform2D(p_phi, Vector2()) * (*this); } +real_t Transform2D::get_skew() const { + real_t det = basis_determinant(); + return Math::acos(elements[0].normalized().dot(SGN(det) * elements[1].normalized())) - Math_PI * 0.5; +} + +void Transform2D::set_skew(float p_angle) { + real_t det = basis_determinant(); + elements[1] = SGN(det) * elements[0].rotated((Math_PI * 0.5 + p_angle)).normalized() * elements[1].length(); +} + real_t Transform2D::get_rotation() const { real_t det = basis_determinant(); Transform2D m = orthonormalized(); @@ -91,7 +98,6 @@ void Transform2D::set_rotation(real_t p_rot) { } Transform2D::Transform2D(real_t p_rot, const Vector2 &p_pos) { - real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); elements[0][0] = cr; @@ -117,24 +123,23 @@ void Transform2D::scale(const Size2 &p_scale) { scale_basis(p_scale); elements[2] *= p_scale; } -void Transform2D::scale_basis(const Size2 &p_scale) { +void Transform2D::scale_basis(const Size2 &p_scale) { elements[0][0] *= p_scale.x; elements[0][1] *= p_scale.y; elements[1][0] *= p_scale.x; elements[1][1] *= p_scale.y; } -void Transform2D::translate(real_t p_tx, real_t p_ty) { +void Transform2D::translate(real_t p_tx, real_t p_ty) { translate(Vector2(p_tx, p_ty)); } -void Transform2D::translate(const Vector2 &p_translation) { +void Transform2D::translate(const Vector2 &p_translation) { elements[2] += basis_xform(p_translation); } void Transform2D::orthonormalize() { - // Gram-Schmidt Process Vector2 x = elements[0]; @@ -149,39 +154,36 @@ void Transform2D::orthonormalize() { } Transform2D Transform2D::orthonormalized() const { - Transform2D on = *this; on.orthonormalize(); return on; } bool Transform2D::is_equal_approx(const Transform2D &p_transform) const { - return elements[0].is_equal_approx(p_transform.elements[0]) && elements[1].is_equal_approx(p_transform.elements[1]) && elements[2].is_equal_approx(p_transform.elements[2]); } bool Transform2D::operator==(const Transform2D &p_transform) const { - for (int i = 0; i < 3; i++) { - if (elements[i] != p_transform.elements[i]) + if (elements[i] != p_transform.elements[i]) { return false; + } } return true; } bool Transform2D::operator!=(const Transform2D &p_transform) const { - for (int i = 0; i < 3; i++) { - if (elements[i] != p_transform.elements[i]) + if (elements[i] != p_transform.elements[i]) { return true; + } } return false; } void Transform2D::operator*=(const Transform2D &p_transform) { - elements[2] = xform(p_transform.elements[2]); real_t x0, x1, y0, y1; @@ -198,54 +200,46 @@ void Transform2D::operator*=(const Transform2D &p_transform) { } Transform2D Transform2D::operator*(const Transform2D &p_transform) const { - Transform2D t = *this; t *= p_transform; return t; } Transform2D Transform2D::scaled(const Size2 &p_scale) const { - Transform2D copy = *this; copy.scale(p_scale); return copy; } Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const { - Transform2D copy = *this; copy.scale_basis(p_scale); return copy; } Transform2D Transform2D::untranslated() const { - Transform2D copy = *this; copy.elements[2] = Vector2(); return copy; } Transform2D Transform2D::translated(const Vector2 &p_offset) const { - Transform2D copy = *this; copy.translate(p_offset); return copy; } Transform2D Transform2D::rotated(real_t p_phi) const { - Transform2D copy = *this; copy.rotate(p_phi); return copy; } real_t Transform2D::basis_determinant() const { - return elements[0].x * elements[1].y - elements[0].y * elements[1].x; } Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t p_c) const { - //extract parameters Vector2 p1 = get_origin(); Vector2 p2 = p_transform.get_origin(); @@ -267,7 +261,7 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t Vector2 v; if (dot > 0.9995) { - v = Vector2::linear_interpolate(v1, v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues + v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues } else { real_t angle = p_c * Math::acos(dot); Vector2 v3 = (v2 - v1 * dot).normalized(); @@ -275,12 +269,11 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t } //construct matrix - Transform2D res(Math::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c)); - res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c)); + Transform2D res(Math::atan2(v.y, v.x), p1.lerp(p2, p_c)); + res.scale_basis(s1.lerp(s2, p_c)); return res; } Transform2D::operator String() const { - return String(String() + elements[0] + ", " + elements[1] + ", " + elements[2]); } diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index fa43762aa4..46e97abaa7 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -70,7 +70,10 @@ struct Transform2D { void set_rotation(real_t p_rot); real_t get_rotation() const; + real_t get_skew() const; + void set_skew(float p_angle); _FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale); + _FORCE_INLINE_ void set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew); void rotate(real_t p_phi); void scale(const Size2 &p_scale); @@ -117,7 +120,6 @@ struct Transform2D { operator String() const; Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { - elements[0][0] = xx; elements[0][1] = xy; elements[1][0] = yx; @@ -134,36 +136,33 @@ struct Transform2D { }; Vector2 Transform2D::basis_xform(const Vector2 &p_vec) const { - return Vector2( tdotx(p_vec), tdoty(p_vec)); } Vector2 Transform2D::basis_xform_inv(const Vector2 &p_vec) const { - return Vector2( elements[0].dot(p_vec), elements[1].dot(p_vec)); } Vector2 Transform2D::xform(const Vector2 &p_vec) const { - return Vector2( tdotx(p_vec), tdoty(p_vec)) + elements[2]; } -Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const { +Vector2 Transform2D::xform_inv(const Vector2 &p_vec) const { Vector2 v = p_vec - elements[2]; return Vector2( elements[0].dot(v), elements[1].dot(v)); } -Rect2 Transform2D::xform(const Rect2 &p_rect) const { +Rect2 Transform2D::xform(const Rect2 &p_rect) const { Vector2 x = elements[0] * p_rect.size.x; Vector2 y = elements[1] * p_rect.size.y; Vector2 pos = xform(p_rect.position); @@ -177,15 +176,20 @@ Rect2 Transform2D::xform(const Rect2 &p_rect) const { } void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) { - elements[0][0] = Math::cos(p_rot) * p_scale.x; elements[1][1] = Math::cos(p_rot) * p_scale.y; elements[1][0] = -Math::sin(p_rot) * p_scale.y; elements[0][1] = Math::sin(p_rot) * p_scale.x; } -Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const { +void Transform2D::set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, float p_skew) { + elements[0][0] = Math::cos(p_rot) * p_scale.x; + elements[1][1] = Math::cos(p_rot + p_skew) * p_scale.y; + elements[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y; + elements[0][1] = Math::sin(p_rot) * p_scale.x; +} +Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const { Vector2 ends[4] = { xform_inv(p_rect.position), xform_inv(Vector2(p_rect.position.x, p_rect.position.y + p_rect.size.y)), @@ -203,7 +207,6 @@ Rect2 Transform2D::xform_inv(const Rect2 &p_rect) const { } Vector<Vector2> Transform2D::xform(const Vector<Vector2> &p_array) const { - Vector<Vector2> array; array.resize(p_array.size()); @@ -217,7 +220,6 @@ Vector<Vector2> Transform2D::xform(const Vector<Vector2> &p_array) const { } Vector<Vector2> Transform2D::xform_inv(const Vector<Vector2> &p_array) const { - Vector<Vector2> array; array.resize(p_array.size()); diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 01d38cf24e..c9a546e385 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -33,30 +33,25 @@ #include "core/sort_array.h" int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc) { - if (p_depth > max_depth) { max_depth = p_depth; } if (p_size == 1) { - return p_bb[p_from] - p_bvh; } else if (p_size == 0) { - return -1; } AABB aabb; aabb = p_bb[p_from]->aabb; for (int i = 1; i < p_size; i++) { - aabb.merge_with(p_bb[p_from + i]->aabb); } int li = aabb.get_longest_axis_index(); switch (li) { - case Vector3::AXIS_X: { SortArray<BVH *, BVHCmpX> sort_x; sort_x.nth_element(0, p_size, p_size / 2, &p_bb[p_from]); @@ -90,9 +85,9 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in } void TriangleMesh::get_indices(Vector<int> *r_triangles_indices) const { - - if (!valid) + if (!valid) { return; + } const int triangles_num = triangles.size(); @@ -110,7 +105,6 @@ void TriangleMesh::get_indices(Vector<int> *r_triangles_indices) const { } void TriangleMesh::create(const Vector<Vector3> &p_faces) { - valid = false; int fc = p_faces.size(); @@ -122,7 +116,6 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { BVH *bw = bvh.ptrw(); { - //create faces and indices and base bvh //except for the Set for repeated triangles, everything //goes in-place. @@ -132,12 +125,10 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { Map<Vector3, int> db; for (int i = 0; i < fc; i++) { - Triangle &f = w[i]; const Vector3 *v = &r[i * 3]; for (int j = 0; j < 3; j++) { - int vidx = -1; Vector3 vs = v[j].snapped(Vector3(0.0001, 0.0001, 0.0001)); Map<Vector3, int>::Element *E = db.find(vs); @@ -149,10 +140,11 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { } f.indices[j] = vidx; - if (j == 0) + if (j == 0) { bw[i].aabb.position = vs; - else + } else { bw[i].aabb.expand_to(vs); + } } f.normal = Face3(r[i * 3 + 0], r[i * 3 + 1], r[i * 3 + 2]).get_plane().get_normal(); @@ -174,7 +166,6 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { bwptrs.resize(fc); BVH **bwp = bwptrs.ptrw(); for (int i = 0; i < fc; i++) { - bwp[i] = &bw[i]; } @@ -188,7 +179,6 @@ void TriangleMesh::create(const Vector<Vector3> &p_faces) { } Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const { - uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth); enum { @@ -215,23 +205,18 @@ Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const { stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const BVH &b = bvhptr[node]; bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - bool valid = b.aabb.intersects(p_aabb); if (!valid) { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.face_index >= 0) { - const Triangle &s = triangleptr[b.face_index]; n += s.normal; n_count++; @@ -239,49 +224,47 @@ Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const { stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node; } } continue; } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.left | TEST_AABB_BIT; level++; continue; } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.right | TEST_AABB_BIT; level++; continue; } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } - if (n_count > 0) + if (n_count > 0) { n /= n_count; + } return n; } bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { - uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth); enum { @@ -309,35 +292,28 @@ bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_en stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const BVH &b = bvhptr[node]; bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - bool valid = b.aabb.intersects_segment(p_begin, p_end); //bool valid = b.aabb.intersects(ray_aabb); if (!valid) { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.face_index >= 0) { - const Triangle &s = triangleptr[b.face_index]; Face3 f3(vertexptr[s.indices[0]], vertexptr[s.indices[1]], vertexptr[s.indices[2]]); Vector3 res; if (f3.intersects_segment(p_begin, p_end, &res)) { - real_t nd = n.dot(res); if (nd < d) { - d = nd; r_point = res; r_normal = f3.get_plane().get_normal(); @@ -348,52 +324,49 @@ bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_en stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node; } } continue; } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.left | TEST_AABB_BIT; level++; continue; } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.right | TEST_AABB_BIT; level++; continue; } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } if (inters) { - - if (n.dot(r_normal) > 0) + if (n.dot(r_normal) > 0) { r_normal = -r_normal; + } } return inters; } bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, Vector3 &r_point, Vector3 &r_normal) const { - uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth); enum { @@ -421,33 +394,26 @@ bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, V stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const BVH &b = bvhptr[node]; bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - bool valid = b.aabb.intersects_ray(p_begin, p_dir); if (!valid) { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.face_index >= 0) { - const Triangle &s = triangleptr[b.face_index]; Face3 f3(vertexptr[s.indices[0]], vertexptr[s.indices[1]], vertexptr[s.indices[2]]); Vector3 res; if (f3.intersects_ray(p_begin, p_dir, &res)) { - real_t nd = n.dot(res); if (nd < d) { - d = nd; r_point = res; r_normal = f3.get_plane().get_normal(); @@ -458,51 +424,49 @@ bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, V stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node; } } continue; } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.left | TEST_AABB_BIT; level++; continue; } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.right | TEST_AABB_BIT; level++; continue; } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } if (inters) { - - if (n.dot(r_normal) > 0) + if (n.dot(r_normal) > 0) { r_normal = -r_normal; + } } return inters; } -bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_count) const { +bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const { uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth); //p_fully_inside = true; @@ -528,23 +492,18 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const BVH &b = bvhptr[node]; bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - - bool valid = b.aabb.intersects_convex_shape(p_planes, p_plane_count); + bool valid = b.aabb.intersects_convex_shape(p_planes, p_plane_count, p_points, p_point_count); if (!valid) { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.face_index >= 0) { - const Triangle &s = triangleptr[b.face_index]; for (int j = 0; j < 3; ++j) { @@ -558,14 +517,18 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou if (p.intersects_segment(point, next_point, &res)) { bool inisde = true; for (int k = 0; k < p_plane_count; k++) { - if (k == i) continue; + if (k == i) { + continue; + } const Plane &pp = p_planes[k]; if (pp.is_point_over(res)) { inisde = false; break; } } - if (inisde) return true; + if (inisde) { + return true; + } } if (p.is_point_over(point)) { @@ -573,51 +536,51 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou break; } } - if (over) return true; + if (over) { + return true; + } } stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node; } } continue; } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.left | TEST_AABB_BIT; level++; continue; } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.right | TEST_AABB_BIT; level++; continue; } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } return false; } -bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, Vector3 p_scale) const { +bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, Vector3 p_scale) const { uint32_t *stack = (uint32_t *)alloca(sizeof(int) * max_depth); enum { @@ -643,84 +606,81 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count, stack[0] = pos; while (true) { - uint32_t node = stack[level] & NODE_IDX_MASK; const BVH &b = bvhptr[node]; bool done = false; switch (stack[level] >> VISITED_BIT_SHIFT) { case TEST_AABB_BIT: { - - bool intersects = scale.xform(b.aabb).intersects_convex_shape(p_planes, p_plane_count); - if (!intersects) return false; + bool intersects = scale.xform(b.aabb).intersects_convex_shape(p_planes, p_plane_count, p_points, p_point_count); + if (!intersects) { + return false; + } bool inside = scale.xform(b.aabb).inside_convex_shape(p_planes, p_plane_count); if (inside) { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - if (b.face_index >= 0) { const Triangle &s = triangleptr[b.face_index]; for (int j = 0; j < 3; ++j) { Vector3 point = scale.xform(vertexptr[s.indices[j]]); for (int i = 0; i < p_plane_count; i++) { const Plane &p = p_planes[i]; - if (p.is_point_over(point)) return false; + if (p.is_point_over(point)) { + return false; + } } } stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; } else { - stack[level] = (VISIT_LEFT_BIT << VISITED_BIT_SHIFT) | node; } } continue; } case VISIT_LEFT_BIT: { - stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.left | TEST_AABB_BIT; level++; continue; } case VISIT_RIGHT_BIT: { - stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node; stack[level + 1] = b.right | TEST_AABB_BIT; level++; continue; } case VISIT_DONE_BIT: { - if (level == 0) { done = true; break; - } else + } else { level--; + } continue; } } - if (done) + if (done) { break; + } } return true; } bool TriangleMesh::is_valid() const { - return valid; } Vector<Face3> TriangleMesh::get_faces() const { - - if (!valid) + if (!valid) { return Vector<Face3>(); + } Vector<Face3> faces; int ts = triangles.size(); @@ -740,7 +700,6 @@ Vector<Face3> TriangleMesh::get_faces() const { } TriangleMesh::TriangleMesh() { - valid = false; max_depth = 0; } diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h index fdbfb90465..86412cf725 100644 --- a/core/math/triangle_mesh.h +++ b/core/math/triangle_mesh.h @@ -35,11 +35,9 @@ #include "core/reference.h" class TriangleMesh : public Reference { - GDCLASS(TriangleMesh, Reference); struct Triangle { - Vector3 normal; int indices[3]; }; @@ -48,7 +46,6 @@ class TriangleMesh : public Reference { Vector<Vector3> vertices; struct BVH { - AABB aabb; Vector3 center; //used for sorting int left; @@ -58,24 +55,18 @@ class TriangleMesh : public Reference { }; struct BVHCmpX { - bool operator()(const BVH *p_left, const BVH *p_right) const { - return p_left->center.x < p_right->center.x; } }; struct BVHCmpY { - bool operator()(const BVH *p_left, const BVH *p_right) const { - return p_left->center.y < p_right->center.y; } }; struct BVHCmpZ { - bool operator()(const BVH *p_left, const BVH *p_right) const { - return p_left->center.z < p_right->center.z; } }; @@ -90,8 +81,8 @@ public: bool is_valid() const; bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const; bool intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, Vector3 &r_point, Vector3 &r_normal) const; - bool intersect_convex_shape(const Plane *p_planes, int p_plane_count) const; - bool inside_convex_shape(const Plane *p_planes, int p_plane_count, Vector3 p_scale = Vector3(1, 1, 1)) const; + bool intersect_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const; + bool inside_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, Vector3 p_scale = Vector3(1, 1, 1)) const; Vector3 get_area_normal(const AABB &p_aabb) const; Vector<Face3> get_faces() const; diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index cbcb232745..12bd384c6a 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -31,7 +31,6 @@ #include "triangulate.h" real_t Triangulate::get_area(const Vector<Vector2> &contour) { - int n = contour.size(); const Vector2 *c = &contour[0]; @@ -80,7 +79,7 @@ bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay, } else { return ((aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0)); } -}; +} bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed) { int p; @@ -103,13 +102,19 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in // To avoid that we allow zero-area triangles if all else failed. float threshold = relaxed ? -CMP_EPSILON : CMP_EPSILON; - if (threshold > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) return false; + if (threshold > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax)))) { + return false; + } for (p = 0; p < n; p++) { - if ((p == u) || (p == v) || (p == w)) continue; + if ((p == u) || (p == v) || (p == w)) { + continue; + } Px = contour[V[p]].x; Py = contour[V[p]].y; - if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py, relaxed)) return false; + if (is_inside_triangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py, relaxed)) { + return false; + } } return true; @@ -119,19 +124,24 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul /* allocate and initialize list of Vertices in polygon */ int n = contour.size(); - if (n < 3) return false; + if (n < 3) { + return false; + } Vector<int> V; V.resize(n); /* we want a counter-clockwise polygon in V */ - if (0.0 < get_area(contour)) - for (int v = 0; v < n; v++) + if (0.0 < get_area(contour)) { + for (int v = 0; v < n; v++) { V.write[v] = v; - else - for (int v = 0; v < n; v++) + } + } else { + for (int v = 0; v < n; v++) { V.write[v] = (n - 1) - v; + } + } bool relaxed = false; @@ -161,11 +171,17 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul /* three consecutive vertices in current polygon, <u,v,w> */ int u = v; - if (nv <= u) u = 0; /* previous */ + if (nv <= u) { + u = 0; /* previous */ + } v = u + 1; - if (nv <= v) v = 0; /* new v */ + if (nv <= v) { + v = 0; /* new v */ + } int w = v + 1; - if (nv <= w) w = 0; /* next */ + if (nv <= w) { + w = 0; /* next */ + } if (snip(contour, u, v, w, nv, V, relaxed)) { int a, b, c, s, t; @@ -181,8 +197,9 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &resul result.push_back(c); /* remove v from remaining polygon */ - for (s = v, t = v + 1; t < nv; s++, t++) + for (s = v, t = v + 1; t < nv; s++, t++) { V.write[s] = V[t]; + } nv--; diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index f4259e388b..233421e070 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -31,25 +31,20 @@ #include "vector2.h" real_t Vector2::angle() const { - return Math::atan2(y, x); } real_t Vector2::length() const { - return Math::sqrt(x * x + y * y); } real_t Vector2::length_squared() const { - return x * x + y * y; } void Vector2::normalize() { - real_t l = x * x + y * y; if (l != 0) { - l = Math::sqrt(l); x /= l; y /= l; @@ -57,7 +52,6 @@ void Vector2::normalize() { } Vector2 Vector2::normalized() const { - Vector2 v = *this; v.normalize(); return v; @@ -69,61 +63,51 @@ bool Vector2::is_normalized() const { } real_t Vector2::distance_to(const Vector2 &p_vector2) const { - return Math::sqrt((x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y)); } real_t Vector2::distance_squared_to(const Vector2 &p_vector2) const { - return (x - p_vector2.x) * (x - p_vector2.x) + (y - p_vector2.y) * (y - p_vector2.y); } real_t Vector2::angle_to(const Vector2 &p_vector2) const { - return Math::atan2(cross(p_vector2), dot(p_vector2)); } real_t Vector2::angle_to_point(const Vector2 &p_vector2) const { - return Math::atan2(y - p_vector2.y, x - p_vector2.x); } real_t Vector2::dot(const Vector2 &p_other) const { - return x * p_other.x + y * p_other.y; } real_t Vector2::cross(const Vector2 &p_other) const { - return x * p_other.y - y * p_other.x; } Vector2 Vector2::sign() const { - return Vector2(SGN(x), SGN(y)); } Vector2 Vector2::floor() const { - return Vector2(Math::floor(x), Math::floor(y)); } Vector2 Vector2::ceil() const { - return Vector2(Math::ceil(x), Math::ceil(y)); } Vector2 Vector2::round() const { - return Vector2(Math::round(x), Math::round(y)); } Vector2 Vector2::rotated(real_t p_by) const { - - Vector2 v; - v.set_rotation(angle() + p_by); - v *= length(); - return v; + real_t sine = Math::sin(p_by); + real_t cosi = Math::cos(p_by); + return Vector2( + x * cosi - y * sine, + x * sine + y * cosi); } Vector2 Vector2::posmod(const real_t p_mod) const { @@ -139,18 +123,15 @@ Vector2 Vector2::project(const Vector2 &p_b) const { } Vector2 Vector2::snapped(const Vector2 &p_by) const { - return Vector2( Math::stepify(x, p_by.x), Math::stepify(y, p_by.y)); } Vector2 Vector2::clamped(real_t p_len) const { - real_t l = length(); Vector2 v = *this; if (l > 0 && p_len < l) { - v /= l; v *= p_len; } @@ -159,7 +140,6 @@ Vector2 Vector2::clamped(real_t p_len) const { } Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const { - Vector2 p0 = p_pre_a; Vector2 p1 = *this; Vector2 p2 = p_b; @@ -210,65 +190,57 @@ bool Vector2::is_equal_approx(const Vector2 &p_v) const { /* Vector2i */ Vector2i Vector2i::operator+(const Vector2i &p_v) const { - return Vector2i(x + p_v.x, y + p_v.y); } -void Vector2i::operator+=(const Vector2i &p_v) { +void Vector2i::operator+=(const Vector2i &p_v) { x += p_v.x; y += p_v.y; } -Vector2i Vector2i::operator-(const Vector2i &p_v) const { +Vector2i Vector2i::operator-(const Vector2i &p_v) const { return Vector2i(x - p_v.x, y - p_v.y); } -void Vector2i::operator-=(const Vector2i &p_v) { +void Vector2i::operator-=(const Vector2i &p_v) { x -= p_v.x; y -= p_v.y; } Vector2i Vector2i::operator*(const Vector2i &p_v1) const { - return Vector2i(x * p_v1.x, y * p_v1.y); -}; +} Vector2i Vector2i::operator*(const int &rvalue) const { - return Vector2i(x * rvalue, y * rvalue); -}; -void Vector2i::operator*=(const int &rvalue) { +} +void Vector2i::operator*=(const int &rvalue) { x *= rvalue; y *= rvalue; -}; +} Vector2i Vector2i::operator/(const Vector2i &p_v1) const { - return Vector2i(x / p_v1.x, y / p_v1.y); -}; +} Vector2i Vector2i::operator/(const int &rvalue) const { - return Vector2i(x / rvalue, y / rvalue); -}; +} void Vector2i::operator/=(const int &rvalue) { - x /= rvalue; y /= rvalue; -}; +} Vector2i Vector2i::operator-() const { - return Vector2i(-x, -y); } bool Vector2i::operator==(const Vector2i &p_vec2) const { - return x == p_vec2.x && y == p_vec2.y; } -bool Vector2i::operator!=(const Vector2i &p_vec2) const { +bool Vector2i::operator!=(const Vector2i &p_vec2) const { return x != p_vec2.x || y != p_vec2.y; } diff --git a/core/math/vector2.h b/core/math/vector2.h index ba5558102f..8a08d3bf64 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -37,18 +37,17 @@ struct Vector2i; struct Vector2 { - enum Axis { AXIS_X, AXIS_Y, }; union { - real_t x; + real_t x = 0; real_t width; }; union { - real_t y; + real_t y = 0; real_t height; }; @@ -82,8 +81,7 @@ struct Vector2 { Vector2 clamped(real_t p_len) const; - _FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t); - _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2 &p_b, real_t p_t) const; + _FORCE_INLINE_ Vector2 lerp(const Vector2 &p_b, real_t p_t) const; _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_b, real_t p_t) const; Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const; @@ -123,20 +121,12 @@ struct Vector2 { real_t angle() const; - void set_rotation(real_t p_radians) { - - x = Math::cos(p_radians); - y = Math::sin(p_radians); - } - _FORCE_INLINE_ Vector2 abs() const { - return Vector2(Math::abs(x), Math::abs(y)); } Vector2 rotated(real_t p_by) const; Vector2 tangent() const { - return Vector2(y, -x); } @@ -149,89 +139,78 @@ struct Vector2 { operator String() const { return String::num(x) + ", " + String::num(y); } + _FORCE_INLINE_ Vector2() {} _FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) { x = p_x; y = p_y; } - _FORCE_INLINE_ Vector2() { x = y = 0; } }; _FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const { - return p_vec - *this * (dot(p_vec) - p_d); } _FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2 &p_vec) { - return p_vec * p_scalar; } _FORCE_INLINE_ Vector2 Vector2::operator+(const Vector2 &p_v) const { - return Vector2(x + p_v.x, y + p_v.y); } -_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) { +_FORCE_INLINE_ void Vector2::operator+=(const Vector2 &p_v) { x += p_v.x; y += p_v.y; } -_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const { +_FORCE_INLINE_ Vector2 Vector2::operator-(const Vector2 &p_v) const { return Vector2(x - p_v.x, y - p_v.y); } -_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) { +_FORCE_INLINE_ void Vector2::operator-=(const Vector2 &p_v) { x -= p_v.x; y -= p_v.y; } _FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const { - return Vector2(x * p_v1.x, y * p_v1.y); -}; +} _FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const { - return Vector2(x * rvalue, y * rvalue); -}; -_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) { +} +_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) { x *= rvalue; y *= rvalue; -}; +} _FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const { - return Vector2(x / p_v1.x, y / p_v1.y); -}; +} _FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const { - return Vector2(x / rvalue, y / rvalue); -}; +} _FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) { - x /= rvalue; y /= rvalue; -}; +} _FORCE_INLINE_ Vector2 Vector2::operator-() const { - return Vector2(-x, -y); } _FORCE_INLINE_ bool Vector2::operator==(const Vector2 &p_vec2) const { - return x == p_vec2.x && y == p_vec2.y; } -_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { +_FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { return x != p_vec2.x || y != p_vec2.y; } -Vector2 Vector2::linear_interpolate(const Vector2 &p_b, real_t p_t) const { - +Vector2 Vector2::lerp(const Vector2 &p_b, real_t p_t) const { Vector2 res = *this; res.x += (p_t * (p_b.x - x)); @@ -254,34 +233,23 @@ Vector2 Vector2::direction_to(const Vector2 &p_b) const { return ret; } -Vector2 Vector2::linear_interpolate(const Vector2 &p_a, const Vector2 &p_b, real_t p_t) { - - Vector2 res = p_a; - - res.x += (p_t * (p_b.x - p_a.x)); - res.y += (p_t * (p_b.y - p_a.y)); - - return res; -} - typedef Vector2 Size2; typedef Vector2 Point2; /* INTEGER STUFF */ struct Vector2i { - enum Axis { AXIS_X, AXIS_Y, }; union { - int x; + int x = 0; int width; }; union { - int y; + int y = 0; int height; }; @@ -324,6 +292,8 @@ struct Vector2i { operator String() const { return String::num(x) + ", " + String::num(y); } operator Vector2() const { return Vector2(x, y); } + + inline Vector2i() {} inline Vector2i(const Vector2 &p_vec2) { x = (int)p_vec2.x; y = (int)p_vec2.y; @@ -332,10 +302,6 @@ struct Vector2i { x = p_x; y = p_y; } - inline Vector2i() { - x = 0; - y = 0; - } }; typedef Vector2i Size2i; diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 353b2acd16..568df48c62 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -33,12 +33,10 @@ #include "core/math/basis.h" void Vector3::rotate(const Vector3 &p_axis, real_t p_phi) { - *this = Basis(p_axis, p_phi).xform(*this); } Vector3 Vector3::rotated(const Vector3 &p_axis, real_t p_phi) const { - Vector3 r = *this; r.rotate(p_axis, p_phi); return r; @@ -48,36 +46,33 @@ void Vector3::set_axis(int p_axis, real_t p_value) { ERR_FAIL_INDEX(p_axis, 3); coord[p_axis] = p_value; } -real_t Vector3::get_axis(int p_axis) const { +real_t Vector3::get_axis(int p_axis) const { ERR_FAIL_INDEX_V(p_axis, 3, 0); return operator[](p_axis); } int Vector3::min_axis() const { - return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2); } -int Vector3::max_axis() const { +int Vector3::max_axis() const { return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0); } void Vector3::snap(Vector3 p_val) { - x = Math::stepify(x, p_val.x); y = Math::stepify(y, p_val.y); z = Math::stepify(z, p_val.z); } -Vector3 Vector3::snapped(Vector3 p_val) const { +Vector3 Vector3::snapped(Vector3 p_val) const { Vector3 v = *this; v.snap(p_val); return v; } Vector3 Vector3::cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const { - Vector3 p0 = p_pre_a; Vector3 p1 = *this; Vector3 p2 = p_b; @@ -90,10 +85,12 @@ Vector3 Vector3::cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, real_t bc = p1.distance_to(p2); real_t cd = p2.distance_to(p3); - if (ab > 0) + if (ab > 0) { p0 = p1 + (p0 - p1) * (bc / ab); - if (cd > 0) + } + if (cd > 0) { p3 = p2 + (p3 - p2) * (bc / cd); + } } real_t t = p_t; @@ -109,7 +106,6 @@ Vector3 Vector3::cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, } Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const { - Vector3 p0 = p_pre_a; Vector3 p1 = *this; Vector3 p2 = p_b; @@ -135,7 +131,6 @@ Vector3 Vector3::move_toward(const Vector3 &p_to, const real_t p_delta) const { } Basis Vector3::outer(const Vector3 &p_b) const { - Vector3 row0(x * p_b.x, x * p_b.y, x * p_b.z); Vector3 row1(y * p_b.x, y * p_b.y, y * p_b.z); Vector3 row2(z * p_b.x, z * p_b.y, z * p_b.z); @@ -150,11 +145,9 @@ Basis Vector3::to_diagonal_matrix() const { } bool Vector3::is_equal_approx(const Vector3 &p_v) const { - return Math::is_equal_approx(x, p_v.x) && Math::is_equal_approx(y, p_v.y) && Math::is_equal_approx(z, p_v.z); } Vector3::operator String() const { - return (rtos(x) + ", " + rtos(y) + ", " + rtos(z)); } diff --git a/core/math/vector3.h b/core/math/vector3.h index 3bf8644af9..0bc1a467f2 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -38,7 +38,6 @@ class Basis; struct Vector3 { - enum Axis { AXIS_X, AXIS_Y, @@ -52,16 +51,14 @@ struct Vector3 { real_t z; }; - real_t coord[3]; + real_t coord[3] = { 0 }; }; _FORCE_INLINE_ const real_t &operator[](int p_axis) const { - return coord[p_axis]; } _FORCE_INLINE_ real_t &operator[](int p_axis) { - return coord[p_axis]; } @@ -89,7 +86,7 @@ struct Vector3 { /* Static Methods between 2 vector3s */ - _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3 &p_b, real_t p_t) const; + _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_b, real_t p_t) const; _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_b, real_t p_t) const; Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const; Vector3 cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const; @@ -152,22 +149,20 @@ struct Vector3 { return Vector3i(x, y, z); } + _FORCE_INLINE_ Vector3() {} _FORCE_INLINE_ Vector3(const Vector3i &p_ivec) { x = p_ivec.x; y = p_ivec.y; z = p_ivec.z; } - _FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) { x = p_x; y = p_y; z = p_z; } - _FORCE_INLINE_ Vector3() { x = y = z = 0; } }; Vector3 Vector3::cross(const Vector3 &p_b) const { - Vector3 ret( (y * p_b.z) - (z * p_b.y), (z * p_b.x) - (x * p_b.z), @@ -177,37 +172,30 @@ Vector3 Vector3::cross(const Vector3 &p_b) const { } real_t Vector3::dot(const Vector3 &p_b) const { - return x * p_b.x + y * p_b.y + z * p_b.z; } Vector3 Vector3::abs() const { - return Vector3(Math::abs(x), Math::abs(y), Math::abs(z)); } Vector3 Vector3::sign() const { - return Vector3(SGN(x), SGN(y), SGN(z)); } Vector3 Vector3::floor() const { - return Vector3(Math::floor(x), Math::floor(y), Math::floor(z)); } Vector3 Vector3::ceil() const { - return Vector3(Math::ceil(x), Math::ceil(y), Math::ceil(z)); } Vector3 Vector3::round() const { - return Vector3(Math::round(x), Math::round(y), Math::round(z)); } -Vector3 Vector3::linear_interpolate(const Vector3 &p_b, real_t p_t) const { - +Vector3 Vector3::lerp(const Vector3 &p_b, real_t p_t) const { return Vector3( x + (p_t * (p_b.x - x)), y + (p_t * (p_b.y - y)), @@ -220,12 +208,10 @@ Vector3 Vector3::slerp(const Vector3 &p_b, real_t p_t) const { } real_t Vector3::distance_to(const Vector3 &p_b) const { - return (p_b - *this).length(); } real_t Vector3::distance_squared_to(const Vector3 &p_b) const { - return (p_b - *this).length_squared(); } @@ -242,7 +228,6 @@ Vector3 Vector3::project(const Vector3 &p_b) const { } real_t Vector3::angle_to(const Vector3 &p_b) const { - return Math::atan2(cross(p_b).length(), dot(p_b)); } @@ -255,7 +240,6 @@ Vector3 Vector3::direction_to(const Vector3 &p_b) const { /* Operators */ Vector3 &Vector3::operator+=(const Vector3 &p_v) { - x += p_v.x; y += p_v.y; z += p_v.z; @@ -263,36 +247,32 @@ Vector3 &Vector3::operator+=(const Vector3 &p_v) { } Vector3 Vector3::operator+(const Vector3 &p_v) const { - return Vector3(x + p_v.x, y + p_v.y, z + p_v.z); } Vector3 &Vector3::operator-=(const Vector3 &p_v) { - x -= p_v.x; y -= p_v.y; z -= p_v.z; return *this; } -Vector3 Vector3::operator-(const Vector3 &p_v) const { +Vector3 Vector3::operator-(const Vector3 &p_v) const { return Vector3(x - p_v.x, y - p_v.y, z - p_v.z); } Vector3 &Vector3::operator*=(const Vector3 &p_v) { - x *= p_v.x; y *= p_v.y; z *= p_v.z; return *this; } -Vector3 Vector3::operator*(const Vector3 &p_v) const { +Vector3 Vector3::operator*(const Vector3 &p_v) const { return Vector3(x * p_v.x, y * p_v.y, z * p_v.z); } Vector3 &Vector3::operator/=(const Vector3 &p_v) { - x /= p_v.x; y /= p_v.y; z /= p_v.z; @@ -300,12 +280,10 @@ Vector3 &Vector3::operator/=(const Vector3 &p_v) { } Vector3 Vector3::operator/(const Vector3 &p_v) const { - return Vector3(x / p_v.x, y / p_v.y, z / p_v.z); } Vector3 &Vector3::operator*=(real_t p_scalar) { - x *= p_scalar; y *= p_scalar; z *= p_scalar; @@ -313,17 +291,14 @@ Vector3 &Vector3::operator*=(real_t p_scalar) { } _FORCE_INLINE_ Vector3 operator*(real_t p_scalar, const Vector3 &p_vec) { - return p_vec * p_scalar; } Vector3 Vector3::operator*(real_t p_scalar) const { - return Vector3(x * p_scalar, y * p_scalar, z * p_scalar); } Vector3 &Vector3::operator/=(real_t p_scalar) { - x /= p_scalar; y /= p_scalar; z /= p_scalar; @@ -331,85 +306,78 @@ Vector3 &Vector3::operator/=(real_t p_scalar) { } Vector3 Vector3::operator/(real_t p_scalar) const { - return Vector3(x / p_scalar, y / p_scalar, z / p_scalar); } Vector3 Vector3::operator-() const { - return Vector3(-x, -y, -z); } bool Vector3::operator==(const Vector3 &p_v) const { - return x == p_v.x && y == p_v.y && z == p_v.z; } bool Vector3::operator!=(const Vector3 &p_v) const { - return x != p_v.x || y != p_v.y || z != p_v.z; } bool Vector3::operator<(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) + if (Math::is_equal_approx(y, p_v.y)) { return z < p_v.z; - else + } else { return y < p_v.y; + } } else { return x < p_v.x; } } bool Vector3::operator>(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) + if (Math::is_equal_approx(y, p_v.y)) { return z > p_v.z; - else + } else { return y > p_v.y; + } } else { return x > p_v.x; } } bool Vector3::operator<=(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) + if (Math::is_equal_approx(y, p_v.y)) { return z <= p_v.z; - else + } else { return y < p_v.y; + } } else { return x < p_v.x; } } bool Vector3::operator>=(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) + if (Math::is_equal_approx(y, p_v.y)) { return z >= p_v.z; - else + } else { return y > p_v.y; + } } else { return x > p_v.x; } } _FORCE_INLINE_ Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) { - return p_a.cross(p_b); } _FORCE_INLINE_ real_t vec3_dot(const Vector3 &p_a, const Vector3 &p_b) { - return p_a.dot(p_b); } real_t Vector3::length() const { - real_t x2 = x * x; real_t y2 = y * y; real_t z2 = z * z; @@ -418,7 +386,6 @@ real_t Vector3::length() const { } real_t Vector3::length_squared() const { - real_t x2 = x * x; real_t y2 = y * y; real_t z2 = z * z; @@ -427,7 +394,6 @@ real_t Vector3::length_squared() const { } void Vector3::normalize() { - real_t lengthsq = length_squared(); if (lengthsq == 0) { x = y = z = 0; @@ -440,7 +406,6 @@ void Vector3::normalize() { } Vector3 Vector3::normalized() const { - Vector3 v = *this; v.normalize(); return v; @@ -452,12 +417,10 @@ bool Vector3::is_normalized() const { } Vector3 Vector3::inverse() const { - return Vector3(1.0 / x, 1.0 / y, 1.0 / z); } void Vector3::zero() { - x = y = z = 0; } diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp index 8a4ddf03b9..718a1553a0 100644 --- a/core/math/vector3i.cpp +++ b/core/math/vector3i.cpp @@ -34,22 +34,20 @@ void Vector3i::set_axis(int p_axis, int32_t p_value) { ERR_FAIL_INDEX(p_axis, 3); coord[p_axis] = p_value; } -int32_t Vector3i::get_axis(int p_axis) const { +int32_t Vector3i::get_axis(int p_axis) const { ERR_FAIL_INDEX_V(p_axis, 3, 0); return operator[](p_axis); } int Vector3i::min_axis() const { - return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2); } -int Vector3i::max_axis() const { +int Vector3i::max_axis() const { return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0); } Vector3i::operator String() const { - return (itos(x) + ", " + itos(y) + ", " + itos(z)); } diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 6f9754d3b9..08729ad056 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -35,7 +35,6 @@ #include "core/ustring.h" struct Vector3i { - enum Axis { AXIS_X, AXIS_Y, @@ -49,16 +48,14 @@ struct Vector3i { int32_t z; }; - int32_t coord[3]; + int32_t coord[3] = { 0 }; }; _FORCE_INLINE_ const int32_t &operator[](int p_axis) const { - return coord[p_axis]; } _FORCE_INLINE_ int32_t &operator[](int p_axis) { - return coord[p_axis]; } @@ -100,28 +97,25 @@ struct Vector3i { operator String() const; + _FORCE_INLINE_ Vector3i() {} _FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) { x = p_x; y = p_y; z = p_z; } - _FORCE_INLINE_ Vector3i() { x = y = z = 0; } }; Vector3i Vector3i::abs() const { - return Vector3i(ABS(x), ABS(y), ABS(z)); } Vector3i Vector3i::sign() const { - return Vector3i(SGN(x), SGN(y), SGN(z)); } /* Operators */ Vector3i &Vector3i::operator+=(const Vector3i &p_v) { - x += p_v.x; y += p_v.y; z += p_v.z; @@ -129,36 +123,32 @@ Vector3i &Vector3i::operator+=(const Vector3i &p_v) { } Vector3i Vector3i::operator+(const Vector3i &p_v) const { - return Vector3i(x + p_v.x, y + p_v.y, z + p_v.z); } Vector3i &Vector3i::operator-=(const Vector3i &p_v) { - x -= p_v.x; y -= p_v.y; z -= p_v.z; return *this; } -Vector3i Vector3i::operator-(const Vector3i &p_v) const { +Vector3i Vector3i::operator-(const Vector3i &p_v) const { return Vector3i(x - p_v.x, y - p_v.y, z - p_v.z); } Vector3i &Vector3i::operator*=(const Vector3i &p_v) { - x *= p_v.x; y *= p_v.y; z *= p_v.z; return *this; } -Vector3i Vector3i::operator*(const Vector3i &p_v) const { +Vector3i Vector3i::operator*(const Vector3i &p_v) const { return Vector3i(x * p_v.x, y * p_v.y, z * p_v.z); } Vector3i &Vector3i::operator/=(const Vector3i &p_v) { - x /= p_v.x; y /= p_v.y; z /= p_v.z; @@ -166,12 +156,10 @@ Vector3i &Vector3i::operator/=(const Vector3i &p_v) { } Vector3i Vector3i::operator/(const Vector3i &p_v) const { - return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z); } Vector3i &Vector3i::operator*=(int32_t p_scalar) { - x *= p_scalar; y *= p_scalar; z *= p_scalar; @@ -179,17 +167,14 @@ Vector3i &Vector3i::operator*=(int32_t p_scalar) { } _FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vec) { - return p_vec * p_scalar; } Vector3i Vector3i::operator*(int32_t p_scalar) const { - return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar); } Vector3i &Vector3i::operator/=(int32_t p_scalar) { - x /= p_scalar; y /= p_scalar; z /= p_scalar; @@ -197,75 +182,70 @@ Vector3i &Vector3i::operator/=(int32_t p_scalar) { } Vector3i Vector3i::operator/(int32_t p_scalar) const { - return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar); } Vector3i Vector3i::operator-() const { - return Vector3i(-x, -y, -z); } bool Vector3i::operator==(const Vector3i &p_v) const { - return (x == p_v.x && y == p_v.y && z == p_v.z); } bool Vector3i::operator!=(const Vector3i &p_v) const { - return (x != p_v.x || y != p_v.y || z != p_v.z); } bool Vector3i::operator<(const Vector3i &p_v) const { - if (x == p_v.x) { - if (y == p_v.y) + if (y == p_v.y) { return z < p_v.z; - else + } else { return y < p_v.y; + } } else { return x < p_v.x; } } bool Vector3i::operator>(const Vector3i &p_v) const { - if (x == p_v.x) { - if (y == p_v.y) + if (y == p_v.y) { return z > p_v.z; - else + } else { return y > p_v.y; + } } else { return x > p_v.x; } } bool Vector3i::operator<=(const Vector3i &p_v) const { - if (x == p_v.x) { - if (y == p_v.y) + if (y == p_v.y) { return z <= p_v.z; - else + } else { return y < p_v.y; + } } else { return x < p_v.x; } } bool Vector3i::operator>=(const Vector3i &p_v) const { - if (x == p_v.x) { - if (y == p_v.y) + if (y == p_v.y) { return z >= p_v.z; - else + } else { return y > p_v.y; + } } else { return x > p_v.x; } } void Vector3i::zero() { - x = y = z = 0; } diff --git a/core/message_queue.cpp b/core/message_queue.cpp index 652c424492..6dcf24e7ed 100644 --- a/core/message_queue.cpp +++ b/core/message_queue.cpp @@ -37,24 +37,22 @@ MessageQueue *MessageQueue::singleton = nullptr; MessageQueue *MessageQueue::get_singleton() { - return singleton; } Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, const Variant **p_args, int p_argcount, bool p_show_error) { - return push_callable(Callable(p_id, p_method), p_args, p_argcount, p_show_error); } Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -62,15 +60,15 @@ Error MessageQueue::push_call(ObjectID p_id, const StringName &p_method, VARIANT } Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value) { - _THREAD_SAFE_METHOD_ uint8_t room_needed = sizeof(Message) + sizeof(Variant); if ((buffer_end + room_needed) >= buffer_size) { String type; - if (ObjectDB::get_instance(p_id)) + if (ObjectDB::get_instance(p_id)) { type = ObjectDB::get_instance(p_id)->get_class(); + } print_line("Failed set: " + type + ":" + p_prop + " target ID: " + itos(p_id)); statistics(); ERR_FAIL_V_MSG(ERR_OUT_OF_MEMORY, "Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_kb' in project settings."); @@ -91,7 +89,6 @@ Error MessageQueue::push_set(ObjectID p_id, const StringName &p_prop, const Vari } Error MessageQueue::push_notification(ObjectID p_id, int p_notification) { - _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(p_notification < 0, ERR_INVALID_PARAMETER); @@ -117,21 +114,18 @@ Error MessageQueue::push_notification(ObjectID p_id, int p_notification) { } Error MessageQueue::push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { - return push_call(p_object->get_instance_id(), p_method, VARIANT_ARG_PASS); } Error MessageQueue::push_notification(Object *p_object, int p_notification) { - return push_notification(p_object->get_instance_id(), p_notification); } -Error MessageQueue::push_set(Object *p_object, const StringName &p_prop, const Variant &p_value) { +Error MessageQueue::push_set(Object *p_object, const StringName &p_prop, const Variant &p_value) { return push_set(p_object->get_instance_id(), p_prop, p_value); } Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error) { - _THREAD_SAFE_METHOD_ int room_needed = sizeof(Message) + sizeof(Variant) * p_argcount; @@ -146,13 +140,13 @@ Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_ msg->args = p_argcount; msg->callable = p_callable; msg->type = TYPE_CALL; - if (p_show_error) + if (p_show_error) { msg->type |= FLAG_SHOW_ERROR; + } buffer_end += sizeof(Message); for (int i = 0; i < p_argcount; i++) { - Variant *v = memnew_placement(&buffer[buffer_end], Variant); buffer_end += sizeof(Variant); *v = *p_args[i]; @@ -161,8 +155,22 @@ Error MessageQueue::push_callable(const Callable &p_callable, const Variant **p_ return OK; } -void MessageQueue::statistics() { +Error MessageQueue::push_callable(const Callable &p_callable, VARIANT_ARG_DECLARE) { + VARIANT_ARGPTRS; + + int argc = 0; + for (int i = 0; i < VARIANT_ARG_MAX; i++) { + if (argptr[i]->get_type() == Variant::NIL) { + break; + } + argc++; + } + + return push_callable(p_callable, argptr, argc); +} + +void MessageQueue::statistics() { Map<StringName, int> set_count; Map<int, int> notify_count; Map<Callable, int> call_count; @@ -175,30 +183,28 @@ void MessageQueue::statistics() { Object *target = message->callable.get_object(); if (target != nullptr) { - switch (message->type & FLAG_MASK) { - case TYPE_CALL: { - - if (!call_count.has(message->callable)) + if (!call_count.has(message->callable)) { call_count[message->callable] = 0; + } call_count[message->callable]++; } break; case TYPE_NOTIFICATION: { - - if (!notify_count.has(message->notification)) + if (!notify_count.has(message->notification)) { notify_count[message->notification] = 0; + } notify_count[message->notification]++; } break; case TYPE_SET: { - StringName t = message->callable.get_method(); - if (!set_count.has(t)) + if (!set_count.has(t)) { set_count[t] = 0; + } set_count[t]++; @@ -213,8 +219,9 @@ void MessageQueue::statistics() { } read_pos += sizeof(Message); - if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) + if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) { read_pos += sizeof(Variant) * message->args; + } } print_line("TOTAL BYTES: " + itos(buffer_end)); @@ -234,12 +241,10 @@ void MessageQueue::statistics() { } int MessageQueue::get_max_buffer_usage() const { - return buffer_max_used; } void MessageQueue::_call_function(const Callable &p_callable, const Variant *p_args, int p_argcount, bool p_show_error) { - const Variant **argptrs = nullptr; if (p_argcount) { argptrs = (const Variant **)alloca(sizeof(Variant *) * p_argcount); @@ -252,13 +257,11 @@ void MessageQueue::_call_function(const Callable &p_callable, const Variant *p_a Variant ret; p_callable.call(argptrs, p_argcount, ret, ce); if (p_show_error && ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT("Error calling deferred method: " + Variant::get_callable_error_text(p_callable, argptrs, p_argcount, ce) + "."); } } void MessageQueue::flush() { - if (buffer_end > buffer_max_used) { buffer_max_used = buffer_end; } @@ -275,14 +278,14 @@ void MessageQueue::flush() { flushing = true; while (read_pos < buffer_end) { - //lock on each iteration, so a call can re-add itself to the message queue Message *message = (Message *)&buffer[read_pos]; uint32_t advance = sizeof(Message); - if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) + if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) { advance += sizeof(Variant) * message->args; + } //pre-advance so this function is reentrant read_pos += advance; @@ -292,10 +295,8 @@ void MessageQueue::flush() { Object *target = message->callable.get_object(); if (target != nullptr) { - switch (message->type & FLAG_MASK) { case TYPE_CALL: { - Variant *args = (Variant *)(message + 1); // messages don't expect a return value @@ -304,13 +305,11 @@ void MessageQueue::flush() { } break; case TYPE_NOTIFICATION: { - // messages don't expect a return value target->notification(message->notification); } break; case TYPE_SET: { - Variant *arg = (Variant *)(message + 1); // messages don't expect a return value target->set(message->callable.get_method(), *arg); @@ -337,18 +336,13 @@ void MessageQueue::flush() { } bool MessageQueue::is_flushing() const { - return flushing; } MessageQueue::MessageQueue() { - ERR_FAIL_COND_MSG(singleton != nullptr, "A MessageQueue singleton already exists."); singleton = this; - flushing = false; - buffer_end = 0; - buffer_max_used = 0; buffer_size = GLOBAL_DEF_RST("memory/limits/message_queue/max_size_kb", DEFAULT_QUEUE_SIZE_KB); ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/message_queue/max_size_kb", PropertyInfo(Variant::INT, "memory/limits/message_queue/max_size_kb", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater")); buffer_size *= 1024; @@ -356,23 +350,23 @@ MessageQueue::MessageQueue() { } MessageQueue::~MessageQueue() { - uint32_t read_pos = 0; while (read_pos < buffer_end) { - Message *message = (Message *)&buffer[read_pos]; Variant *args = (Variant *)(message + 1); int argc = message->args; if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) { - for (int i = 0; i < argc; i++) + for (int i = 0; i < argc; i++) { args[i].~Variant(); + } } message->~Message(); read_pos += sizeof(Message); - if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) + if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) { read_pos += sizeof(Variant) * message->args; + } } singleton = nullptr; diff --git a/core/message_queue.h b/core/message_queue.h index 9ba748bb42..7d13e26208 100644 --- a/core/message_queue.h +++ b/core/message_queue.h @@ -35,7 +35,6 @@ #include "core/os/thread_safe.h" class MessageQueue { - _THREAD_SAFE_CLASS_ enum { @@ -53,7 +52,6 @@ class MessageQueue { }; struct Message { - Callable callable; int16_t type; union { @@ -63,15 +61,15 @@ class MessageQueue { }; uint8_t *buffer; - uint32_t buffer_end; - uint32_t buffer_max_used; + uint32_t buffer_end = 0; + uint32_t buffer_max_used = 0; uint32_t buffer_size; void _call_function(const Callable &p_callable, const Variant *p_args, int p_argcount, bool p_show_error); static MessageQueue *singleton; - bool flushing; + bool flushing = false; public: static MessageQueue *get_singleton(); @@ -81,6 +79,7 @@ public: Error push_notification(ObjectID p_id, int p_notification); Error push_set(ObjectID p_id, const StringName &p_prop, const Variant &p_value); Error push_callable(const Callable &p_callable, const Variant **p_args, int p_argcount, bool p_show_error = false); + Error push_callable(const Callable &p_callable, VARIANT_ARG_LIST); Error push_call(Object *p_object, const StringName &p_method, VARIANT_ARG_LIST); Error push_notification(Object *p_object, int p_notification); diff --git a/core/method_bind.cpp b/core/method_bind.cpp index c513de9ca0..3244c63292 100644 --- a/core/method_bind.cpp +++ b/core/method_bind.cpp @@ -36,7 +36,6 @@ #ifdef DEBUG_METHODS_ENABLED PropertyInfo MethodBind::get_argument_info(int p_argument) const { - ERR_FAIL_INDEX_V(p_argument, get_argument_count(), PropertyInfo()); PropertyInfo info = _gen_argument_type_info(p_argument); @@ -45,35 +44,32 @@ PropertyInfo MethodBind::get_argument_info(int p_argument) const { } PropertyInfo MethodBind::get_return_info() const { - return _gen_argument_type_info(-1); } #endif void MethodBind::_set_const(bool p_const) { - _const = p_const; } void MethodBind::_set_returns(bool p_returns) { - _returns = p_returns; } StringName MethodBind::get_name() const { return name; } + void MethodBind::set_name(const StringName &p_name) { name = p_name; } #ifdef DEBUG_METHODS_ENABLED void MethodBind::set_argument_names(const Vector<StringName> &p_names) { - arg_names = p_names; } -Vector<StringName> MethodBind::get_argument_names() const { +Vector<StringName> MethodBind::get_argument_names() const { return arg_names; } @@ -86,7 +82,6 @@ void MethodBind::set_default_arguments(const Vector<Variant> &p_defargs) { #ifdef DEBUG_METHODS_ENABLED void MethodBind::_generate_argument_types(int p_count) { - set_argument_count(p_count); Variant::Type *argt = memnew_arr(Variant::Type, p_count + 1); @@ -104,19 +99,12 @@ void MethodBind::_generate_argument_types(int p_count) { MethodBind::MethodBind() { static int last_id = 0; method_id = last_id++; - hint_flags = METHOD_FLAGS_DEFAULT; - argument_count = 0; - default_argument_count = 0; -#ifdef DEBUG_METHODS_ENABLED - argument_types = nullptr; -#endif - _const = false; - _returns = false; } MethodBind::~MethodBind() { #ifdef DEBUG_METHODS_ENABLED - if (argument_types) + if (argument_types) { memdelete_arr(argument_types); + } #endif } diff --git a/core/method_bind.h b/core/method_bind.h index 588b472b62..ff2c771f81 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -39,6 +39,7 @@ #include "core/method_ptrcall.h" #include "core/object.h" #include "core/type_info.h" +#include "core/typedefs.h" #include "core/variant.h" #include <stdio.h> @@ -58,27 +59,21 @@ enum MethodFlags { template <class T> struct VariantCaster { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; } }; template <class T> struct VariantCaster<T &> { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; } }; template <class T> struct VariantCaster<const T &> { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; } }; @@ -92,7 +87,6 @@ struct VariantCaster<const T &> { MAKE_ENUM_TYPE_INFO(m_enum) \ template <> \ struct VariantCaster<m_enum> { \ - \ static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ return (m_enum)p_variant.operator int(); \ } \ @@ -113,7 +107,6 @@ struct VariantCaster<const T &> { MAKE_ENUM_TYPE_INFO(m_enum) \ template <> \ struct VariantCaster<m_enum> { \ - \ static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ return (m_enum)p_variant.operator int(); \ } \ @@ -164,7 +157,9 @@ struct VariantObjectClassChecker<Control *> { #define CHECK_NOARG(m_arg) \ { \ if (p_arg##m_arg.get_type() != Variant::NIL) { \ - if (r_argerror) *r_argerror = (m_arg - 1); \ + if (r_argerror) { \ + *r_argerror = (m_arg - 1); \ + } \ return CALL_ERROR_EXTRA_ARGUMENT; \ } \ } @@ -204,20 +199,19 @@ struct PtrToArg<wchar_t> { #endif class MethodBind { - int method_id; - uint32_t hint_flags; + uint32_t hint_flags = METHOD_FLAGS_DEFAULT; StringName name; Vector<Variant> default_arguments; - int default_argument_count; - int argument_count; + int default_argument_count = 0; + int argument_count = 0; - bool _const; - bool _returns; + bool _const = false; + bool _returns = false; protected: #ifdef DEBUG_METHODS_ENABLED - Variant::Type *argument_types; + Variant::Type *argument_types = nullptr; Vector<StringName> arg_names; #endif void _set_const(bool p_const); @@ -235,29 +229,28 @@ public: _FORCE_INLINE_ int get_default_argument_count() const { return default_argument_count; } _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { - int idx = argument_count - p_arg - 1; - if (idx < 0 || idx >= default_arguments.size()) + if (idx < 0 || idx >= default_arguments.size()) { return false; - else + } else { return true; + } } _FORCE_INLINE_ Variant get_default_argument(int p_arg) const { - int idx = argument_count - p_arg - 1; - if (idx < 0 || idx >= default_arguments.size()) + if (idx < 0 || idx >= default_arguments.size()) { return Variant(); - else + } else { return default_arguments[idx]; + } } #ifdef DEBUG_METHODS_ENABLED _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { - ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); return argument_types[p_argument + 1]; } @@ -302,17 +295,15 @@ public: typedef Variant (T::*NativeCall)(const Variant **, int, Callable::CallError &); protected: - NativeCall call_method; + NativeCall call_method = nullptr; #ifdef DEBUG_METHODS_ENABLED - MethodInfo arguments; - #endif + public: #ifdef DEBUG_METHODS_ENABLED virtual PropertyInfo _gen_argument_type_info(int p_arg) const { - if (p_arg < 0) { return arguments.return_val; } else if (p_arg < arguments.arguments.size()) { @@ -338,23 +329,19 @@ public: #endif virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - T *instance = static_cast<T *>(p_object); return (instance->*call_method)(p_args, p_arg_count, r_error); } void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) { - set_argument_count(p_info.arguments.size()); #ifdef DEBUG_METHODS_ENABLED Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1); at[0] = p_info.return_val.type; if (p_info.arguments.size()) { - Vector<StringName> names; names.resize(p_info.arguments.size()); for (int i = 0; i < p_info.arguments.size(); i++) { - at[i + 1] = p_info.arguments[i].type; names.write[i] = p_info.arguments[i].name; } @@ -382,14 +369,12 @@ public: virtual bool is_vararg() const { return true; } MethodBindVarArg() { - call_method = nullptr; _set_returns(true); } }; template <class T> MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { - MethodBindVarArg<T> *a = memnew((MethodBindVarArg<T>)); a->set_method(p_method); a->set_method_info(p_info, p_return_nil_is_variant); diff --git a/core/method_ptrcall.h b/core/method_ptrcall.h index 7ae0a788bd..022ed2a5d6 100644 --- a/core/method_ptrcall.h +++ b/core/method_ptrcall.h @@ -150,28 +150,22 @@ MAKE_PTRARG_BY_REFERENCE(Variant); template <class T> struct PtrToArg<T *> { - _FORCE_INLINE_ static T *convert(const void *p_ptr) { - return const_cast<T *>(reinterpret_cast<const T *>(p_ptr)); } _FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) { - *((T **)p_ptr) = p_var; } }; template <class T> struct PtrToArg<const T *> { - _FORCE_INLINE_ static const T *convert(const void *p_ptr) { - return reinterpret_cast<const T *>(p_ptr); } _FORCE_INLINE_ static void encode(T *p_var, void *p_ptr) { - *((T **)p_ptr) = p_var; } }; @@ -181,12 +175,10 @@ struct PtrToArg<const T *> { template <> struct PtrToArg<ObjectID> { _FORCE_INLINE_ static const ObjectID convert(const void *p_ptr) { - return ObjectID(*reinterpret_cast<const uint64_t *>(p_ptr)); } _FORCE_INLINE_ static void encode(const ObjectID &p_val, void *p_ptr) { - *((uint64_t *)p_ptr) = p_val; } }; diff --git a/core/node_path.cpp b/core/node_path.cpp index 83233622a0..2a51dca74a 100644 --- a/core/node_path.cpp +++ b/core/node_path.cpp @@ -33,7 +33,6 @@ #include "core/print_string.h" void NodePath::_update_hash_cache() const { - uint32_t h = data->absolute ? 1 : 0; int pc = data->path.size(); const StringName *sn = data->path.ptr(); @@ -51,7 +50,6 @@ void NodePath::_update_hash_cache() const { } void NodePath::prepend_period() { - if (data->path.size() && data->path[0].operator String() != ".") { data->path.insert(0, "."); data->hash_cache_valid = false; @@ -59,59 +57,60 @@ void NodePath::prepend_period() { } bool NodePath::is_absolute() const { - - if (!data) + if (!data) { return false; + } return data->absolute; } -int NodePath::get_name_count() const { - if (!data) +int NodePath::get_name_count() const { + if (!data) { return 0; + } return data->path.size(); } -StringName NodePath::get_name(int p_idx) const { +StringName NodePath::get_name(int p_idx) const { ERR_FAIL_COND_V(!data, StringName()); ERR_FAIL_INDEX_V(p_idx, data->path.size(), StringName()); return data->path[p_idx]; } int NodePath::get_subname_count() const { - - if (!data) + if (!data) { return 0; + } return data->subpath.size(); } -StringName NodePath::get_subname(int p_idx) const { +StringName NodePath::get_subname(int p_idx) const { ERR_FAIL_COND_V(!data, StringName()); ERR_FAIL_INDEX_V(p_idx, data->subpath.size(), StringName()); return data->subpath[p_idx]; } void NodePath::unref() { - if (data && data->refcount.unref()) { - memdelete(data); } data = nullptr; } bool NodePath::operator==(const NodePath &p_path) const { - - if (data == p_path.data) + if (data == p_path.data) { return true; + } - if (!data || !p_path.data) + if (!data || !p_path.data) { return false; + } - if (data->absolute != p_path.data->absolute) + if (data->absolute != p_path.data->absolute) { return false; + } int path_size = data->path.size(); @@ -129,85 +128,74 @@ bool NodePath::operator==(const NodePath &p_path) const { const StringName *r_path_ptr = p_path.data->path.ptr(); for (int i = 0; i < path_size; i++) { - - if (l_path_ptr[i] != r_path_ptr[i]) + if (l_path_ptr[i] != r_path_ptr[i]) { return false; + } } const StringName *l_subpath_ptr = data->subpath.ptr(); const StringName *r_subpath_ptr = p_path.data->subpath.ptr(); for (int i = 0; i < subpath_size; i++) { - - if (l_subpath_ptr[i] != r_subpath_ptr[i]) + if (l_subpath_ptr[i] != r_subpath_ptr[i]) { return false; + } } return true; } -bool NodePath::operator!=(const NodePath &p_path) const { +bool NodePath::operator!=(const NodePath &p_path) const { return (!(*this == p_path)); } void NodePath::operator=(const NodePath &p_path) { - - if (this == &p_path) + if (this == &p_path) { return; + } unref(); if (p_path.data && p_path.data->refcount.ref()) { - data = p_path.data; } } NodePath::operator String() const { - - if (!data) + if (!data) { return String(); + } String ret; - if (data->absolute) + if (data->absolute) { ret = "/"; + } for (int i = 0; i < data->path.size(); i++) { - - if (i > 0) + if (i > 0) { ret += "/"; + } ret += data->path[i].operator String(); } for (int i = 0; i < data->subpath.size(); i++) { - ret += ":" + data->subpath[i].operator String(); } return ret; } -NodePath::NodePath(const NodePath &p_path) { - - data = nullptr; - - if (p_path.data && p_path.data->refcount.ref()) { - - data = p_path.data; - } -} - Vector<StringName> NodePath::get_names() const { - - if (data) + if (data) { return data->path; + } return Vector<StringName>(); } Vector<StringName> NodePath::get_subnames() const { - - if (data) + if (data) { return data->subpath; + } return Vector<StringName>(); } @@ -227,7 +215,6 @@ StringName NodePath::get_concatenated_subnames() const { } NodePath NodePath::rel_path_to(const NodePath &p_np) const { - ERR_FAIL_COND_V(!is_absolute(), NodePath()); ERR_FAIL_COND_V(!p_np.is_absolute(), NodePath()); @@ -238,12 +225,15 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const { int common_parent = 0; while (true) { - if (src_dirs.size() == common_parent) + if (src_dirs.size() == common_parent) { break; - if (dst_dirs.size() == common_parent) + } + if (dst_dirs.size() == common_parent) { break; - if (src_dirs[common_parent] != dst_dirs[common_parent]) + } + if (src_dirs[common_parent] != dst_dirs[common_parent]) { break; + } common_parent++; } @@ -252,23 +242,21 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const { Vector<StringName> relpath; for (int i = src_dirs.size() - 1; i > common_parent; i--) { - relpath.push_back(".."); } for (int i = common_parent + 1; i < dst_dirs.size(); i++) { - relpath.push_back(dst_dirs[i]); } - if (relpath.size() == 0) + if (relpath.size() == 0) { relpath.push_back("."); + } return NodePath(relpath, p_np.get_subnames(), false); } NodePath NodePath::get_as_property_path() const { - if (!data || !data->path.size()) { return *this; } else { @@ -285,44 +273,18 @@ NodePath NodePath::get_as_property_path() const { } } -NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) { - - data = nullptr; - - if (p_path.size() == 0) - return; - - data = memnew(Data); - data->refcount.init(); - data->absolute = p_absolute; - data->path = p_path; - data->has_slashes = true; - data->hash_cache_valid = false; -} - -NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute) { - - data = nullptr; - - if (p_path.size() == 0 && p_subpath.size() == 0) - return; - - data = memnew(Data); - data->refcount.init(); - data->absolute = p_absolute; - data->path = p_path; - data->subpath = p_subpath; - data->has_slashes = true; - data->hash_cache_valid = false; +bool NodePath::is_empty() const { + return !data; } void NodePath::simplify() { - - if (!data) + if (!data) { return; + } for (int i = 0; i < data->path.size(); i++) { - if (data->path.size() == 1) + if (data->path.size() == 1) { break; + } if (data->path[i].operator String() == ".") { data->path.remove(i); i--; @@ -341,18 +303,48 @@ void NodePath::simplify() { } NodePath NodePath::simplified() const { - NodePath np = *this; np.simplify(); return np; } -NodePath::NodePath(const String &p_path) { +NodePath::NodePath(const Vector<StringName> &p_path, bool p_absolute) { + if (p_path.size() == 0) { + return; + } - data = nullptr; + data = memnew(Data); + data->refcount.init(); + data->absolute = p_absolute; + data->path = p_path; + data->has_slashes = true; + data->hash_cache_valid = false; +} - if (p_path.length() == 0) +NodePath::NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute) { + if (p_path.size() == 0 && p_subpath.size() == 0) { return; + } + + data = memnew(Data); + data->refcount.init(); + data->absolute = p_absolute; + data->path = p_path; + data->subpath = p_subpath; + data->has_slashes = true; + data->hash_cache_valid = false; +} + +NodePath::NodePath(const NodePath &p_path) { + if (p_path.data && p_path.data->refcount.ref()) { + data = p_path.data; + } +} + +NodePath::NodePath(const String &p_path) { + if (p_path.length() == 0) { + return; + } String path = p_path; Vector<StringName> subpath; @@ -364,16 +356,15 @@ NodePath::NodePath(const String &p_path) { int subpath_pos = path.find(":"); if (subpath_pos != -1) { - int from = subpath_pos + 1; for (int i = from; i <= path.length(); i++) { - if (path[i] == ':' || path[i] == 0) { - String str = path.substr(from, i - from); if (str == "") { - if (path[i] == 0) continue; // Allow end-of-path : + if (path[i] == 0) { + continue; // Allow end-of-path : + } ERR_FAIL_MSG("Invalid NodePath '" + p_path + "'."); } @@ -387,22 +378,21 @@ NodePath::NodePath(const String &p_path) { } for (int i = (int)absolute; i < path.length(); i++) { - if (path[i] == '/') { - last_is_slash = true; has_slashes = true; } else { - - if (last_is_slash) + if (last_is_slash) { slices++; + } last_is_slash = false; } } - if (slices == 0 && !absolute && !subpath.size()) + if (slices == 0 && !absolute && !subpath.size()) { return; + } data = memnew(Data); data->refcount.init(); @@ -411,19 +401,17 @@ NodePath::NodePath(const String &p_path) { data->subpath = subpath; data->hash_cache_valid = false; - if (slices == 0) + if (slices == 0) { return; + } data->path.resize(slices); last_is_slash = true; int from = (int)absolute; int slice = 0; for (int i = (int)absolute; i < path.length() + 1; i++) { - if (path[i] == '/' || path[i] == 0) { - if (!last_is_slash) { - String name = path.substr(from, i - from); ERR_FAIL_INDEX(slice, data->path.size()); data->path.write[slice++] = name; @@ -436,16 +424,6 @@ NodePath::NodePath(const String &p_path) { } } -bool NodePath::is_empty() const { - - return !data; -} -NodePath::NodePath() { - - data = nullptr; -} - NodePath::~NodePath() { - unref(); } diff --git a/core/node_path.h b/core/node_path.h index 76de36cd9f..7c06bf01ce 100644 --- a/core/node_path.h +++ b/core/node_path.h @@ -35,9 +35,7 @@ #include "core/ustring.h" class NodePath { - struct Data { - SafeRefCount refcount; Vector<StringName> path; Vector<StringName> subpath; @@ -48,7 +46,7 @@ class NodePath { mutable uint32_t hash_cache; }; - mutable Data *data; + mutable Data *data = nullptr; void unref(); void _update_hash_cache() const; @@ -71,8 +69,9 @@ public: NodePath get_parent() const; _FORCE_INLINE_ uint32_t hash() const { - if (!data) + if (!data) { return 0; + } if (!data->hash_cache_valid) { _update_hash_cache(); } @@ -93,7 +92,7 @@ public: NodePath(const Vector<StringName> &p_path, const Vector<StringName> &p_subpath, bool p_absolute); NodePath(const NodePath &p_path); NodePath(const String &p_path); - NodePath(); + NodePath() {} ~NodePath(); }; diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index 71e3ba9068..775e17fdb5 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -45,20 +45,24 @@ * * The entries are stored inplace, so huge keys or values might fill cache lines * a lot faster. + * + * Only used keys and values are constructed. For free positions there's space + * in the arrays for each, but that memory is kept uninitialized. + * + * The assignment operator copy the pairs from one map to the other. */ template <class TKey, class TValue, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>> class OAHashMap { - private: - TValue *values; - TKey *keys; - uint32_t *hashes; + TValue *values = nullptr; + TKey *keys = nullptr; + uint32_t *hashes = nullptr; - uint32_t capacity; + uint32_t capacity = 0; - uint32_t num_elements; + uint32_t num_elements = 0; static const uint32_t EMPTY_HASH = 0; @@ -90,7 +94,7 @@ private: uint32_t pos = hash % capacity; uint32_t distance = 0; - while (42) { + while (true) { if (hashes[pos] == EMPTY_HASH) { return false; } @@ -110,7 +114,6 @@ private: } void _insert_with_hash(uint32_t p_hash, const TKey &p_key, const TValue &p_value) { - uint32_t hash = p_hash; uint32_t distance = 0; uint32_t pos = hash % capacity; @@ -118,7 +121,7 @@ private: TKey key = p_key; TValue value = p_value; - while (42) { + while (true) { if (hashes[pos] == EMPTY_HASH) { _construct(pos, hash, key, value); @@ -140,34 +143,43 @@ private: } void _resize_and_rehash(uint32_t p_new_capacity) { - uint32_t old_capacity = capacity; - capacity = p_new_capacity; + + // Capacity can't be 0. + capacity = MAX(1, p_new_capacity); TKey *old_keys = keys; TValue *old_values = values; uint32_t *old_hashes = hashes; num_elements = 0; - keys = memnew_arr(TKey, capacity); - values = memnew_arr(TValue, capacity); - hashes = memnew_arr(uint32_t, capacity); + keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity)); + values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity)); + hashes = static_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity)); for (uint32_t i = 0; i < capacity; i++) { hashes[i] = 0; } + if (old_capacity == 0) { + // Nothing to do. + return; + } + for (uint32_t i = 0; i < old_capacity; i++) { if (old_hashes[i] == EMPTY_HASH) { continue; } _insert_with_hash(old_hashes[i], old_keys[i], old_values[i]); + + old_keys[i].~TKey(); + old_values[i].~TValue(); } - memdelete_arr(old_keys); - memdelete_arr(old_values); - memdelete_arr(old_hashes); + Memory::free_static(old_keys); + Memory::free_static(old_values); + Memory::free_static(old_hashes); } void _resize_and_rehash() { @@ -183,9 +195,7 @@ public: } void clear() { - for (uint32_t i = 0; i < capacity; i++) { - if (hashes[i] == EMPTY_HASH) { continue; } @@ -199,7 +209,6 @@ public: } void insert(const TKey &p_key, const TValue &p_value) { - if (num_elements + 1 > 0.9 * capacity) { _resize_and_rehash(); } @@ -214,8 +223,7 @@ public: bool exists = _lookup_pos(p_key, pos); if (exists) { - values[pos].~TValue(); - memnew_placement(&values[pos], TValue(p_data)); + values[pos] = p_data; } else { insert(p_key, p_data); } @@ -232,8 +240,7 @@ public: bool exists = _lookup_pos(p_key, pos); if (exists) { - r_data.~TValue(); - memnew_placement(&r_data, TValue(values[pos])); + r_data = values[pos]; return true; } @@ -300,7 +307,7 @@ public: bool valid; const TKey *key; - const TValue *value; + TValue *value; private: uint32_t pos; @@ -317,7 +324,6 @@ public: } Iterator next_iter(const Iterator &p_iter) const { - if (!p_iter.valid) { return p_iter; } @@ -344,28 +350,49 @@ public: return it; } - OAHashMap(const OAHashMap &) = delete; // Delete the copy constructor so we don't get unexpected copies and dangling pointers. - OAHashMap &operator=(const OAHashMap &) = delete; // Same for assignment operator. + OAHashMap(const OAHashMap &p_other) { + (*this) = p_other; + } - OAHashMap(uint32_t p_initial_capacity = 64) { + OAHashMap &operator=(const OAHashMap &p_other) { + if (capacity != 0) { + clear(); + } - capacity = p_initial_capacity; - num_elements = 0; + _resize_and_rehash(p_other.capacity); + + for (Iterator it = p_other.iter(); it.valid; it = p_other.next_iter(it)) { + set(*it.key, *it.value); + } + return *this; + } - keys = memnew_arr(TKey, p_initial_capacity); - values = memnew_arr(TValue, p_initial_capacity); - hashes = memnew_arr(uint32_t, p_initial_capacity); + OAHashMap(uint32_t p_initial_capacity = 64) { + // Capacity can't be 0. + capacity = MAX(1, p_initial_capacity); + + keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity)); + values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity)); + hashes = static_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity)); - for (uint32_t i = 0; i < p_initial_capacity; i++) { + for (uint32_t i = 0; i < capacity; i++) { hashes[i] = EMPTY_HASH; } } ~OAHashMap() { + for (uint32_t i = 0; i < capacity; i++) { + if (hashes[i] == EMPTY_HASH) { + continue; + } + + values[i].~TValue(); + keys[i].~TKey(); + } - memdelete_arr(keys); - memdelete_arr(values); - memdelete_arr(hashes); + Memory::free_static(keys); + Memory::free_static(values); + Memory::free_static(hashes); } }; diff --git a/core/object.cpp b/core/object.cpp index b0e6f2bdae..8abea9ca7e 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -42,7 +42,6 @@ #ifdef DEBUG_ENABLED struct _ObjectDebugLock { - Object *obj; _ObjectDebugLock(Object *p_obj) { @@ -63,7 +62,6 @@ struct _ObjectDebugLock { #endif PropertyInfo::operator Dictionary() const { - Dictionary d; d["name"] = name; d["class_name"] = class_name; @@ -75,36 +73,38 @@ PropertyInfo::operator Dictionary() const { } PropertyInfo PropertyInfo::from_dict(const Dictionary &p_dict) { - PropertyInfo pi; - if (p_dict.has("type")) + if (p_dict.has("type")) { pi.type = Variant::Type(int(p_dict["type"])); + } - if (p_dict.has("name")) + if (p_dict.has("name")) { pi.name = p_dict["name"]; + } - if (p_dict.has("class_name")) + if (p_dict.has("class_name")) { pi.class_name = p_dict["class_name"]; + } - if (p_dict.has("hint")) + if (p_dict.has("hint")) { pi.hint = PropertyHint(int(p_dict["hint"])); + } - if (p_dict.has("hint_string")) - + if (p_dict.has("hint_string")) { pi.hint_string = p_dict["hint_string"]; + } - if (p_dict.has("usage")) + if (p_dict.has("usage")) { pi.usage = p_dict["usage"]; + } return pi; } Array convert_property_list(const List<PropertyInfo> *p_list) { - Array va; for (const List<PropertyInfo>::Element *E = p_list->front(); E; E = E->next()) { - va.push_back(Dictionary(E->get())); } @@ -112,13 +112,13 @@ Array convert_property_list(const List<PropertyInfo> *p_list) { } MethodInfo::operator Dictionary() const { - Dictionary d; d["name"] = name; d["args"] = convert_property_list(&arguments); Array da; - for (int i = 0; i < default_arguments.size(); i++) + for (int i = 0; i < default_arguments.size(); i++) { da.push_back(default_arguments[i]); + } d["default_args"] = da; d["flags"] = flags; d["id"] = id; @@ -127,17 +127,12 @@ MethodInfo::operator Dictionary() const { return d; } -MethodInfo::MethodInfo() : - flags(METHOD_FLAG_NORMAL), - id(0) { -} - MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) { - MethodInfo mi; - if (p_dict.has("name")) + if (p_dict.has("name")) { mi.name = p_dict["name"]; + } Array args; if (p_dict.has("args")) { args = p_dict["args"]; @@ -159,35 +154,37 @@ MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) { mi.return_val = PropertyInfo::from_dict(p_dict["return"]); } - if (p_dict.has("flags")) + if (p_dict.has("flags")) { mi.flags = p_dict["flags"]; + } return mi; } +MethodInfo::MethodInfo() : + flags(METHOD_FLAG_NORMAL) {} + MethodInfo::MethodInfo(const String &p_name) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { } + MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); } + MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); } MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -195,8 +192,7 @@ MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -205,8 +201,7 @@ MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const MethodInfo::MethodInfo(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), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -215,28 +210,26 @@ MethodInfo::MethodInfo(const String &p_name, const PropertyInfo &p_param1, const } MethodInfo::MethodInfo(Variant::Type ret) : - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; } MethodInfo::MethodInfo(Variant::Type ret, const String &p_name) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; } + MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; arguments.push_back(p_param1); } + MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; arguments.push_back(p_param1); arguments.push_back(p_param2); @@ -244,8 +237,7 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; arguments.push_back(p_param1); arguments.push_back(p_param2); @@ -254,8 +246,7 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; arguments.push_back(p_param1); arguments.push_back(p_param2); @@ -265,8 +256,7 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn MethodInfo::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) : name(p_name), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { return_val.type = ret; arguments.push_back(p_param1); arguments.push_back(p_param2); @@ -278,23 +268,20 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name) : name(p_name), return_val(p_ret), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { } 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) { + flags(METHOD_FLAG_NORMAL) { 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) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); } @@ -302,8 +289,7 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) : name(p_name), return_val(p_ret), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -312,8 +298,7 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) : name(p_name), return_val(p_ret), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -323,8 +308,7 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) : name(p_name), return_val(p_ret), - flags(METHOD_FLAG_NORMAL), - id(0) { + flags(METHOD_FLAG_NORMAL) { arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -333,7 +317,6 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr } Object::Connection::operator Variant() const { - Dictionary d; d["signal"] = signal; d["callable"] = callable; @@ -343,28 +326,30 @@ Object::Connection::operator Variant() const { } bool Object::Connection::operator<(const Connection &p_conn) const { - if (signal == p_conn.signal) { return callable < p_conn.callable; } else { return signal < p_conn.signal; } } -Object::Connection::Connection(const Variant &p_variant) { +Object::Connection::Connection(const Variant &p_variant) { Dictionary d = p_variant; - if (d.has("signal")) + if (d.has("signal")) { signal = d["signal"]; - if (d.has("callable")) + } + if (d.has("callable")) { callable = d["callable"]; - if (d.has("flags")) + } + if (d.has("flags")) { flags = d["flags"]; - if (d.has("binds")) + } + if (d.has("binds")) { binds = d["binds"]; + } } bool Object::_predelete() { - _predelete_ok = 1; notification(NOTIFICATION_PREDELETE, true); if (_predelete_ok) { @@ -381,21 +366,21 @@ void Object::_postinitialize() { void Object::get_valid_parents_static(List<String> *p_parents) { } + void Object::_get_valid_parents_static(List<String> *p_parents) { } void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid) { - #ifdef TOOLS_ENABLED _edited = true; #endif if (script_instance) { - if (script_instance->set(p_name, p_value)) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return; } } @@ -413,23 +398,26 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid if (p_name == CoreStringNames::get_singleton()->_script) { set_script(p_value); - if (r_valid) + if (r_valid) { *r_valid = true; + } return; } else if (p_name == CoreStringNames::get_singleton()->_meta) { //set_meta(p_name,p_value); metadata = p_value.duplicate(); - if (r_valid) + if (r_valid) { *r_valid = true; + } return; } //something inside the object... :| bool success = _setv(p_name, p_value); if (success) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return; } @@ -437,8 +425,9 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid bool valid; setvar(p_name, p_value, &valid); if (valid) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return; } } @@ -448,26 +437,27 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid bool valid; script_instance->property_set_fallback(p_name, p_value, &valid); if (valid) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return; } } #endif - if (r_valid) + if (r_valid) { *r_valid = false; + } } Variant Object::get(const StringName &p_name, bool *r_valid) const { - Variant ret; if (script_instance) { - if (script_instance->get(p_name, ret)) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } } @@ -475,30 +465,34 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { //try built-in setgetter { if (ClassDB::get_property(const_cast<Object *>(this), p_name, ret)) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } } if (p_name == CoreStringNames::get_singleton()->_script) { ret = get_script(); - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } else if (p_name == CoreStringNames::get_singleton()->_meta) { ret = metadata; - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } else { //something inside the object... :| bool success = _getv(p_name, ret); if (success) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } @@ -507,8 +501,9 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { bool valid; ret = getvar(p_name, &valid); if (valid) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } } @@ -518,23 +513,26 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { bool valid; ret = script_instance->property_get_fallback(p_name, &valid); if (valid) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return ret; } } #endif - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant(); } } void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid) { if (p_names.empty()) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return; } if (p_names.size() == 1) { @@ -543,7 +541,9 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val } bool valid = false; - if (!r_valid) r_valid = &valid; + if (!r_valid) { + r_valid = &valid; + } List<Variant> value_stack; @@ -566,7 +566,6 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val value_stack.push_back(p_value); // p_names[p_names.size() - 1] for (int i = p_names.size() - 1; i > 0; i--) { - value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), r_valid); value_stack.pop_back(); @@ -584,8 +583,9 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) const { if (p_names.empty()) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant(); } bool valid = false; @@ -594,17 +594,18 @@ Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) co for (int i = 1; i < p_names.size(); i++) { current_value = current_value.get_named(p_names[i], &valid); - if (!valid) + if (!valid) { break; + } } - if (r_valid) + if (r_valid) { *r_valid = valid; + } return current_value; } void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) const { - if (script_instance && p_reversed) { p_list->push_back(PropertyInfo(Variant::NIL, "Script Variables", PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); script_instance->get_property_list(p_list); @@ -631,7 +632,6 @@ void Object::_validate_property(PropertyInfo &property) const { } void Object::get_method_list(List<MethodInfo> *p_list) const { - ClassDB::get_method_list(get_class_name(), p_list); if (script_instance) { script_instance->get_method_list(p_list); @@ -639,7 +639,6 @@ void Object::get_method_list(List<MethodInfo> *p_list) const { } Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 0; @@ -659,7 +658,6 @@ Variant Object::_call_bind(const Variant **p_args, int p_argcount, Callable::Cal } Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 0; @@ -684,24 +682,19 @@ Variant Object::_call_deferred_bind(const Variant **p_args, int p_argcount, Call #ifdef DEBUG_ENABLED static void _test_call_error(const StringName &p_func, const Callable::CallError &error) { - switch (error.error) { - case Callable::CallError::CALL_OK: case Callable::CallError::CALL_ERROR_INVALID_METHOD: break; case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { - ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Invalid type for argument " + itos(error.argument) + ", expected " + Variant::get_type_name(Variant::Type(error.expected)) + "."); break; } case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { - ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too many arguments, expected " + itos(error.argument) + "."); break; } case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: { - ERR_FAIL_MSG("Error calling function: " + String(p_func) + " - Too few arguments, expected " + itos(error.argument) + "."); break; } @@ -716,7 +709,6 @@ static void _test_call_error(const StringName &p_func, const Callable::CallError #endif void Object::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) { - if (p_method == CoreStringNames::get_singleton()->_free) { #ifdef DEBUG_ENABLED ERR_FAIL_COND_MSG(Object::cast_to<Reference>(this), "Can't 'free' a reference."); @@ -742,21 +734,18 @@ void Object::call_multilevel(const StringName &p_method, const Variant **p_args, MethodBind *method = ClassDB::get_method(get_class_name(), p_method); if (method) { - method->call(this, p_args, p_argcount, error); _test_call_error(p_method, error); } } void Object::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) { - MethodBind *method = ClassDB::get_method(get_class_name(), p_method); Callable::CallError error; OBJ_DEBUG_LOCK if (method) { - method->call(this, p_args, p_argcount, error); _test_call_error(p_method, error); } @@ -770,7 +759,6 @@ void Object::call_multilevel_reversed(const StringName &p_method, const Variant } bool Object::has_method(const StringName &p_method) const { - if (p_method == CoreStringNames::get_singleton()->_free) { return true; } @@ -785,15 +773,16 @@ bool Object::has_method(const StringName &p_method) const { } Variant Object::getvar(const Variant &p_key, bool *r_valid) const { - - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant(); } -void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) { - if (r_valid) +void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) { + if (r_valid) { *r_valid = false; + } } Variant Object::callv(const StringName &p_method, const Array &p_args) { @@ -815,13 +804,13 @@ Variant Object::callv(const StringName &p_method, const Array &p_args) { } Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -832,13 +821,13 @@ Variant Object::call(const StringName &p_name, VARIANT_ARG_DECLARE) { } void Object::call_multilevel(const StringName &p_name, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -847,7 +836,6 @@ void Object::call_multilevel(const StringName &p_name, VARIANT_ARG_DECLARE) { } Variant Object::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_OK; if (p_method == CoreStringNames::get_singleton()->_free) { @@ -883,7 +871,6 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a ret = script_instance->call(p_method, p_args, p_argcount, r_error); //force jumptable switch (r_error.error) { - case Callable::CallError::CALL_OK: return ret; case Callable::CallError::CALL_ERROR_INVALID_METHOD: @@ -909,7 +896,6 @@ Variant Object::call(const StringName &p_method, const Variant **p_args, int p_a } void Object::notification(int p_notification, bool p_reversed) { - _notificationv(p_notification, p_reversed); if (script_instance) { @@ -921,8 +907,9 @@ String Object::to_string() { if (script_instance) { bool valid; String ret = script_instance->to_string(&valid); - if (valid) + if (valid) { return ret; + } } return "[" + get_class() + ":" + itos(get_instance_id()) + "]"; } @@ -931,27 +918,22 @@ void Object::_changed_callback(Object *p_changed, const char *p_prop) { } void Object::add_change_receptor(Object *p_receptor) { - change_receptors.insert(p_receptor); } void Object::remove_change_receptor(Object *p_receptor) { - change_receptors.erase(p_receptor); } void Object::property_list_changed_notify() { - _change_notify(); } void Object::cancel_delete() { - _predelete_ok = true; } void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) { - //this function is not meant to be used in any of these ways ERR_FAIL_COND(p_script.is_null()); ERR_FAIL_COND(!p_instance); @@ -962,9 +944,9 @@ void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_ } void Object::set_script(const Variant &p_script) { - - if (script == p_script) + if (script == p_script) { return; + } if (script_instance) { memdelete(script_instance); @@ -989,43 +971,41 @@ void Object::set_script(const Variant &p_script) { } void Object::set_script_instance(ScriptInstance *p_instance) { - - if (script_instance == p_instance) + if (script_instance == p_instance) { return; + } - if (script_instance) + if (script_instance) { memdelete(script_instance); + } script_instance = p_instance; - if (p_instance) + if (p_instance) { script = p_instance->get_script(); - else + } else { script = Variant(); + } } Variant Object::get_script() const { - return script; } bool Object::has_meta(const String &p_name) const { - return metadata.has(p_name); } void Object::set_meta(const String &p_name, const Variant &p_value) { - if (p_value.get_type() == Variant::NIL) { metadata.erase(p_name); return; - }; + } metadata[p_name] = p_value; } Variant Object::get_meta(const String &p_name) const { - ERR_FAIL_COND_V(!metadata.has(p_name), Variant()); return metadata[p_name]; } @@ -1035,20 +1015,17 @@ void Object::remove_meta(const String &p_name) { } Array Object::_get_property_list_bind() const { - List<PropertyInfo> lpi; get_property_list(&lpi); return convert_property_list(&lpi); } Array Object::_get_method_list_bind() const { - List<MethodInfo> ml; get_method_list(&ml); Array ret; for (List<MethodInfo>::Element *E = ml.front(); E; E = E->next()) { - Dictionary d = E->get(); //va.push_back(d); ret.push_back(d); @@ -1058,30 +1035,26 @@ Array Object::_get_method_list_bind() const { } Vector<String> Object::_get_meta_list_bind() const { - Vector<String> _metaret; List<Variant> keys; metadata.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - _metaret.push_back(E->get()); } return _metaret; } -void Object::get_meta_list(List<String> *p_list) const { +void Object::get_meta_list(List<String> *p_list) const { List<Variant> keys; metadata.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - p_list->push_back(E->get()); } } void Object::add_user_signal(const MethodInfo &p_signal) { - ERR_FAIL_COND_MSG(p_signal.name == "", "Signal name cannot be empty."); ERR_FAIL_COND_MSG(ClassDB::has_signal(get_class_name(), p_signal.name), "User signal's name conflicts with a built-in signal of '" + get_class_name() + "'."); ERR_FAIL_COND_MSG(signal_map.has(p_signal.name), "Trying to add already existing signal '" + p_signal.name + "'."); @@ -1091,20 +1064,18 @@ void Object::add_user_signal(const MethodInfo &p_signal) { } bool Object::_has_user_signal(const StringName &p_name) const { - - if (!signal_map.has(p_name)) + if (!signal_map.has(p_name)) { return false; + } return signal_map[p_name].user.name.length() > 0; } struct _ObjectSignalDisconnectData { - StringName signal; Callable callable; }; Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; ERR_FAIL_COND_V(p_argcount < 1, Variant()); @@ -1132,9 +1103,9 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Callable::C } Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) { - - if (_block_signals) + if (_block_signals) { return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked + } SignalData *s = signal_map.getptr(p_name); if (!s) { @@ -1163,7 +1134,6 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int Error err = OK; for (int i = 0; i < ssize; i++) { - const Connection &c = slot_map.getv(i).conn; Object *target = c.callable.get_object(); @@ -1201,8 +1171,9 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int if (ce.error != Callable::CallError::CALL_OK) { #ifdef DEBUG_ENABLED - if (c.flags & CONNECT_PERSIST && Engine::get_singleton()->is_editor_hint() && (script.is_null() || !Ref<Script>(script)->is_tool())) + if (c.flags & CONNECT_PERSIST && Engine::get_singleton()->is_editor_hint() && (script.is_null() || !Ref<Script>(script)->is_tool())) { continue; + } #endif if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD && !ClassDB::class_exists(target->get_class_name())) { //most likely object is not initialized yet, do not throw error. @@ -1221,7 +1192,6 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int } #endif if (disconnect) { - _ObjectSignalDisconnectData dd; dd.signal = p_name; dd.callable = c.callable; @@ -1230,7 +1200,6 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int } while (!disconnect_data.empty()) { - const _ObjectSignalDisconnectData &dd = disconnect_data.front()->get(); _disconnect(dd.signal, dd.callable); @@ -1241,15 +1210,14 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int } Error Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -1257,7 +1225,6 @@ Error Object::emit_signal(const StringName &p_name, VARIANT_ARG_DECLARE) { } void Object::_add_user_signal(const String &p_name, const Array &p_args) { - // this version of add_user_signal is meant to be used from scripts or external apis // without access to ADD_SIGNAL in bind_methods // added events are per instance, as opposed to the other ones, which are global @@ -1266,14 +1233,15 @@ void Object::_add_user_signal(const String &p_name, const Array &p_args) { mi.name = p_name; for (int i = 0; i < p_args.size(); i++) { - Dictionary d = p_args[i]; PropertyInfo param; - if (d.has("name")) + if (d.has("name")) { param.name = d["name"]; - if (d.has("type")) + } + if (d.has("type")) { param.type = (Variant::Type)(int)d["type"]; + } mi.arguments.push_back(param); } @@ -1282,13 +1250,11 @@ void Object::_add_user_signal(const String &p_name, const Array &p_args) { } Array Object::_get_signal_list() const { - List<MethodInfo> signal_list; get_signal_list(&signal_list); Array ret; for (List<MethodInfo>::Element *E = signal_list.front(); E; E = E->next()) { - ret.push_back(Dictionary(E->get())); } @@ -1296,14 +1262,12 @@ Array Object::_get_signal_list() const { } Array Object::_get_signal_connection_list(const String &p_signal) const { - List<Connection> conns; get_all_signal_connections(&conns); Array ret; for (List<Connection>::Element *E = conns.front(); E; E = E->next()) { - Connection &c = E->get(); if (c.signal.get_name() == p_signal) { ret.push_back(c); @@ -1314,7 +1278,6 @@ Array Object::_get_signal_connection_list(const String &p_signal) const { } Array Object::_get_incoming_connections() const { - Array ret; int connections_amount = connections.size(); for (int idx_conn = 0; idx_conn < connections_amount; idx_conn++) { @@ -1344,7 +1307,6 @@ bool Object::has_signal(const StringName &p_name) const { } void Object::get_signal_list(List<MethodInfo> *p_signals) const { - if (!script.is_null()) { Ref<Script> scr = script; if (scr.is_valid()) { @@ -1357,7 +1319,6 @@ void Object::get_signal_list(List<MethodInfo> *p_signals) const { const StringName *S = nullptr; while ((S = signal_map.next(S))) { - if (signal_map[*S].user.name != "") { //user signal p_signals->push_back(signal_map[*S].user); @@ -1366,37 +1327,33 @@ void Object::get_signal_list(List<MethodInfo> *p_signals) const { } void Object::get_all_signal_connections(List<Connection> *p_connections) const { - const StringName *S = nullptr; while ((S = signal_map.next(S))) { - const SignalData *s = &signal_map[*S]; for (int i = 0; i < s->slot_map.size(); i++) { - p_connections->push_back(s->slot_map.getv(i).conn); } } } void Object::get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const { - const SignalData *s = signal_map.getptr(p_signal); - if (!s) + if (!s) { return; //nothing + } - for (int i = 0; i < s->slot_map.size(); i++) + for (int i = 0; i < s->slot_map.size(); i++) { p_connections->push_back(s->slot_map.getv(i).conn); + } } int Object::get_persistent_signal_connection_count() const { - int count = 0; const StringName *S = nullptr; while ((S = signal_map.next(S))) { - const SignalData *s = &signal_map[*S]; for (int i = 0; i < s->slot_map.size(); i++) { @@ -1410,18 +1367,16 @@ int Object::get_persistent_signal_connection_count() const { } void Object::get_signals_connected_to_this(List<Connection> *p_connections) const { - for (const List<Connection>::Element *E = connections.front(); E; E = E->next()) { p_connections->push_back(E->get()); } } Error Object::connect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds, uint32_t p_flags) { - return connect(p_signal, Callable(p_to_object, p_to_method), p_binds, p_flags); } -Error Object::connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) { +Error Object::connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) { ERR_FAIL_COND_V(p_callable.is_null(), ERR_INVALID_PARAMETER); Object *target_object = p_callable.get_object(); @@ -1432,7 +1387,6 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, co bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal); //check in script if (!signal_is_valid && !script.is_null()) { - if (Ref<Script>(script)->has_script_signal(p_signal)) { signal_is_valid = true; } @@ -1482,21 +1436,21 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, co } bool Object::is_connected_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const { - return is_connected(p_signal, Callable(p_to_object, p_to_method)); } bool Object::is_connected(const StringName &p_signal, const Callable &p_callable) const { - ERR_FAIL_COND_V(p_callable.is_null(), false); const SignalData *s = signal_map.getptr(p_signal); if (!s) { bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal); - if (signal_is_valid) + if (signal_is_valid) { return false; + } - if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) + if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) { return false; + } ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + "."); } @@ -1509,7 +1463,6 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable } void Object::disconnect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) { - _disconnect(p_signal, Callable(p_to_object, p_to_method)); } @@ -1518,7 +1471,6 @@ void Object::disconnect(const StringName &p_signal, const Callable &p_callable) } void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, bool p_force) { - ERR_FAIL_COND(p_callable.is_null()); Object *target_object = p_callable.get_object(); @@ -1548,65 +1500,60 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, } void Object::_set_bind(const String &p_set, const Variant &p_value) { - set(p_set, p_value); } Variant Object::_get_bind(const String &p_name) const { - return get(p_name); } void Object::_set_indexed_bind(const NodePath &p_name, const Variant &p_value) { - set_indexed(p_name.get_as_property_path().get_subnames(), p_value); } Variant Object::_get_indexed_bind(const NodePath &p_name) const { - return get_indexed(p_name.get_as_property_path().get_subnames()); } void Object::initialize_class() { - static bool initialized = false; - if (initialized) + if (initialized) { return; + } ClassDB::_add_class<Object>(); _bind_methods(); initialized = true; } StringName Object::tr(const StringName &p_message) const { - - if (!_can_translate || !TranslationServer::get_singleton()) + if (!_can_translate || !TranslationServer::get_singleton()) { return p_message; + } return TranslationServer::get_singleton()->translate(p_message); } void Object::_clear_internal_resource_paths(const Variant &p_var) { - switch (p_var.get_type()) { - case Variant::OBJECT: { - RES r = p_var; - if (!r.is_valid()) + if (!r.is_valid()) { return; + } - if (!r->get_path().begins_with("res://") || r->get_path().find("::") == -1) + if (!r->get_path().begins_with("res://") || r->get_path().find("::") == -1) { return; //not an internal resource + } Object *object = p_var; - if (!object) + if (!object) { return; + } r->set_path(""); r->clear_internal_resource_paths(); } break; case Variant::ARRAY: { - Array a = p_var; for (int i = 0; i < a.size(); i++) { _clear_internal_resource_paths(a[i]); @@ -1614,13 +1561,11 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) { } break; case Variant::DICTIONARY: { - Dictionary d = p_var; List<Variant> keys; d.get_key_list(&keys); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - _clear_internal_resource_paths(E->get()); _clear_internal_resource_paths(d[E->get()]); } @@ -1632,35 +1577,31 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) { #ifdef TOOLS_ENABLED void Object::editor_set_section_unfold(const String &p_section, bool p_unfolded) { - set_edited(true); - if (p_unfolded) + if (p_unfolded) { editor_section_folding.insert(p_section); - else + } else { editor_section_folding.erase(p_section); + } } bool Object::editor_is_section_unfolded(const String &p_section) { - return editor_section_folding.has(p_section); } #endif void Object::clear_internal_resource_paths() { - List<PropertyInfo> pinfo; get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - _clear_internal_resource_paths(get(E->get().name)); } } void Object::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_class"), &Object::get_class); ClassDB::bind_method(D_METHOD("is_class", "class"), &Object::is_class); ClassDB::bind_method(D_METHOD("set", "property", "value"), &Object::_set_bind); @@ -1765,7 +1706,6 @@ void Object::_bind_methods() { } void Object::call_deferred(const StringName &p_method, VARIANT_ARG_DECLARE) { - MessageQueue::get_singleton()->push_call(this, p_method, VARIANT_ARG_PASS); } @@ -1774,58 +1714,57 @@ void Object::set_deferred(const StringName &p_property, const Variant &p_value) } void Object::set_block_signals(bool p_block) { - _block_signals = p_block; } bool Object::is_blocking_signals() const { - return _block_signals; } void Object::get_translatable_strings(List<String> *p_strings) const { - List<PropertyInfo> plist; get_property_list(&plist); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_INTERNATIONALIZED)) + if (!(E->get().usage & PROPERTY_USAGE_INTERNATIONALIZED)) { continue; + } String text = get(E->get().name); - if (text == "") + if (text == "") { continue; + } p_strings->push_back(text); } } Variant::Type Object::get_static_property_type(const StringName &p_property, bool *r_valid) const { - bool valid; Variant::Type t = ClassDB::get_property_type(get_class_name(), p_property, &valid); if (valid) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return t; } if (get_script_instance()) { return get_script_instance()->get_property_type(p_property, r_valid); } - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant::NIL; } Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> &p_path, bool *r_valid) const { - if (p_path.size() == 0) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant::NIL; } @@ -1833,8 +1772,9 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> bool valid = false; Variant::Type t = get_static_property_type(p_path[0], &valid); if (!valid) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant::NIL; } @@ -1845,22 +1785,25 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> for (int i = 1; i < p_path.size(); i++) { if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) { // We cannot be sure about the type of properties this types can have - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant::NIL; } check = check.get_named(p_path[i], &valid); if (!valid) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant::NIL; } } - if (r_valid) + if (r_valid) { *r_valid = true; + } return check.get_type(); } @@ -1871,18 +1814,15 @@ bool Object::is_queued_for_deletion() const { #ifdef TOOLS_ENABLED void Object::set_edited(bool p_edited) { - _edited = p_edited; _edited_version++; } bool Object::is_edited() const { - return _edited; } uint32_t Object::get_edited_version() const { - return _edited_version; } #endif @@ -1909,7 +1849,6 @@ void *Object::get_script_instance_binding(int p_script_language_index) { } bool Object::has_script_instance_binding(int p_script_language_index) { - return _script_instance_bindings[p_script_language_index] != nullptr; } @@ -1922,39 +1861,26 @@ void Object::set_script_instance_binding(int p_script_language_index, void *p_da void Object::_construct_object(bool p_reference) { type_is_reference = p_reference; - _class_ptr = nullptr; - _block_signals = false; - _predelete_ok = 0; _instance_id = ObjectDB::add_instance(this); - _can_translate = true; - _is_queued_for_deletion = false; - _emitting = false; - instance_binding_count = 0; memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS); - script_instance = nullptr; -#ifdef TOOLS_ENABLED - - _edited = false; - _edited_version = 0; -#endif #ifdef DEBUG_ENABLED _lock_index.init(1); #endif } + Object::Object(bool p_reference) { _construct_object(p_reference); } Object::Object() { - _construct_object(false); } Object::~Object() { - - if (script_instance) + if (script_instance) { memdelete(script_instance); + } script_instance = nullptr; const StringName *S = nullptr; @@ -1965,7 +1891,6 @@ Object::~Object() { } while ((S = signal_map.next(nullptr))) { - SignalData *s = &signal_map[*S]; //brute force disconnect for performance @@ -1973,7 +1898,6 @@ Object::~Object() { const VMap<Callable, SignalData::Slot>::Pair *slot_list = s->slot_map.get_array(); for (int i = 0; i < slot_count; i++) { - slot_list[i].value.conn.callable.get_object()->connections.erase(slot_list[i].value.cE); } @@ -1982,7 +1906,6 @@ Object::~Object() { //signals from nodes that connect to this node while (connections.size()) { - Connection c = connections.front()->get(); c.signal.get_object()->_disconnect(c.signal.get_name(), c.callable, true); } @@ -2001,17 +1924,14 @@ Object::~Object() { } bool predelete_handler(Object *p_object) { - return p_object->_predelete(); } void postinitialize_handler(Object *p_object) { - p_object->_postinitialize(); } void ObjectDB::debug_objects(DebugFunc p_func) { - spin_lock.lock(); for (uint32_t i = 0; i < slot_count; i++) { uint32_t slot = object_slots[i].next_free; @@ -2030,15 +1950,12 @@ ObjectDB::ObjectSlot *ObjectDB::object_slots = nullptr; uint64_t ObjectDB::validator_counter = 0; int ObjectDB::get_object_count() { - return slot_count; } ObjectID ObjectDB::add_instance(Object *p_object) { - spin_lock.lock(); if (unlikely(slot_count == slot_max)) { - CRASH_COND(slot_count == (1 << OBJECTDB_SLOT_MAX_COUNT_BITS)); uint32_t new_slot_max = slot_max > 0 ? slot_max * 2 : 1; @@ -2114,30 +2031,38 @@ void ObjectDB::remove_instance(Object *p_object) { } void ObjectDB::setup() { - //nothing to do now } void ObjectDB::cleanup() { - if (slot_count > 0) { spin_lock.lock(); - WARN_PRINT("ObjectDB Instances still exist!"); + WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details)."); if (OS::get_singleton()->is_stdout_verbose()) { + // Ensure calling the native classes because if a leaked instance has a script + // that overrides any of those methods, it'd not be OK to call them at this point, + // now the scripting languages have already been terminated. + MethodBind *node_get_name = ClassDB::get_method("Node", "get_name"); + MethodBind *resource_get_path = ClassDB::get_method("Resource", "get_path"); + Callable::CallError call_error; + for (uint32_t i = 0; i < slot_count; i++) { uint32_t slot = object_slots[i].next_free; Object *obj = object_slots[slot].object; - String node_name; - if (obj->is_class("Node")) - node_name = " - Node name: " + String(obj->call("get_name")); - if (obj->is_class("Resource")) - node_name = " - Resource name: " + String(obj->call("get_name")) + " Path: " + String(obj->call("get_path")); + String extra_info; + if (obj->is_class("Node")) { + extra_info = " - Node name: " + String(node_get_name->call(obj, nullptr, 0, call_error)); + } + if (obj->is_class("Resource")) { + extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error)); + } uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0); - print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + node_name); + print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + extra_info); } + print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`)."); } spin_lock.unlock(); } diff --git a/core/object.h b/core/object.h index 1eaab5034e..5b46a0f93a 100644 --- a/core/object.h +++ b/core/object.h @@ -91,6 +91,7 @@ enum PropertyHint { PROPERTY_HINT_NODE_PATH_VALID_TYPES, PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog PROPERTY_HINT_INT_IS_OBJECTID, + PROPERTY_HINT_ARRAY_TYPE, PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; @@ -123,6 +124,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT = 1 << 24, PROPERTY_USAGE_KEYING_INCREMENTS = 1 << 25, // Used in inspector to increment property when keyed in animation player PROPERTY_USAGE_DEFERRED_SET_RESOURCE = 1 << 26, // when loading, the resource for this property can be set at the end of loading + PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT = 1 << 27, // For Object properties, instantiate them when creating in editor. PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, @@ -137,13 +139,12 @@ enum PropertyUsageFlags { #define ADD_SUBGROUP(m_name, m_prefix) ClassDB::add_property_subgroup(get_class_static(), m_name, m_prefix) struct PropertyInfo { - - Variant::Type type; + Variant::Type type = Variant::NIL; String name; StringName class_name; //for classes - PropertyHint hint; + PropertyHint hint = PROPERTY_HINT_NONE; String hint_string; - uint32_t usage; + uint32_t usage = PROPERTY_USAGE_DEFAULT; _FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const { PropertyInfo pi = *this; @@ -155,11 +156,7 @@ struct PropertyInfo { static PropertyInfo from_dict(const Dictionary &p_dict); - PropertyInfo() : - type(Variant::NIL), - hint(PROPERTY_HINT_NONE), - usage(PROPERTY_USAGE_DEFAULT) { - } + PropertyInfo() {} 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), @@ -167,7 +164,6 @@ struct PropertyInfo { hint(p_hint), hint_string(p_hint_string), usage(p_usage) { - if (hint == PROPERTY_HINT_RESOURCE_TYPE) { class_name = hint_string; } else { @@ -177,10 +173,7 @@ struct PropertyInfo { 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 { return ((type == p_info.type) && @@ -199,11 +192,10 @@ struct PropertyInfo { Array convert_property_list(const List<PropertyInfo> *p_list); struct MethodInfo { - String name; PropertyInfo return_val; - uint32_t flags; - int id; + uint32_t flags; // NOLINT - prevent clang-tidy to assign method_bind.h constant here, it should stay in .cpp. + int id = 0; List<PropertyInfo> arguments; Vector<Variant> default_arguments; @@ -213,6 +205,7 @@ struct MethodInfo { operator Dictionary() const; static MethodInfo from_dict(const Dictionary &p_dict); + MethodInfo(); MethodInfo(const String &p_name); MethodInfo(const String &p_name, const PropertyInfo &p_param1); @@ -268,8 +261,9 @@ public: return String(#m_class); \ } \ virtual const StringName *_get_class_namev() const { \ - if (!_class_name) \ + if (!_class_name) { \ _class_name = get_class_static(); \ + } \ return &_class_name; \ } \ static _FORCE_INLINE_ void *get_class_ptr_static() { \ @@ -289,8 +283,9 @@ public: static String get_category_static() { \ String category = m_inherits::get_category_static(); \ if (_get_category != m_inherits::_get_category) { \ - if (category != "") \ + if (category != "") { \ category += "/"; \ + } \ category += _get_category(); \ } \ return category; \ @@ -302,7 +297,6 @@ public: virtual bool is_class_ptr(void *p_ptr) const { return (p_ptr == get_class_ptr_static()) ? true : m_inherits::is_class_ptr(p_ptr); } \ \ static void get_valid_parents_static(List<String> *p_parents) { \ - \ if (m_class::_get_valid_parents_static != m_inherits::_get_valid_parents_static) { \ m_class::_get_valid_parents_static(p_parents); \ } \ @@ -318,12 +312,14 @@ protected: public: \ static void initialize_class() { \ static bool initialized = false; \ - if (initialized) \ + if (initialized) { \ return; \ + } \ m_inherits::initialize_class(); \ ClassDB::_add_class<m_class>(); \ - if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) \ + if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \ _bind_methods(); \ + } \ initialized = true; \ } \ \ @@ -336,8 +332,9 @@ protected: } \ virtual bool _getv(const StringName &p_name, Variant &r_ret) const { \ if (m_class::_get_get() != m_inherits::_get_get()) { \ - if (_get(p_name, r_ret)) \ + if (_get(p_name, r_ret)) { \ return true; \ + } \ } \ return m_inherits::_getv(p_name, r_ret); \ } \ @@ -345,7 +342,9 @@ protected: return (bool (Object::*)(const StringName &, const Variant &)) & m_class::_set; \ } \ virtual bool _setv(const StringName &p_name, const Variant &p_property) { \ - if (m_inherits::_setv(p_name, p_property)) return true; \ + if (m_inherits::_setv(p_name, p_property)) { \ + return true; \ + } \ if (m_class::_get_set() != m_inherits::_get_set()) { \ return _set(p_name, p_property); \ } \ @@ -359,13 +358,15 @@ protected: m_inherits::_get_property_listv(p_list, p_reversed); \ } \ p_list->push_back(PropertyInfo(Variant::NIL, get_class_static(), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_CATEGORY)); \ - if (!_is_gpl_reversed()) \ + if (!_is_gpl_reversed()) { \ ClassDB::get_property_list(#m_class, p_list, true, this); \ + } \ if (m_class::_get_get_property_list() != m_inherits::_get_get_property_list()) { \ _get_property_list(p_list); \ } \ - if (_is_gpl_reversed()) \ + if (_is_gpl_reversed()) { \ ClassDB::get_property_list(#m_class, p_list, true, this); \ + } \ if (p_reversed) { \ m_inherits::_get_property_listv(p_list, p_reversed); \ } \ @@ -374,13 +375,15 @@ protected: return (void (Object::*)(int)) & m_class::_notification; \ } \ virtual void _notificationv(int p_notification, bool p_reversed) { \ - if (!p_reversed) \ + if (!p_reversed) { \ m_inherits::_notificationv(p_notification, p_reversed); \ + } \ if (m_class::_get_notification() != m_inherits::_get_notification()) { \ _notification(p_notification); \ } \ - if (p_reversed) \ + if (p_reversed) { \ m_inherits::_notificationv(p_notification, p_reversed); \ + } \ } \ \ private: @@ -410,18 +413,16 @@ public: }; struct Connection { - ::Signal signal; Callable callable; - uint32_t flags; + uint32_t flags = 0; Vector<Variant> binds; bool operator<(const Connection &p_conn) const; operator Variant() const; - Connection() { - flags = 0; - } + + Connection() {} Connection(const Variant &p_variant); }; @@ -437,18 +438,14 @@ private: friend void postinitialize_handler(Object *); struct SignalData { - struct Slot { - - int reference_count; + int reference_count = 0; Connection conn; - List<Connection>::Element *cE; - Slot() { reference_count = 0; } + List<Connection>::Element *cE = nullptr; }; MethodInfo user; VMap<Callable, Slot> slot_map; - SignalData() {} }; HashMap<StringName, SignalData> signal_map; @@ -456,24 +453,24 @@ private: #ifdef DEBUG_ENABLED SafeRefCount _lock_index; #endif - bool _block_signals; - int _predelete_ok; + bool _block_signals = false; + int _predelete_ok = 0; Set<Object *> change_receptors; ObjectID _instance_id; bool _predelete(); void _postinitialize(); - bool _can_translate; - bool _emitting; + bool _can_translate = true; + bool _emitting = false; #ifdef TOOLS_ENABLED - bool _edited; - uint32_t _edited_version; + bool _edited = false; + uint32_t _edited_version = 0; Set<String> editor_section_folding; #endif - ScriptInstance *script_instance; + ScriptInstance *script_instance = nullptr; Variant script; //reference does not yet exist, store it in a Dictionary metadata; mutable StringName _class_name; - mutable const StringName *_class_ptr; + mutable const StringName *_class_ptr = nullptr; void _add_user_signal(const String &p_name, const Array &p_args = Array()); bool _has_user_signal(const StringName &p_name) const; @@ -492,8 +489,9 @@ private: friend class Reference; bool type_is_reference = false; - uint32_t instance_binding_count; + uint32_t instance_binding_count = 0; void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS]; + Object(bool p_reference); protected: @@ -501,14 +499,14 @@ protected: virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; }; virtual bool _getv(const StringName &p_name, Variant &r_property) const { return false; }; virtual void _get_property_listv(List<PropertyInfo> *p_list, bool p_reversed) const {}; - virtual void _notificationv(int p_notification, bool p_reversed){}; + virtual void _notificationv(int p_notification, bool p_reversed) {} static String _get_category() { return ""; } static void _bind_methods(); bool _set(const StringName &p_name, const Variant &p_property) { return false; }; bool _get(const StringName &p_name, Variant &r_property) const { return false; }; void _get_property_list(List<PropertyInfo> *p_list) const {}; - void _notification(int p_notification){}; + void _notification(int p_notification) {} _FORCE_INLINE_ static void (*_get_bind_methods())() { return &Object::_bind_methods; @@ -539,8 +537,9 @@ protected: Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); virtual const StringName *_get_class_namev() const { - if (!_class_name) + if (!_class_name) { _class_name = get_class_static(); + } return &_class_name; } @@ -557,14 +556,15 @@ protected: public: //should be protected, but bug in clang++ static void initialize_class(); - _FORCE_INLINE_ static void register_custom_data_to_otdb(){}; + _FORCE_INLINE_ static void register_custom_data_to_otdb() {} public: #ifdef TOOLS_ENABLED _FORCE_INLINE_ void _change_notify(const char *p_property = "") { _edited = true; - for (Set<Object *>::Element *E = change_receptors.front(); E; E = E->next()) + for (Set<Object *>::Element *E = change_receptors.front(); E; E = E->next()) { ((Object *)(E->get()))->_changed_callback(this, p_property); + } } #else _FORCE_INLINE_ void _change_notify(const char *p_what = "") {} @@ -577,8 +577,8 @@ public: bool _is_gpl_reversed() const { return false; } _FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; } - // this is used for editors + // this is used for editors void add_change_receptor(Object *p_receptor); void remove_change_receptor(Object *p_receptor); @@ -587,12 +587,14 @@ public: #ifndef NO_SAFE_CAST return dynamic_cast<T *>(p_object); #else - if (!p_object) + if (!p_object) { return nullptr; - if (p_object->is_class_ptr(T::get_class_ptr_static())) + } + if (p_object->is_class_ptr(T::get_class_ptr_static())) { return static_cast<T *>(p_object); - else + } else { return nullptr; + } #endif } @@ -601,17 +603,18 @@ public: #ifndef NO_SAFE_CAST return dynamic_cast<const T *>(p_object); #else - if (!p_object) + if (!p_object) { return nullptr; - if (p_object->is_class_ptr(T::get_class_ptr_static())) + } + if (p_object->is_class_ptr(T::get_class_ptr_static())) { return static_cast<const T *>(p_object); - else + } else { return nullptr; + } #endif } enum { - NOTIFICATION_POSTINITIALIZE = 0, NOTIFICATION_PREDELETE = 1 }; @@ -721,7 +724,7 @@ public: StringName tr(const StringName &p_message) const; // translate message (internationalization) - bool _is_queued_for_deletion; // set to true by SceneTree::queue_delete() + bool _is_queued_for_deletion = false; // set to true by SceneTree::queue_delete() bool is_queued_for_deletion() const; _FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate = p_enable; } @@ -743,6 +746,7 @@ public: void clear_internal_resource_paths(); _ALWAYS_INLINE_ bool is_reference() const { return type_is_reference; } + Object(); virtual ~Object(); }; @@ -751,7 +755,6 @@ bool predelete_handler(Object *p_object); void postinitialize_handler(Object *p_object); class ObjectDB { - //this needs to add up to 63, 1 bit is for reference #define OBJECTDB_VALIDATOR_BITS 39 #define OBJECTDB_VALIDATOR_MASK ((uint64_t(1) << OBJECTDB_VALIDATOR_BITS) - 1) @@ -786,7 +789,6 @@ public: typedef void (*DebugFunc)(Object *p_obj); _ALWAYS_INLINE_ static Object *get_instance(ObjectID p_instance_id) { - uint64_t id = p_instance_id; uint32_t slot = id & OBJECTDB_SLOT_MAX_COUNT_MASK; diff --git a/core/ordered_hash_map.h b/core/ordered_hash_map.h index 05debd529f..e6a6340a2f 100644 --- a/core/ordered_hash_map.h +++ b/core/ordered_hash_map.h @@ -55,9 +55,9 @@ 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; + typename InternalList::Element *list_element = nullptr; + typename InternalList::Element *prev_element = nullptr; + typename InternalList::Element *next_element = nullptr; Element(typename InternalList::Element *p_element) { list_element = p_element; @@ -69,11 +69,7 @@ public: } public: - _FORCE_INLINE_ Element() : - list_element(nullptr), - prev_element(nullptr), - next_element(nullptr) { - } + _FORCE_INLINE_ Element() {} Element next() const { return Element(next_element); @@ -110,42 +106,40 @@ public: 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; + const typename InternalList::Element *list_element = nullptr; ConstElement(const typename InternalList::Element *p_element) : list_element(p_element) { } public: - _FORCE_INLINE_ ConstElement() : - list_element(nullptr) { - } + _FORCE_INLINE_ ConstElement() {} ConstElement(const ConstElement &other) : list_element(other.list_element) { @@ -178,17 +172,17 @@ public: 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 { @@ -299,8 +293,7 @@ public: _copy_from(p_map); } - _FORCE_INLINE_ OrderedHashMap() { - } + _FORCE_INLINE_ OrderedHashMap() {} }; #endif // ORDERED_HASH_MAP_H diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 94c8cd5d73..5e1cb8ea29 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -36,56 +36,56 @@ #include "core/project_settings.h" String DirAccess::_get_root_path() const { - switch (_access_type) { - - case ACCESS_RESOURCES: return ProjectSettings::get_singleton()->get_resource_path(); - case ACCESS_USERDATA: return OS::get_singleton()->get_user_data_dir(); - default: return ""; + case ACCESS_RESOURCES: + return ProjectSettings::get_singleton()->get_resource_path(); + case ACCESS_USERDATA: + return OS::get_singleton()->get_user_data_dir(); + default: + return ""; } } -String DirAccess::_get_root_string() const { +String DirAccess::_get_root_string() const { switch (_access_type) { - - case ACCESS_RESOURCES: return "res://"; - case ACCESS_USERDATA: return "user://"; - default: return ""; + case ACCESS_RESOURCES: + return "res://"; + case ACCESS_USERDATA: + return "user://"; + default: + return ""; } } int DirAccess::get_current_drive() { - String path = get_current_dir().to_lower(); for (int i = 0; i < get_drive_count(); i++) { String d = get_drive(i).to_lower(); - if (path.begins_with(d)) + if (path.begins_with(d)) { return i; + } } return 0; } bool DirAccess::drives_are_shortcuts() { - return false; } static Error _erase_recursive(DirAccess *da) { - List<String> dirs; List<String> files; da->list_dir_begin(); String n = da->get_next(); while (n != String()) { - if (n != "." && n != "..") { - - if (da->current_is_dir()) + if (da->current_is_dir()) { dirs.push_back(n); - else + } else { files.push_back(n); + } } n = da->get_next(); @@ -94,10 +94,8 @@ static Error _erase_recursive(DirAccess *da) { da->list_dir_end(); for (List<String>::Element *E = dirs.front(); E; E = E->next()) { - Error err = da->change_dir(E->get()); if (err == OK) { - err = _erase_recursive(da); if (err) { da->change_dir(".."); @@ -117,7 +115,6 @@ static Error _erase_recursive(DirAccess *da) { } for (List<String>::Element *E = files.front(); E; E = E->next()) { - Error err = da->remove(da->get_current_dir().plus_file(E->get())); if (err) { return err; @@ -128,15 +125,13 @@ static Error _erase_recursive(DirAccess *da) { } Error DirAccess::erase_contents_recursive() { - return _erase_recursive(this); } Error DirAccess::make_dir_recursive(String p_dir) { - if (p_dir.length() < 1) { return OK; - }; + } String full_dir; @@ -154,13 +149,13 @@ Error DirAccess::make_dir_recursive(String p_dir) { String base; - if (full_dir.begins_with("res://")) + if (full_dir.begins_with("res://")) { base = "res://"; - else if (full_dir.begins_with("user://")) + } else if (full_dir.begins_with("user://")) { base = "user://"; - else if (full_dir.begins_with("/")) + } else if (full_dir.begins_with("/")) { base = "/"; - else if (full_dir.find(":/") != -1) { + } else if (full_dir.find(":/") != -1) { base = full_dir.substr(0, full_dir.find(":/") + 2); } else { ERR_FAIL_V(ERR_INVALID_PARAMETER); @@ -172,11 +167,9 @@ Error DirAccess::make_dir_recursive(String p_dir) { String curpath = base; for (int i = 0; i < subdirs.size(); i++) { - curpath = curpath.plus_file(subdirs[i]); Error err = make_dir(curpath); if (err != OK && err != ERR_ALREADY_EXISTS) { - ERR_FAIL_V(err); } } @@ -185,42 +178,34 @@ Error DirAccess::make_dir_recursive(String p_dir) { } String DirAccess::fix_path(String p_path) const { - switch (_access_type) { - case ACCESS_RESOURCES: { - if (ProjectSettings::get_singleton()) { if (p_path.begins_with("res://")) { - String resource_path = ProjectSettings::get_singleton()->get_resource_path(); if (resource_path != "") { - return p_path.replace_first("res:/", resource_path); - }; + } return p_path.replace_first("res://", ""); } } } break; case ACCESS_USERDATA: { - if (p_path.begins_with("user://")) { - String data_dir = OS::get_singleton()->get_user_data_dir(); if (data_dir != "") { - return p_path.replace_first("user:/", data_dir); - }; + } return p_path.replace_first("user://", ""); } } break; case ACCESS_FILESYSTEM: { - return p_path; } break; - case ACCESS_MAX: break; // Can't happen, but silences warning + case ACCESS_MAX: + break; // Can't happen, but silences warning } return p_path; @@ -229,16 +214,12 @@ String DirAccess::fix_path(String p_path) const { DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX] = { nullptr, nullptr, nullptr }; DirAccess *DirAccess::create_for_path(const String &p_path) { - DirAccess *da = nullptr; if (p_path.begins_with("res://")) { - da = create(ACCESS_RESOURCES); } else if (p_path.begins_with("user://")) { - da = create(ACCESS_USERDATA); } else { - da = create(ACCESS_FILESYSTEM); } @@ -246,13 +227,13 @@ DirAccess *DirAccess::create_for_path(const String &p_path) { } DirAccess *DirAccess::open(const String &p_path, Error *r_error) { - DirAccess *da = create_for_path(p_path); ERR_FAIL_COND_V_MSG(!da, nullptr, "Cannot create DirAccess for path '" + p_path + "'."); Error err = da->change_dir(p_path); - if (r_error) + if (r_error) { *r_error = err; + } if (err != OK) { memdelete(da); return nullptr; @@ -262,20 +243,19 @@ DirAccess *DirAccess::open(const String &p_path, Error *r_error) { } DirAccess *DirAccess::create(AccessType p_access) { - DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr; if (da) { da->_access_type = p_access; } return da; -}; +} String DirAccess::get_full_path(const String &p_path, AccessType p_access) { - DirAccess *d = DirAccess::create(p_access); - if (!d) + if (!d) { return p_path; + } d->change_dir(p_path); String full = d->get_current_dir(); @@ -284,7 +264,6 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) { } Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { - //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err); @@ -296,7 +275,6 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); if (err) { - fsrc->close(); memdelete(fsrc); ERR_PRINT("Failed to open " + p_to); @@ -308,7 +286,6 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { fsrc->seek(0); err = OK; while (size--) { - if (fsrc->get_error() != OK) { err = fsrc->get_error(); break; @@ -325,8 +302,9 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { fdst->close(); err = FileAccess::set_unix_permissions(p_to, p_chmod_flags); // If running on a platform with no chmod support (i.e., Windows), don't fail - if (err == ERR_UNAVAILABLE) + if (err == ERR_UNAVAILABLE) { err = OK; + } } memdelete(fsrc); @@ -360,12 +338,10 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag list_dir_begin(); String n = get_next(); while (n != String()) { - if (n != "." && n != "..") { - - if (current_is_dir()) + if (current_is_dir()) { dirs.push_back(n); - else { + } else { const String &rel_path = n; if (!n.is_rel_path()) { list_dir_end(); @@ -433,17 +409,8 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) { } bool DirAccess::exists(String p_dir) { - DirAccess *da = DirAccess::create_for_path(p_dir); bool valid = da->change_dir(p_dir) == OK; memdelete(da); return valid; } - -DirAccess::DirAccess() { - - _access_type = ACCESS_FILESYSTEM; -} - -DirAccess::~DirAccess() { -} diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 60eb553968..6bce9a4c12 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -47,7 +47,7 @@ public: typedef DirAccess *(*CreateFunc)(); private: - AccessType _access_type; + AccessType _access_type = ACCESS_FILESYSTEM; static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags); @@ -61,7 +61,6 @@ protected: template <class T> static DirAccess *_create_builtin() { - return memnew(T); } @@ -110,42 +109,33 @@ public: static String get_full_path(const String &p_path, AccessType p_access); static DirAccess *create_for_path(const String &p_path); - /* - enum DirType { - - FILE_TYPE_INVALID, - FILE_TYPE_FILE, - FILE_TYPE_DIR, - }; - - //virtual DirType get_file_type() const=0; -*/ static DirAccess *create(AccessType p_access); template <class T> static void make_default(AccessType p_access) { - create_func[p_access] = _create_builtin<T>; } static DirAccess *open(const String &p_path, Error *r_error = nullptr); - DirAccess(); - virtual ~DirAccess(); + DirAccess() {} + virtual ~DirAccess() {} }; struct DirAccessRef { - _FORCE_INLINE_ DirAccess *operator->() { - return f; } operator bool() const { return f != nullptr; } + DirAccess *f; + DirAccessRef(DirAccess *fa) { f = fa; } ~DirAccessRef() { - if (f) memdelete(f); + if (f) { + memdelete(f); + } } }; diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 3922f031b7..20b3435911 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -43,7 +43,6 @@ FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr; bool FileAccess::backup_save = false; FileAccess *FileAccess::create(AccessType p_access) { - ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr); FileAccess *ret = create_func[p_access](); @@ -52,34 +51,30 @@ FileAccess *FileAccess::create(AccessType p_access) { } bool FileAccess::exists(const String &p_name) { - - if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) + if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) { return true; + } FileAccess *f = open(p_name, READ); - if (!f) + if (!f) { return false; + } memdelete(f); return true; } void FileAccess::_set_access_type(AccessType p_access) { - _access_type = p_access; -}; +} FileAccess *FileAccess::create_for_path(const String &p_path) { - FileAccess *ret = nullptr; if (p_path.begins_with("res://")) { - ret = create(ACCESS_RESOURCES); } else if (p_path.begins_with("user://")) { - ret = create(ACCESS_USERDATA); } else { - ret = create(ACCESS_FILESYSTEM); } @@ -87,20 +82,19 @@ FileAccess *FileAccess::create_for_path(const String &p_path) { } Error FileAccess::reopen(const String &p_path, int p_mode_flags) { - return _open(p_path, p_mode_flags); -}; +} FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) { - //try packed data first FileAccess *ret = nullptr; if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) { ret = PackedData::get_singleton()->try_open_path(p_path); if (ret) { - if (r_error) + if (r_error) { *r_error = OK; + } return ret; } } @@ -108,10 +102,10 @@ FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_er ret = create_for_path(p_path); Error err = ret->_open(p_path, p_mode_flags); - if (r_error) + if (r_error) { *r_error = err; + } if (err != OK) { - memdelete(ret); ret = nullptr; } @@ -120,9 +114,8 @@ FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_er } FileAccess::CreateFunc FileAccess::get_create_func(AccessType p_access) { - return create_func[p_access]; -}; +} String FileAccess::fix_path(const String &p_path) const { //helper used by file accesses that use a single filesystem @@ -130,40 +123,33 @@ String FileAccess::fix_path(const String &p_path) const { String r_path = p_path.replace("\\", "/"); switch (_access_type) { - case ACCESS_RESOURCES: { - if (ProjectSettings::get_singleton()) { if (r_path.begins_with("res://")) { - String resource_path = ProjectSettings::get_singleton()->get_resource_path(); if (resource_path != "") { - return r_path.replace("res:/", resource_path); - }; + } return r_path.replace("res://", ""); } } } break; case ACCESS_USERDATA: { - if (r_path.begins_with("user://")) { - String data_dir = OS::get_singleton()->get_user_data_dir(); if (data_dir != "") { - return r_path.replace("user:/", data_dir); - }; + } return r_path.replace("user://", ""); } } break; case ACCESS_FILESYSTEM: { - return r_path; } break; - case ACCESS_MAX: break; // Can't happen, but silences warning + case ACCESS_MAX: + break; // Can't happen, but silences warning } return r_path; @@ -172,7 +158,6 @@ String FileAccess::fix_path(const String &p_path) const { /* these are all implemented for ease of porting, then can later be optimized */ uint16_t FileAccess::get_16() const { - uint16_t res; uint8_t a, b; @@ -180,7 +165,6 @@ uint16_t FileAccess::get_16() const { b = get_8(); if (endian_swap) { - SWAP(a, b); } @@ -190,8 +174,8 @@ uint16_t FileAccess::get_16() const { return res; } -uint32_t FileAccess::get_32() const { +uint32_t FileAccess::get_32() const { uint32_t res; uint16_t a, b; @@ -199,7 +183,6 @@ uint32_t FileAccess::get_32() const { b = get_16(); if (endian_swap) { - SWAP(a, b); } @@ -209,8 +192,8 @@ uint32_t FileAccess::get_32() const { return res; } -uint64_t FileAccess::get_64() const { +uint64_t FileAccess::get_64() const { uint64_t res; uint32_t a, b; @@ -218,7 +201,6 @@ uint64_t FileAccess::get_64() const { b = get_32(); if (endian_swap) { - SWAP(a, b); } @@ -230,38 +212,35 @@ uint64_t FileAccess::get_64() const { } float FileAccess::get_float() const { - MarshallFloat m; m.i = get_32(); return m.f; -}; +} real_t FileAccess::get_real() const { - - if (real_is_double) + if (real_is_double) { return get_double(); - else + } else { return get_float(); + } } double FileAccess::get_double() const { - MarshallDouble m; m.l = get_64(); return m.d; -}; +} String FileAccess::get_token() const { - CharString token; CharType c = get_8(); while (!eof_reached()) { - if (c <= ' ') { - if (token.length()) + if (token.length()) { break; + } } else { token += c; } @@ -277,19 +256,16 @@ class CharBuffer { char *buffer; int capacity; - int written; + int written = 0; bool grow() { - if (vector.resize(next_power_of_2(1 + written)) != OK) { - return false; } if (buffer == stack_buffer) { // first chunk? for (int i = 0; i < written; i++) { - vector.write[i] = stack_buffer[i]; } } @@ -304,14 +280,11 @@ class CharBuffer { public: _FORCE_INLINE_ CharBuffer() : buffer(stack_buffer), - capacity(sizeof(stack_buffer) / sizeof(char)), - written(0) { + capacity(sizeof(stack_buffer) / sizeof(char)) { } _FORCE_INLINE_ void push_back(char c) { - if (written >= capacity) { - ERR_FAIL_COND(!grow()); } @@ -319,24 +292,22 @@ public: } _FORCE_INLINE_ const char *get_data() const { - return buffer; } }; String FileAccess::get_line() const { - CharBuffer line; CharType c = get_8(); while (!eof_reached()) { - if (c == '\n' || c == '\0') { line.push_back(0); return String::utf8(line.get_data()); - } else if (c != '\r') + } else if (c != '\r') { line.push_back(c); + } c = get_8(); } @@ -345,21 +316,21 @@ String FileAccess::get_line() const { } Vector<String> FileAccess::get_csv_line(const String &p_delim) const { - ERR_FAIL_COND_V(p_delim.length() != 1, Vector<String>()); String l; int qc = 0; do { - if (eof_reached()) + if (eof_reached()) { break; + } l += get_line() + "\n"; qc = 0; for (int i = 0; i < l.length(); i++) { - - if (l[i] == '"') + if (l[i] == '"') { qc++; + } } } while (qc % 2); @@ -371,7 +342,6 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const { bool in_quote = false; String current; for (int i = 0; i < l.length(); i++) { - CharType c = l[i]; CharType s[2] = { 0, 0 }; @@ -384,7 +354,6 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const { current += s; i++; } else { - in_quote = !in_quote; } } else { @@ -399,10 +368,10 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const { } int FileAccess::get_buffer(uint8_t *p_dst, int p_length) const { - int i = 0; - for (i = 0; i < p_length && !eof_reached(); i++) + for (i = 0; i < p_length && !eof_reached(); i++) { p_dst[i] = get_8(); + } return i; } @@ -425,44 +394,40 @@ String FileAccess::get_as_utf8_string() const { } void FileAccess::store_16(uint16_t p_dest) { - uint8_t a, b; a = p_dest & 0xFF; b = p_dest >> 8; if (endian_swap) { - SWAP(a, b); } store_8(a); store_8(b); } -void FileAccess::store_32(uint32_t p_dest) { +void FileAccess::store_32(uint32_t p_dest) { uint16_t a, b; a = p_dest & 0xFFFF; b = p_dest >> 16; if (endian_swap) { - SWAP(a, b); } store_16(a); store_16(b); } -void FileAccess::store_64(uint64_t p_dest) { +void FileAccess::store_64(uint64_t p_dest) { uint32_t a, b; a = p_dest & 0xFFFFFFFF; b = p_dest >> 32; if (endian_swap) { - SWAP(a, b); } @@ -471,31 +436,29 @@ void FileAccess::store_64(uint64_t p_dest) { } void FileAccess::store_real(real_t p_real) { - - if (sizeof(real_t) == 4) + if (sizeof(real_t) == 4) { store_float(p_real); - else + } else { store_double(p_real); + } } void FileAccess::store_float(float p_dest) { - MarshallFloat m; m.f = p_dest; store_32(m.i); -}; +} void FileAccess::store_double(double p_dest) { - MarshallDouble m; m.d = p_dest; store_64(m.l); -}; +} uint64_t FileAccess::get_modified_time(const String &p_file) { - - if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) { return 0; + } FileAccess *fa = create_for_path(p_file); ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'."); @@ -506,9 +469,9 @@ uint64_t FileAccess::get_modified_time(const String &p_file) { } uint32_t FileAccess::get_unix_permissions(const String &p_file) { - - if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) { return 0; + } FileAccess *fa = create_for_path(p_file); ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'."); @@ -519,7 +482,6 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) { } Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) { - FileAccess *fa = create_for_path(p_file); ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'."); @@ -529,23 +491,21 @@ Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissi } void FileAccess::store_string(const String &p_string) { - - if (p_string.length() == 0) + if (p_string.length() == 0) { return; + } CharString cs = p_string.utf8(); store_buffer((uint8_t *)&cs[0], cs.length()); } void FileAccess::store_pascal_string(const String &p_string) { - CharString cs = p_string.utf8(); store_32(cs.length()); store_buffer((uint8_t *)&cs[0], cs.length()); -}; +} String FileAccess::get_pascal_string() { - uint32_t sl = get_32(); CharString cs; cs.resize(sl + 1); @@ -556,16 +516,14 @@ String FileAccess::get_pascal_string() { ret.parse_utf8(cs.ptr()); return ret; -}; +} void FileAccess::store_line(const String &p_line) { - store_string(p_line); store_8('\n'); } void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_delim) { - ERR_FAIL_COND(p_delim.length() != 1); String line = ""; @@ -587,13 +545,12 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_ } void FileAccess::store_buffer(const uint8_t *p_src, int p_length) { - - for (int i = 0; i < p_length; i++) + for (int i = 0; i < p_length; i++) { store_8(p_src[i]); + } } Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) { - FileAccess *f = FileAccess::open(p_path, READ, r_error); if (!f) { if (r_error) { // if error requested, do not throw error @@ -609,7 +566,6 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err } String FileAccess::get_file_as_string(const String &p_path, Error *r_error) { - Error err; Vector<uint8_t> array = get_file_as_array(p_path, &err); if (r_error) { @@ -628,10 +584,10 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) { } String FileAccess::get_md5(const String &p_file) { - FileAccess *f = FileAccess::open(p_file, READ); - if (!f) + if (!f) { return String(); + } CryptoCore::MD5Context ctx; ctx.start(); @@ -639,14 +595,13 @@ String FileAccess::get_md5(const String &p_file) { unsigned char step[32768]; while (true) { - int br = f->get_buffer(step, 32768); if (br > 0) { - ctx.update(step, br); } - if (br < 4096) + if (br < 4096) { break; + } } unsigned char hash[16]; @@ -658,7 +613,6 @@ String FileAccess::get_md5(const String &p_file) { } String FileAccess::get_multiple_md5(const Vector<String> &p_file) { - CryptoCore::MD5Context ctx; ctx.start(); @@ -669,14 +623,13 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) { unsigned char step[32768]; while (true) { - int br = f->get_buffer(step, 32768); if (br > 0) { - ctx.update(step, br); } - if (br < 4096) + if (br < 4096) { break; + } } memdelete(f); } @@ -688,10 +641,10 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) { } String FileAccess::get_sha256(const String &p_file) { - FileAccess *f = FileAccess::open(p_file, READ); - if (!f) + if (!f) { return String(); + } CryptoCore::SHA256Context ctx; ctx.start(); @@ -699,14 +652,13 @@ String FileAccess::get_sha256(const String &p_file) { unsigned char step[32768]; while (true) { - int br = f->get_buffer(step, 32768); if (br > 0) { - ctx.update(step, br); } - if (br < 4096) + if (br < 4096) { break; + } } unsigned char hash[32]; @@ -715,10 +667,3 @@ String FileAccess::get_sha256(const String &p_file) { memdelete(f); return String::hex_encode_buffer(hash, 32); } - -FileAccess::FileAccess() { - - endian_swap = false; - real_is_double = false; - _access_type = ACCESS_FILESYSTEM; -}; diff --git a/core/os/file_access.h b/core/os/file_access.h index 010cc74a87..48b9ee4269 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -41,7 +41,6 @@ */ class FileAccess { - public: enum AccessType { ACCESS_RESOURCES, @@ -53,8 +52,8 @@ public: typedef void (*FileCloseFailNotify)(const String &); typedef FileAccess *(*CreateFunc)(); - bool endian_swap; - bool real_is_double; + bool endian_swap = false; + bool real_is_double = false; virtual uint32_t _get_unix_permissions(const String &p_file) = 0; virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0; @@ -69,11 +68,10 @@ protected: private: static bool backup_save; - AccessType _access_type; + AccessType _access_type = ACCESS_FILESYSTEM; static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */ template <class T> static FileAccess *_create_builtin() { - return memnew(T); } @@ -172,27 +170,29 @@ public: template <class T> static void make_default(AccessType p_access) { - create_func[p_access] = _create_builtin<T>; } - FileAccess(); + FileAccess() {} virtual ~FileAccess() {} }; struct FileAccessRef { - _FORCE_INLINE_ FileAccess *operator->() { - return f; } operator bool() const { return f != nullptr; } + FileAccess *f; + operator FileAccess *() { return f; } + FileAccessRef(FileAccess *fa) { f = fa; } ~FileAccessRef() { - if (f) memdelete(f); + if (f) { + memdelete(f); + } } }; diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index c65d3fefc2..d088151a6d 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -293,9 +293,7 @@ static const _KeyCodeText _keycodes[] = { }; bool keycode_has_unicode(uint32_t p_keycode) { - switch (p_keycode) { - case KEY_ESCAPE: case KEY_TAB: case KEY_BACKTAB: @@ -394,7 +392,6 @@ bool keycode_has_unicode(uint32_t p_keycode) { } String keycode_get_string(uint32_t p_code) { - String codestr; if (p_code & KEY_MASK_SHIFT) { codestr += find_keycode_name(KEY_SHIFT); @@ -418,9 +415,7 @@ String keycode_get_string(uint32_t p_code) { const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { - if (kct->code == (int)p_code) { - codestr += kct->text; return codestr; } @@ -433,11 +428,9 @@ String keycode_get_string(uint32_t p_code) { } int find_keycode(const String &p_code) { - const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { - if (p_code.nocasecmp_to(kct->text) == 0) { return kct->code; } @@ -448,11 +441,9 @@ int find_keycode(const String &p_code) { } const char *find_keycode_name(int p_keycode) { - const _KeyCodeText *kct = &_keycodes[0]; while (kct->text) { - if (kct->code == p_keycode) { return kct->text; } @@ -463,12 +454,10 @@ const char *find_keycode_name(int p_keycode) { } int keycode_get_count() { - const _KeyCodeText *kct = &_keycodes[0]; int count = 0; while (kct->text) { - count++; kct++; } diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 0d1a080682..dc68c2a9f9 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -33,7 +33,6 @@ #include "core/script_language.h" void MainLoop::_bind_methods() { - ClassDB::bind_method(D_METHOD("init"), &MainLoop::init); ClassDB::bind_method(D_METHOD("iteration", "delta"), &MainLoop::iteration); ClassDB::bind_method(D_METHOD("idle", "delta"), &MainLoop::idle); @@ -56,41 +55,36 @@ void MainLoop::_bind_methods() { }; void MainLoop::set_init_script(const Ref<Script> &p_init_script) { - init_script = p_init_script; } -MainLoop::MainLoop() { -} - -MainLoop::~MainLoop() { -} - void MainLoop::init() { - - if (init_script.is_valid()) + if (init_script.is_valid()) { set_script(init_script); + } - if (get_script_instance()) + if (get_script_instance()) { get_script_instance()->call("_initialize"); + } } -bool MainLoop::iteration(float p_time) { - if (get_script_instance()) +bool MainLoop::iteration(float p_time) { + if (get_script_instance()) { return get_script_instance()->call("_iteration", p_time); + } return false; } -bool MainLoop::idle(float p_time) { - if (get_script_instance()) +bool MainLoop::idle(float p_time) { + if (get_script_instance()) { return get_script_instance()->call("_idle", p_time); + } return false; } void MainLoop::finish() { - if (get_script_instance()) { get_script_instance()->call("_finalize"); set_script(Variant()); //clear script diff --git a/core/os/main_loop.h b/core/os/main_loop.h index 8f6c8c91b1..90790a45a1 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -36,7 +36,6 @@ #include "core/script_language.h" class MainLoop : public Object { - GDCLASS(MainLoop, Object); OBJ_CATEGORY("Main Loop"); @@ -64,8 +63,8 @@ public: void set_init_script(const Ref<Script> &p_init_script); - MainLoop(); - virtual ~MainLoop(); + MainLoop() {} + virtual ~MainLoop() {} }; #endif // MAIN_LOOP_H diff --git a/core/os/memory.cpp b/core/os/memory.cpp index d921c10ad4..8457c52092 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -38,28 +38,23 @@ #include <stdlib.h> void *operator new(size_t p_size, const char *p_description) { - return Memory::alloc_static(p_size, false); } void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) { - return p_allocfunc(p_size); } #ifdef _MSC_VER void operator delete(void *p_mem, const char *p_description) { - CRASH_NOW_MSG("Call to placement delete should not happen."); } void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) { - CRASH_NOW_MSG("Call to placement delete should not happen."); } void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) { - CRASH_NOW_MSG("Call to placement delete should not happen."); } #endif @@ -72,7 +67,6 @@ uint64_t Memory::max_usage = 0; uint64_t Memory::alloc_count = 0; void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { - #ifdef DEBUG_ENABLED bool prepad = true; #else @@ -102,7 +96,6 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { } void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { - if (p_memory == nullptr) { return alloc_static(p_bytes, p_pad_align); } @@ -144,7 +137,6 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { return mem + PAD_ALIGN; } } else { - mem = (uint8_t *)realloc(mem, p_bytes); ERR_FAIL_COND_V(mem == nullptr && p_bytes > 0, nullptr); @@ -154,7 +146,6 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { } void Memory::free_static(void *p_ptr, bool p_pad_align) { - ERR_FAIL_COND(p_ptr == nullptr); uint8_t *mem = (uint8_t *)p_ptr; @@ -177,13 +168,11 @@ void Memory::free_static(void *p_ptr, bool p_pad_align) { free(mem); } else { - free(mem); } } uint64_t Memory::get_mem_available() { - return -1; // 0xFFFF... } @@ -204,8 +193,6 @@ uint64_t Memory::get_mem_max_usage() { } _GlobalNil::_GlobalNil() { - - color = 1; left = this; right = this; parent = this; diff --git a/core/os/memory.h b/core/os/memory.h index dcaedd92ba..46ffb4124b 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -41,7 +41,6 @@ #endif class Memory { - Memory(); #ifdef DEBUG_ENABLED static uint64_t mem_usage; @@ -87,7 +86,6 @@ _ALWAYS_INLINE_ void postinitialize_handler(void *) {} template <class T> _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) { - postinitialize_handler(p_obj); return p_obj; } @@ -110,44 +108,48 @@ _ALWAYS_INLINE_ bool predelete_handler(void *) { template <class T> void memdelete(T *p_class) { - - if (!predelete_handler(p_class)) + if (!predelete_handler(p_class)) { return; // doesn't want to be deleted - if (!__has_trivial_destructor(T)) + } + if (!__has_trivial_destructor(T)) { p_class->~T(); + } Memory::free_static(p_class, false); } template <class T, class A> void memdelete_allocator(T *p_class) { - - if (!predelete_handler(p_class)) + if (!predelete_handler(p_class)) { return; // doesn't want to be deleted - if (!__has_trivial_destructor(T)) + } + if (!__has_trivial_destructor(T)) { p_class->~T(); + } A::free(p_class); } -#define memdelete_notnull(m_v) \ - { \ - if (m_v) memdelete(m_v); \ +#define memdelete_notnull(m_v) \ + { \ + if (m_v) { \ + memdelete(m_v); \ + } \ } #define memnew_arr(m_class, m_count) memnew_arr_template<m_class>(m_count) template <typename T> T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { - - if (p_elements == 0) - return 0; + if (p_elements == 0) { + return nullptr; + } /** overloading operator new[] cannot be done , because it may not return the real allocated address (it may pad the 'element count' before the actual array). Because of that, it must be done by hand. This is the same strategy used by std::vector, and the Vector class, so it should be safe.*/ size_t len = sizeof(T) * p_elements; uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true); - T *failptr = 0; //get rid of a warning + T *failptr = nullptr; //get rid of a warning ERR_FAIL_COND_V(!mem, failptr); *(mem - 1) = p_elements; @@ -170,14 +172,12 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { template <typename T> size_t memarr_len(const T *p_class) { - uint64_t *ptr = (uint64_t *)p_class; return *(ptr - 1); } template <typename T> void memdelete_arr(T *p_class) { - uint64_t *ptr = (uint64_t *)p_class; if (!__has_trivial_destructor(T)) { @@ -192,8 +192,7 @@ void memdelete_arr(T *p_class) { } struct _GlobalNil { - - int color; + int color = 1; _GlobalNil *right; _GlobalNil *left; _GlobalNil *parent; @@ -202,7 +201,6 @@ struct _GlobalNil { }; struct _GlobalNilClass { - static _GlobalNil _nil; }; diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index 985f6f38e5..e9919aeb86 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -30,23 +30,20 @@ #include "midi_driver.h" -#include "core/input/input_filter.h" +#include "core/input/input.h" #include "core/os/os.h" uint8_t MIDIDriver::last_received_message = 0x00; MIDIDriver *MIDIDriver::singleton = nullptr; MIDIDriver *MIDIDriver::get_singleton() { - return singleton; } void MIDIDriver::set_singleton() { - singleton = this; } void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length) { - Ref<InputEventMIDI> event; event.instance(); uint32_t param_position = 1; @@ -117,17 +114,15 @@ void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_ break; } - InputFilter *id = InputFilter::get_singleton(); + Input *id = Input::get_singleton(); id->parse_input_event(event); } PackedStringArray MIDIDriver::get_connected_inputs() { - PackedStringArray list; return list; } MIDIDriver::MIDIDriver() { - set_singleton(); } diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h index b7377a8a40..bc922e1fcf 100644 --- a/core/os/midi_driver.h +++ b/core/os/midi_driver.h @@ -39,7 +39,6 @@ */ class MIDIDriver { - static MIDIDriver *singleton; static uint8_t last_received_message; diff --git a/core/os/mutex.h b/core/os/mutex.h index 526549dd93..d42cbed821 100644 --- a/core/os/mutex.h +++ b/core/os/mutex.h @@ -82,8 +82,7 @@ extern template class MutexLock<MutexImpl<std::mutex>>; #else class FakeMutex { - - FakeMutex(){}; + FakeMutex() {} }; template <class MutexT> diff --git a/core/os/os.cpp b/core/os/os.cpp index 0636810e4b..c842be333c 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -30,7 +30,7 @@ #include "os.h" -#include "core/input/input_filter.h" +#include "core/input/input.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/os/midi_driver.h" @@ -43,7 +43,6 @@ OS *OS::singleton = nullptr; OS *OS::get_singleton() { - return singleton; } @@ -83,20 +82,14 @@ String OS::get_iso_date_time(bool local) const { uint64_t OS::get_splash_tick_msec() const { return _msec_splash; } -uint64_t OS::get_unix_time() const { - return 0; -}; -uint64_t OS::get_system_time_secs() const { +double OS::get_unix_time() const { return 0; } -uint64_t OS::get_system_time_msecs() const { - return 0; -} -void OS::debug_break(){ +void OS::debug_break() { // something -}; +} void OS::_set_logger(CompositeLogger *p_logger) { if (_logger) { @@ -116,19 +109,17 @@ void OS::add_logger(Logger *p_logger) { } 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) { - _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type); } void OS::print(const char *p_format, ...) { - va_list argp; va_start(argp, p_format); _logger->logv(p_format, argp, false); va_end(argp); -}; +} void OS::printerr(const char *p_format, ...) { va_list argp; @@ -137,73 +128,63 @@ void OS::printerr(const char *p_format, ...) { _logger->logv(p_format, argp, true); va_end(argp); -}; +} void OS::set_low_processor_usage_mode(bool p_enabled) { - low_processor_usage_mode = p_enabled; } bool OS::is_in_low_processor_usage_mode() const { - return low_processor_usage_mode; } void OS::set_low_processor_usage_mode_sleep_usec(int p_usec) { - low_processor_usage_mode_sleep_usec = p_usec; } int OS::get_low_processor_usage_mode_sleep_usec() const { - return low_processor_usage_mode_sleep_usec; } String OS::get_executable_path() const { - return _execpath; } int OS::get_process_id() const { - return -1; -}; +} void OS::vibrate_handheld(int p_duration_ms) { - WARN_PRINT("vibrate_handheld() only works with Android and iOS"); } bool OS::is_stdout_verbose() const { - return _verbose_stdout; } void OS::dump_memory_to_file(const char *p_file) { - //Memory::dump_static_mem_to_file(p_file); } static FileAccess *_OSPRF = nullptr; static void _OS_printres(Object *p_obj) { - Resource *res = Object::cast_to<Resource>(p_obj); - if (!res) + if (!res) { return; + } String str = itos(res->get_instance_id()) + String(res->get_class()) + ":" + String(res->get_name()) + " - " + res->get_path(); - if (_OSPRF) + if (_OSPRF) { _OSPRF->store_line(str); - else + } else { print_line(str); + } } void OS::print_all_resources(String p_to_file) { - ERR_FAIL_COND(p_to_file != "" && _OSPRF); if (p_to_file != "") { - Error err; _OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err); if (err != OK) { @@ -215,50 +196,43 @@ void OS::print_all_resources(String p_to_file) { ObjectDB::debug_objects(_OS_printres); if (p_to_file != "") { - - if (_OSPRF) + if (_OSPRF) { memdelete(_OSPRF); + } _OSPRF = nullptr; } } void OS::print_resources_in_use(bool p_short) { - ResourceCache::dump(nullptr, p_short); } void OS::dump_resources_to_file(const char *p_file) { - ResourceCache::dump(p_file); } void OS::set_no_window_mode(bool p_enable) { - _no_window = p_enable; } bool OS::is_no_window_mode_enabled() const { - return _no_window; } int OS::get_exit_code() const { - return _exit_code; } -void OS::set_exit_code(int p_code) { +void OS::set_exit_code(int p_code) { _exit_code = p_code; } String OS::get_locale() const { - return "en"; } // Helper function to ensure that a dir name/path will be valid on the OS String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separator) const { - Vector<String> invalid_chars = String(": * ? \" < > |").split(" "); if (p_allow_dir_separator) { // Dir separators are allowed, but disallow ".." to avoid going up the filesystem @@ -278,76 +252,64 @@ String OS::get_safe_dir_name(const String &p_dir_name, bool p_allow_dir_separato // Get properly capitalized engine name for system paths String OS::get_godot_dir_name() const { - // Default to lowercase, so only override when different case is needed return String(VERSION_SHORT_NAME).to_lower(); } // OS equivalent of XDG_DATA_HOME String OS::get_data_path() const { - return "."; } // OS equivalent of XDG_CONFIG_HOME String OS::get_config_path() const { - return "."; } // OS equivalent of XDG_CACHE_HOME String OS::get_cache_path() const { - return "."; } // Path to macOS .app bundle resources String OS::get_bundle_resource_dir() const { - return "."; -}; +} // OS specific path for user:// String OS::get_user_data_dir() const { - return "."; -}; +} // Absolute path to res:// String OS::get_resource_dir() const { - return ProjectSettings::get_singleton()->get_resource_path(); } // Access system-specific dirs like Documents, Downloads, etc. String OS::get_system_dir(SystemDir p_dir) const { - return "."; } Error OS::shell_open(String p_uri) { return ERR_UNAVAILABLE; -}; +} // implement these with the canvas? uint64_t OS::get_static_memory_usage() const { - return Memory::get_mem_usage(); } uint64_t OS::get_static_memory_peak_usage() const { - return Memory::get_mem_max_usage(); } Error OS::set_cwd(const String &p_cwd) { - return ERR_CANT_OPEN; } uint64_t OS::get_free_static_memory() const { - return Memory::get_mem_available(); } @@ -355,7 +317,6 @@ void OS::yield() { } void OS::ensure_user_data_dir() { - String dd = get_user_data_dir(); DirAccess *da = DirAccess::open(dd); if (da) { @@ -371,28 +332,23 @@ void OS::ensure_user_data_dir() { } String OS::get_model_name() const { - return "GenericDevice"; } void OS::set_cmdline(const char *p_execpath, const List<String> &p_args) { - _execpath = p_execpath; _cmdline = p_args; -}; +} String OS::get_unique_id() const { - ERR_FAIL_V(""); } int OS::get_processor_count() const { - return 1; } bool OS::can_use_threads() const { - #ifdef NO_THREADS return false; #else @@ -401,24 +357,25 @@ bool OS::can_use_threads() const { } void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) { - has_server_feature_callback = p_callback; } bool OS::has_feature(const String &p_feature) { - - if (p_feature == get_name()) + if (p_feature == get_name()) { return true; + } #ifdef DEBUG_ENABLED - if (p_feature == "debug") + if (p_feature == "debug") { return true; + } #else if (p_feature == "release") return true; #endif #ifdef TOOLS_ENABLED - if (p_feature == "editor") + if (p_feature == "editor") { return true; + } #else if (p_feature == "standalone") return true; @@ -458,15 +415,17 @@ bool OS::has_feature(const String &p_feature) { } #endif - if (_check_internal_feature_support(p_feature)) + if (_check_internal_feature_support(p_feature)) { return true; + } if (has_server_feature_callback && has_server_feature_callback(p_feature)) { return true; } - if (ProjectSettings::get_singleton()->has_custom_feature(p_feature)) + if (ProjectSettings::get_singleton()->has_custom_feature(p_feature)) { return true; + } return false; } @@ -485,48 +444,37 @@ List<String> OS::get_restart_on_exit_arguments() const { } PackedStringArray OS::get_connected_midi_inputs() { - - if (MIDIDriver::get_singleton()) + if (MIDIDriver::get_singleton()) { return MIDIDriver::get_singleton()->get_connected_inputs(); + } PackedStringArray list; - return list; + ERR_FAIL_V_MSG(list, vformat("MIDI input isn't supported on %s.", OS::get_singleton()->get_name())); } void OS::open_midi_inputs() { - - if (MIDIDriver::get_singleton()) + if (MIDIDriver::get_singleton()) { MIDIDriver::get_singleton()->open(); + } else { + ERR_PRINT(vformat("MIDI input isn't supported on %s.", OS::get_singleton()->get_name())); + } } void OS::close_midi_inputs() { - - if (MIDIDriver::get_singleton()) + if (MIDIDriver::get_singleton()) { MIDIDriver::get_singleton()->close(); + } else { + ERR_PRINT(vformat("MIDI input isn't supported on %s.", OS::get_singleton()->get_name())); + } } OS::OS() { void *volatile stack_bottom; - restart_on_exit = false; singleton = this; - _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. - low_processor_usage_mode = false; - low_processor_usage_mode_sleep_usec = 10000; - _verbose_stdout = false; - _no_window = false; - _exit_code = 0; - - _render_thread_mode = RENDER_THREAD_SAFE; - _allow_hidpi = false; - _allow_layered = false; _stack_bottom = (void *)(&stack_bottom); - _logger = nullptr; - - has_server_feature_callback = nullptr; - Vector<Logger *> loggers; loggers.push_back(memnew(StdLogger)); _set_logger(memnew(CompositeLogger(loggers))); diff --git a/core/os/os.h b/core/os/os.h index 714a10bf76..04e10518dc 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -42,21 +42,20 @@ #include <stdarg.h> class OS { - static OS *singleton; String _execpath; List<String> _cmdline; - bool _keep_screen_on; - bool low_processor_usage_mode; - int low_processor_usage_mode_sleep_usec; - bool _verbose_stdout; + bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. + bool low_processor_usage_mode = false; + int low_processor_usage_mode_sleep_usec = 10000; + bool _verbose_stdout = false; String _local_clipboard; uint64_t _msec_splash; - bool _no_window; - int _exit_code; + bool _no_window = false; + int _exit_code = 0; int _orientation; - bool _allow_hidpi; - bool _allow_layered; + bool _allow_hidpi = false; + bool _allow_layered = false; bool _use_vsync; bool _vsync_via_compositor; @@ -64,9 +63,9 @@ class OS { void *_stack_bottom; - CompositeLogger *_logger; + CompositeLogger *_logger = nullptr; - bool restart_on_exit; + bool restart_on_exit = false; List<String> restart_commandline; protected: @@ -86,8 +85,8 @@ public: protected: friend class Main; - HasServerFeatureCallback has_server_feature_callback; - RenderThreadMode _render_thread_mode; + HasServerFeatureCallback has_server_feature_callback = nullptr; + RenderThreadMode _render_thread_mode = RENDER_THREAD_SAFE; // functions used by main to initialize/deinitialize the OS void add_logger(Logger *p_logger); @@ -149,6 +148,11 @@ public: bool is_layered_allowed() const { return _allow_layered; } bool is_hidpi_allowed() const { return _allow_hidpi; } + virtual int get_tablet_driver_count() const { return 0; }; + virtual String get_tablet_driver_name(int p_driver) const { return ""; }; + virtual String get_current_tablet_driver() const { return ""; }; + virtual void set_current_tablet_driver(const String &p_driver){}; + void ensure_user_data_dir(); virtual MainLoop *get_main_loop() const = 0; @@ -183,7 +187,6 @@ public: }; struct Date { - int year; Month month; int day; @@ -192,7 +195,6 @@ public: }; struct Time { - int hour; int min; int sec; @@ -207,9 +209,7 @@ public: virtual Time get_time(bool local = false) const = 0; virtual TimeZoneInfo get_time_zone_info() const = 0; virtual String get_iso_date_time(bool local = false) const; - virtual uint64_t get_unix_time() const; - virtual uint64_t get_system_time_secs() const; - virtual uint64_t get_system_time_msecs() const; + virtual double get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const = 0; virtual uint64_t get_ticks_usec() const = 0; diff --git a/core/os/rw_lock.cpp b/core/os/rw_lock.cpp index 1dd2c3bccb..a668fe2b4c 100644 --- a/core/os/rw_lock.cpp +++ b/core/os/rw_lock.cpp @@ -37,11 +37,7 @@ RWLock *(*RWLock::create_func)() = nullptr; RWLock *RWLock::create() { - ERR_FAIL_COND_V(!create_func, nullptr); return create_func(); } - -RWLock::~RWLock() { -} diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h index 64dfbef20c..1035072cce 100644 --- a/core/os/rw_lock.h +++ b/core/os/rw_lock.h @@ -48,34 +48,40 @@ public: static RWLock *create(); ///< Create a rwlock - virtual ~RWLock(); + virtual ~RWLock() {} }; class RWLockRead { - RWLock *lock; public: RWLockRead(const RWLock *p_lock) { lock = const_cast<RWLock *>(p_lock); - if (lock) lock->read_lock(); + if (lock) { + lock->read_lock(); + } } ~RWLockRead() { - if (lock) lock->read_unlock(); + if (lock) { + lock->read_unlock(); + } } }; class RWLockWrite { - RWLock *lock; public: RWLockWrite(RWLock *p_lock) { lock = p_lock; - if (lock) lock->write_lock(); + if (lock) { + lock->write_lock(); + } } ~RWLockWrite() { - if (lock) lock->write_unlock(); + if (lock) { + lock->write_unlock(); + } } }; diff --git a/core/os/semaphore.cpp b/core/os/semaphore.cpp deleted file mode 100644 index 93f1e2dff4..0000000000 --- a/core/os/semaphore.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************/ -/* semaphore.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "semaphore.h" diff --git a/core/os/semaphore.h b/core/os/semaphore.h index 3d9d1ab984..077e04704b 100644 --- a/core/os/semaphore.h +++ b/core/os/semaphore.h @@ -54,8 +54,9 @@ public: _ALWAYS_INLINE_ void wait() const { std::unique_lock<decltype(mutex_)> lock(mutex_); - while (!count_) // Handle spurious wake-ups. + while (!count_) { // Handle spurious wake-ups. condition_.wait(lock); + } --count_; } diff --git a/core/os/thread.cpp b/core/os/thread.cpp index 294b52f00c..fc0ce3c9b4 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -38,37 +38,29 @@ Error (*Thread::set_name_func)(const String &) = nullptr; Thread::ID Thread::_main_thread_id = 0; Thread::ID Thread::get_caller_id() { - - if (get_thread_id_func) + if (get_thread_id_func) { return get_thread_id_func(); + } return 0; } Thread *Thread::create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings) { - if (create_func) { - return create_func(p_callback, p_user, p_settings); } return nullptr; } void Thread::wait_to_finish(Thread *p_thread) { - - if (wait_to_finish_func) + if (wait_to_finish_func) { wait_to_finish_func(p_thread); + } } Error Thread::set_name(const String &p_name) { - - if (set_name_func) + if (set_name_func) { return set_name_func(p_name); + } return ERR_UNAVAILABLE; -}; - -Thread::Thread() { -} - -Thread::~Thread() { } diff --git a/core/os/thread.h b/core/os/thread.h index 76d296bcf7..f761d4ca43 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -46,7 +46,6 @@ public: }; struct Settings { - Priority priority; Settings() { priority = PRIORITY_NORMAL; } }; @@ -63,7 +62,7 @@ protected: static ID _main_thread_id; - Thread(); + Thread() {} public: virtual ID get_id() const = 0; @@ -74,7 +73,7 @@ public: static void wait_to_finish(Thread *p_thread); ///< waits until thread is finished, and deallocates it. static Thread *create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings = Settings()); ///< Static function to create a thread, will call p_callback - virtual ~Thread(); + virtual ~Thread() {} }; #endif // THREAD_H diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp index 9dcddcae11..2672cd7ad9 100644 --- a/core/os/thread_dummy.cpp +++ b/core/os/thread_dummy.cpp @@ -34,16 +34,16 @@ Thread *ThreadDummy::create(ThreadCreateCallback p_callback, void *p_user, const Thread::Settings &p_settings) { return memnew(ThreadDummy); -}; +} void ThreadDummy::make_default() { Thread::create_func = &ThreadDummy::create; -}; +} RWLock *RWLockDummy::create() { return memnew(RWLockDummy); -}; +} void RWLockDummy::make_default() { RWLock::create_func = &RWLockDummy::create; -}; +} diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h index 066ee498ac..37d9ee0846 100644 --- a/core/os/thread_dummy.h +++ b/core/os/thread_dummy.h @@ -36,7 +36,6 @@ #include "core/os/thread.h" class ThreadDummy : public Thread { - static Thread *create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings = Settings()); public: @@ -46,7 +45,6 @@ public: }; class RWLockDummy : public RWLock { - static RWLock *create(); public: diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h index 00dc53286e..d27399e4cc 100644 --- a/core/os/threaded_array_processor.h +++ b/core/os/threaded_array_processor.h @@ -54,19 +54,18 @@ struct ThreadArrayProcessData { template <class T> void process_array_thread(void *ud) { - T &data = *(T *)ud; while (true) { uint32_t index = atomic_increment(&data.index); - if (index >= data.elements) + if (index >= data.elements) { break; + } data.process(index); } } template <class C, class M, class U> void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - ThreadArrayProcessData<C, U> data; data.method = p_method; data.instance = p_instance; @@ -93,7 +92,6 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us template <class C, class M, class U> void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - ThreadArrayProcessData<C, U> data; data.method = p_method; data.instance = p_instance; diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp index 04deba2c14..e335ec0daa 100644 --- a/core/packed_data_container.cpp +++ b/core/packed_data_container.cpp @@ -34,51 +34,50 @@ #include "core/io/marshalls.h" Variant PackedDataContainer::getvar(const Variant &p_key, bool *r_valid) const { - bool err = false; Variant ret = _key_at_ofs(0, p_key, err); - if (r_valid) + if (r_valid) { *r_valid = !err; + } return ret; } int PackedDataContainer::size() const { - return _size(0); -}; +} Variant PackedDataContainer::_iter_init_ofs(const Array &p_iter, uint32_t p_offset) { - Array ref = p_iter; uint32_t size = _size(p_offset); - if (size == 0 || ref.size() != 1) + if (size == 0 || ref.size() != 1) { return false; - else { + } else { ref[0] = 0; return true; } } Variant PackedDataContainer::_iter_next_ofs(const Array &p_iter, uint32_t p_offset) { - Array ref = p_iter; int size = _size(p_offset); - if (ref.size() != 1) + if (ref.size() != 1) { return false; + } int pos = ref[0]; - if (pos < 0 || pos >= size) + if (pos < 0 || pos >= size) { return false; + } pos += 1; ref[0] = pos; return pos != size; } Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_offset) { - int size = _size(p_offset); int pos = p_iter; - if (pos < 0 || pos >= size) + if (pos < 0 || pos >= size) { return Variant(); + } const uint8_t *rd = data.ptr(); const uint8_t *r = &rd[p_offset]; @@ -86,12 +85,10 @@ Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_off bool err = false; if (type == TYPE_ARRAY) { - uint32_t vpos = decode_uint32(rd + p_offset + 8 + pos * 4); return _get_at_ofs(vpos, rd, err); } else if (type == TYPE_DICT) { - uint32_t vpos = decode_uint32(rd + p_offset + 8 + pos * 12 + 4); return _get_at_ofs(vpos, rd, err); } else { @@ -100,11 +97,9 @@ Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_off } Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, bool &err) const { - uint32_t type = decode_uint32(p_buf + p_ofs); if (type == TYPE_ARRAY || type == TYPE_DICT) { - Ref<PackedDataContainerRef> pdcr = memnew(PackedDataContainerRef); Ref<PackedDataContainer> pdc = Ref<PackedDataContainer>((PackedDataContainer *)this); @@ -112,12 +107,10 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b pdcr->offset = p_ofs; return pdcr; } else { - Variant v; Error rerr = decode_variant(v, p_buf + p_ofs, datalen - p_ofs, nullptr, false); if (rerr != OK) { - err = true; ERR_FAIL_COND_V_MSG(err != OK, Variant(), "Error when trying to decode Variant."); } @@ -126,45 +119,38 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b } uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const { - const uint8_t *rd = data.ptr(); const uint8_t *r = &rd[p_ofs]; uint32_t type = decode_uint32(r); return type; -}; +} int PackedDataContainer::_size(uint32_t p_ofs) const { - const uint8_t *rd = data.ptr(); ERR_FAIL_COND_V(!rd, 0); const uint8_t *r = &rd[p_ofs]; uint32_t type = decode_uint32(r); if (type == TYPE_ARRAY) { - uint32_t len = decode_uint32(r + 4); return len; } else if (type == TYPE_DICT) { - uint32_t len = decode_uint32(r + 4); return len; - }; + } return -1; -}; +} Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, bool &err) const { - const uint8_t *rd = data.ptr(); const uint8_t *r = &rd[p_ofs]; uint32_t type = decode_uint32(r); if (type == TYPE_ARRAY) { - if (p_key.is_num()) { - int idx = p_key; int len = decode_uint32(r + 4); if (idx < 0 || idx >= len) { @@ -180,7 +166,6 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b } } else if (type == TYPE_DICT) { - uint32_t hash = p_key.hash(); uint32_t len = decode_uint32(r + 4); @@ -189,16 +174,18 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b 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, err); - if (err) + if (err) { return Variant(); + } if (key == p_key) { //key matches, return value return _get_at_ofs(decode_uint32(r + 8 + i * 12 + 8), rd, err); } found = true; } else { - if (found) + if (found) { break; + } } } @@ -206,18 +193,14 @@ Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, b return Variant(); } else { - err = true; return Variant(); } } uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpdata, Map<String, uint32_t> &string_cache) { - switch (p_data.get_type()) { - case Variant::STRING: { - String s = p_data; if (string_cache.has(s)) { return string_cache[s]; @@ -251,7 +234,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd case Variant::PACKED_COLOR_ARRAY: case Variant::STRING_NAME: case Variant::NODE_PATH: { - uint32_t pos = tmpdata.size(); int len; encode_variant(p_data, nullptr, len, false); @@ -263,11 +245,9 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd // misc types case Variant::_RID: case Variant::OBJECT: { - return _pack(Variant(), tmpdata, string_cache); } break; case Variant::DICTIONARY: { - Dictionary d = p_data; //size is known, use sort uint32_t pos = tmpdata.size(); @@ -281,7 +261,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd List<DictKey> sortk; for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - DictKey dk; dk.hash = E->get().hash(); dk.key = E->get(); @@ -292,7 +271,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd int idx = 0; for (List<DictKey>::Element *E = sortk.front(); E; E = E->next()) { - encode_uint32(E->get().hash, &tmpdata.write[pos + 8 + idx * 12 + 0]); uint32_t ofs = _pack(E->get().key, tmpdata, string_cache); encode_uint32(ofs, &tmpdata.write[pos + 8 + idx * 12 + 4]); @@ -305,7 +283,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd } break; case Variant::ARRAY: { - Array a = p_data; //size is known, use sort uint32_t pos = tmpdata.size(); @@ -315,7 +292,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd encode_uint32(len, &tmpdata.write[pos + 4]); for (int i = 0; i < len; i++) { - uint32_t ofs = _pack(a[i], tmpdata, string_cache); encode_uint32(ofs, &tmpdata.write[pos + 8 + i * 4]); } @@ -332,7 +308,6 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd } Error PackedDataContainer::pack(const Variant &p_data) { - Vector<uint8_t> tmpdata; Map<String, uint32_t> string_cache; _pack(p_data, tmpdata, string_cache); @@ -345,7 +320,6 @@ Error PackedDataContainer::pack(const Variant &p_data) { } void PackedDataContainer::_set_data(const Vector<uint8_t> &p_data) { - data = p_data; datalen = data.size(); } @@ -355,21 +329,18 @@ Vector<uint8_t> PackedDataContainer::_get_data() const { } Variant PackedDataContainer::_iter_init(const Array &p_iter) { - return _iter_init_ofs(p_iter, 0); } Variant PackedDataContainer::_iter_next(const Array &p_iter) { - return _iter_next_ofs(p_iter, 0); } -Variant PackedDataContainer::_iter_get(const Variant &p_iter) { +Variant PackedDataContainer::_iter_get(const Variant &p_iter) { return _iter_get_ofs(p_iter, 0); } void PackedDataContainer::_bind_methods() { - ClassDB::bind_method(D_METHOD("_set_data"), &PackedDataContainer::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &PackedDataContainer::_get_data); ClassDB::bind_method(D_METHOD("_iter_init"), &PackedDataContainer::_iter_init); @@ -381,34 +352,25 @@ void PackedDataContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "__data__"), "_set_data", "_get_data"); } -PackedDataContainer::PackedDataContainer() { - - datalen = 0; -} - ////////////////// Variant PackedDataContainerRef::_iter_init(const Array &p_iter) { - return from->_iter_init_ofs(p_iter, offset); } Variant PackedDataContainerRef::_iter_next(const Array &p_iter) { - return from->_iter_next_ofs(p_iter, offset); } -Variant PackedDataContainerRef::_iter_get(const Variant &p_iter) { +Variant PackedDataContainerRef::_iter_get(const Variant &p_iter) { return from->_iter_get_ofs(p_iter, offset); } bool PackedDataContainerRef::_is_dictionary() const { - return from->_type_at_ofs(offset) == PackedDataContainer::TYPE_DICT; -}; +} void PackedDataContainerRef::_bind_methods() { - ClassDB::bind_method(D_METHOD("size"), &PackedDataContainerRef::size); ClassDB::bind_method(D_METHOD("_iter_init"), &PackedDataContainerRef::_iter_init); ClassDB::bind_method(D_METHOD("_iter_get"), &PackedDataContainerRef::_iter_get); @@ -417,18 +379,14 @@ void PackedDataContainerRef::_bind_methods() { } Variant PackedDataContainerRef::getvar(const Variant &p_key, bool *r_valid) const { - bool err = false; Variant ret = from->_key_at_ofs(offset, p_key, err); - if (r_valid) + if (r_valid) { *r_valid = !err; + } return ret; } int PackedDataContainerRef::size() const { - return from->_size(offset); -}; - -PackedDataContainerRef::PackedDataContainerRef() { } diff --git a/core/packed_data_container.h b/core/packed_data_container.h index 0f08a1cb7b..b41e9aaefc 100644 --- a/core/packed_data_container.h +++ b/core/packed_data_container.h @@ -34,7 +34,6 @@ #include "core/resource.h" class PackedDataContainer : public Resource { - GDCLASS(PackedDataContainer, Resource); enum { @@ -49,7 +48,7 @@ class PackedDataContainer : public Resource { }; Vector<uint8_t> data; - int datalen; + int datalen = 0; uint32_t _pack(const Variant &p_data, Vector<uint8_t> &tmpdata, Map<String, uint32_t> &string_cache); @@ -78,7 +77,7 @@ public: int size() const; - PackedDataContainer(); + PackedDataContainer() {} }; class PackedDataContainerRef : public Reference { @@ -100,7 +99,7 @@ public: int size() const; virtual Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const; - PackedDataContainerRef(); + PackedDataContainerRef() {} }; #endif // PACKED_DATA_CONTAINER_H diff --git a/core/pair.h b/core/pair.h index 26a317e9d4..89ea2b9fd9 100644 --- a/core/pair.h +++ b/core/pair.h @@ -33,7 +33,6 @@ template <class F, class S> struct Pair { - F first; S second; @@ -60,7 +59,6 @@ bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) { template <class F, class S> struct PairSort { - bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const { return A.first < B.first; } diff --git a/core/path_remap.cpp b/core/path_remap.cpp deleted file mode 100644 index e1708e0350..0000000000 --- a/core/path_remap.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************/ -/* path_remap.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "path_remap.h" diff --git a/core/path_remap.h b/core/path_remap.h deleted file mode 100644 index 1580e88625..0000000000 --- a/core/path_remap.h +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************/ -/* path_remap.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PATH_REMAP_H -#define PATH_REMAP_H - -#endif // PATH_REMAP_H diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp index b74540395c..b222c20a00 100644 --- a/core/pool_allocator.cpp +++ b/core/pool_allocator.cpp @@ -53,12 +53,11 @@ void PoolAllocator::mt_unlock() const { } bool PoolAllocator::get_free_entry(EntryArrayPos *p_pos) { - - if (entry_count == entry_max) + if (entry_count == entry_max) { return false; + } for (int i = 0; i < entry_max; i++) { - if (entry_array[i].len == 0) { *p_pos = i; return true; @@ -77,13 +76,11 @@ bool PoolAllocator::get_free_entry(EntryArrayPos *p_pos) { * @return false if hole found, true if no hole found */ bool PoolAllocator::find_hole(EntryArrayPos *p_pos, int p_for_size) { - /* position where previous entry ends. Defaults to zero (begin of pool) */ int prev_entry_end_pos = 0; for (int i = 0; i < entry_count; i++) { - Entry &entry = entry_array[entry_indices[i]]; /* determine hole size to previous entry */ @@ -111,13 +108,12 @@ bool PoolAllocator::find_hole(EntryArrayPos *p_pos, int p_for_size) { } void PoolAllocator::compact(int p_up_to) { - uint32_t prev_entry_end_pos = 0; - if (p_up_to < 0) + if (p_up_to < 0) { p_up_to = entry_count; + } for (int i = 0; i < p_up_to; i++) { - Entry &entry = entry_array[entry_indices[i]]; /* determine hole size to previous entry */ @@ -126,7 +122,6 @@ void PoolAllocator::compact(int p_up_to) { /* if we can compact, do it */ if (hole_size > 0 && !entry.lock) { - COMPACT_CHUNK(entry, prev_entry_end_pos); } @@ -136,11 +131,9 @@ void PoolAllocator::compact(int p_up_to) { } void PoolAllocator::compact_up(int p_from) { - uint32_t next_entry_end_pos = pool_size; // - static_area_size; for (int i = entry_count - 1; i >= p_from; i--) { - Entry &entry = entry_array[entry_indices[i]]; /* determine hole size to nextious entry */ @@ -149,7 +142,6 @@ void PoolAllocator::compact_up(int p_from) { /* if we can compact, do it */ if (hole_size > 0 && !entry.lock) { - COMPACT_CHUNK(entry, (next_entry_end_pos - aligned(entry.len))); } @@ -159,30 +151,29 @@ void PoolAllocator::compact_up(int p_from) { } bool PoolAllocator::find_entry_index(EntryIndicesPos *p_map_pos, Entry *p_entry) { - EntryArrayPos entry_pos = entry_max; for (int i = 0; i < entry_count; i++) { - if (&entry_array[entry_indices[i]] == p_entry) { - entry_pos = i; break; } } - if (entry_pos == entry_max) + if (entry_pos == entry_max) { return false; + } *p_map_pos = entry_pos; return true; } PoolAllocator::ID PoolAllocator::alloc(int p_size) { - ERR_FAIL_COND_V(p_size < 1, POOL_ALLOCATOR_INVALID_ID); #ifdef DEBUG_ENABLED - if (p_size > free_mem) OS::get_singleton()->debug_break(); + if (p_size > free_mem) { + OS::get_singleton()->debug_break(); + } #endif ERR_FAIL_COND_V(p_size > free_mem, POOL_ALLOCATOR_INVALID_ID); @@ -220,7 +211,6 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) { /* move all entry indices up, make room for this one */ for (int i = entry_count; i > new_entry_indices_pos; i--) { - entry_indices[i] = entry_indices[i - 1]; } @@ -235,8 +225,9 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) { entry.lock = 0; entry.check = (check_count++) & CHECK_MASK; free_mem -= size_to_alloc; - if (free_mem < free_mem_peak) + if (free_mem < free_mem_peak) { free_mem_peak = free_mem; + } ID retval = (entry_indices[new_entry_indices_pos] << CHECK_BITS) | entry.check; mt_unlock(); @@ -247,7 +238,6 @@ PoolAllocator::ID PoolAllocator::alloc(int p_size) { } PoolAllocator::Entry *PoolAllocator::get_entry(ID p_mem) { - unsigned int check = p_mem & CHECK_MASK; int entry = p_mem >> CHECK_BITS; ERR_FAIL_INDEX_V(entry, entry_max, nullptr); @@ -258,7 +248,6 @@ PoolAllocator::Entry *PoolAllocator::get_entry(ID p_mem) { } const PoolAllocator::Entry *PoolAllocator::get_entry(ID p_mem) const { - unsigned int check = p_mem & CHECK_MASK; int entry = p_mem >> CHECK_BITS; ERR_FAIL_INDEX_V(entry, entry_max, nullptr); @@ -269,7 +258,6 @@ const PoolAllocator::Entry *PoolAllocator::get_entry(ID p_mem) const { } void PoolAllocator::free(ID p_mem) { - mt_lock(); Entry *e = get_entry(p_mem); if (!e) { @@ -287,13 +275,11 @@ void PoolAllocator::free(ID p_mem) { bool index_found = find_entry_index(&entry_indices_pos, e); if (!index_found) { - mt_unlock(); ERR_FAIL_COND(!index_found); } for (int i = entry_indices_pos; i < (entry_count - 1); i++) { - entry_indices[i] = entry_indices[i + 1]; } @@ -304,13 +290,11 @@ void PoolAllocator::free(ID p_mem) { } int PoolAllocator::get_size(ID p_mem) const { - int size; mt_lock(); const Entry *e = get_entry(p_mem); if (!e) { - mt_unlock(); ERR_PRINT("!e"); return 0; @@ -324,7 +308,6 @@ int PoolAllocator::get_size(ID p_mem) const { } Error PoolAllocator::resize(ID p_mem, int p_new_size) { - mt_lock(); Entry *e = get_entry(p_mem); @@ -341,12 +324,10 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) { uint32_t alloc_size = aligned(p_new_size); if ((uint32_t)aligned(e->len) == alloc_size) { - e->len = p_new_size; mt_unlock(); return OK; } else if (e->len > (uint32_t)p_new_size) { - free_mem += aligned(e->len); free_mem -= alloc_size; e->len = p_new_size; @@ -360,14 +341,13 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) { if (uint32_t(_free + aligned(e->len)) < alloc_size) { mt_unlock(); ERR_FAIL_V(ERR_OUT_OF_MEMORY); - }; + } EntryIndicesPos entry_indices_pos; bool index_found = find_entry_index(&entry_indices_pos, e); if (!index_found) { - mt_unlock(); ERR_FAIL_COND_V(!index_found, ERR_BUG); } @@ -378,7 +358,7 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) { next_pos = pool_size; // - static_area_size; } else { next_pos = entry_array[entry_indices[entry_indices_pos + 1]].pos; - }; + } if ((next_pos - e->pos) > alloc_size) { free_mem += aligned(e->len); @@ -397,8 +377,9 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) { e->len = p_new_size; free_mem -= alloc_size; mt_unlock(); - if (free_mem < free_mem_peak) + if (free_mem < free_mem_peak) { free_mem_peak = free_mem; + } return OK; } @@ -412,8 +393,9 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) { e->len = p_new_size; free_mem -= alloc_size; mt_unlock(); - if (free_mem < free_mem_peak) + if (free_mem < free_mem_peak) { free_mem_peak = free_mem; + } return OK; } @@ -422,13 +404,12 @@ Error PoolAllocator::resize(ID p_mem, int p_new_size) { } Error PoolAllocator::lock(ID p_mem) { - - if (!needs_locking) + if (!needs_locking) { return OK; + } mt_lock(); Entry *e = get_entry(p_mem); if (!e) { - mt_unlock(); ERR_PRINT("!e"); return ERR_INVALID_PARAMETER; @@ -439,14 +420,13 @@ Error PoolAllocator::lock(ID p_mem) { } bool PoolAllocator::is_locked(ID p_mem) const { - - if (!needs_locking) + if (!needs_locking) { return false; + } mt_lock(); const Entry *e = ((PoolAllocator *)(this))->get_entry(p_mem); if (!e) { - mt_unlock(); ERR_PRINT("!e"); return false; @@ -457,9 +437,7 @@ bool PoolAllocator::is_locked(ID p_mem) const { } const void *PoolAllocator::get(ID p_mem) const { - if (!needs_locking) { - const Entry *e = get_entry(p_mem); ERR_FAIL_COND_V(!e, nullptr); return &pool[e->pos]; @@ -469,19 +447,16 @@ const void *PoolAllocator::get(ID p_mem) const { const Entry *e = get_entry(p_mem); if (!e) { - mt_unlock(); ERR_FAIL_COND_V(!e, nullptr); } if (e->lock == 0) { - mt_unlock(); ERR_PRINT("e->lock == 0"); return nullptr; } if ((int)e->pos >= pool_size) { - mt_unlock(); ERR_PRINT("e->pos<0 || e->pos>=pool_size"); return nullptr; @@ -494,9 +469,7 @@ const void *PoolAllocator::get(ID p_mem) const { } void *PoolAllocator::get(ID p_mem) { - if (!needs_locking) { - Entry *e = get_entry(p_mem); ERR_FAIL_COND_V(!e, nullptr); return &pool[e->pos]; @@ -506,12 +479,10 @@ void *PoolAllocator::get(ID p_mem) { Entry *e = get_entry(p_mem); if (!e) { - mt_unlock(); ERR_FAIL_COND_V(!e, nullptr); } if (e->lock == 0) { - //assert(0); mt_unlock(); ERR_PRINT("e->lock == 0"); @@ -519,7 +490,6 @@ void *PoolAllocator::get(ID p_mem) { } if ((int)e->pos >= pool_size) { - mt_unlock(); ERR_PRINT("e->pos<0 || e->pos>=pool_size"); return nullptr; @@ -530,10 +500,11 @@ void *PoolAllocator::get(ID p_mem) { return ptr; } -void PoolAllocator::unlock(ID p_mem) { - if (!needs_locking) +void PoolAllocator::unlock(ID p_mem) { + if (!needs_locking) { return; + } mt_lock(); Entry *e = get_entry(p_mem); if (!e) { @@ -550,22 +521,18 @@ void PoolAllocator::unlock(ID p_mem) { } int PoolAllocator::get_used_mem() const { - return pool_size - free_mem; } int PoolAllocator::get_free_peak() { - return free_mem_peak; } int PoolAllocator::get_free_mem() { - return free_mem; } void PoolAllocator::create_pool(void *p_mem, int p_size, int p_max_entries) { - pool = (uint8_t *)p_mem; pool_size = p_size; @@ -581,7 +548,6 @@ void PoolAllocator::create_pool(void *p_mem, int p_size, int p_max_entries) { } PoolAllocator::PoolAllocator(int p_size, bool p_needs_locking, int p_max_entries) { - mem_ptr = memalloc(p_size); ERR_FAIL_COND(!mem_ptr); align = 1; @@ -590,9 +556,7 @@ PoolAllocator::PoolAllocator(int p_size, bool p_needs_locking, int p_max_entries } PoolAllocator::PoolAllocator(void *p_mem, int p_size, int p_align, bool p_needs_locking, int p_max_entries) { - if (p_align > 1) { - uint8_t *mem8 = (uint8_t *)p_mem; uint64_t ofs = (uint64_t)mem8; if (ofs % p_align) { @@ -600,8 +564,8 @@ PoolAllocator::PoolAllocator(void *p_mem, int p_size, int p_align, bool p_needs_ mem8 += p_align - (ofs % p_align); p_size -= dif; p_mem = (void *)mem8; - }; - }; + } + } create_pool(p_mem, p_size, p_max_entries); needs_locking = p_needs_locking; @@ -610,22 +574,22 @@ PoolAllocator::PoolAllocator(void *p_mem, int p_size, int p_align, bool p_needs_ } PoolAllocator::PoolAllocator(int p_align, int p_size, bool p_needs_locking, int p_max_entries) { - ERR_FAIL_COND(p_align < 1); mem_ptr = Memory::alloc_static(p_size + p_align, true); uint8_t *mem8 = (uint8_t *)mem_ptr; uint64_t ofs = (uint64_t)mem8; - if (ofs % p_align) + if (ofs % p_align) { mem8 += p_align - (ofs % p_align); + } create_pool(mem8, p_size, p_max_entries); needs_locking = p_needs_locking; align = p_align; } PoolAllocator::~PoolAllocator() { - - if (mem_ptr) + if (mem_ptr) { memfree(mem_ptr); + } memdelete_arr(entry_array); memdelete_arr(entry_indices); diff --git a/core/pool_allocator.h b/core/pool_allocator.h index 8c1710ebe0..7d77af6266 100644 --- a/core/pool_allocator.h +++ b/core/pool_allocator.h @@ -60,11 +60,10 @@ private: }; struct Entry { - - unsigned int pos; - unsigned int len; - unsigned int lock; - unsigned int check; + unsigned int pos = 0; + unsigned int len = 0; + unsigned int lock = 0; + unsigned int check = 0; inline void clear() { pos = 0; @@ -72,7 +71,7 @@ private: lock = 0; check = 0; } - Entry() { clear(); } + Entry() {} }; typedef int EntryArrayPos; @@ -99,10 +98,10 @@ private: return p_entry.pos + aligned(p_entry.len); } inline int aligned(int p_size) const { - int rem = p_size % align; - if (rem) + if (rem) { p_size += align - rem; + } return p_size; } diff --git a/core/print_string.cpp b/core/print_string.cpp index 8eb1d9e86a..54de229471 100644 --- a/core/print_string.cpp +++ b/core/print_string.cpp @@ -39,7 +39,6 @@ bool _print_line_enabled = true; bool _print_error_enabled = true; void add_print_handler(PrintHandlerList *p_handler) { - _global_lock(); p_handler->next = print_handler_list; print_handler_list = p_handler; @@ -47,20 +46,18 @@ void add_print_handler(PrintHandlerList *p_handler) { } void remove_print_handler(PrintHandlerList *p_handler) { - _global_lock(); PrintHandlerList *prev = nullptr; PrintHandlerList *l = print_handler_list; while (l) { - if (l == p_handler) { - - if (prev) + if (prev) { prev->next = l->next; - else + } else { print_handler_list = l->next; + } break; } prev = l; @@ -73,16 +70,15 @@ void remove_print_handler(PrintHandlerList *p_handler) { } void print_line(String p_string) { - - if (!_print_line_enabled) + if (!_print_line_enabled) { return; + } OS::get_singleton()->print("%s\n", p_string.utf8().get_data()); _global_lock(); PrintHandlerList *l = print_handler_list; while (l) { - l->printfunc(l->userdata, p_string, false); l = l->next; } @@ -91,16 +87,15 @@ void print_line(String p_string) { } void print_error(String p_string) { - - if (!_print_error_enabled) + if (!_print_error_enabled) { return; + } OS::get_singleton()->printerr("%s\n", p_string.utf8().get_data()); _global_lock(); PrintHandlerList *l = print_handler_list; while (l) { - l->printfunc(l->userdata, p_string, true); l = l->next; } @@ -109,7 +104,6 @@ void print_error(String p_string) { } void print_verbose(String p_string) { - if (OS::get_singleton()->is_stdout_verbose()) { print_line(p_string); } diff --git a/core/print_string.h b/core/print_string.h index d83cc35dd6..4d03f4a6de 100644 --- a/core/print_string.h +++ b/core/print_string.h @@ -38,17 +38,12 @@ extern void (*_print_func)(String); typedef void (*PrintHandlerFunc)(void *, const String &p_string, bool p_error); struct PrintHandlerList { + PrintHandlerFunc printfunc = nullptr; + void *userdata = nullptr; - PrintHandlerFunc printfunc; - void *userdata; + PrintHandlerList *next = nullptr; - PrintHandlerList *next; - - PrintHandlerList() { - printfunc = 0; - next = 0; - userdata = 0; - } + PrintHandlerList() {} }; void add_print_handler(PrintHandlerList *p_handler); diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 63b52661b4..5247f6da40 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -46,30 +46,28 @@ ProjectSettings *ProjectSettings::singleton = nullptr; ProjectSettings *ProjectSettings::get_singleton() { - return singleton; } String ProjectSettings::get_resource_path() const { - return resource_path; -}; +} String ProjectSettings::localize_path(const String &p_path) const { - - if (resource_path == "") + if (resource_path == "") { return p_path; //not initialized yet + } if (p_path.begins_with("res://") || p_path.begins_with("user://") || - (p_path.is_abs_path() && !p_path.begins_with(resource_path))) + (p_path.is_abs_path() && !p_path.begins_with(resource_path))) { return p_path.simplify_path(); + } DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); String path = p_path.replace("\\", "/").simplify_path(); if (dir->change_dir(path) == OK) { - String cwd = dir->get_current_dir(); cwd = cwd.replace("\\", "/"); @@ -89,59 +87,52 @@ String ProjectSettings::localize_path(const String &p_path) const { if (!cwd.begins_with(res_path)) { return p_path; - }; + } return cwd.replace_first(res_path, "res://"); } else { - memdelete(dir); int sep = path.find_last("/"); if (sep == -1) { return "res://" + path; - }; + } String parent = path.substr(0, sep); String plocal = localize_path(parent); if (plocal == "") { return ""; - }; + } // Only strip the starting '/' from 'path' if its parent ('plocal') ends with '/' if (plocal[plocal.length() - 1] == '/') { sep += 1; } return plocal + path.substr(sep, path.size() - sep); - }; + } } void ProjectSettings::set_initial_value(const String &p_name, const Variant &p_value) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); props[p_name].initial = p_value; } -void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) { +void ProjectSettings::set_restart_if_changed(const String &p_name, bool p_restart) { ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); props[p_name].restart_if_changed = p_restart; } String ProjectSettings::globalize_path(const String &p_path) const { - if (p_path.begins_with("res://")) { - if (resource_path != "") { - 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_user_data_dir(); if (data_dir != "") { - return p_path.replace("user:/", data_dir); - }; + } return p_path.replace("user://", ""); } @@ -149,17 +140,14 @@ String ProjectSettings::globalize_path(const String &p_path) const { } bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { - _THREAD_SAFE_METHOD_ - if (p_value.get_type() == Variant::NIL) + if (p_value.get_type() == Variant::NIL) { props.erase(p_name); - else { - + } else { if (p_name == CoreStringNames::get_singleton()->_custom_features) { Vector<String> custom_feature_array = String(p_value).split(","); for (int i = 0; i < custom_feature_array.size(); i++) { - custom_features.insert(custom_feature_array[i]); } return true; @@ -180,15 +168,15 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { } if (override_valid) { - feature_overrides[s[0]] = p_name; } } } if (props.has(p_name)) { - if (!props[p_name].overridden) + if (!props[p_name].overridden) { props[p_name].variant = p_value; + } } else { props[p_name] = VariantContainer(p_value, last_order++); @@ -197,8 +185,8 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) { return true; } -bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const { +bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const { _THREAD_SAFE_METHOD_ StringName name = p_name; @@ -214,7 +202,6 @@ bool ProjectSettings::_get(const StringName &p_name, Variant &r_ret) const { } struct _VCSort { - String name; Variant::Type type; int order; @@ -224,26 +211,26 @@ struct _VCSort { }; void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const { - _THREAD_SAFE_METHOD_ Set<_VCSort> vclist; for (Map<StringName, VariantContainer>::Element *E = props.front(); E; E = E->next()) { - const VariantContainer *v = &E->get(); - if (v->hide_from_editor) + if (v->hide_from_editor) { continue; + } _VCSort vc; vc.name = E->key(); vc.order = v->order; vc.type = v->variant.get_type(); - if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload")) + if (vc.name.begins_with("input/") || vc.name.begins_with("import/") || vc.name.begins_with("export/") || vc.name.begins_with("/remap") || vc.name.begins_with("/locale") || vc.name.begins_with("/autoload")) { vc.flags = PROPERTY_USAGE_STORAGE; - else + } else { vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE; + } if (v->restart_if_changed) { vc.flags |= PROPERTY_USAGE_RESTART_IF_CHANGED; @@ -252,31 +239,33 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const { } for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) { - String prop_info_name = E->get().name; int dot = prop_info_name.find("."); - if (dot != -1) + if (dot != -1) { prop_info_name = prop_info_name.substr(0, dot); + } if (custom_prop_info.has(prop_info_name)) { PropertyInfo pi = custom_prop_info[prop_info_name]; pi.name = E->get().name; pi.usage = E->get().flags; p_list->push_back(pi); - } else + } else { p_list->push_back(PropertyInfo(E->get().type, E->get().name, PROPERTY_HINT_NONE, "", E->get().flags)); + } } } bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_files) { - - if (PackedData::get_singleton()->is_disabled()) + if (PackedData::get_singleton()->is_disabled()) { return false; + } bool ok = PackedData::get_singleton()->add_pack(p_pack, p_replace_files) == OK; - if (!ok) + if (!ok) { return false; + } //if data.pck is found, all directory access will be from here DirAccess::make_default<DirAccessPack>(DirAccess::ACCESS_RESOURCES); @@ -286,7 +275,6 @@ bool ProjectSettings::_load_resource_pack(const String &p_pack, bool p_replace_f } void ProjectSettings::_convert_to_last_version(int p_from_version) { - if (p_from_version <= 3) { // Converts the actions from array to dictionary (array of events to dictionary with deadzone + events) for (Map<StringName, ProjectSettings::VariantContainer>::Element *E = props.front(); E; E = E->next()) { @@ -307,10 +295,16 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) { * using the following merit order: * - If using NetworkClient, try to lookup project file or fail. * - If --main-pack was passed by the user (`p_main_pack`), load it or fail. - * - Search for .pck file matching binary name. There are two possibilities: - * o exec_path.get_basename() + '.pck' (e.g. 'win_game.exe' -> 'win_game.pck') - * o exec_path + '.pck' (e.g. 'linux_game' -> 'linux_game.pck') - * For each tentative, if the file exists, load it or fail. + * - Search for project PCKs automatically. For each step we try loading a potential + * PCK, and if it doesn't work, we proceed to the next step. If any step succeeds, + * we try loading the project settings, and abort if it fails. Steps: + * o Bundled PCK in the executable. + * o [macOS only] PCK with same basename as the binary in the .app resource dir. + * o PCK with same basename as the binary in the binary's directory. We handle both + * changing the extension to '.pck' (e.g. 'win_game.exe' -> 'win_game.pck') and + * appending '.pck' to the binary name (e.g. 'linux_game' -> 'linux_game.pck'). + * o PCK with the same basename as the binary in the current working directory. + * Same as above for the two possible PCK file names. * - On relevant platforms (Android/iOS), lookup project file in OS resource path. * If found, load it or fail. * - Lookup project file in passed `p_path` (--path passed by the user), i.e. we @@ -322,11 +316,9 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) { * If nothing was found, error out. */ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, bool p_upwards) { - // If looking for files in a network client, use it directly if (FileAccessNetworkClient::get_singleton()) { - Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); if (err == OK) { // Optional, we don't mind if it fails @@ -338,7 +330,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b // Attempt with a user-defined main pack first if (p_main_pack != "") { - bool ok = _load_resource_pack(p_main_pack); ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, "Cannot open resource pack '" + p_main_pack + "'."); @@ -354,76 +345,68 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b String exec_path = OS::get_singleton()->get_executable_path(); if (exec_path != "") { - // Attempt with exec_name.pck - // (This is the usual case when distributing a Godot game.) - - // Based on the OS, it can be the exec path + '.pck' (Linux w/o extension, macOS in .app bundle) - // or the exec path's basename + '.pck' (Windows). - // We need to test both possibilities as extensions for Linux binaries are optional - // (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck'). + // We do several tests sequentially until one succeeds to find a PCK, + // and if so we attempt loading it at the end. - bool found = false; + // Attempt with PCK bundled into executable. + bool found = _load_resource_pack(exec_path); + // Attempt with exec_name.pck. + // (This is the usual case when distributing a Godot game.) String exec_dir = exec_path.get_base_dir(); String exec_filename = exec_path.get_file(); String exec_basename = exec_filename.get_basename(); - // Try to load data pack at the location of the executable - // As mentioned above, we have two potential names to attempt - - if (_load_resource_pack(exec_dir.plus_file(exec_basename + ".pck")) || - _load_resource_pack(exec_dir.plus_file(exec_filename + ".pck"))) { - found = true; - } else { - // If we couldn't find them next to the executable, we attempt - // the current working directory. Same story, two tests. - if (_load_resource_pack(exec_basename + ".pck") || - _load_resource_pack(exec_filename + ".pck")) { - found = true; - } - } + // Based on the OS, it can be the exec path + '.pck' (Linux w/o extension, macOS in .app bundle) + // or the exec path's basename + '.pck' (Windows). + // We need to test both possibilities as extensions for Linux binaries are optional + // (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck'). #ifdef OSX_ENABLED - // Attempt to load PCK from macOS .app bundle resources if (!found) { - if (_load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck"))) { - found = true; - } + // Attempt to load PCK from macOS .app bundle resources. + found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")); } #endif - // Attempt with PCK bundled into executable if (!found) { - if (_load_resource_pack(exec_path)) { - found = true; - } + // Try to load data pack at the location of the executable. + // As mentioned above, we have two potential names to attempt. + found = _load_resource_pack(exec_dir.plus_file(exec_basename + ".pck")) || _load_resource_pack(exec_dir.plus_file(exec_filename + ".pck")); + } + + if (!found) { + // If we couldn't find them next to the executable, we attempt + // the current working directory. Same story, two tests. + found = _load_resource_pack(exec_basename + ".pck") || _load_resource_pack(exec_filename + ".pck"); } - // If we opened our package, try and load our project + // If we opened our package, try and load our project. if (found) { Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); if (err == OK) { - // Load override from location of executable - // Optional, we don't mind if it fails + // Load override from location of the executable. + // Optional, we don't mind if it fails. _load_settings_text(exec_path.get_base_dir().plus_file("override.cfg")); } return err; } } - // Try to use the filesystem for files, according to OS. (only Android -when reading from pck- and iOS use this) + // Try to use the filesystem for files, according to OS. + // (Only Android -when reading from pck- and iOS use this.) if (OS::get_singleton()->get_resource_dir() != "") { // OS will call ProjectSettings->get_resource_path which will be empty if not overridden! // If the OS would rather use a specific location, then it will not be empty. resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/"); if (resource_path != "" && resource_path[resource_path.length() - 1] == '/') { - resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end + resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end. } Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); if (err == OK) { - // Optional, we don't mind if it fails + // Optional, we don't mind if it fails. _load_settings_text("res://override.cfg"); } return err; @@ -444,7 +427,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b while (true) { err = _load_settings_text_or_binary(current_dir.plus_file("project.godot"), current_dir.plus_file("project.binary")); if (err == OK) { - // Optional, we don't mind if it fails + // Optional, we don't mind if it fails. _load_settings_text(current_dir.plus_file("override.cfg")); candidate = current_dir; found = true; @@ -454,8 +437,9 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b if (p_upwards) { // Try to load settings ascending through parent directories d->change_dir(".."); - if (d->get_current_dir() == current_dir) + if (d->get_current_dir() == current_dir) { break; // not doing anything useful + } current_dir = d->get_current_dir(); } else { break; @@ -463,14 +447,16 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b } resource_path = candidate; - resource_path = resource_path.replace("\\", "/"); // windows path to unix path just in case + resource_path = resource_path.replace("\\", "/"); // Windows path to Unix path just in case. memdelete(d); - if (!found) + if (!found) { return err; + } - if (resource_path.length() && resource_path[resource_path.length() - 1] == '/') - resource_path = resource_path.substr(0, resource_path.length() - 1); // chop end + if (resource_path.length() && resource_path[resource_path.length() - 1] == '/') { + resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end. + } return OK; } @@ -488,19 +474,16 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bo } bool ProjectSettings::has_setting(String p_var) const { - _THREAD_SAFE_METHOD_ return props.has(p_var); } void ProjectSettings::set_registering_order(bool p_enable) { - registering_order = p_enable; } Error ProjectSettings::_load_settings_binary(const String &p_path) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); if (err != OK) { @@ -510,7 +493,6 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) { uint8_t hdr[4]; f->get_buffer(hdr, 4); if (hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G') { - memdelete(f); ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Corrupted header in binary project.binary (not ECFG)."); } @@ -518,7 +500,6 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) { uint32_t count = f->get_32(); for (uint32_t i = 0; i < count; i++) { - uint32_t slen = f->get_32(); CharString cs; cs.resize(slen + 1); @@ -543,7 +524,6 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) { } Error ProjectSettings::_load_settings_text(const String &p_path) { - Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -566,7 +546,6 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { int config_version = 0; while (true) { - assign = Variant(); next_tag.fields.clear(); next_tag.name = String(); @@ -605,7 +584,6 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { } Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, const String &p_bin_path) { - // Attempt first to load the text-based project.godot file Error err_text = _load_settings_text(p_text_path); if (err_text == OK) { @@ -622,19 +600,16 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, } int ProjectSettings::get_order(const String &p_name) const { - ERR_FAIL_COND_V_MSG(!props.has(p_name), -1, "Request for nonexistent project setting: " + p_name + "."); return props[p_name].order; } void ProjectSettings::set_order(const String &p_name, int p_order) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); props[p_name].order = p_order; } void ProjectSettings::set_builtin_order(const String &p_name) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); if (props[p_name].order >= NO_BUILTIN_ORDER_BASE) { props[p_name].order = last_builtin_order++; @@ -642,18 +617,15 @@ void ProjectSettings::set_builtin_order(const String &p_name) { } void ProjectSettings::clear(const String &p_name) { - ERR_FAIL_COND_MSG(!props.has(p_name), "Request for nonexistent project setting: " + p_name + "."); props.erase(p_name); } Error ProjectSettings::save() { - return save_custom(get_resource_path().plus_file("project.godot")); } Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) { - Error err; FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err); ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + "."); @@ -664,9 +636,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str int count = 0; for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) { - for (List<String>::Element *F = E->get().front(); F; F = F->next()) { - count++; } } @@ -701,33 +671,35 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str } for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) { - for (List<String>::Element *F = E->get().front(); F; F = F->next()) { - String key = F->get(); - if (E->key() != "") + if (E->key() != "") { key = E->key() + "/" + key; + } Variant value; - if (p_custom.has(key)) + if (p_custom.has(key)) { value = p_custom[key]; - else + } else { value = get(key); + } file->store_32(key.length()); file->store_string(key); int len; err = encode_variant(value, nullptr, len, true); - if (err != OK) + if (err != OK) { memdelete(file); + } ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant."); Vector<uint8_t> buff; buff.resize(len); err = encode_variant(value, buff.ptrw(), len, true); - if (err != OK) + if (err != OK) { memdelete(file); + } ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant."); file->store_32(len); file->store_buffer(buff.ptr(), buff.size()); @@ -741,7 +713,6 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str } Error ProjectSettings::_save_settings_text(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) { - Error err; FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err); @@ -757,27 +728,30 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin file->store_line(""); file->store_string("config_version=" + itos(CONFIG_VERSION) + "\n"); - if (p_custom_features != String()) + if (p_custom_features != String()) { file->store_string("custom_features=\"" + p_custom_features + "\"\n"); + } file->store_string("\n"); for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) { - - if (E != props.front()) + if (E != props.front()) { file->store_string("\n"); + } - if (E->key() != "") + if (E->key() != "") { file->store_string("[" + E->key() + "]\n\n"); + } for (List<String>::Element *F = E->get().front(); F; F = F->next()) { - String key = F->get(); - if (E->key() != "") + if (E->key() != "") { key = E->key() + "/" + key; + } Variant value; - if (p_custom.has(key)) + if (p_custom.has(key)) { value = p_custom[key]; - else + } else { value = get(key); + } String vstr; VariantWriter::write_to_string(value, vstr); @@ -794,39 +768,39 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin Error ProjectSettings::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array? return save_custom(p_file); -}; +} Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_custom, const Vector<String> &p_custom_features, bool p_merge_with_current) { - ERR_FAIL_COND_V_MSG(p_path == "", ERR_INVALID_PARAMETER, "Project settings save path cannot be empty."); Set<_VCSort> vclist; if (p_merge_with_current) { for (Map<StringName, VariantContainer>::Element *G = props.front(); G; G = G->next()) { - const VariantContainer *v = &G->get(); - if (v->hide_from_editor) + if (v->hide_from_editor) { continue; + } - if (p_custom.has(G->key())) + if (p_custom.has(G->key())) { continue; + } _VCSort vc; vc.name = G->key(); //*k; vc.order = v->order; vc.type = v->variant.get_type(); vc.flags = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE; - if (v->variant == v->initial) + if (v->variant == v->initial) { continue; + } vclist.insert(vc); } } for (const Map<String, Variant>::Element *E = p_custom.front(); E; E = E->next()) { - // Lookup global prop to store in the same order Map<StringName, VariantContainer>::Element *global_prop = props.find(E->key()); @@ -841,16 +815,14 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust Map<String, List<String>> props; for (Set<_VCSort>::Element *E = vclist.front(); E; E = E->next()) { - String category = E->get().name; String name = E->get().name; int div = category.find("/"); - if (div < 0) + if (div < 0) { category = ""; - else { - + } else { category = category.substr(0, div); name = name.substr(div + 1, name.size()); } @@ -860,25 +832,24 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust String custom_features; for (int i = 0; i < p_custom_features.size(); i++) { - if (i > 0) + if (i > 0) { custom_features += ","; + } String f = p_custom_features[i].strip_edges().replace("\"", ""); custom_features += f; } - if (p_path.ends_with(".godot")) + if (p_path.ends_with(".godot")) { return _save_settings_text(p_path, props, p_custom, custom_features); - else if (p_path.ends_with(".binary")) + } else if (p_path.ends_with(".binary")) { return _save_settings_binary(p_path, props, p_custom, custom_features); - else { - + } else { ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unknown config file format: " + p_path + "."); } } Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restart_if_changed) { - Variant ret; if (!ProjectSettings::get_singleton()->has_setting(p_var)) { ProjectSettings::get_singleton()->set(p_var, p_default); @@ -892,15 +863,14 @@ Variant _GLOBAL_DEF(const String &p_var, const Variant &p_default, bool p_restar } Vector<String> ProjectSettings::get_optimizer_presets() const { - List<PropertyInfo> pi; ProjectSettings::get_singleton()->get_property_list(&pi); Vector<String> names; for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) { - - if (!E->get().name.begins_with("optimizer_presets/")) + if (!E->get().name.begins_with("optimizer_presets/")) { continue; + } names.push_back(E->get().name.get_slicec('/', 1)); } @@ -910,7 +880,6 @@ Vector<String> ProjectSettings::get_optimizer_presets() const { } void ProjectSettings::_add_property_info_bind(const Dictionary &p_info) { - ERR_FAIL_COND(!p_info.has("name")); ERR_FAIL_COND(!p_info.has("type")); @@ -920,16 +889,17 @@ void ProjectSettings::_add_property_info_bind(const Dictionary &p_info) { pinfo.type = Variant::Type(p_info["type"].operator int()); ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX); - if (p_info.has("hint")) + if (p_info.has("hint")) { pinfo.hint = PropertyHint(p_info["hint"].operator int()); - if (p_info.has("hint_string")) + } + if (p_info.has("hint_string")) { pinfo.hint_string = p_info["hint_string"]; + } set_custom_property_info(pinfo.name, pinfo); } void ProjectSettings::set_custom_property_info(const String &p_prop, const PropertyInfo &p_info) { - ERR_FAIL_COND(!props.has(p_prop)); custom_prop_info[p_prop] = p_info; custom_prop_info[p_prop].name = p_prop; @@ -940,27 +910,25 @@ const Map<StringName, PropertyInfo> &ProjectSettings::get_custom_property_info() } void ProjectSettings::set_disable_feature_overrides(bool p_disable) { - disable_feature_overrides = p_disable; } bool ProjectSettings::is_using_datapack() const { - return using_datapack; } bool ProjectSettings::property_can_revert(const String &p_name) { - - if (!props.has(p_name)) + if (!props.has(p_name)) { return false; + } return props[p_name].initial != props[p_name].variant; } Variant ProjectSettings::property_get_revert(const String &p_name) { - - if (!props.has(p_name)) + if (!props.has(p_name)) { return Variant(); + } return props[p_name].initial; } @@ -978,7 +946,6 @@ bool ProjectSettings::has_custom_feature(const String &p_feature) const { } void ProjectSettings::_bind_methods() { - 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); @@ -998,12 +965,7 @@ void ProjectSettings::_bind_methods() { } ProjectSettings::ProjectSettings() { - singleton = this; - last_order = NO_BUILTIN_ORDER_BASE; - last_builtin_order = 0; - disable_feature_overrides = false; - registering_order = true; Array events; Dictionary action; @@ -1025,8 +987,9 @@ ProjectSettings::ProjectSettings() { PackedStringArray extensions = PackedStringArray(); extensions.push_back("gd"); - if (Engine::get_singleton()->has_singleton("GodotSharp")) + if (Engine::get_singleton()->has_singleton("GodotSharp")) { extensions.push_back("cs"); + } extensions.push_back("shader"); GLOBAL_DEF("editor/search_in_file_extensions", extensions); @@ -1048,7 +1011,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_SPACE); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_BUTTON_0); + joyb->set_button_index(JOY_BUTTON_A); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_accept", action); @@ -1061,7 +1024,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_SPACE); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_BUTTON_3); + joyb->set_button_index(JOY_BUTTON_Y); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_select", action); @@ -1074,7 +1037,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_ESCAPE); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_BUTTON_1); + joyb->set_button_index(JOY_BUTTON_B); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_cancel", action); @@ -1108,7 +1071,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_LEFT); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_DPAD_LEFT); + joyb->set_button_index(JOY_BUTTON_DPAD_LEFT); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_left", action); @@ -1121,7 +1084,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_RIGHT); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_DPAD_RIGHT); + joyb->set_button_index(JOY_BUTTON_DPAD_RIGHT); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_right", action); @@ -1134,7 +1097,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_UP); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_DPAD_UP); + joyb->set_button_index(JOY_BUTTON_DPAD_UP); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_up", action); @@ -1147,7 +1110,7 @@ ProjectSettings::ProjectSettings() { key->set_keycode(KEY_DOWN); events.push_back(key); joyb.instance(); - joyb->set_button_index(JOY_DPAD_DOWN); + joyb->set_button_index(JOY_BUTTON_DPAD_DOWN); events.push_back(joyb); action["events"] = events; GLOBAL_DEF("input/ui_down", action); @@ -1214,11 +1177,8 @@ ProjectSettings::ProjectSettings() { 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"); - - using_datapack = false; } ProjectSettings::~ProjectSettings() { - singleton = nullptr; } diff --git a/core/project_settings.h b/core/project_settings.h index 7b3ca18c62..3ed80738a1 100644 --- a/core/project_settings.h +++ b/core/project_settings.h @@ -36,7 +36,6 @@ #include "core/set.h" class ProjectSettings : public Object { - GDCLASS(ProjectSettings, Object); _THREAD_SAFE_CLASS_ @@ -50,38 +49,31 @@ public: protected: struct VariantContainer { - int order; - bool persist; + int order = 0; + bool persist = false; Variant variant; Variant initial; - bool hide_from_editor; - bool overridden; - bool restart_if_changed; - VariantContainer() : - order(0), - persist(false), - hide_from_editor(false), - overridden(false), - restart_if_changed(false) { - } + bool hide_from_editor = false; + bool overridden = false; + bool restart_if_changed = false; + + VariantContainer() {} + VariantContainer(const Variant &p_variant, int p_order, bool p_persist = false) : order(p_order), persist(p_persist), - variant(p_variant), - hide_from_editor(false), - overridden(false), - restart_if_changed(false) { + variant(p_variant) { } }; - bool registering_order; - int last_order; - int last_builtin_order; + bool registering_order = true; + int last_order = 0; + int last_builtin_order = NO_BUILTIN_ORDER_BASE; Map<StringName, VariantContainer> props; String resource_path; Map<StringName, PropertyInfo> custom_prop_info; - bool disable_feature_overrides; - bool using_datapack; + bool disable_feature_overrides = false; + bool using_datapack = false; List<String> input_presets; Set<String> custom_features; diff --git a/core/reference.cpp b/core/reference.cpp index dd65ccce69..d1dba0d9bf 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -33,22 +33,18 @@ #include "core/script_language.h" bool Reference::init_ref() { - if (reference()) { - if (!is_referenced() && refcount_init.unref()) { unreference(); // first referencing is already 1, so compensate for the ref above } return true; } else { - return false; } } void Reference::_bind_methods() { - ClassDB::bind_method(D_METHOD("init_ref"), &Reference::init_ref); ClassDB::bind_method(D_METHOD("reference"), &Reference::reference); ClassDB::bind_method(D_METHOD("unreference"), &Reference::unreference); @@ -59,7 +55,6 @@ int Reference::reference_get_count() const { } bool Reference::reference() { - uint32_t rc_val = refcount.refval(); bool success = rc_val != 0; @@ -80,7 +75,6 @@ bool Reference::reference() { } bool Reference::unreference() { - uint32_t rc_val = refcount.unrefval(); bool die = rc_val == 0; @@ -104,25 +98,21 @@ bool Reference::unreference() { Reference::Reference() : Object(true) { - refcount.init(); refcount_init.init(); } -Reference::~Reference() { -} - Variant WeakRef::get_ref() const { - - if (ref.is_null()) + if (ref.is_null()) { return Variant(); + } Object *obj = ObjectDB::get_instance(ref); - if (!obj) + if (!obj) { return Variant(); + } Reference *r = cast_to<Reference>(obj); if (r) { - return REF(r); } @@ -134,14 +124,9 @@ void WeakRef::set_obj(Object *p_object) { } void WeakRef::set_ref(const REF &p_ref) { - ref = p_ref.is_valid() ? p_ref->get_instance_id() : ObjectID(); } -WeakRef::WeakRef() { -} - void WeakRef::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_ref"), &WeakRef::get_ref); } diff --git a/core/reference.h b/core/reference.h index 30a93d82a6..f5794b0b67 100644 --- a/core/reference.h +++ b/core/reference.h @@ -36,7 +36,6 @@ #include "core/safe_refcount.h" class Reference : public Object { - GDCLASS(Reference, Object); SafeRefCount refcount; SafeRefCount refcount_init; @@ -52,32 +51,32 @@ public: int reference_get_count() const; Reference(); - ~Reference(); + ~Reference() {} }; template <class T> class Ref { - - T *reference; + T *reference = nullptr; void ref(const Ref &p_from) { - - if (p_from.reference == reference) + if (p_from.reference == reference) { return; + } unref(); reference = p_from.reference; - if (reference) + if (reference) { reference->reference(); + } } void ref_pointer(T *p_ref) { - ERR_FAIL_COND(!p_ref); - if (p_ref->init_ref()) + if (p_ref->init_ref()) { reference = p_ref; + } } //virtual Reference * get_reference() const { return reference; } @@ -90,60 +89,48 @@ public: } _FORCE_INLINE_ bool operator<(const Ref<T> &p_r) const { - return reference < p_r.reference; } _FORCE_INLINE_ bool operator==(const Ref<T> &p_r) const { - return reference == p_r.reference; } _FORCE_INLINE_ bool operator!=(const Ref<T> &p_r) const { - return reference != p_r.reference; } _FORCE_INLINE_ T *operator->() { - return reference; } _FORCE_INLINE_ T *operator*() { - return reference; } _FORCE_INLINE_ const T *operator->() const { - return reference; } _FORCE_INLINE_ const T *ptr() const { - return reference; } _FORCE_INLINE_ T *ptr() { - return reference; } _FORCE_INLINE_ const T *operator*() const { - return reference; } operator Variant() const { - return Variant(reference); } void operator=(const Ref &p_from) { - ref(p_from); } template <class T_Other> void operator=(const Ref<T_Other> &p_from) { - Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr())); if (!refb) { unref(); @@ -156,7 +143,6 @@ public: } void operator=(const Variant &p_variant) { - Object *object = p_variant.get_validated_object(); if (object == reference) { @@ -189,15 +175,11 @@ public: } Ref(const Ref &p_from) { - - reference = nullptr; ref(p_from); } template <class T_Other> Ref(const Ref<T_Other> &p_from) { - - reference = nullptr; Reference *refb = const_cast<Reference *>(static_cast<const Reference *>(p_from.ptr())); if (!refb) { unref(); @@ -210,26 +192,21 @@ public: } Ref(T *p_reference) { - - reference = nullptr; - if (p_reference) + if (p_reference) { ref_pointer(p_reference); + } } Ref(const Variant &p_variant) { - Object *object = p_variant.get_validated_object(); if (!object) { - reference = nullptr; return; } T *r = Object::cast_to<T>(object); if (r && r->reference()) { reference = r; - } else { - reference = nullptr; } } @@ -242,7 +219,6 @@ public: // mutexes will avoid more crashes? if (reference && reference->unreference()) { - memdelete(reference); } reference = nullptr; @@ -252,13 +228,9 @@ public: ref(memnew(T)); } - Ref() { - - reference = nullptr; - } + Ref() {} ~Ref() { - unref(); } }; @@ -266,7 +238,6 @@ public: typedef Ref<Reference> REF; class WeakRef : public Reference { - GDCLASS(WeakRef, Reference); ObjectID ref; @@ -279,30 +250,25 @@ public: void set_obj(Object *p_object); void set_ref(const REF &p_ref); - WeakRef(); + WeakRef() {} }; #ifdef PTRCALL_ENABLED template <class T> struct PtrToArg<Ref<T>> { - _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { - return Ref<T>(const_cast<T *>(reinterpret_cast<const T *>(p_ptr))); } _FORCE_INLINE_ static void encode(Ref<T> p_val, const void *p_ptr) { - *(Ref<Reference> *)p_ptr = p_val; } }; template <class T> struct PtrToArg<const Ref<T> &> { - _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { - return Ref<T>((T *)p_ptr); } }; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 905f43d61b..c0f9eea76d 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -38,7 +38,7 @@ #include "core/crypto/hashing_context.h" #include "core/engine.h" #include "core/func_ref.h" -#include "core/input/input_filter.h" +#include "core/input/input.h" #include "core/input/input_map.h" #include "core/io/config_file.h" #include "core/io/dtls_server.h" @@ -60,12 +60,12 @@ #include "core/io/xml_parser.h" #include "core/math/a_star.h" #include "core/math/expression.h" -#include "core/math/geometry.h" +#include "core/math/geometry_2d.h" +#include "core/math/geometry_3d.h" #include "core/math/random_number_generator.h" #include "core/math/triangle_mesh.h" #include "core/os/main_loop.h" #include "core/packed_data_container.h" -#include "core/path_remap.h" #include "core/project_settings.h" #include "core/translation.h" #include "core/undo_redo.h" @@ -88,7 +88,8 @@ static _JSON *_json = nullptr; static IP *ip = nullptr; -static _Geometry *_geometry = nullptr; +static _Geometry2D *_geometry_2d = nullptr; +static _Geometry3D *_geometry_3d = nullptr; extern Mutex _global_mutex; @@ -98,7 +99,6 @@ extern void register_variant_methods(); extern void unregister_variant_methods(); void register_core_types() { - //consistency check static_assert(sizeof(Callable) <= 16); @@ -215,7 +215,8 @@ void register_core_types() { ip = IP::create(); - _geometry = memnew(_Geometry); + _geometry_2d = memnew(_Geometry2D); + _geometry_3d = memnew(_Geometry3D); _resource_loader = memnew(_ResourceLoader); _resource_saver = memnew(_ResourceSaver); @@ -233,15 +234,15 @@ void register_core_settings() { GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16)); ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater")); - GLOBAL_DEF("network/ssl/certificates", ""); - ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt")); + GLOBAL_DEF("network/ssl/certificate_bundle_override", ""); + ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificate_bundle_override", PropertyInfo(Variant::STRING, "network/ssl/certificate_bundle_override", PROPERTY_HINT_FILE, "*.crt")); } void register_core_singletons() { - ClassDB::register_class<ProjectSettings>(); ClassDB::register_virtual_class<IP>(); - ClassDB::register_class<_Geometry>(); + ClassDB::register_class<_Geometry2D>(); + ClassDB::register_class<_Geometry3D>(); ClassDB::register_class<_ResourceLoader>(); ClassDB::register_class<_ResourceSaver>(); ClassDB::register_class<_OS>(); @@ -249,14 +250,15 @@ void register_core_singletons() { ClassDB::register_class<_ClassDB>(); ClassDB::register_class<_Marshalls>(); ClassDB::register_class<TranslationServer>(); - ClassDB::register_virtual_class<InputFilter>(); + ClassDB::register_virtual_class<Input>(); ClassDB::register_class<InputMap>(); ClassDB::register_class<_JSON>(); ClassDB::register_class<Expression>(); Engine::get_singleton()->add_singleton(Engine::Singleton("ProjectSettings", ProjectSettings::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("IP", IP::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry", _Geometry::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry2D", _Geometry2D::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("Geometry3D", _Geometry3D::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceLoader", _ResourceLoader::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceSaver", _ResourceSaver::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("OS", _OS::get_singleton())); @@ -264,13 +266,12 @@ void register_core_singletons() { Engine::get_singleton()->add_singleton(Engine::Singleton("ClassDB", _classdb)); Engine::get_singleton()->add_singleton(Engine::Singleton("Marshalls", _Marshalls::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("TranslationServer", TranslationServer::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("Input", InputFilter::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("Input", Input::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("InputMap", InputMap::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("JSON", _JSON::get_singleton())); } void unregister_core_types() { - memdelete(_resource_loader); memdelete(_resource_saver); memdelete(_os); @@ -279,7 +280,8 @@ void unregister_core_types() { memdelete(_marshalls); memdelete(_json); - memdelete(_geometry); + memdelete(_geometry_2d); + memdelete(_geometry_3d); ResourceLoader::remove_resource_format_loader(resource_format_image); resource_format_image.unref(); @@ -301,8 +303,9 @@ void unregister_core_types() { ResourceLoader::remove_resource_format_loader(resource_format_loader_crypto); resource_format_loader_crypto.unref(); - if (ip) + if (ip) { memdelete(ip); + } ResourceLoader::finalize(); diff --git a/core/resource.cpp b/core/resource.cpp index d1883d8043..3b589793ef 100644 --- a/core/resource.cpp +++ b/core/resource.cpp @@ -33,13 +33,13 @@ #include "core/core_string_names.h" #include "core/io/resource_loader.h" #include "core/os/file_access.h" +#include "core/os/os.h" #include "core/script_language.h" #include "scene/main/node.h" //only so casting works #include <stdio.h> void Resource::emit_changed() { - emit_signal(CoreStringNames::get_singleton()->changed); } @@ -47,12 +47,11 @@ void Resource::_resource_path_changed() { } void Resource::set_path(const String &p_path, bool p_take_over) { - - if (path_cache == p_path) + if (path_cache == p_path) { return; + } if (path_cache != "") { - ResourceCache::lock->write_lock(); ResourceCache::resources.erase(path_cache); ResourceCache::lock->write_unlock(); @@ -66,7 +65,6 @@ void Resource::set_path(const String &p_path, bool p_take_over) { if (has_path) { if (p_take_over) { - ResourceCache::lock->write_lock(); Resource **res = ResourceCache::resources.getptr(p_path); if (res) { @@ -84,7 +82,6 @@ void Resource::set_path(const String &p_path, bool p_take_over) { path_cache = p_path; if (path_cache != "") { - ResourceCache::lock->write_lock(); ResourceCache::resources[path_cache] = this; ResourceCache::lock->write_unlock(); @@ -95,62 +92,58 @@ void Resource::set_path(const String &p_path, bool p_take_over) { } String Resource::get_path() const { - return path_cache; } void Resource::set_subindex(int p_sub_index) { - subindex = p_sub_index; } int Resource::get_subindex() const { - return subindex; } void Resource::set_name(const String &p_name) { - name = p_name; _change_notify("resource_name"); } -String Resource::get_name() const { +String Resource::get_name() const { return name; } bool Resource::editor_can_reload_from_file() { - return true; //by default yes } void Resource::reload_from_file() { - String path = get_path(); - if (!path.is_resource_file()) + if (!path.is_resource_file()) { return; + } Ref<Resource> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), true); - if (!s.is_valid()) + if (!s.is_valid()) { return; + } List<PropertyInfo> pi; s->get_property_list(&pi); for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; - if (E->get().name == "resource_path") + } + if (E->get().name == "resource_path") { continue; //do not change path + } set(E->get().name, s->get(E->get().name)); } } Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) { - List<PropertyInfo> plist; get_property_list(&plist); @@ -160,20 +153,17 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res r->local_scene = p_for_scene; for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } Variant p = get(E->get().name); if (p.get_type() == Variant::OBJECT) { - RES sr = p; if (sr.is_valid()) { - if (sr->is_local_to_scene()) { if (remap_cache.has(sr)) { p = remap_cache[sr]; } else { - RES dupe = sr->duplicate_for_local_scene(p_for_scene, remap_cache); p = dupe; remap_cache[sr] = dupe; @@ -191,22 +181,19 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res } void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) { - List<PropertyInfo> plist; get_property_list(&plist); local_scene = p_for_scene; for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } Variant p = get(E->get().name); if (p.get_type() == Variant::OBJECT) { - RES sr = p; if (sr.is_valid()) { - if (sr->is_local_to_scene()) { if (!remap_cache.has(sr)) { sr->configure_for_local_scene(p_for_scene, remap_cache); @@ -219,7 +206,6 @@ void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, R } Ref<Resource> Resource::duplicate(bool p_subresources) const { - List<PropertyInfo> plist; get_property_list(&plist); @@ -227,21 +213,19 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { ERR_FAIL_COND_V(!r, Ref<Resource>()); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { continue; + } Variant p = get(E->get().name); if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) { r->set(E->get().name, p.duplicate(p_subresources)); } else if (p.get_type() == Variant::OBJECT && (p_subresources || (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE))) { - RES sr = p; if (sr.is_valid()) { r->set(E->get().name, sr->duplicate(p_subresources)); } } else { - r->set(E->get().name, p); } } @@ -250,34 +234,27 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { } void Resource::_set_path(const String &p_path) { - set_path(p_path, false); } void Resource::_take_over_path(const String &p_path) { - set_path(p_path, true); } RID Resource::get_rid() const { - return RID(); } void Resource::register_owner(Object *p_owner) { - owners.insert(p_owner->get_instance_id()); } void Resource::unregister_owner(Object *p_owner) { - owners.erase(p_owner->get_instance_id()); } void Resource::notify_change_to_owners() { - for (Set<ObjectID>::Element *E = owners.front(); E; E = E->next()) { - Object *obj = ObjectDB::get_instance(E->get()); ERR_CONTINUE_MSG(!obj, "Object was deleted, while still owning a resource."); //wtf //TODO store string @@ -288,14 +265,12 @@ void Resource::notify_change_to_owners() { #ifdef TOOLS_ENABLED uint32_t Resource::hash_edited_version() const { - uint32_t hash = hash_djb2_one_32(get_edited_version()); List<PropertyInfo> plist; get_property_list(&plist); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { - if (E->get().usage & PROPERTY_USAGE_STORAGE && E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) { RES res = get(E->get().name); if (res.is_valid()) { @@ -310,19 +285,17 @@ uint32_t Resource::hash_edited_version() const { #endif void Resource::set_local_to_scene(bool p_enable) { - local_to_scene = p_enable; } bool Resource::is_local_to_scene() const { - return local_to_scene; } Node *Resource::get_local_scene() const { - - if (local_scene) + if (local_scene) { return local_scene; + } if (_get_local_scene_func) { return _get_local_scene_func(); @@ -332,17 +305,17 @@ Node *Resource::get_local_scene() const { } void Resource::setup_local_to_scene() { - - if (get_script_instance()) + if (get_script_instance()) { get_script_instance()->call("_setup_local_to_scene"); + } } Node *(*Resource::_get_local_scene_func)() = nullptr; void Resource::set_as_translation_remapped(bool p_remapped) { - - if (remapped_list.in_list() == p_remapped) + if (remapped_list.in_list() == p_remapped) { return; + } if (ResourceCache::lock) { ResourceCache::lock->write_lock(); @@ -360,7 +333,6 @@ void Resource::set_as_translation_remapped(bool p_remapped) { } bool Resource::is_translation_remapped() const { - return remapped_list.in_list(); } @@ -406,7 +378,6 @@ int Resource::get_id_for_path(const String &p_path) const { #endif void Resource::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_path", "path"), &Resource::_set_path); ClassDB::bind_method(D_METHOD("take_over_path", "path"), &Resource::_take_over_path); ClassDB::bind_method(D_METHOD("get_path"), &Resource::get_path); @@ -429,20 +400,9 @@ void Resource::_bind_methods() { } Resource::Resource() : - remapped_list(this) { - -#ifdef TOOLS_ENABLED - last_modified_time = 0; - import_last_modified_time = 0; -#endif - - subindex = 0; - local_to_scene = false; - local_scene = nullptr; -} + remapped_list(this) {} Resource::~Resource() { - if (path_cache != "") { ResourceCache::lock->write_lock(); ResourceCache::resources.erase(path_cache); @@ -464,7 +424,6 @@ RWLock *ResourceCache::path_cache_lock = nullptr; #endif void ResourceCache::setup() { - lock = RWLock::create(); #ifdef TOOLS_ENABLED path_cache_lock = RWLock::create(); @@ -472,33 +431,36 @@ void ResourceCache::setup() { } void ResourceCache::clear() { - if (resources.size()) - ERR_PRINT("Resources Still in use at Exit!"); + if (resources.size()) { + ERR_PRINT("Resources still in use at exit (run with --verbose for details)."); + if (OS::get_singleton()->is_stdout_verbose()) { + const String *K = nullptr; + while ((K = resources.next(K))) { + Resource *r = resources[*K]; + print_line(vformat("Resource still in use: %s (%s)", *K, r->get_class())); + } + } + } resources.clear(); memdelete(lock); +#ifdef TOOLS_ENABLED + memdelete(path_cache_lock); +#endif } void ResourceCache::reload_externals() { - - /* - const String *K=nullptr; - while ((K=resources.next(K))) { - resources[*K]->reload_external_data(); - } - */ } bool ResourceCache::has(const String &p_path) { - lock->read_lock(); bool b = resources.has(p_path); lock->read_unlock(); return b; } -Resource *ResourceCache::get(const String &p_path) { +Resource *ResourceCache::get(const String &p_path) { lock->read_lock(); Resource **res = resources.getptr(p_path); @@ -513,11 +475,9 @@ Resource *ResourceCache::get(const String &p_path) { } void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) { - lock->read_lock(); const String *K = nullptr; while ((K = resources.next(K))) { - Resource *r = resources[*K]; p_resources->push_back(Ref<Resource>(r)); } @@ -525,7 +485,6 @@ void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) { } int ResourceCache::get_cached_resource_count() { - lock->read_lock(); int rc = resources.size(); lock->read_unlock(); @@ -547,7 +506,6 @@ void ResourceCache::dump(const char *p_file, bool p_short) { const String *K = nullptr; while ((K = resources.next(K))) { - Resource *r = resources[*K]; if (!type_count.has(r->get_class())) { @@ -557,15 +515,16 @@ void ResourceCache::dump(const char *p_file, bool p_short) { type_count[r->get_class()]++; if (!p_short) { - if (f) + if (f) { f->store_line(r->get_class() + ": " + r->get_path()); + } } } for (Map<String, int>::Element *E = type_count.front(); E; E = E->next()) { - - if (f) + if (f) { f->store_line(E->key() + " count: " + itos(E->get())); + } } if (f) { f->close(); @@ -573,6 +532,5 @@ void ResourceCache::dump(const char *p_file, bool p_short) { } lock->read_unlock(); - #endif } diff --git a/core/resource.h b/core/resource.h index 3b7812c870..ad2f3ce913 100644 --- a/core/resource.h +++ b/core/resource.h @@ -45,7 +45,6 @@ public: private: class Resource : public Reference { - GDCLASS(Resource, Reference); OBJ_CATEGORY("Resources"); RES_BASE_EXTENSION("res"); @@ -57,19 +56,19 @@ class Resource : public Reference { String name; String path_cache; - int subindex; + int subindex = 0; virtual bool _use_builtin_script() const { return true; } #ifdef TOOLS_ENABLED - uint64_t last_modified_time; - uint64_t import_last_modified_time; + uint64_t last_modified_time = 0; + uint64_t import_last_modified_time = 0; String import_path; #endif - bool local_to_scene; + bool local_to_scene = false; friend class SceneState; - Node *local_scene; + Node *local_scene = nullptr; SelfList<Resource> remapped_list; diff --git a/core/rid.h b/core/rid.h index a2f73423a3..4b65f3fb6a 100644 --- a/core/rid.h +++ b/core/rid.h @@ -37,27 +37,22 @@ class RID_AllocBase; class RID { friend class RID_AllocBase; - uint64_t _id; + uint64_t _id = 0; public: _FORCE_INLINE_ bool operator==(const RID &p_rid) const { - return _id == p_rid._id; } _FORCE_INLINE_ bool operator<(const RID &p_rid) const { - return _id < p_rid._id; } _FORCE_INLINE_ bool operator<=(const RID &p_rid) const { - return _id <= p_rid._id; } _FORCE_INLINE_ bool operator>(const RID &p_rid) const { - return _id > p_rid._id; } _FORCE_INLINE_ bool operator!=(const RID &p_rid) const { - return _id != p_rid._id; } _FORCE_INLINE_ bool is_valid() const { return _id != 0; } @@ -65,9 +60,7 @@ public: _FORCE_INLINE_ uint64_t get_id() const { return _id; } - _FORCE_INLINE_ RID() { - _id = 0; - } + _FORCE_INLINE_ RID() {} }; #endif // RID_H diff --git a/core/rid_owner.h b/core/rid_owner.h index ad6996b9a7..2489475c68 100644 --- a/core/rid_owner.h +++ b/core/rid_owner.h @@ -39,11 +39,11 @@ #include "core/safe_refcount.h" #include "core/set.h" #include "core/spin_lock.h" + #include <stdio.h> #include <typeinfo> class RID_AllocBase { - static volatile uint64_t base_id; protected: @@ -67,22 +67,20 @@ public: template <class T, bool THREAD_SAFE = false> class RID_Alloc : public RID_AllocBase { - - T **chunks; - uint32_t **free_list_chunks; - uint32_t **validator_chunks; + T **chunks = nullptr; + uint32_t **free_list_chunks = nullptr; + uint32_t **validator_chunks = nullptr; uint32_t elements_in_chunk; - uint32_t max_alloc; - uint32_t alloc_count; + uint32_t max_alloc = 0; + uint32_t alloc_count = 0; - const char *description; + const char *description = nullptr; SpinLock spin_lock; public: RID make_rid(const T &p_value) { - if (THREAD_SAFE) { spin_lock.lock(); } @@ -136,7 +134,6 @@ public: } _FORCE_INLINE_ T *getornull(const RID &p_rid) { - if (THREAD_SAFE) { spin_lock.lock(); } @@ -171,7 +168,6 @@ public: } _FORCE_INLINE_ bool owns(const RID &p_rid) { - if (THREAD_SAFE) { spin_lock.lock(); } @@ -200,7 +196,6 @@ public: } _FORCE_INLINE_ void free(const RID &p_rid) { - if (THREAD_SAFE) { spin_lock.lock(); } @@ -288,14 +283,7 @@ public: } RID_Alloc(uint32_t p_target_chunk_byte_size = 4096) { - chunks = nullptr; - free_list_chunks = nullptr; - validator_chunks = nullptr; - elements_in_chunk = sizeof(T) > p_target_chunk_byte_size ? 1 : (p_target_chunk_byte_size / sizeof(T)); - max_alloc = 0; - alloc_count = 0; - description = nullptr; } ~RID_Alloc() { @@ -412,4 +400,5 @@ public: RID_Owner(uint32_t p_target_chunk_byte_size = 4096) : alloc(p_target_chunk_byte_size) {} }; + #endif // RID_OWNER_H diff --git a/core/ring_buffer.h b/core/ring_buffer.h index 620a3a3846..6b71d12cf3 100644 --- a/core/ring_buffer.h +++ b/core/ring_buffer.h @@ -35,10 +35,9 @@ template <typename T> class RingBuffer { - Vector<T> data; - int read_pos; - int write_pos; + int read_pos = 0; + int write_pos = 0; int size_mask; inline int inc(int &p_var, int p_size) const { @@ -46,13 +45,13 @@ class RingBuffer { p_var += p_size; p_var = p_var & size_mask; return ret; - }; + } public: T read() { ERR_FAIL_COND_V(space_left() < 1, T()); return data.ptr()[inc(read_pos, 1)]; - }; + } int read(T *p_buf, int p_size, bool p_advance = true) { int left = data_left(); @@ -67,23 +66,23 @@ public: const T *read = data.ptr(); for (int i = 0; i < total; i++) { p_buf[dst++] = read[pos + i]; - }; + } to_read -= total; pos = 0; - }; + } if (p_advance) { inc(read_pos, p_size); - }; + } return p_size; - }; + } int copy(T *p_buf, int p_offset, int p_size) const { - int left = data_left(); if ((p_offset + p_size) > left) { p_size -= left - p_offset; - if (p_size <= 0) + if (p_size <= 0) { return 0; + } } p_size = MIN(left, p_size); int pos = read_pos; @@ -96,20 +95,20 @@ public: int total = end - pos; for (int i = 0; i < total; i++) { p_buf[dst++] = data[pos + i]; - }; + } to_read -= total; pos = 0; - }; + } return p_size; - }; + } int find(const T &t, int p_offset, int p_max_size) const { - int left = data_left(); if ((p_offset + p_max_size) > left) { p_max_size -= left - p_offset; - if (p_max_size <= 0) + if (p_max_size <= 0) { return 0; + } } p_max_size = MIN(left, p_max_size); int pos = read_pos; @@ -120,9 +119,10 @@ public: end = MIN(end, size()); int total = end - pos; for (int i = 0; i < total; i++) { - if (data[pos + i] == t) + if (data[pos + i] == t) { return i + (p_max_size - to_read); - }; + } + } to_read -= total; pos = 0; } @@ -133,7 +133,7 @@ public: p_n = MIN(p_n, data_left()); inc(read_pos, p_n); return p_n; - }; + } inline int decrease_write(int p_n) { p_n = MIN(p_n, data_left()); @@ -145,10 +145,9 @@ public: ERR_FAIL_COND_V(space_left() < 1, FAILED); data.write[inc(write_pos, 1)] = p_v; return OK; - }; + } int write(const T *p_buf, int p_size) { - int left = space_left(); p_size = MIN(left, p_size); @@ -156,39 +155,38 @@ public: int to_write = p_size; int src = 0; while (to_write) { - int end = pos + to_write; end = MIN(end, size()); int total = end - pos; for (int i = 0; i < total; i++) { data.write[pos + i] = p_buf[src++]; - }; + } to_write -= total; pos = 0; - }; + } inc(write_pos, p_size); return p_size; - }; + } inline int space_left() const { int left = read_pos - write_pos; if (left < 0) { return size() + left - 1; - }; + } if (left == 0) { return size() - 1; - }; + } return left - 1; - }; + } inline int data_left() const { return size() - space_left() - 1; - }; + } inline int size() const { return data.size(); - }; + } inline void clear() { read_pos = 0; @@ -203,22 +201,20 @@ public: if (old_size < new_size && read_pos > write_pos) { for (int i = 0; i < write_pos; i++) { data.write[(old_size + i) & mask] = data[i]; - }; + } write_pos = (old_size + write_pos) & mask; } else { read_pos = read_pos & mask; write_pos = write_pos & mask; - }; + } size_mask = mask; - }; + } RingBuffer<T>(int p_power = 0) { - read_pos = 0; - write_pos = 0; resize(p_power); - }; - ~RingBuffer<T>(){}; + } + ~RingBuffer<T>() {} }; #endif // RING_BUFFER_H diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp index e4604faa09..d5ee778ef7 100644 --- a/core/safe_refcount.cpp +++ b/core/safe_refcount.cpp @@ -42,79 +42,71 @@ /* taken from boost */ \ while (true) { \ m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \ - if (tmp == 0) \ + if (tmp == 0) { \ return 0; /* if zero, can't add to it anymore */ \ - if (m_win_cmpxchg((m_win_type volatile *)(m_pw), tmp + 1, tmp) == tmp) \ + } \ + if (m_win_cmpxchg((m_win_type volatile *)(m_pw), tmp + 1, tmp) == tmp) { \ return tmp + 1; \ + } \ } #define ATOMIC_EXCHANGE_IF_GREATER_BODY(m_pw, m_val, m_win_type, m_win_cmpxchg, m_cpp_type) \ while (true) { \ m_cpp_type tmp = static_cast<m_cpp_type const volatile &>(*(m_pw)); \ - if (tmp >= m_val) \ + if (tmp >= m_val) { \ return tmp; /* already greater, or equal */ \ - if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) \ + } \ + if (m_win_cmpxchg((m_win_type volatile *)(m_pw), m_val, tmp) == tmp) { \ return m_val; \ + } \ } -_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw){ - - ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t) +_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(volatile uint32_t *pw) { + ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t); } _ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(volatile uint32_t *pw) { - return InterlockedDecrement((LONG volatile *)pw); } _ALWAYS_INLINE_ uint32_t _atomic_increment_impl(volatile uint32_t *pw) { - return InterlockedIncrement((LONG volatile *)pw); } _ALWAYS_INLINE_ uint32_t _atomic_sub_impl(volatile uint32_t *pw, volatile uint32_t val) { - return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val; } _ALWAYS_INLINE_ uint32_t _atomic_add_impl(volatile uint32_t *pw, volatile uint32_t val) { - return InterlockedAdd((LONG volatile *)pw, val); } -_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val){ - - ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t) +_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(volatile uint32_t *pw, volatile uint32_t val) { + ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t); } -_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw){ - - ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t) +_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(volatile uint64_t *pw) { + ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t); } _ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(volatile uint64_t *pw) { - return InterlockedDecrement64((LONGLONG volatile *)pw); } _ALWAYS_INLINE_ uint64_t _atomic_increment_impl(volatile uint64_t *pw) { - return InterlockedIncrement64((LONGLONG volatile *)pw); } _ALWAYS_INLINE_ uint64_t _atomic_sub_impl(volatile uint64_t *pw, volatile uint64_t val) { - return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val; } _ALWAYS_INLINE_ uint64_t _atomic_add_impl(volatile uint64_t *pw, volatile uint64_t val) { - return InterlockedAdd64((LONGLONG volatile *)pw, val); } -_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val){ - - ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t) +_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(volatile uint64_t *pw, volatile uint64_t val) { + ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t); } // The actual advertised functions; they'll call the right implementation diff --git a/core/safe_refcount.h b/core/safe_refcount.h index 953a877397..dc4e62354a 100644 --- a/core/safe_refcount.h +++ b/core/safe_refcount.h @@ -43,9 +43,9 @@ template <class T> static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) { - - if (*pw == 0) + if (*pw == 0) { return 0; + } (*pw)++; @@ -54,7 +54,6 @@ static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) { template <class T> static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) { - (*pw)--; return *pw; @@ -62,7 +61,6 @@ static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) { template <class T> static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) { - (*pw)++; return *pw; @@ -70,7 +68,6 @@ static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) { template <class T, class V> static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) { - (*pw) -= val; return *pw; @@ -78,7 +75,6 @@ static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) { template <class T, class V> static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) { - (*pw) += val; return *pw; @@ -86,9 +82,9 @@ static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) { template <class T, class V> static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) { - - if (val > *pw) + if (val > *pw) { *pw = val; + } return *pw; } @@ -102,49 +98,47 @@ static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V v template <class T> static _ALWAYS_INLINE_ T atomic_conditional_increment(volatile T *pw) { - while (true) { T tmp = static_cast<T const volatile &>(*pw); - if (tmp == 0) + if (tmp == 0) { return 0; // if zero, can't add to it anymore - if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp) + } + if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp) { return tmp + 1; + } } } template <class T> static _ALWAYS_INLINE_ T atomic_decrement(volatile T *pw) { - return __sync_sub_and_fetch(pw, 1); } template <class T> static _ALWAYS_INLINE_ T atomic_increment(volatile T *pw) { - return __sync_add_and_fetch(pw, 1); } template <class T, class V> static _ALWAYS_INLINE_ T atomic_sub(volatile T *pw, volatile V val) { - return __sync_sub_and_fetch(pw, val); } template <class T, class V> static _ALWAYS_INLINE_ T atomic_add(volatile T *pw, volatile V val) { - return __sync_add_and_fetch(pw, val); } template <class T, class V> static _ALWAYS_INLINE_ T atomic_exchange_if_greater(volatile T *pw, volatile V val) { - while (true) { T tmp = static_cast<T const volatile &>(*pw); - if (tmp >= val) + if (tmp >= val) { return tmp; // already greater, or equal - if (__sync_val_compare_and_swap(pw, tmp, val) == tmp) + } + if (__sync_val_compare_and_swap(pw, tmp, val) == tmp) { return val; + } } } @@ -171,7 +165,6 @@ uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val #endif struct SafeRefCount { - uint32_t count; public: @@ -203,7 +196,6 @@ public: } _ALWAYS_INLINE_ void init(uint32_t p_value = 1) { - count = p_value; } }; diff --git a/core/script_language.cpp b/core/script_language.cpp index 82cac6bc9a..38a970f3c6 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -34,6 +34,7 @@ #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" #include "core/project_settings.h" + #include <stdint.h> ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; @@ -45,11 +46,10 @@ bool ScriptServer::languages_finished = false; ScriptEditRequestFunction ScriptServer::edit_request_func = nullptr; void Script::_notification(int p_what) { - if (p_what == NOTIFICATION_POSTINITIALIZE) { - - if (EngineDebugger::is_active()) + if (EngineDebugger::is_active()) { EngineDebugger::get_script_debugger()->set_break_language(get_language()); + } } } @@ -100,7 +100,6 @@ Dictionary Script::_get_script_constant_map() { } void Script::_bind_methods() { - ClassDB::bind_method(D_METHOD("can_instance"), &Script::can_instance); //ClassDB::bind_method(D_METHOD("instance_create","base_object"),&Script::instance_create); ClassDB::bind_method(D_METHOD("instance_has", "base_object"), &Script::instance_has); @@ -125,30 +124,25 @@ void Script::_bind_methods() { } void ScriptServer::set_scripting_enabled(bool p_enabled) { - scripting_enabled = p_enabled; } bool ScriptServer::is_scripting_enabled() { - return scripting_enabled; } ScriptLanguage *ScriptServer::get_language(int p_idx) { - ERR_FAIL_INDEX_V(p_idx, _language_count, nullptr); return _languages[p_idx]; } void ScriptServer::register_language(ScriptLanguage *p_language) { - ERR_FAIL_COND(_language_count >= MAX_LANGUAGES); _languages[_language_count++] = p_language; } void ScriptServer::unregister_language(ScriptLanguage *p_language) { - for (int i = 0; i < _language_count; i++) { if (_languages[i] == p_language) { _language_count--; @@ -161,7 +155,6 @@ void ScriptServer::unregister_language(ScriptLanguage *p_language) { } void ScriptServer::init_languages() { - { //load global classes global_classes_clear(); if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { @@ -169,8 +162,9 @@ void ScriptServer::init_languages() { for (int i = 0; i < script_classes.size(); i++) { Dictionary c = script_classes[i]; - if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) + if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { continue; + } add_global_class(c["class"], c["base"], c["language"], c["path"]); } } @@ -182,7 +176,6 @@ void ScriptServer::init_languages() { } void ScriptServer::finish_languages() { - for (int i = 0; i < _language_count; i++) { _languages[i]->finish(); } @@ -191,24 +184,20 @@ void ScriptServer::finish_languages() { } void ScriptServer::set_reload_scripts_on_save(bool p_enable) { - reload_scripts_on_save = p_enable; } bool ScriptServer::is_reload_scripts_on_save_enabled() { - return reload_scripts_on_save; } void ScriptServer::thread_enter() { - for (int i = 0; i < _language_count; i++) { _languages[i]->thread_enter(); } } void ScriptServer::thread_exit() { - for (int i = 0; i < _language_count; i++) { _languages[i]->thread_exit(); } @@ -228,16 +217,20 @@ void ScriptServer::add_global_class(const StringName &p_class, const StringName g.base = p_base; global_classes[p_class] = g; } + void ScriptServer::remove_global_class(const StringName &p_class) { global_classes.erase(p_class); } + bool ScriptServer::is_global_class(const StringName &p_class) { return global_classes.has(p_class); } + StringName ScriptServer::get_global_class_language(const StringName &p_class) { ERR_FAIL_COND_V(!global_classes.has(p_class), StringName()); return global_classes[p_class].language; } + String ScriptServer::get_global_class_path(const String &p_class) { ERR_FAIL_COND_V(!global_classes.has(p_class), String()); return global_classes[p_class].path; @@ -247,6 +240,7 @@ StringName ScriptServer::get_global_class_base(const String &p_class) { ERR_FAIL_COND_V(!global_classes.has(p_class), String()); return global_classes[p_class].base; } + StringName ScriptServer::get_global_class_native_base(const String &p_class) { ERR_FAIL_COND_V(!global_classes.has(p_class), String()); String base = global_classes[p_class].base; @@ -255,6 +249,7 @@ StringName ScriptServer::get_global_class_native_base(const String &p_class) { } return base; } + void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { const StringName *K = nullptr; List<StringName> classes; @@ -266,6 +261,7 @@ void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { r_global_classes->push_back(E->get()); } } + void ScriptServer::save_global_classes() { List<StringName> gc; get_global_class_list(&gc); @@ -285,27 +281,26 @@ void ScriptServer::save_global_classes() { //////////////////// void ScriptInstance::get_property_state(List<Pair<StringName, Variant>> &state) { - List<PropertyInfo> pinfo; get_property_list(&pinfo); for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) { - if (E->get().usage & PROPERTY_USAGE_STORAGE) { Pair<StringName, Variant> p; p.first = E->get().name; - if (get(p.first, p.second)) + if (get(p.first, p.second)) { state.push_back(p); + } } } } Variant ScriptInstance::call(const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -324,23 +319,25 @@ void ScriptInstance::call_multilevel_reversed(const StringName &p_method, const } void ScriptInstance::property_set_fallback(const StringName &, const Variant &, bool *r_valid) { - if (r_valid) + if (r_valid) { *r_valid = false; + } } Variant ScriptInstance::property_get_fallback(const StringName &, bool *r_valid) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant(); } void ScriptInstance::call_multilevel(const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -359,9 +356,9 @@ void ScriptLanguage::frame() { } bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) { - - if (script->is_placeholder_fallback_enabled()) + if (script->is_placeholder_fallback_enabled()) { return false; + } if (values.has(p_name)) { Variant defval; @@ -384,8 +381,8 @@ bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_v } return false; } -bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) const { +bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) const { if (values.has(p_name)) { r_ret = values[p_name]; return true; @@ -408,7 +405,6 @@ bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) co } void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const { - if (script->is_placeholder_fallback_enabled()) { for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) { p_properties->push_back(E->get()); @@ -425,38 +421,41 @@ void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properti } Variant::Type PlaceHolderScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const { - if (values.has(p_name)) { - if (r_is_valid) + if (r_is_valid) { *r_is_valid = true; + } return values[p_name].get_type(); } if (constants.has(p_name)) { - if (r_is_valid) + if (r_is_valid) { *r_is_valid = true; + } return constants[p_name].get_type(); } - if (r_is_valid) + if (r_is_valid) { *r_is_valid = false; + } return Variant::NIL; } void PlaceHolderScriptInstance::get_method_list(List<MethodInfo> *p_list) const { - - if (script->is_placeholder_fallback_enabled()) + if (script->is_placeholder_fallback_enabled()) { return; + } if (script.is_valid()) { script->get_script_method_list(p_list); } } -bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const { - if (script->is_placeholder_fallback_enabled()) +bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const { + if (script->is_placeholder_fallback_enabled()) { return false; + } if (script.is_valid()) { return script->has_method(p_method); @@ -465,17 +464,15 @@ bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const { } void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values) { - Set<StringName> new_values; for (const List<PropertyInfo>::Element *E = p_properties.front(); E; E = E->next()) { - StringName n = E->get().name; new_values.insert(n); if (!values.has(n) || values[n].get_type() != E->get().type) { - - if (p_values.has(n)) + if (p_values.has(n)) { values[n] = p_values[n]; + } } } @@ -483,9 +480,9 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c List<StringName> to_remove; for (Map<StringName, Variant>::Element *E = values.front(); E; E = E->next()) { - - if (!new_values.has(E->key())) + if (!new_values.has(E->key())) { to_remove.push_back(E->key()); + } Variant defval; if (script->get_property_default_value(E->key(), defval)) { @@ -497,13 +494,11 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c } while (to_remove.size()) { - values.erase(to_remove.front()->get()); to_remove.pop_front(); } if (owner && owner->get_script_instance() == this) { - owner->_change_notify(); } //change notify @@ -513,7 +508,6 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c } void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, const Variant &p_value, bool *r_valid) { - if (script->is_placeholder_fallback_enabled()) { Map<StringName, Variant>::Element *E = values.find(p_name); @@ -535,31 +529,34 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name, } } - if (r_valid) + if (r_valid) { *r_valid = false; // Cannot change the value in either case + } } Variant PlaceHolderScriptInstance::property_get_fallback(const StringName &p_name, bool *r_valid) { - if (script->is_placeholder_fallback_enabled()) { const Map<StringName, Variant>::Element *E = values.find(p_name); if (E) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return E->value(); } E = constants.find(p_name); if (E) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return E->value(); } } - if (r_valid) + if (r_valid) { *r_valid = false; + } return Variant(); } @@ -579,7 +576,6 @@ PlaceHolderScriptInstance::PlaceHolderScriptInstance(ScriptLanguage *p_language, } PlaceHolderScriptInstance::~PlaceHolderScriptInstance() { - if (script.is_valid()) { script->_placeholder_erased(this); } diff --git a/core/script_language.h b/core/script_language.h index 2d86c5166d..b6c2a47245 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -112,7 +112,6 @@ class ScriptInstance; class PlaceHolderScriptInstance; class Script : public Resource { - GDCLASS(Script, Resource); OBJ_SAVE_TYPE(Script); @@ -135,6 +134,8 @@ public: virtual Ref<Script> get_base_script() const = 0; //for script inheritance + virtual bool inherits_script(const Ref<Script> &p_script) const = 0; + virtual StringName get_instance_base_type() const = 0; // this may not work in all scripts, will return empty if so virtual ScriptInstance *instance_create(Object *p_this) = 0; virtual PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) { return nullptr; } @@ -203,8 +204,9 @@ public: virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); virtual void notification(int p_notification) = 0; virtual String to_string(bool *r_valid) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return String(); } @@ -251,14 +253,12 @@ struct ScriptCodeCompletionOption { KIND_FILE_PATH, KIND_PLAIN_TEXT, }; - Kind kind; + Kind kind = KIND_PLAIN_TEXT; String display; String insert_text; RES icon; - ScriptCodeCompletionOption() { - kind = KIND_PLAIN_TEXT; - } + ScriptCodeCompletionOption() {} ScriptCodeCompletionOption(const String &p_text, Kind p_kind) { display = p_text; @@ -268,7 +268,6 @@ struct ScriptCodeCompletionOption { }; class ScriptCodeCompletionCache { - static ScriptCodeCompletionCache *singleton; public: @@ -406,7 +405,6 @@ public: extern uint8_t script_encryption_key[32]; class PlaceHolderScriptInstance : public ScriptInstance { - Object *owner; List<PropertyInfo> properties; Map<StringName, Variant> values; diff --git a/core/self_list.h b/core/self_list.h index 19d2783208..3104bcb714 100644 --- a/core/self_list.h +++ b/core/self_list.h @@ -38,13 +38,11 @@ template <class T> class SelfList { public: class List { - - SelfList<T> *_first; - SelfList<T> *_last; + SelfList<T> *_first = nullptr; + SelfList<T> *_last = nullptr; public: void add(SelfList<T> *p_elem) { - ERR_FAIL_COND(p_elem->_root); p_elem->_root = this; @@ -62,7 +60,6 @@ public: } void add_last(SelfList<T> *p_elem) { - ERR_FAIL_COND(p_elem->_root); p_elem->_root = this; @@ -80,7 +77,6 @@ public: } void remove(SelfList<T> *p_elem) { - ERR_FAIL_COND(p_elem->_root != this); if (p_elem->_next) { p_elem->_next->_prev = p_elem->_prev; @@ -105,21 +101,24 @@ public: _FORCE_INLINE_ SelfList<T> *first() { return _first; } _FORCE_INLINE_ const SelfList<T> *first() const { return _first; } - _FORCE_INLINE_ List() { - _first = nullptr; - _last = nullptr; - } + + _FORCE_INLINE_ List() {} _FORCE_INLINE_ ~List() { ERR_FAIL_COND(_first != nullptr); } }; private: - List *_root; + List *_root = nullptr; T *_self; - SelfList<T> *_next; - SelfList<T> *_prev; + SelfList<T> *_next = nullptr; + SelfList<T> *_prev = nullptr; public: _FORCE_INLINE_ bool in_list() const { return _root; } + _FORCE_INLINE_ void remove_from_list() { + if (_root) { + _root->remove(this); + } + } _FORCE_INLINE_ SelfList<T> *next() { return _next; } _FORCE_INLINE_ SelfList<T> *prev() { return _prev; } _FORCE_INLINE_ const SelfList<T> *next() const { return _next; } @@ -127,17 +126,13 @@ public: _FORCE_INLINE_ T *self() const { return _self; } _FORCE_INLINE_ SelfList(T *p_self) { - _self = p_self; - _next = nullptr; - _prev = nullptr; - _root = nullptr; } _FORCE_INLINE_ ~SelfList() { - - if (_root) + if (_root) { _root->remove(this); + } } }; diff --git a/core/set.h b/core/set.h index c17ee15350..1bc0a3f41e 100644 --- a/core/set.h +++ b/core/set.h @@ -39,7 +39,6 @@ template <class T, class C = Comparator<T>, class A = DefaultAllocator> class Set { - enum Color { RED, BLACK @@ -48,54 +47,41 @@ class Set { public: class Element { - private: friend class Set<T, C, A>; - int color; - Element *right; - Element *left; - Element *parent; - Element *_next; - Element *_prev; + int color = RED; + Element *right = nullptr; + Element *left = nullptr; + Element *parent = nullptr; + Element *_next = nullptr; + Element *_prev = nullptr; T value; //_Data *data; public: const Element *next() const { - return _next; } Element *next() { - return _next; } const Element *prev() const { - return _prev; } Element *prev() { - return _prev; } const T &get() const { return value; }; - Element() { - color = RED; - right = nullptr; - left = nullptr; - parent = nullptr; - _next = nullptr; - _prev = nullptr; - }; + Element() {} }; private: struct _Data { - - Element *_root; + Element *_root = nullptr; Element *_nil; - int size_cache; + int size_cache = 0; _FORCE_INLINE_ _Data() { #ifdef GLOBALNIL_DISABLED @@ -105,19 +91,15 @@ private: #else _nil = (Element *)&_GlobalNilClass::_nil; #endif - _root = nullptr; - size_cache = 0; } void _create_root() { - _root = memnew_allocator(Element, A); _root->parent = _root->left = _root->right = _nil; _root->color = BLACK; } void _free_root() { - if (_root) { memdelete_allocator<Element, A>(_root); _root = nullptr; @@ -125,7 +107,6 @@ private: } ~_Data() { - _free_root(); #ifdef GLOBALNIL_DISABLED @@ -137,62 +118,61 @@ private: _Data _data; inline void _set_color(Element *p_node, int p_color) { - 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; p_node->right = r->left; - if (r->left != _data._nil) + if (r->left != _data._nil) { r->left->parent = p_node; + } r->parent = p_node->parent; - if (p_node == p_node->parent->left) + if (p_node == p_node->parent->left) { p_node->parent->left = r; - else + } else { p_node->parent->right = r; + } r->left = p_node; p_node->parent = r; } inline void _rotate_right(Element *p_node) { - Element *l = p_node->left; p_node->left = l->right; - if (l->right != _data._nil) + if (l->right != _data._nil) { l->right->parent = p_node; + } l->parent = p_node->parent; - if (p_node == p_node->parent->right) + if (p_node == p_node->parent->right) { p_node->parent->right = l; - else + } else { p_node->parent->left = l; + } l->right = p_node; p_node->parent = l; } inline Element *_successor(Element *p_node) const { - Element *node = p_node; if (node->right != _data._nil) { - node = node->right; while (node->left != _data._nil) { /* returns the minimum of the right subtree of node */ node = node->left; } return node; } else { - while (node == node->parent->right) { node = node->parent; } - if (node->parent == _data._root) + if (node->parent == _data._root) { return nullptr; // No successor, as p_node = last node + } return node->parent; } } @@ -201,43 +181,41 @@ private: Element *node = p_node; if (node->left != _data._nil) { - node = node->left; while (node->right != _data._nil) { /* returns the minimum of the left subtree of node */ node = node->right; } return node; } else { - while (node == node->parent->left) { node = node->parent; } - if (node == _data._root) + if (node == _data._root) { return nullptr; // No predecessor, as p_node = first node. + } return node->parent; } } Element *_find(const T &p_value) const { - Element *node = _data._root->left; C less; while (node != _data._nil) { - if (less(p_value, node->value)) + if (less(p_value, node->value)) { node = node->left; - else if (less(node->value, p_value)) + } else if (less(node->value, p_value)) { node = node->right; - else + } else { return node; // found + } } return nullptr; } Element *_lower_bound(const T &p_value) const { - Element *node = _data._root->left; Element *prev = nullptr; C less; @@ -245,25 +223,27 @@ private: while (node != _data._nil) { prev = node; - if (less(p_value, node->value)) + if (less(p_value, node->value)) { node = node->left; - else if (less(node->value, p_value)) + } else if (less(node->value, p_value)) { node = node->right; - else + } else { return node; // found + } } - if (prev == nullptr) + if (prev == nullptr) { return nullptr; // tree empty + } - if (less(prev->value, p_value)) + if (less(prev->value, p_value)) { prev = prev->_next; + } return prev; } void _insert_rb_fix(Element *p_new_node) { - Element *node = p_new_node; Element *nparent = node->parent; Element *ngrand_parent; @@ -312,20 +292,18 @@ private: } Element *_insert(const T &p_value) { - Element *new_parent = _data._root; Element *node = _data._root->left; C less; while (node != _data._nil) { - new_parent = node; - if (less(p_value, node->value)) + if (less(p_value, node->value)) { node = node->left; - else if (less(node->value, p_value)) + } else if (less(node->value, p_value)) { node = node->right; - else { + } else { return node; // Return existing node } } @@ -345,10 +323,12 @@ private: new_node->_next = _successor(new_node); new_node->_prev = _predecessor(new_node); - if (new_node->_next) + if (new_node->_next) { new_node->_next->_prev = new_node; - if (new_node->_prev) + } + if (new_node->_prev) { new_node->_prev->_next = new_node; + } _data.size_cache++; _insert_rb_fix(new_node); @@ -356,7 +336,6 @@ private: } void _erase_fix_rb(Element *p_node) { - Element *root = _data._root->left; Element *node = _data._nil; Element *sibling = p_node; @@ -418,7 +397,6 @@ private: } void _erase(Element *p_node) { - 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; @@ -439,17 +417,18 @@ private: } if (rp != p_node) { - ERR_FAIL_COND(rp == _data._nil); rp->left = p_node->left; rp->right = p_node->right; rp->parent = p_node->parent; rp->color = p_node->color; - if (p_node->left != _data._nil) + if (p_node->left != _data._nil) { p_node->left->parent = rp; - if (p_node->right != _data._nil) + } + if (p_node->right != _data._nil) { p_node->right->parent = rp; + } if (p_node == p_node->parent->left) { p_node->parent->left = rp; @@ -458,10 +437,12 @@ private: } } - if (p_node->_next) + if (p_node->_next) { p_node->_next->_prev = p_node->_prev; - if (p_node->_prev) + } + if (p_node->_prev) { p_node->_prev->_next = p_node->_next; + } memdelete_allocator<Element, A>(p_node); _data.size_cache--; @@ -469,21 +450,22 @@ 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) + if (d > max_d) { max_d = d; + } } void _cleanup_tree(Element *p_element) { - - if (p_element == _data._nil) + if (p_element == _data._nil) { return; + } _cleanup_tree(p_element->left); _cleanup_tree(p_element->right); @@ -491,102 +473,105 @@ private: } void _copy_from(const Set &p_set) { - clear(); // not the fastest way, but safeset to write. for (Element *I = p_set.front(); I; I = I->next()) { - insert(I->get()); } } public: const Element *find(const T &p_value) const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } const Element *res = _find(p_value); return res; } Element *find(const T &p_value) { - - if (!_data._root) + if (!_data._root) { return nullptr; + } 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 { - return find(p_value) != nullptr; } Element *insert(const T &p_value) { - - if (!_data._root) + if (!_data._root) { _data._create_root(); + } return _insert(p_value); } void erase(Element *p_element) { - - if (!_data._root || !p_element) + if (!_data._root || !p_element) { return; + } _erase(p_element); - if (_data.size_cache == 0 && _data._root) + if (_data.size_cache == 0 && _data._root) { _data._free_root(); + } } bool erase(const T &p_value) { - - if (!_data._root) + if (!_data._root) { return false; + } Element *e = find(p_value); - if (!e) + if (!e) { return false; + } _erase(e); - if (_data.size_cache == 0 && _data._root) + if (_data.size_cache == 0 && _data._root) { _data._free_root(); + } return true; } Element *front() const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } Element *e = _data._root->left; - if (e == _data._nil) + if (e == _data._nil) { return nullptr; + } - while (e->left != _data._nil) + while (e->left != _data._nil) { e = e->left; + } return e; } Element *back() const { - - if (!_data._root) + if (!_data._root) { return nullptr; + } Element *e = _data._root->left; - if (e == _data._nil) + if (e == _data._nil) { return nullptr; + } - while (e->right != _data._nil) + while (e->right != _data._nil) { e = e->right; + } return e; } @@ -596,8 +581,9 @@ public: int calculate_depth() const { // used for debug mostly - if (!_data._root) + if (!_data._root) { return 0; + } int max_d = 0; _calculate_depth(_data._root->left, max_d, 0); @@ -605,9 +591,9 @@ public: } void clear() { - - if (!_data._root) + if (!_data._root) { return; + } _cleanup_tree(_data._root->left); _data._root->left = _data._nil; @@ -616,20 +602,16 @@ public: } void operator=(const Set &p_set) { - _copy_from(p_set); } Set(const Set &p_set) { - _copy_from(p_set); } - _FORCE_INLINE_ Set() { - } + _FORCE_INLINE_ Set() {} ~Set() { - clear(); } }; diff --git a/core/simple_type.h b/core/simple_type.h index da031854c6..10dc36cbd4 100644 --- a/core/simple_type.h +++ b/core/simple_type.h @@ -35,19 +35,16 @@ template <class T> struct GetSimpleTypeT { - typedef T type_t; }; template <class T> struct GetSimpleTypeT<T &> { - typedef T type_t; }; template <class T> struct GetSimpleTypeT<T const> { - typedef T type_t; }; diff --git a/core/sort_array.h b/core/sort_array.h index 8aff0fb502..93cc6f727d 100644 --- a/core/sort_array.h +++ b/core/sort_array.h @@ -42,7 +42,6 @@ template <class T> struct _DefaultComparator { - _FORCE_INLINE_ bool operator()(const T &a, const T &b) const { return (a < b); } }; @@ -54,7 +53,6 @@ struct _DefaultComparator { template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED> class SortArray { - enum { INTROSORT_THRESHOLD = 16 @@ -64,36 +62,36 @@ public: Comparator compare; inline const T &median_of_3(const T &a, const T &b, const T &c) const { - - if (compare(a, b)) - if (compare(b, c)) + if (compare(a, b)) { + if (compare(b, c)) { return b; - else if (compare(a, c)) + } else if (compare(a, c)) { return c; - else + } else { return a; - else if (compare(a, c)) + } + } else if (compare(a, c)) { return a; - else if (compare(b, c)) + } else if (compare(b, c)) { return c; - else + } else { return b; + } } inline int bitlog(int n) const { int k; - for (k = 0; n != 1; n >>= 1) + for (k = 0; n != 1; n >>= 1) { ++k; + } return k; } /* Heap / Heapsort functions */ inline void push_heap(int p_first, int p_hole_idx, int p_top_index, T p_value, T *p_array) const { - int parent = (p_hole_idx - 1) / 2; while (p_hole_idx > p_top_index && compare(p_array[p_first + parent], p_value)) { - p_array[p_first + p_hole_idx] = p_array[p_first + parent]; p_hole_idx = parent; parent = (p_hole_idx - 1) / 2; @@ -102,24 +100,21 @@ public: } inline void pop_heap(int p_first, int p_last, int p_result, T p_value, T *p_array) const { - p_array[p_result] = p_array[p_first]; adjust_heap(p_first, 0, p_last - p_first, p_value, p_array); } inline void pop_heap(int p_first, int p_last, T *p_array) const { - pop_heap(p_first, p_last - 1, p_last - 1, p_array[p_last - 1], p_array); } inline void adjust_heap(int p_first, int p_hole_idx, int p_len, T p_value, T *p_array) const { - int top_index = p_hole_idx; int second_child = 2 * p_hole_idx + 2; while (second_child < p_len) { - - if (compare(p_array[p_first + second_child], p_array[p_first + (second_child - 1)])) + if (compare(p_array[p_first + second_child], p_array[p_first + (second_child - 1)])) { second_child--; + } p_array[p_first + p_hole_idx] = p_array[p_first + second_child]; p_hole_idx = second_child; @@ -134,46 +129,47 @@ public: } inline void sort_heap(int p_first, int p_last, T *p_array) const { - while (p_last - p_first > 1) { - pop_heap(p_first, p_last--, p_array); } } inline void make_heap(int p_first, int p_last, T *p_array) const { - if (p_last - p_first < 2) + if (p_last - p_first < 2) { return; + } int len = p_last - p_first; int parent = (len - 2) / 2; while (true) { adjust_heap(p_first, parent, len, p_array[p_first + parent], p_array); - if (parent == 0) + if (parent == 0) { return; + } parent--; } } inline void partial_sort(int p_first, int p_last, int p_middle, T *p_array) const { - make_heap(p_first, p_middle, p_array); - for (int i = p_middle; i < p_last; i++) - if (compare(p_array[i], p_array[p_first])) + for (int i = p_middle; i < p_last; i++) { + if (compare(p_array[i], p_array[p_first])) { pop_heap(p_first, p_middle, i, p_array[i], p_array); + } + } sort_heap(p_first, p_middle, p_array); } inline void partial_select(int p_first, int p_last, int p_middle, T *p_array) const { - make_heap(p_first, p_middle, p_array); - for (int i = p_middle; i < p_last; i++) - if (compare(p_array[i], p_array[p_first])) + for (int i = p_middle; i < p_last; i++) { + if (compare(p_array[i], p_array[p_first])) { pop_heap(p_first, p_middle, i, p_array[i], p_array); + } + } } inline int partitioner(int p_first, int p_last, T p_pivot, T *p_array) const { - const int unmodified_first = p_first; const int unmodified_last = p_last; @@ -192,8 +188,9 @@ public: p_last--; } - if (!(p_first < p_last)) + if (!(p_first < p_last)) { return p_first; + } SWAP(p_array[p_first], p_array[p_last]); p_first++; @@ -201,9 +198,7 @@ public: } inline void introsort(int p_first, int p_last, T *p_array, int p_max_depth) const { - while (p_last - p_first > INTROSORT_THRESHOLD) { - if (p_max_depth == 0) { partial_sort(p_first, p_last, p_last, p_array); return; @@ -226,9 +221,7 @@ public: } inline void introselect(int p_first, int p_nth, int p_last, T *p_array, int p_max_depth) const { - while (p_last - p_first > 3) { - if (p_max_depth == 0) { partial_select(p_first, p_nth + 1, p_last, p_array); SWAP(p_first, p_nth); @@ -246,17 +239,17 @@ public: p_array[p_last - 1]), p_array); - if (cut <= p_nth) + if (cut <= p_nth) { p_first = cut; - else + } else { p_last = cut; + } } insertion_sort(p_first, p_last, p_array); } inline void unguarded_linear_insert(int p_last, T p_value, T *p_array) const { - int next = p_last - 1; while (compare(p_value, p_array[next])) { if (Validate) { @@ -270,45 +263,43 @@ public: } inline void linear_insert(int p_first, int p_last, T *p_array) const { - T val = p_array[p_last]; if (compare(val, p_array[p_first])) { - - for (int i = p_last; i > p_first; i--) + for (int i = p_last; i > p_first; i--) { p_array[i] = p_array[i - 1]; + } p_array[p_first] = val; - } else + } else { unguarded_linear_insert(p_last, val, p_array); + } } inline void insertion_sort(int p_first, int p_last, T *p_array) const { - - if (p_first == p_last) + if (p_first == p_last) { return; - for (int i = p_first + 1; i != p_last; i++) + } + for (int i = p_first + 1; i != p_last; i++) { linear_insert(p_first, i, p_array); + } } inline void unguarded_insertion_sort(int p_first, int p_last, T *p_array) const { - - for (int i = p_first; i != p_last; i++) + for (int i = p_first; i != p_last; i++) { unguarded_linear_insert(i, p_array[i], p_array); + } } inline void final_insertion_sort(int p_first, int p_last, T *p_array) const { - if (p_last - p_first > INTROSORT_THRESHOLD) { insertion_sort(p_first, p_first + INTROSORT_THRESHOLD, p_array); unguarded_insertion_sort(p_first + INTROSORT_THRESHOLD, p_last, p_array); } else { - insertion_sort(p_first, p_last, p_array); } } inline void sort_range(int p_first, int p_last, T *p_array) const { - if (p_first != p_last) { introsort(p_first, p_last, p_array, bitlog(p_last - p_first) * 2); final_insertion_sort(p_first, p_last, p_array); @@ -316,14 +307,13 @@ public: } inline void sort(T *p_array, int p_len) const { - sort_range(0, p_len, p_array); } inline void nth_element(int p_first, int p_last, int p_nth, T *p_array) const { - - if (p_first == p_last || p_nth == p_last) + if (p_first == p_last || p_nth == p_last) { return; + } introselect(p_first, p_nth, p_last, p_array, bitlog(p_last - p_first) * 2); } }; diff --git a/core/spin_lock.h b/core/spin_lock.h index c48631f94a..1bb810bb29 100644 --- a/core/spin_lock.h +++ b/core/spin_lock.h @@ -32,6 +32,7 @@ #define SPIN_LOCK_H #include "core/typedefs.h" + #include <atomic> class SpinLock { diff --git a/core/string_buffer.h b/core/string_buffer.h index a140f0abf7..956a6333d9 100644 --- a/core/string_buffer.h +++ b/core/string_buffer.h @@ -35,10 +35,9 @@ template <int SHORT_BUFFER_SIZE = 64> class StringBuffer { - CharType short_buffer[SHORT_BUFFER_SIZE]; String buffer; - int string_length; + int string_length = 0; _FORCE_INLINE_ CharType *current_buffer_ptr() { return static_cast<String &>(buffer).empty() ? short_buffer : buffer.ptrw(); @@ -78,10 +77,6 @@ public: _FORCE_INLINE_ operator String() { return as_string(); } - - StringBuffer() { - string_length = 0; - } }; template <int SHORT_BUFFER_SIZE> @@ -123,8 +118,9 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const C template <int SHORT_BUFFER_SIZE> StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::reserve(int p_size) { - if (p_size < SHORT_BUFFER_SIZE || p_size < buffer.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)); diff --git a/core/string_builder.cpp b/core/string_builder.cpp index 46c7e1c53f..c8d6498f27 100644 --- a/core/string_builder.cpp +++ b/core/string_builder.cpp @@ -33,9 +33,9 @@ #include <string.h> StringBuilder &StringBuilder::append(const String &p_string) { - - if (p_string == String()) + if (p_string == String()) { return *this; + } strings.push_back(p_string); appended_strings.push_back(-1); @@ -46,7 +46,6 @@ StringBuilder &StringBuilder::append(const String &p_string) { } StringBuilder &StringBuilder::append(const char *p_cstring) { - int32_t len = strlen(p_cstring); c_strings.push_back(p_cstring); @@ -58,9 +57,9 @@ StringBuilder &StringBuilder::append(const char *p_cstring) { } String StringBuilder::as_string() const { - - if (string_length == 0) + if (string_length == 0) { return ""; + } CharType *buffer = memnew_arr(CharType, string_length); @@ -80,7 +79,6 @@ String StringBuilder::as_string() const { godot_string_elem++; } else { - const char *s = c_strings[c_string_elem]; for (int32_t j = 0; j < appended_strings[i]; j++) { diff --git a/core/string_builder.h b/core/string_builder.h index dd8a154890..2a37d14218 100644 --- a/core/string_builder.h +++ b/core/string_builder.h @@ -32,12 +32,10 @@ #define STRING_BUILDER_H #include "core/ustring.h" - #include "core/vector.h" class StringBuilder { - - uint32_t string_length; + uint32_t string_length = 0; Vector<String> strings; Vector<const char *> c_strings; @@ -80,9 +78,7 @@ public: return as_string(); } - StringBuilder() { - string_length = 0; - } + StringBuilder() {} }; #endif // STRING_BUILDER_H diff --git a/core/string_name.cpp b/core/string_name.cpp index 9cbac97a7c..cbf6009681 100644 --- a/core/string_name.cpp +++ b/core/string_name.cpp @@ -42,7 +42,6 @@ StaticCString StaticCString::create(const char *p_ptr) { StringName::_Data *StringName::_table[STRING_TABLE_LEN]; StringName _scs_create(const char *p_chr) { - return (p_chr[0] ? StringName(StaticCString::create(p_chr)) : StringName()); } @@ -50,24 +49,19 @@ bool StringName::configured = false; Mutex StringName::mutex; void StringName::setup() { - ERR_FAIL_COND(configured); for (int i = 0; i < STRING_TABLE_LEN; i++) { - _table[i] = nullptr; } configured = true; } void StringName::cleanup() { - MutexLock lock(mutex); int lost_strings = 0; for (int i = 0; i < STRING_TABLE_LEN; i++) { - while (_table[i]) { - _Data *d = _table[i]; lost_strings++; if (OS::get_singleton()->is_stdout_verbose()) { @@ -88,11 +82,9 @@ void StringName::cleanup() { } void StringName::unref() { - ERR_FAIL_COND(!configured); if (_data && _data->refcount.unref()) { - MutexLock lock(mutex); if (_data->prev) { @@ -114,9 +106,7 @@ void StringName::unref() { } bool StringName::operator==(const String &p_name) const { - if (!_data) { - return (p_name.length() == 0); } @@ -124,9 +114,7 @@ bool StringName::operator==(const String &p_name) const { } bool StringName::operator==(const char *p_name) const { - if (!_data) { - return (p_name[0] == 0); } @@ -134,32 +122,28 @@ bool StringName::operator==(const char *p_name) const { } bool StringName::operator!=(const String &p_name) const { - return !(operator==(p_name)); } bool StringName::operator!=(const StringName &p_name) const { - // the real magic of all this mess happens here. // this is why path comparisons are very fast return _data != p_name._data; } void StringName::operator=(const StringName &p_name) { - - if (this == &p_name) + if (this == &p_name) { return; + } unref(); if (p_name._data && p_name._data->refcount.ref()) { - _data = p_name._data; } } StringName::StringName(const StringName &p_name) { - _data = nullptr; ERR_FAIL_COND(!configured); @@ -170,13 +154,13 @@ StringName::StringName(const StringName &p_name) { } StringName::StringName(const char *p_name) { - _data = nullptr; ERR_FAIL_COND(!configured); - if (!p_name || p_name[0] == 0) + if (!p_name || p_name[0] == 0) { return; //empty, ignore + } MutexLock lock(mutex); @@ -187,10 +171,10 @@ StringName::StringName(const char *p_name) { _data = _table[idx]; while (_data) { - // compare hash first - if (_data->hash == hash && _data->get_name() == p_name) + if (_data->hash == hash && _data->get_name() == p_name) { break; + } _data = _data->next; } @@ -209,13 +193,13 @@ StringName::StringName(const char *p_name) { _data->cname = nullptr; _data->next = _table[idx]; _data->prev = nullptr; - if (_table[idx]) + if (_table[idx]) { _table[idx]->prev = _data; + } _table[idx] = _data; } StringName::StringName(const StaticCString &p_static_string) { - _data = nullptr; ERR_FAIL_COND(!configured); @@ -231,10 +215,10 @@ StringName::StringName(const StaticCString &p_static_string) { _data = _table[idx]; while (_data) { - // compare hash first - if (_data->hash == hash && _data->get_name() == p_static_string.ptr) + if (_data->hash == hash && _data->get_name() == p_static_string.ptr) { break; + } _data = _data->next; } @@ -253,19 +237,20 @@ StringName::StringName(const StaticCString &p_static_string) { _data->cname = p_static_string.ptr; _data->next = _table[idx]; _data->prev = nullptr; - if (_table[idx]) + if (_table[idx]) { _table[idx]->prev = _data; + } _table[idx] = _data; } StringName::StringName(const String &p_name) { - _data = nullptr; ERR_FAIL_COND(!configured); - if (p_name == String()) + if (p_name == String()) { return; + } MutexLock lock(mutex); @@ -275,9 +260,9 @@ StringName::StringName(const String &p_name) { _data = _table[idx]; while (_data) { - - if (_data->hash == hash && _data->get_name() == p_name) + if (_data->hash == hash && _data->get_name() == p_name) { break; + } _data = _data->next; } @@ -296,18 +281,19 @@ StringName::StringName(const String &p_name) { _data->cname = nullptr; _data->next = _table[idx]; _data->prev = nullptr; - if (_table[idx]) + if (_table[idx]) { _table[idx]->prev = _data; + } _table[idx] = _data; } StringName StringName::search(const char *p_name) { - ERR_FAIL_COND_V(!configured, StringName()); ERR_FAIL_COND_V(!p_name, StringName()); - if (!p_name[0]) + if (!p_name[0]) { return StringName(); + } MutexLock lock(mutex); @@ -317,10 +303,10 @@ StringName StringName::search(const char *p_name) { _Data *_data = _table[idx]; while (_data) { - // compare hash first - if (_data->hash == hash && _data->get_name() == p_name) + if (_data->hash == hash && _data->get_name() == p_name) { break; + } _data = _data->next; } @@ -332,12 +318,12 @@ StringName StringName::search(const char *p_name) { } StringName StringName::search(const CharType *p_name) { - ERR_FAIL_COND_V(!configured, StringName()); ERR_FAIL_COND_V(!p_name, StringName()); - if (!p_name[0]) + if (!p_name[0]) { return StringName(); + } MutexLock lock(mutex); @@ -348,10 +334,10 @@ StringName StringName::search(const CharType *p_name) { _Data *_data = _table[idx]; while (_data) { - // compare hash first - if (_data->hash == hash && _data->get_name() == p_name) + if (_data->hash == hash && _data->get_name() == p_name) { break; + } _data = _data->next; } @@ -361,8 +347,8 @@ StringName StringName::search(const CharType *p_name) { return StringName(); //does not exist } -StringName StringName::search(const String &p_name) { +StringName StringName::search(const String &p_name) { ERR_FAIL_COND_V(p_name == "", StringName()); MutexLock lock(mutex); @@ -374,10 +360,10 @@ StringName StringName::search(const String &p_name) { _Data *_data = _table[idx]; while (_data) { - // compare hash first - if (_data->hash == hash && p_name == _data->get_name()) + if (_data->hash == hash && p_name == _data->get_name()) { break; + } _data = _data->next; } @@ -388,12 +374,6 @@ StringName StringName::search(const String &p_name) { return StringName(); //does not exist } -StringName::StringName() { - - _data = nullptr; -} - StringName::~StringName() { - unref(); } diff --git a/core/string_name.h b/core/string_name.h index aec87b8e66..df6b458581 100644 --- a/core/string_name.h +++ b/core/string_name.h @@ -36,13 +36,11 @@ #include "core/ustring.h" struct StaticCString { - const char *ptr; static StaticCString create(const char *p_ptr); }; class StringName { - enum { STRING_TABLE_BITS = 12, @@ -52,28 +50,22 @@ class StringName { struct _Data { SafeRefCount refcount; - const char *cname; + const char *cname = nullptr; String name; String get_name() const { return cname ? String(cname) : name; } - int idx; - uint32_t hash; - _Data *prev; - _Data *next; - _Data() { - cname = nullptr; - next = prev = nullptr; - idx = 0; - hash = 0; - } + int idx = 0; + uint32_t hash = 0; + _Data *prev = nullptr; + _Data *next = nullptr; + _Data() {} }; static _Data *_table[STRING_TABLE_LEN]; - _Data *_data; + _Data *_data = nullptr; union _HashUnion { - _Data *ptr; uint32_t hash; }; @@ -90,13 +82,12 @@ class StringName { StringName(_Data *p_data) { _data = p_data; } public: - operator const void *() const { return (_data && (_data->cname || !_data->name.empty())) ? (void *)1 : 0; } + operator const void *() const { return (_data && (_data->cname || !_data->name.empty())) ? (void *)1 : nullptr; } bool operator==(const String &p_name) const; bool operator==(const char *p_name) const; bool operator!=(const String &p_name) const; _FORCE_INLINE_ bool operator<(const StringName &p_name) const { - return _data < p_name._data; } _FORCE_INLINE_ bool operator==(const StringName &p_name) const { @@ -105,11 +96,11 @@ public: return _data == p_name._data; } _FORCE_INLINE_ uint32_t hash() const { - - if (_data) + if (_data) { return _data->hash; - else + } else { return 0; + } } _FORCE_INLINE_ const void *data_unique_pointer() const { return (void *)_data; @@ -117,12 +108,12 @@ public: bool operator!=(const StringName &p_name) const; _FORCE_INLINE_ operator String() const { - if (_data) { - if (_data->cname) + if (_data->cname) { return String(_data->cname); - else + } else { return _data->name; + } } return String(); @@ -133,24 +124,22 @@ public: static StringName search(const String &p_name); struct AlphCompare { - _FORCE_INLINE_ bool operator()(const StringName &l, const StringName &r) const { - const char *l_cname = l._data ? l._data->cname : ""; const char *r_cname = r._data ? r._data->cname : ""; if (l_cname) { - - if (r_cname) + if (r_cname) { return is_str_less(l_cname, r_cname); - else + } else { return is_str_less(l_cname, r._data->name.ptr()); + } } else { - - if (r_cname) + if (r_cname) { return is_str_less(l._data->name.ptr(), r_cname); - else + } else { return is_str_less(l._data->name.ptr(), r._data->name.ptr()); + } } } }; @@ -160,7 +149,7 @@ public: StringName(const StringName &p_name); StringName(const String &p_name); StringName(const StaticCString &p_static_string); - StringName(); + StringName() {} ~StringName(); }; diff --git a/core/thread_work_pool.cpp b/core/thread_work_pool.cpp index c8311f102f..3a95e83ffc 100644 --- a/core/thread_work_pool.cpp +++ b/core/thread_work_pool.cpp @@ -29,10 +29,10 @@ /*************************************************************************/ #include "thread_work_pool.h" + #include "core/os/os.h" void ThreadWorkPool::_thread_function(ThreadData *p_thread) { - while (true) { p_thread->start.wait(); if (p_thread->exit.load()) { @@ -59,7 +59,6 @@ void ThreadWorkPool::init(int p_thread_count) { } void ThreadWorkPool::finish() { - if (threads == nullptr) { return; } @@ -78,6 +77,5 @@ void ThreadWorkPool::finish() { } ThreadWorkPool::~ThreadWorkPool() { - finish(); } diff --git a/core/thread_work_pool.h b/core/thread_work_pool.h index 214d2c4aa7..e21d3974ee 100644 --- a/core/thread_work_pool.h +++ b/core/thread_work_pool.h @@ -33,10 +33,11 @@ #include "core/os/memory.h" #include "core/os/semaphore.h" + #include <atomic> #include <thread> -class ThreadWorkPool { +class ThreadWorkPool { std::atomic<uint32_t> index; struct BaseWork { @@ -52,7 +53,6 @@ class ThreadWorkPool { M method; U userdata; virtual void work() { - while (true) { uint32_t work_index = index->fetch_add(1, std::memory_order_relaxed); if (work_index >= max_elements) { @@ -79,7 +79,6 @@ class ThreadWorkPool { public: template <class C, class M, class U> void do_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - ERR_FAIL_COND(!threads); //never initialized index.store(0); diff --git a/core/translation.cpp b/core/translation.cpp index 3f45bb17c9..4f835bd7b4 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -795,12 +795,10 @@ static const char *locale_renames[][2] = { /////////////////////////////////////////////// Vector<String> Translation::_get_messages() const { - Vector<String> msgs; msgs.resize(translation_map.size() * 2); int idx = 0; for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { - msgs.set(idx + 0, E->key()); msgs.set(idx + 1, E->get()); idx += 2; @@ -810,12 +808,10 @@ Vector<String> Translation::_get_messages() const { } Vector<String> Translation::_get_message_list() const { - Vector<String> msgs; msgs.resize(translation_map.size()); int idx = 0; for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { - msgs.set(idx, E->key()); idx += 1; } @@ -824,20 +820,17 @@ Vector<String> Translation::_get_message_list() const { } void Translation::_set_messages(const Vector<String> &p_messages) { - int msg_count = p_messages.size(); ERR_FAIL_COND(msg_count % 2); const String *r = p_messages.ptr(); for (int i = 0; i < msg_count; i += 2) { - add_message(r[i + 0], r[i + 1]); } } void Translation::set_locale(const String &p_locale) { - String univ_locale = TranslationServer::standardize_locale(p_locale); if (!TranslationServer::is_locale_valid(univ_locale)) { @@ -856,38 +849,33 @@ void Translation::set_locale(const String &p_locale) { } void Translation::add_message(const StringName &p_src_text, const StringName &p_xlated_text) { - translation_map[p_src_text] = p_xlated_text; } -StringName Translation::get_message(const StringName &p_src_text) const { +StringName Translation::get_message(const StringName &p_src_text) const { const Map<StringName, StringName>::Element *E = translation_map.find(p_src_text); - if (!E) + if (!E) { return StringName(); + } return E->get(); } void Translation::erase_message(const StringName &p_src_text) { - translation_map.erase(p_src_text); } void Translation::get_message_list(List<StringName> *r_messages) const { - for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) { - r_messages->push_back(E->key()); } } int Translation::get_message_count() const { - return translation_map.size(); -}; +} void Translation::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_locale", "locale"), &Translation::set_locale); ClassDB::bind_method(D_METHOD("get_locale"), &Translation::get_locale); ClassDB::bind_method(D_METHOD("add_message", "src_message", "xlated_message"), &Translation::add_message); @@ -902,20 +890,15 @@ void Translation::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale"); } -Translation::Translation() : - locale("en") { -} - /////////////////////////////////////////////// bool TranslationServer::is_locale_valid(const String &p_locale) { - const char **ptr = locale_list; while (*ptr) { - - if (*ptr == p_locale) + if (*ptr == p_locale) { return true; + } ptr++; } @@ -923,7 +906,6 @@ bool TranslationServer::is_locale_valid(const String &p_locale) { } String TranslationServer::standardize_locale(const String &p_locale) { - // Replaces '-' with '_' for macOS Sierra-style locales String univ_locale = p_locale.replace("-", "_"); @@ -941,7 +923,6 @@ String TranslationServer::standardize_locale(const String &p_locale) { } String TranslationServer::get_language_code(const String &p_locale) { - ERR_FAIL_COND_V_MSG(p_locale.length() < 2, p_locale, "Invalid locale '" + p_locale + "'."); // Most language codes are two letters, but some are three, // so we have to look for a regional code separator ('_' or '-') @@ -958,7 +939,6 @@ String TranslationServer::get_language_code(const String &p_locale) { } void TranslationServer::set_locale(const String &p_locale) { - String univ_locale = standardize_locale(p_locale); if (!is_locale_valid(univ_locale)) { @@ -983,20 +963,19 @@ void TranslationServer::set_locale(const String &p_locale) { } 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(); + if (!locale_name_map.has(p_locale)) { + return String(); + } return locale_name_map[p_locale]; } Array TranslationServer::get_loaded_locales() const { Array locales; for (const Set<Ref<Translation>>::Element *E = translations.front(); E; E = E->next()) { - const Ref<Translation> &t = E->get(); ERR_FAIL_COND_V(t.is_null(), Array()); String l = t->get_locale(); @@ -1008,7 +987,6 @@ Array TranslationServer::get_loaded_locales() const { } Vector<String> TranslationServer::get_all_locales() { - Vector<String> locales; const char **ptr = locale_list; @@ -1022,7 +1000,6 @@ Vector<String> TranslationServer::get_all_locales() { } Vector<String> TranslationServer::get_all_locale_names() { - Vector<String> locales; const char **ptr = locale_names; @@ -1036,25 +1013,23 @@ Vector<String> TranslationServer::get_all_locale_names() { } void TranslationServer::add_translation(const Ref<Translation> &p_translation) { - translations.insert(p_translation); } -void TranslationServer::remove_translation(const Ref<Translation> &p_translation) { +void TranslationServer::remove_translation(const Ref<Translation> &p_translation) { translations.erase(p_translation); } void TranslationServer::clear() { - translations.clear(); -}; +} StringName TranslationServer::translate(const StringName &p_message) const { - // Match given message against the translation catalog for the project locale. - if (!enabled) + if (!enabled) { return p_message; + } ERR_FAIL_COND_V_MSG(locale.length() < 2, p_message, "Could not translate message as configured locale '" + locale + "' is invalid."); @@ -1144,7 +1119,6 @@ StringName TranslationServer::translate(const StringName &p_message) const { TranslationServer *TranslationServer::singleton = nullptr; bool TranslationServer::_load_translations(const String &p_from) { - if (ProjectSettings::get_singleton()->has_setting(p_from)) { Vector<String> translations = ProjectSettings::get_singleton()->get(p_from); @@ -1154,10 +1128,10 @@ bool TranslationServer::_load_translations(const String &p_from) { const String *r = translations.ptr(); for (int i = 0; i < tcount; i++) { - Ref<Translation> tr = ResourceLoader::load(r[i]); - if (tr.is_valid()) + if (tr.is_valid()) { add_translation(tr); + } } } return true; @@ -1167,21 +1141,22 @@ bool TranslationServer::_load_translations(const String &p_from) { } void TranslationServer::setup() { - String test = GLOBAL_DEF("locale/test", ""); test = test.strip_edges(); - if (test != "") + if (test != "") { set_locale(test); - else + } else { set_locale(OS::get_singleton()->get_locale()); + } fallback = GLOBAL_DEF("locale/fallback", "en"); #ifdef TOOLS_ENABLED { String options = ""; int idx = 0; while (locale_list[idx]) { - if (idx > 0) + if (idx > 0) { options += ","; + } options += locale_list[idx]; idx++; } @@ -1219,7 +1194,6 @@ StringName TranslationServer::doc_translate(const StringName &p_message) const { } 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); @@ -1236,7 +1210,6 @@ void TranslationServer::_bind_methods() { } void TranslationServer::load_translations() { - String locale = get_locale(); _load_translations("locale/translations"); //all _load_translations("locale/translations_" + locale.substr(0, 2)); @@ -1246,13 +1219,10 @@ void TranslationServer::load_translations() { } } -TranslationServer::TranslationServer() : - locale("en"), - enabled(true) { +TranslationServer::TranslationServer() { singleton = this; for (int i = 0; locale_list[i]; ++i) { - locale_name_map.insert(locale_list[i], String::utf8(locale_names[i])); } } diff --git a/core/translation.h b/core/translation.h index 29a068f450..4f50a1a4bc 100644 --- a/core/translation.h +++ b/core/translation.h @@ -34,12 +34,11 @@ #include "core/resource.h" class Translation : public Resource { - GDCLASS(Translation, Resource); OBJ_SAVE_TYPE(Translation); RES_BASE_EXTENSION("translation"); - String locale; + String locale = "en"; Map<StringName, StringName> translation_map; Vector<String> _get_message_list() const; @@ -61,14 +60,13 @@ public: void get_message_list(List<StringName> *r_messages) const; int get_message_count() const; - Translation(); + Translation() {} }; class TranslationServer : public Object { - GDCLASS(TranslationServer, Object); - String locale; + String locale = "en"; String fallback; Set<Ref<Translation>> translations; @@ -77,7 +75,7 @@ class TranslationServer : public Object { Map<String, String> locale_name_map; - bool enabled; + bool enabled = true; static TranslationServer *singleton; bool _load_translations(const String &p_from); diff --git a/core/type_info.h b/core/type_info.h index 816d0d9381..e3d2b5bd53 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -35,7 +35,6 @@ template <bool C, typename T = void> struct EnableIf { - typedef T type; }; @@ -45,19 +44,16 @@ struct EnableIf<false, T> { template <typename, typename> struct TypesAreSame { - static bool const value = false; }; template <typename A> struct TypesAreSame<A, A> { - static bool const value = true; }; template <typename B, typename D> struct TypeInherits { - static D *get_d(); static char (&test(B *))[1]; @@ -262,8 +258,9 @@ struct GetTypeInfo<const T *, typename EnableIf<TypeInherits<Object, T>::value>: template <typename T> inline StringName __constant_get_enum_name(T param, const String &p_constant) { - if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) + if (GetTypeInfo<T>::VARIANT_TYPE == Variant::NIL) { ERR_PRINT("Missing VARIANT_ENUM_CAST for constant's enum: " + p_constant); + } return GetTypeInfo<T>::get_class_info().class_name; } diff --git a/core/typed_array.h b/core/typed_array.h new file mode 100644 index 0000000000..86f26d7550 --- /dev/null +++ b/core/typed_array.h @@ -0,0 +1,227 @@ +/*************************************************************************/ +/* typed_array.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TYPED_ARRAY_H +#define TYPED_ARRAY_H + +#include "core/array.h" +#include "core/method_ptrcall.h" +#include "core/variant.h" + +template <class T> +class TypedArray : public Array { +public: + template <class U> + _FORCE_INLINE_ void operator=(const TypedArray<U> &p_array) { + static_assert(__is_base_of(T, U)); + _assign(p_array); + } + + _FORCE_INLINE_ void operator=(const Array &p_array) { + _assign(p_array); + } + _FORCE_INLINE_ TypedArray(const Variant &p_variant) : + Array(Array(p_variant), Variant::OBJECT, T::get_class_static(), Variant()) { + } + _FORCE_INLINE_ TypedArray(const Array &p_array) : + Array(p_array, Variant::OBJECT, T::get_class_static(), Variant()) { + } + _FORCE_INLINE_ TypedArray() { + set_typed(Variant::OBJECT, T::get_class_static(), Variant()); + } +}; + +//specialization for the rest of variant types + +#define MAKE_TYPED_ARRAY(m_type, m_variant_type) \ + template <> \ + class TypedArray<m_type> : public Array { \ + public: \ + _FORCE_INLINE_ void operator=(const Array &p_array) { \ + _assign(p_array); \ + } \ + _FORCE_INLINE_ TypedArray(const Variant &p_variant) : \ + Array(Array(p_variant), m_variant_type, StringName(), Variant()) { \ + } \ + _FORCE_INLINE_ TypedArray(const Array &p_array) : \ + Array(p_array, m_variant_type, StringName(), Variant()) { \ + } \ + _FORCE_INLINE_ TypedArray() { \ + set_typed(m_variant_type, StringName(), Variant()); \ + } \ + }; + +MAKE_TYPED_ARRAY(bool, Variant::BOOL) +MAKE_TYPED_ARRAY(uint8_t, Variant::INT) +MAKE_TYPED_ARRAY(int8_t, Variant::INT) +MAKE_TYPED_ARRAY(uint16_t, Variant::INT) +MAKE_TYPED_ARRAY(int16_t, Variant::INT) +MAKE_TYPED_ARRAY(uint32_t, Variant::INT) +MAKE_TYPED_ARRAY(int32_t, Variant::INT) +MAKE_TYPED_ARRAY(uint64_t, Variant::INT) +MAKE_TYPED_ARRAY(int64_t, Variant::INT) +MAKE_TYPED_ARRAY(float, Variant::FLOAT) +MAKE_TYPED_ARRAY(double, Variant::FLOAT) +MAKE_TYPED_ARRAY(String, Variant::STRING) +MAKE_TYPED_ARRAY(Vector2, Variant::VECTOR2) +MAKE_TYPED_ARRAY(Vector2i, Variant::VECTOR2I) +MAKE_TYPED_ARRAY(Rect2, Variant::RECT2) +MAKE_TYPED_ARRAY(Rect2i, Variant::RECT2I) +MAKE_TYPED_ARRAY(Vector3, Variant::VECTOR3) +MAKE_TYPED_ARRAY(Vector3i, Variant::VECTOR3I) +MAKE_TYPED_ARRAY(Transform2D, Variant::TRANSFORM2D) +MAKE_TYPED_ARRAY(Plane, Variant::PLANE) +MAKE_TYPED_ARRAY(Quat, Variant::QUAT) +MAKE_TYPED_ARRAY(AABB, Variant::AABB) +MAKE_TYPED_ARRAY(Basis, Variant::BASIS) +MAKE_TYPED_ARRAY(Transform, Variant::TRANSFORM) +MAKE_TYPED_ARRAY(Color, Variant::COLOR) +MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME) +MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH) +MAKE_TYPED_ARRAY(RID, Variant::_RID) +MAKE_TYPED_ARRAY(Callable, Variant::CALLABLE) +MAKE_TYPED_ARRAY(Signal, Variant::SIGNAL) +MAKE_TYPED_ARRAY(Dictionary, Variant::DICTIONARY) +MAKE_TYPED_ARRAY(Array, Variant::ARRAY) +MAKE_TYPED_ARRAY(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY) +MAKE_TYPED_ARRAY(Vector<int32_t>, Variant::PACKED_INT32_ARRAY) +MAKE_TYPED_ARRAY(Vector<int64_t>, Variant::PACKED_INT64_ARRAY) +MAKE_TYPED_ARRAY(Vector<float>, Variant::PACKED_FLOAT32_ARRAY) +MAKE_TYPED_ARRAY(Vector<double>, Variant::PACKED_FLOAT64_ARRAY) +MAKE_TYPED_ARRAY(Vector<String>, Variant::PACKED_STRING_ARRAY) +MAKE_TYPED_ARRAY(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY) +MAKE_TYPED_ARRAY(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY) +MAKE_TYPED_ARRAY(Vector<Color>, Variant::PACKED_COLOR_ARRAY) + +#ifdef PTRCALL_ENABLED + +template <class T> +struct PtrToArg<TypedArray<T>> { + _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { + return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr)); + } + + _FORCE_INLINE_ static void encode(TypedArray<T> p_val, void *p_ptr) { + *(Array *)p_ptr = p_val; + } +}; + +template <class T> +struct PtrToArg<const TypedArray<T> &> { + _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { + return TypedArray<T>(*reinterpret_cast<const Array *>(p_ptr)); + } +}; + +#endif // PTRCALL_ENABLED + +#ifdef DEBUG_METHODS_ENABLED + +template <class T> +struct GetTypeInfo<TypedArray<T>> { + static const Variant::Type VARIANT_TYPE = Variant::ARRAY; + static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, T::get_class_static()); + } +}; + +template <class T> +struct GetTypeInfo<const TypedArray<T> &> { + static const Variant::Type VARIANT_TYPE = Variant::ARRAY; + static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; + static inline PropertyInfo get_class_info() { + return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, T::get_class_static()); + } +}; + +#define MAKE_TYPED_ARRAY_INFO(m_type, m_variant_type) \ + template <> \ + struct GetTypeInfo<TypedArray<m_type>> { \ + static const Variant::Type VARIANT_TYPE = Variant::ARRAY; \ + static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type)); \ + } \ + }; \ + template <> \ + struct GetTypeInfo<const TypedArray<m_type> &> { \ + static const Variant::Type VARIANT_TYPE = Variant::ARRAY; \ + static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE; \ + static inline PropertyInfo get_class_info() { \ + return PropertyInfo(Variant::ARRAY, String(), PROPERTY_HINT_ARRAY_TYPE, Variant::get_type_name(m_variant_type)); \ + } \ + }; + +MAKE_TYPED_ARRAY_INFO(bool, Variant::BOOL) +MAKE_TYPED_ARRAY_INFO(uint8_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(int8_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(uint16_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(int16_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(uint32_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(int32_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(uint64_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(int64_t, Variant::INT) +MAKE_TYPED_ARRAY_INFO(float, Variant::FLOAT) +MAKE_TYPED_ARRAY_INFO(double, Variant::FLOAT) +MAKE_TYPED_ARRAY_INFO(String, Variant::STRING) +MAKE_TYPED_ARRAY_INFO(Vector2, Variant::VECTOR2) +MAKE_TYPED_ARRAY_INFO(Vector2i, Variant::VECTOR2I) +MAKE_TYPED_ARRAY_INFO(Rect2, Variant::RECT2) +MAKE_TYPED_ARRAY_INFO(Rect2i, Variant::RECT2I) +MAKE_TYPED_ARRAY_INFO(Vector3, Variant::VECTOR3) +MAKE_TYPED_ARRAY_INFO(Vector3i, Variant::VECTOR3I) +MAKE_TYPED_ARRAY_INFO(Transform2D, Variant::TRANSFORM2D) +MAKE_TYPED_ARRAY_INFO(Plane, Variant::PLANE) +MAKE_TYPED_ARRAY_INFO(Quat, Variant::QUAT) +MAKE_TYPED_ARRAY_INFO(AABB, Variant::AABB) +MAKE_TYPED_ARRAY_INFO(Basis, Variant::BASIS) +MAKE_TYPED_ARRAY_INFO(Transform, Variant::TRANSFORM) +MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR) +MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME) +MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH) +MAKE_TYPED_ARRAY_INFO(RID, Variant::_RID) +MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE) +MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL) +MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY) +MAKE_TYPED_ARRAY_INFO(Array, Variant::ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<uint8_t>, Variant::PACKED_BYTE_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<int32_t>, Variant::PACKED_INT32_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<int64_t>, Variant::PACKED_INT64_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<float>, Variant::PACKED_FLOAT32_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<double>, Variant::PACKED_FLOAT64_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<String>, Variant::PACKED_STRING_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY) +MAKE_TYPED_ARRAY_INFO(Vector<Color>, Variant::PACKED_COLOR_ARRAY) + +#endif + +#endif // TYPED_ARRAY_H diff --git a/core/typedefs.h b/core/typedefs.h index bafbffcded..4bfa5debac 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -185,8 +185,9 @@ static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) { // Function to find the nearest (bigger) power of 2 to an integer. static inline unsigned int nearest_shift(unsigned int p_number) { for (int i = 30; i >= 0; i--) { - if (p_number & (1 << i)) + if (p_number & (1 << i)) { return i + 1; + } } return 0; diff --git a/core/ucaps.h b/core/ucaps.h index ad71731617..79b346acba 100644 --- a/core/ucaps.h +++ b/core/ucaps.h @@ -1373,7 +1373,6 @@ static const int reverse_caps_table[CAPS_LEN - 1][2] = { }; static int _find_upper(int ch) { - int low = 0; int high = CAPS_LEN - 1; int middle; @@ -1394,7 +1393,6 @@ static int _find_upper(int ch) { } static int _find_lower(int ch) { - int low = 0; int high = CAPS_LEN - 2; int middle; diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 62ad3e9f98..90750f2c6e 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -33,19 +33,17 @@ #include "core/os/os.h" void UndoRedo::_discard_redo() { - - if (current_action == actions.size() - 1) + if (current_action == actions.size() - 1) { return; + } for (int i = current_action + 1; i < actions.size(); i++) { - for (List<Operation>::Element *E = actions.write[i].do_ops.front(); E; E = E->next()) { - if (E->get().type == Operation::TYPE_REFERENCE) { - Object *obj = ObjectDB::get_instance(E->get().object); - if (obj) + if (obj) { memdelete(obj); + } } } //ERASE do data @@ -55,31 +53,26 @@ void UndoRedo::_discard_redo() { } void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { - uint32_t ticks = OS::get_singleton()->get_ticks_msec(); if (action_level == 0) { - _discard_redo(); // Check if the merge operation is valid if (p_mode != MERGE_DISABLE && actions.size() && actions[actions.size() - 1].name == p_name && actions[actions.size() - 1].last_tick + 800 > ticks) { - current_action = actions.size() - 2; if (p_mode == MERGE_ENDS) { - // Clear all do ops from last action, and delete all object references List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); while (E) { - if (E->get().type == Operation::TYPE_REFERENCE) { - Object *obj = ObjectDB::get_instance(E->get().object); - if (obj) + if (obj) { memdelete(obj); + } } E = E->next(); @@ -92,7 +85,6 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { merge_mode = p_mode; merging = true; } else { - Action new_action; new_action.name = p_name; new_action.last_tick = ticks; @@ -106,15 +98,15 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { } void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND((current_action + 1) >= actions.size()); Operation do_op; do_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) + if (Object::cast_to<Resource>(p_object)) { do_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + } do_op.type = Operation::TYPE_METHOD; do_op.name = p_method; @@ -126,20 +118,21 @@ void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIA } void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) + if (merge_mode == MERGE_ENDS) { return; + } Operation undo_op; undo_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) + if (Object::cast_to<Resource>(p_object)) { undo_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + } undo_op.type = Operation::TYPE_METHOD; undo_op.name = p_method; @@ -149,87 +142,92 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR } actions.write[current_action + 1].undo_ops.push_back(undo_op); } -void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value) { +void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, const Variant &p_value) { ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND((current_action + 1) >= actions.size()); Operation do_op; do_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) + if (Object::cast_to<Resource>(p_object)) { do_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + } do_op.type = Operation::TYPE_PROPERTY; do_op.name = p_property; do_op.args[0] = p_value; actions.write[current_action + 1].do_ops.push_back(do_op); } -void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value) { +void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, const Variant &p_value) { ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) + if (merge_mode == MERGE_ENDS) { return; + } Operation undo_op; undo_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) + if (Object::cast_to<Resource>(p_object)) { undo_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + } undo_op.type = Operation::TYPE_PROPERTY; undo_op.name = p_property; undo_op.args[0] = p_value; actions.write[current_action + 1].undo_ops.push_back(undo_op); } -void UndoRedo::add_do_reference(Object *p_object) { +void UndoRedo::add_do_reference(Object *p_object) { ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND((current_action + 1) >= actions.size()); Operation do_op; do_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) + if (Object::cast_to<Resource>(p_object)) { do_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + } do_op.type = Operation::TYPE_REFERENCE; actions.write[current_action + 1].do_ops.push_back(do_op); } -void UndoRedo::add_undo_reference(Object *p_object) { +void UndoRedo::add_undo_reference(Object *p_object) { ERR_FAIL_COND(p_object == nullptr); ERR_FAIL_COND(action_level <= 0); ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) + if (merge_mode == MERGE_ENDS) { return; + } Operation undo_op; undo_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) + if (Object::cast_to<Resource>(p_object)) { undo_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + } undo_op.type = Operation::TYPE_REFERENCE; actions.write[current_action + 1].undo_ops.push_back(undo_op); } void UndoRedo::_pop_history_tail() { - _discard_redo(); - if (!actions.size()) + if (!actions.size()) { return; + } for (List<Operation>::Element *E = actions.write[0].undo_ops.front(); E; E = E->next()) { - if (E->get().type == Operation::TYPE_REFERENCE) { - Object *obj = ObjectDB::get_instance(E->get().object); - if (obj) + if (obj) { memdelete(obj); + } } } @@ -244,11 +242,11 @@ bool UndoRedo::is_committing_action() const { } void UndoRedo::commit_action() { - ERR_FAIL_COND(action_level <= 0); action_level--; - if (action_level > 0) + if (action_level > 0) { return; //still nested + } if (merging) { version--; @@ -264,19 +262,16 @@ void UndoRedo::commit_action() { } void UndoRedo::_process_operation_list(List<Operation>::Element *E) { - for (; E; E = E->next()) { - Operation &op = E->get(); Object *obj = ObjectDB::get_instance(op.object); - if (!obj) //may have been deleted and this is fine + if (!obj) { //may have been deleted and this is fine continue; + } switch (op.type) { - case Operation::TYPE_METHOD: { - Vector<const Variant *> argptrs; argptrs.resize(VARIANT_ARG_MAX); int argc = 0; @@ -297,8 +292,9 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { } #ifdef TOOLS_ENABLED Resource *res = Object::cast_to<Resource>(obj); - if (res) + if (res) { res->set_edited(true); + } #endif @@ -307,12 +303,12 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { } } break; case Operation::TYPE_PROPERTY: { - obj->set(op.name, op.args[0]); #ifdef TOOLS_ENABLED Resource *res = Object::cast_to<Resource>(obj); - if (res) + if (res) { res->set_edited(true); + } #endif if (property_callback) { property_callback(prop_callback_ud, obj, op.name, op.args[0]); @@ -326,11 +322,11 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) { } bool UndoRedo::redo() { - ERR_FAIL_COND_V(action_level > 0, false); - if ((current_action + 1) >= actions.size()) + if ((current_action + 1) >= actions.size()) { return false; //nothing to redo + } current_action++; @@ -342,10 +338,10 @@ bool UndoRedo::redo() { } bool UndoRedo::undo() { - ERR_FAIL_COND_V(action_level > 0, false); - if (current_action < 0) + if (current_action < 0) { return false; //nothing to redo + } _process_operation_list(actions.write[current_action].undo_ops.front()); current_action--; version--; @@ -355,12 +351,12 @@ bool UndoRedo::undo() { } void UndoRedo::clear_history(bool p_increase_version) { - ERR_FAIL_COND(action_level > 0); _discard_redo(); - while (actions.size()) + while (actions.size()) { _pop_history_tail(); + } if (p_increase_version) { version++; @@ -369,70 +365,45 @@ void UndoRedo::clear_history(bool p_increase_version) { } String UndoRedo::get_current_action_name() const { - ERR_FAIL_COND_V(action_level > 0, ""); - if (current_action < 0) + if (current_action < 0) { return ""; + } return actions[current_action].name; } bool UndoRedo::has_undo() { - return current_action >= 0; } bool UndoRedo::has_redo() { - return (current_action + 1) < actions.size(); } uint64_t UndoRedo::get_version() const { - return version; } void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback, void *p_ud) { - callback = p_callback; callback_ud = p_ud; } void UndoRedo::set_method_notify_callback(MethodNotifyCallback p_method_callback, void *p_ud) { - method_callback = p_method_callback; method_callbck_ud = p_ud; } void UndoRedo::set_property_notify_callback(PropertyNotifyCallback p_property_callback, void *p_ud) { - property_callback = p_property_callback; prop_callback_ud = p_ud; } -UndoRedo::UndoRedo() { - - committing = 0; - version = 1; - action_level = 0; - current_action = -1; - merge_mode = MERGE_DISABLE; - merging = false; - callback = nullptr; - callback_ud = nullptr; - - method_callbck_ud = nullptr; - prop_callback_ud = nullptr; - method_callback = nullptr; - property_callback = nullptr; -} - UndoRedo::~UndoRedo() { - clear_history(); } Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 0; @@ -461,7 +432,6 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl Variant v[VARIANT_ARG_MAX]; for (int i = 0; i < MIN(VARIANT_ARG_MAX, p_argcount - 2); ++i) { - v[i] = *p_args[i + 2]; } @@ -470,7 +440,6 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl } Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 0; @@ -499,7 +468,6 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla Variant v[VARIANT_ARG_MAX]; for (int i = 0; i < MIN(VARIANT_ARG_MAX, p_argcount - 2); ++i) { - v[i] = *p_args[i + 2]; } @@ -508,7 +476,6 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla } void UndoRedo::_bind_methods() { - ClassDB::bind_method(D_METHOD("create_action", "name", "merge_mode"), &UndoRedo::create_action, DEFVAL(MERGE_DISABLE)); ClassDB::bind_method(D_METHOD("commit_action"), &UndoRedo::commit_action); ClassDB::bind_method(D_METHOD("is_committing_action"), &UndoRedo::is_committing_action); diff --git a/core/undo_redo.h b/core/undo_redo.h index 3b91e9ce36..b46f7ff867 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -35,7 +35,6 @@ #include "core/resource.h" class UndoRedo : public Object { - GDCLASS(UndoRedo, Object); OBJ_SAVE_TYPE(UndoRedo); @@ -55,7 +54,6 @@ public: private: struct Operation { - enum Type { TYPE_METHOD, TYPE_PROPERTY, @@ -77,25 +75,25 @@ private: }; Vector<Action> actions; - int current_action; - int action_level; - MergeMode merge_mode; - bool merging; - uint64_t version; + int current_action = -1; + int action_level = 0; + MergeMode merge_mode = MERGE_DISABLE; + bool merging = false; + uint64_t version = 1; void _pop_history_tail(); void _process_operation_list(List<Operation>::Element *E); void _discard_redo(); - CommitNotifyCallback callback; - void *callback_ud; - void *method_callbck_ud; - void *prop_callback_ud; + CommitNotifyCallback callback = nullptr; + void *callback_ud = nullptr; + void *method_callbck_ud = nullptr; + void *prop_callback_ud = nullptr; - MethodNotifyCallback method_callback; - PropertyNotifyCallback property_callback; + MethodNotifyCallback method_callback = nullptr; + PropertyNotifyCallback property_callback = nullptr; - int committing; + int committing = 0; protected: static void _bind_methods(); @@ -128,7 +126,7 @@ public: void set_method_notify_callback(MethodNotifyCallback p_method_callback, void *p_ud); void set_property_notify_callback(PropertyNotifyCallback p_property_callback, void *p_ud); - UndoRedo(); + UndoRedo() {} ~UndoRedo(); }; diff --git a/core/ustring.cpp b/core/ustring.cpp index fbe3fcb1b2..444338d5ae 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -28,10 +28,6 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS // to disable build-time warning which suggested to use strcpy_s instead strcpy -#endif - #include "ustring.h" #include "core/color.h" @@ -51,6 +47,10 @@ #include <stdlib.h> #endif +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS // to disable build-time warning which suggested to use strcpy_s instead strcpy +#endif + #if defined(MINGW_ENABLED) || defined(_MSC_VER) #define snprintf _snprintf_s #endif @@ -69,13 +69,11 @@ bool is_symbol(CharType c) { } bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) { - const String &s = p_s; int beg = CLAMP(p_col, 0, s.length()); int end = beg; if (s[beg] > 32 || beg == s.length()) { - bool symbol = beg < s.length() && is_symbol(s[beg]); while (beg > 0 && s[beg - 1] > 32 && (symbol == is_symbol(s[beg - 1]))) { @@ -85,15 +83,15 @@ bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) { end++; } - if (end < s.length()) + if (end < s.length()) { end += 1; + } r_beg = beg; r_end = end; return true; } else { - return false; } } @@ -101,7 +99,6 @@ bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) { /** STRING **/ bool CharString::operator<(const CharString &p_right) const { - if (length() == 0) { return p_right.length() != 0; } @@ -110,7 +107,6 @@ bool CharString::operator<(const CharString &p_right) const { } CharString &CharString::operator+=(char p_char) { - resize(size() ? size() + 1 : 2); set(length(), 0); set(length() - 1, p_char); @@ -119,21 +115,19 @@ CharString &CharString::operator+=(char p_char) { } const char *CharString::get_data() const { - - if (size()) + if (size()) { return &operator[](0); - else + } else { return ""; + } } CharString &CharString::operator=(const char *p_cstr) { - copy_from(p_cstr); return *this; } void CharString::copy_from(const char *p_cstr) { - if (!p_cstr) { resize(0); return; @@ -154,20 +148,18 @@ void CharString::copy_from(const char *p_cstr) { } void String::copy_from(const char *p_cstr) { - if (!p_cstr) { - resize(0); return; } int len = 0; const char *ptr = p_cstr; - while (*(ptr++) != 0) + while (*(ptr++) != 0) { len++; + } if (len == 0) { - resize(0); return; } @@ -177,26 +169,23 @@ void String::copy_from(const char *p_cstr) { CharType *dst = this->ptrw(); for (int i = 0; i < len + 1; i++) { - dst[i] = p_cstr[i]; } } void String::copy_from(const CharType *p_cstr, const int p_clip_to) { - if (!p_cstr) { - resize(0); return; } int len = 0; const CharType *ptr = p_cstr; - while ((p_clip_to < 0 || len < p_clip_to) && *(ptr++) != 0) + while ((p_clip_to < 0 || len < p_clip_to) && *(ptr++) != 0) { len++; + } if (len == 0) { - resize(0); return; } @@ -220,18 +209,18 @@ void String::copy_from_unchecked(const CharType *p_char, const int p_length) { } void String::copy_from(const CharType &p_char) { - resize(2); set(0, p_char); set(1, 0); } bool String::operator==(const String &p_str) const { - - if (length() != p_str.length()) + if (length() != p_str.length()) { return false; - if (empty()) + } + if (empty()) { return true; + } int l = length(); @@ -240,43 +229,33 @@ bool String::operator==(const String &p_str) const { /* Compare char by char */ for (int i = 0; i < l; i++) { - - if (src[i] != dst[i]) + if (src[i] != dst[i]) { return false; + } } return true; } bool String::operator!=(const String &p_str) const { - return !(*this == p_str); } String String::operator+(const String &p_str) const { - String res = *this; res += p_str; return res; } -/* -String String::operator+(CharType p_chr) const { - - String res=*this; - res+=p_chr; - return res; -} -*/ String &String::operator+=(const String &p_str) { - if (empty()) { *this = p_str; return *this; } - if (p_str.empty()) + if (p_str.empty()) { return *this; + } int from = length(); @@ -287,20 +266,19 @@ String &String::operator+=(const String &p_str) { set(length(), 0); - for (int i = 0; i < p_str.length(); i++) + for (int i = 0; i < p_str.length(); i++) { dst[from + i] = src[i]; + } return *this; } String &String::operator+=(const CharType *p_str) { - *this += String(p_str); return *this; } String &String::operator+=(CharType p_char) { - resize(size() ? size() + 1 : 2); set(length(), 0); set(length() - 1, p_char); @@ -309,14 +287,15 @@ String &String::operator+=(CharType p_char) { } String &String::operator+=(const char *p_str) { - - if (!p_str || p_str[0] == 0) + if (!p_str || p_str[0] == 0) { return *this; + } int src_len = 0; const char *ptr = p_str; - while (*(ptr++) != 0) + while (*(ptr++) != 0) { src_len++; + } int from = length(); @@ -326,56 +305,58 @@ String &String::operator+=(const char *p_str) { set(length(), 0); - for (int i = 0; i < src_len; i++) + for (int i = 0; i < src_len; i++) { dst[from + i] = p_str[i]; + } return *this; } void String::operator=(const char *p_str) { - copy_from(p_str); } void String::operator=(const CharType *p_str) { - copy_from(p_str); } bool String::operator==(const StrRange &p_str_range) const { - int len = p_str_range.len; - if (length() != len) + if (length() != len) { return false; - if (empty()) + } + if (empty()) { return true; + } const CharType *c_str = p_str_range.c_str; const CharType *dst = &operator[](0); /* Compare char by char */ for (int i = 0; i < len; i++) { - - if (c_str[i] != dst[i]) + if (c_str[i] != dst[i]) { return false; + } } return true; } bool String::operator==(const char *p_str) const { - int len = 0; const char *aux = p_str; - while (*(aux++) != 0) + while (*(aux++) != 0) { len++; + } - if (length() != len) + if (length() != len) { return false; - if (empty()) + } + if (empty()) { return true; + } int l = length(); @@ -383,26 +364,28 @@ bool String::operator==(const char *p_str) const { /* Compare char by char */ for (int i = 0; i < l; i++) { - - if (p_str[i] != dst[i]) + if (p_str[i] != dst[i]) { return false; + } } return true; } bool String::operator==(const CharType *p_str) const { - int len = 0; const CharType *aux = p_str; - while (*(aux++) != 0) + while (*(aux++) != 0) { len++; + } - if (length() != len) + if (length() != len) { return false; - if (empty()) + } + if (empty()) { return true; + } int l = length(); @@ -410,78 +393,78 @@ bool String::operator==(const CharType *p_str) const { /* Compare char by char */ for (int i = 0; i < l; i++) { - - if (p_str[i] != dst[i]) + if (p_str[i] != dst[i]) { return false; + } } return true; } bool String::operator!=(const char *p_str) const { - return (!(*this == p_str)); } bool String::operator!=(const CharType *p_str) const { - return (!(*this == p_str)); } bool String::operator<(const CharType *p_str) const { - - if (empty() && p_str[0] == 0) + if (empty() && p_str[0] == 0) { return false; - if (empty()) + } + if (empty()) { return true; + } return is_str_less(c_str(), p_str); } bool String::operator<=(const String &p_str) const { - return (*this < p_str) || (*this == p_str); } bool String::operator<(const char *p_str) const { - - if (empty() && p_str[0] == 0) + if (empty() && p_str[0] == 0) { return false; - if (empty()) + } + if (empty()) { return true; + } return is_str_less(c_str(), p_str); } bool String::operator<(const String &p_str) const { - return operator<(p_str.c_str()); } signed char String::nocasecmp_to(const String &p_str) const { - - if (empty() && p_str.empty()) + if (empty() && p_str.empty()) { return 0; - if (empty()) + } + if (empty()) { return -1; - if (p_str.empty()) + } + if (p_str.empty()) { return 1; + } const CharType *that_str = p_str.c_str(); const CharType *this_str = c_str(); while (true) { - - if (*that_str == 0 && *this_str == 0) + if (*that_str == 0 && *this_str == 0) { return 0; //we're equal - else if (*this_str == 0) + } else if (*this_str == 0) { return -1; //if this is empty, and the other one is not, then we're less.. I think? - else if (*that_str == 0) + } else if (*that_str == 0) { return 1; //otherwise the other one is smaller.. - else if (_find_upper(*this_str) < _find_upper(*that_str)) //more than + } else if (_find_upper(*this_str) < _find_upper(*that_str)) { //more than return -1; - else if (_find_upper(*this_str) > _find_upper(*that_str)) //less than + } else if (_find_upper(*this_str) > _find_upper(*that_str)) { //less than return 1; + } this_str++; that_str++; @@ -489,29 +472,31 @@ signed char String::nocasecmp_to(const String &p_str) const { } signed char String::casecmp_to(const String &p_str) const { - - if (empty() && p_str.empty()) + if (empty() && p_str.empty()) { return 0; - if (empty()) + } + if (empty()) { return -1; - if (p_str.empty()) + } + if (p_str.empty()) { return 1; + } const CharType *that_str = p_str.c_str(); const CharType *this_str = c_str(); while (true) { - - if (*that_str == 0 && *this_str == 0) + if (*that_str == 0 && *this_str == 0) { return 0; //we're equal - else if (*this_str == 0) + } else if (*this_str == 0) { return -1; //if this is empty, and the other one is not, then we're less.. I think? - else if (*that_str == 0) + } else if (*that_str == 0) { return 1; //otherwise the other one is smaller.. - else if (*this_str < *that_str) //more than + } else if (*this_str < *that_str) { //more than return -1; - else if (*this_str > *that_str) //less than + } else if (*this_str > *that_str) { //less than return 1; + } this_str++; that_str++; @@ -519,84 +504,87 @@ signed char String::casecmp_to(const String &p_str) const { } signed char String::naturalnocasecmp_to(const String &p_str) const { - const CharType *this_str = c_str(); const CharType *that_str = p_str.c_str(); if (this_str && that_str) { - while (*this_str == '.' || *that_str == '.') { - if (*this_str++ != '.') + if (*this_str++ != '.') { return 1; - if (*that_str++ != '.') + } + if (*that_str++ != '.') { return -1; - if (!*that_str) + } + if (!*that_str) { return 1; - if (!*this_str) + } + if (!*this_str) { return -1; + } } while (*this_str) { - - if (!*that_str) + if (!*that_str) { return 1; - else if (IS_DIGIT(*this_str)) { - + } else if (IS_DIGIT(*this_str)) { int64_t this_int, that_int; - if (!IS_DIGIT(*that_str)) + if (!IS_DIGIT(*that_str)) { return -1; + } /* Compare the numbers */ - this_int = to_int(this_str); - that_int = to_int(that_str); + this_int = to_int(this_str, -1, true); + that_int = to_int(that_str, -1, true); - if (this_int < that_int) + if (this_int < that_int) { return -1; - else if (this_int > that_int) + } else if (this_int > that_int) { return 1; + } /* Skip */ - while (IS_DIGIT(*this_str)) + while (IS_DIGIT(*this_str)) { this_str++; - while (IS_DIGIT(*that_str)) + } + while (IS_DIGIT(*that_str)) { that_str++; - } else if (IS_DIGIT(*that_str)) + } + } else if (IS_DIGIT(*that_str)) { return 1; - else { - if (_find_upper(*this_str) < _find_upper(*that_str)) //more than + } else { + if (_find_upper(*this_str) < _find_upper(*that_str)) { //more than return -1; - else if (_find_upper(*this_str) > _find_upper(*that_str)) //less than + } else if (_find_upper(*this_str) > _find_upper(*that_str)) { //less than return 1; + } this_str++; that_str++; } } - if (*that_str) + if (*that_str) { return -1; + } } return 0; } void String::erase(int p_pos, int p_chars) { - *this = left(p_pos) + substr(p_pos + p_chars, length() - ((p_pos + p_chars))); } String String::capitalize() const { - String aux = this->camelcase_to_underscore(true).replace("_", " ").strip_edges(); String cap; for (int i = 0; i < aux.get_slice_count(" "); i++) { - String slice = aux.get_slicec(' ', i); if (slice.length() > 0) { - slice[0] = _find_upper(slice[0]); - if (i > 0) + if (i > 0) { cap += " "; + } cap += slice; } } @@ -657,18 +645,19 @@ String String::get_with_code_lines() const { } return ret; } -int String::get_slice_count(String p_splitter) const { - if (empty()) +int String::get_slice_count(String p_splitter) const { + if (empty()) { return 0; - if (p_splitter.empty()) + } + if (p_splitter.empty()) { return 0; + } int pos = 0; int slices = 1; while ((pos = find(p_splitter, pos)) >= 0) { - slices++; pos += p_splitter.length(); } @@ -677,35 +666,37 @@ int String::get_slice_count(String p_splitter) const { } String String::get_slice(String p_splitter, int p_slice) const { - - if (empty() || p_splitter.empty()) + if (empty() || p_splitter.empty()) { return ""; + } int pos = 0; int prev_pos = 0; //int slices=1; - if (p_slice < 0) + if (p_slice < 0) { return ""; - if (find(p_splitter) == -1) + } + if (find(p_splitter) == -1) { return *this; + } int i = 0; while (true) { - pos = find(p_splitter, pos); - if (pos == -1) + if (pos == -1) { pos = length(); //reached end + } int from = prev_pos; //int to=pos; if (p_slice == i) { - return substr(from, pos - from); } - if (pos == length()) //reached end and no find + if (pos == length()) { //reached end and no find break; + } pos += p_splitter.length(); prev_pos = pos; i++; @@ -715,23 +706,21 @@ String String::get_slice(String p_splitter, int p_slice) const { } String String::get_slicec(CharType p_splitter, int p_slice) const { - - if (empty()) + if (empty()) { return String(); + } - if (p_slice < 0) + if (p_slice < 0) { return String(); + } const CharType *c = this->ptr(); int i = 0; int prev = 0; int count = 0; while (true) { - if (c[i] == 0 || c[i] == p_splitter) { - if (p_slice == count) { - return substr(prev, i - prev); } else if (c[i] == 0) { return String(); @@ -746,22 +735,22 @@ String String::get_slicec(CharType p_splitter, int p_slice) const { } Vector<String> String::split_spaces() const { - Vector<String> ret; int from = 0; int i = 0; int len = length(); - if (len == 0) + if (len == 0) { return ret; + } bool inside = false; while (true) { - bool empty = operator[](i) < 33; - if (i == 0) + if (i == 0) { inside = !empty; + } if (!empty && !inside) { inside = true; @@ -769,13 +758,13 @@ Vector<String> String::split_spaces() const { } if (empty && inside) { - ret.push_back(substr(from, i - from)); inside = false; } - if (i == len) + if (i == len) { break; + } i++; } @@ -783,21 +772,19 @@ Vector<String> String::split_spaces() const { } Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const { - Vector<String> ret; int from = 0; int len = length(); while (true) { - int end = find(p_splitter, from); - if (end < 0) + if (end < 0) { end = len; + } if (p_allow_empty || (end > from)) { - if (p_maxsplit <= 0) + if (p_maxsplit <= 0) { ret.push_back(substr(from, end - from)); - else { - + } else { // Put rest of the string and leave cycle. if (p_maxsplit == ret.size()) { ret.push_back(substr(from, len)); @@ -809,8 +796,9 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p } } - if (end == len) + if (end == len) { break; + } from = end + p_splitter.length(); } @@ -819,13 +807,11 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p } Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const { - Vector<String> ret; const int len = length(); int remaining_len = len; while (true) { - if (remaining_len < p_splitter.length() || (p_maxsplit > 0 && p_maxsplit == ret.size())) { // no room for another splitter or hit max splits, push what's left and we're done if (p_allow_empty || remaining_len > 0) { @@ -855,21 +841,22 @@ Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int } Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) const { - Vector<float> ret; int from = 0; int len = length(); while (true) { - int end = find(p_splitter, from); - if (end < 0) + if (end < 0) { end = len; - if (p_allow_empty || (end > from)) + } + if (p_allow_empty || (end > from)) { ret.push_back(String::to_double(&c_str()[from])); + } - if (end == len) + if (end == len) { break; + } from = end + p_splitter.length(); } @@ -878,13 +865,11 @@ Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) } Vector<float> String::split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty) const { - Vector<float> ret; int from = 0; int len = length(); while (true) { - int idx; int end = findmk(p_splitters, from, &idx); int spl_len = 1; @@ -898,8 +883,9 @@ Vector<float> String::split_floats_mk(const Vector<String> &p_splitters, bool p_ ret.push_back(String::to_double(&c_str()[from])); } - if (end == len) + if (end == len) { break; + } from = end + spl_len; } @@ -908,21 +894,22 @@ Vector<float> String::split_floats_mk(const Vector<String> &p_splitters, bool p_ } Vector<int> String::split_ints(const String &p_splitter, bool p_allow_empty) const { - Vector<int> ret; int from = 0; int len = length(); while (true) { - int end = find(p_splitter, from); - if (end < 0) + if (end < 0) { end = len; - if (p_allow_empty || (end > from)) + } + if (p_allow_empty || (end > from)) { ret.push_back(String::to_int(&c_str()[from], end - from)); + } - if (end == len) + if (end == len) { break; + } from = end + p_splitter.length(); } @@ -931,13 +918,11 @@ Vector<int> String::split_ints(const String &p_splitter, bool p_allow_empty) con } Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty) const { - Vector<int> ret; int from = 0; int len = length(); while (true) { - int idx; int end = findmk(p_splitters, from, &idx); int spl_len = 1; @@ -947,11 +932,13 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo spl_len = p_splitters[idx].length(); } - if (p_allow_empty || (end > from)) + if (p_allow_empty || (end > from)) { ret.push_back(String::to_int(&c_str()[from], end - from)); + } - if (end == len) + if (end == len) { break; + } from = end + spl_len; } @@ -971,47 +958,42 @@ String String::join(Vector<String> parts) { } CharType String::char_uppercase(CharType p_char) { - return _find_upper(p_char); } CharType String::char_lowercase(CharType p_char) { - return _find_lower(p_char); } String String::to_upper() const { - String upper = *this; for (int i = 0; i < upper.size(); i++) { - const CharType s = upper[i]; const CharType t = _find_upper(s); - if (s != t) // avoid copy on write + if (s != t) { // avoid copy on write upper[i] = t; + } } return upper; } String String::to_lower() const { - String lower = *this; for (int i = 0; i < lower.size(); i++) { - const CharType s = lower[i]; const CharType t = _find_lower(s); - if (s != t) // avoid copy on write + if (s != t) { // avoid copy on write lower[i] = t; + } } return lower; } const CharType *String::c_str() const { - static const CharType zero = 0; return size() ? &operator[](0) : &zero; @@ -1038,23 +1020,22 @@ String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) { } String String::chr(CharType p_char) { - CharType c[2] = { p_char, 0 }; return String(c); } -String String::num(double p_num, int p_decimals) { +String String::num(double p_num, int p_decimals) { #ifndef NO_USE_STDLIB - if (p_decimals > 16) + if (p_decimals > 16) { p_decimals = 16; + } char fmt[7]; fmt[0] = '%'; fmt[1] = '.'; if (p_decimals < 0) { - fmt[1] = 'l'; fmt[2] = 'f'; fmt[3] = 0; @@ -1082,28 +1063,24 @@ String String::num(double p_num, int p_decimals) { buf[255] = 0; //destroy trailing zeroes { - bool period = false; int z = 0; while (buf[z]) { - if (buf[z] == '.') + if (buf[z] == '.') { period = true; + } z++; } if (period) { z--; while (z > 0) { - if (buf[z] == '0') { - buf[z] = 0; } else if (buf[z] == '.') { - buf[z] = 0; break; } else { - break; } @@ -1126,7 +1103,6 @@ String String::num(double p_num, int p_decimals) { /* decimal part */ if (p_decimals > 0 || (p_decimals == -1 && (int)p_num != p_num)) { - double dec = p_num - (float)((int)p_num); int digit = 0; @@ -1137,14 +1113,12 @@ String String::num(double p_num, int p_decimals) { int dec_max = 0; while (true) { - dec *= 10.0; dec_int = dec_int * 10 + (int)dec % 10; dec_max = dec_max * 10 + 9; digit++; if (p_decimals == -1) { - if (digit == MAX_DIGITS) //no point in going to infinite break; @@ -1160,18 +1134,15 @@ String String::num(double p_num, int p_decimals) { if (last > 5) { if (dec_int == dec_max) { - dec_int = 0; intn++; } else { - dec_int++; } } String decimal; for (int i = 0; i < digit; i++) { - char num[2] = { 0, 0 }; num[0] = '0' + dec_int % 10; decimal = num + decimal; @@ -1185,7 +1156,6 @@ String String::num(double p_num, int p_decimals) { s = "0"; else { while (intn) { - CharType num = '0' + (intn % 10); intn /= 10; s = num + s; @@ -1200,7 +1170,6 @@ String String::num(double p_num, int p_decimals) { } String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { - bool sign = p_num < 0; int64_t n = p_num; @@ -1211,8 +1180,9 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { chars++; } while (n); - if (sign) + if (sign) { chars++; + } String s; s.resize(chars + 1); CharType *c = s.ptrw(); @@ -1230,14 +1200,14 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { n /= base; } while (n); - if (sign) + if (sign) { c[0] = '-'; + } return s; } String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { - uint64_t n = p_num; int chars = 0; @@ -1267,7 +1237,6 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { } String String::num_real(double p_num) { - String s; String sd; /* integer part */ @@ -1279,7 +1248,6 @@ String String::num_real(double p_num) { /* decimal part */ if ((int)p_num != p_num) { - double dec = p_num - (float)((int)p_num); int digit = 0; @@ -1289,17 +1257,18 @@ String String::num_real(double p_num) { int dec_max = 0; while (true) { - dec *= 10.0; dec_int = dec_int * 10 + (int)dec % 10; dec_max = dec_max * 10 + 9; digit++; - if ((dec - (float)((int)dec)) < 1e-6) + if ((dec - (float)((int)dec)) < 1e-6) { break; + } - if (digit == decimals) + if (digit == decimals) { break; + } } dec *= 10; @@ -1307,18 +1276,15 @@ String String::num_real(double p_num) { if (last > 5) { if (dec_int == dec_max) { - dec_int = 0; intn++; } else { - dec_int++; } } String decimal; for (int i = 0; i < digit; i++) { - char num[2] = { 0, 0 }; num[0] = '0' + dec_int % 10; decimal = num + decimal; @@ -1329,12 +1295,10 @@ String String::num_real(double p_num) { sd = ".0"; } - if (intn == 0) - + if (intn == 0) { s = "0"; - else { + } else { while (intn) { - CharType num = '0' + (intn % 10); intn /= 10; s = num + s; @@ -1342,13 +1306,13 @@ String String::num_real(double p_num) { } s = s + sd; - if (neg) + if (neg) { s = "-" + s; + } return s; } String String::num_scientific(double p_num) { - #ifndef NO_USE_STDLIB char buf[256]; @@ -1379,33 +1343,33 @@ String String::num_scientific(double p_num) { } CharString String::ascii(bool p_allow_extended) const { - - if (!length()) + if (!length()) { return CharString(); + } CharString cs; cs.resize(size()); - for (int i = 0; i < size(); i++) + for (int i = 0; i < size(); i++) { cs[i] = operator[](i); + } return cs; } String String::utf8(const char *p_utf8, int p_len) { - String ret; ret.parse_utf8(p_utf8, p_len); return ret; -}; +} bool String::parse_utf8(const char *p_utf8, int p_len) { - #define _UNICERROR(m_err) print_line("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?"); - if (!p_utf8) + if (!p_utf8) { return true; + } String aux; @@ -1414,13 +1378,12 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { /* HANDLE BOM (Byte Order Mark) */ if (p_len < 0 || p_len >= 3) { - bool has_bom = uint8_t(p_utf8[0]) == 0xEF && uint8_t(p_utf8[1]) == 0xBB && uint8_t(p_utf8[2]) == 0xBF; if (has_bom) { - //just skip it - if (p_len >= 0) + if (p_len >= 0) { p_len -= 3; + } p_utf8 += 3; } } @@ -1430,25 +1393,23 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { const char *ptrtmp_limit = &p_utf8[p_len]; int skip = 0; while (ptrtmp != ptrtmp_limit && *ptrtmp) { - if (skip == 0) { - uint8_t c = *ptrtmp >= 0 ? *ptrtmp : uint8_t(256 + *ptrtmp); /* Determine the number of characters in sequence */ - if ((c & 0x80) == 0) + if ((c & 0x80) == 0) { skip = 0; - else if ((c & 0xE0) == 0xC0) + } else if ((c & 0xE0) == 0xC0) { skip = 1; - else if ((c & 0xF0) == 0xE0) + } else if ((c & 0xF0) == 0xE0) { skip = 2; - else if ((c & 0xF8) == 0xF0) + } else if ((c & 0xF8) == 0xF0) { skip = 3; - else if ((c & 0xFC) == 0xF8) + } else if ((c & 0xFC) == 0xF8) { skip = 4; - else if ((c & 0xFE) == 0xFC) + } else if ((c & 0xFE) == 0xFC) { skip = 5; - else { + } else { _UNICERROR("invalid skip"); return true; //invalid utf8 } @@ -1462,7 +1423,6 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { str_size++; } else { - --skip; } @@ -1486,23 +1446,22 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { dst[str_size] = 0; while (cstr_size) { - int len = 0; /* Determine the number of characters in sequence */ - if ((*p_utf8 & 0x80) == 0) + if ((*p_utf8 & 0x80) == 0) { len = 1; - else if ((*p_utf8 & 0xE0) == 0xC0) + } else if ((*p_utf8 & 0xE0) == 0xC0) { len = 2; - else if ((*p_utf8 & 0xF0) == 0xE0) + } else if ((*p_utf8 & 0xF0) == 0xE0) { len = 3; - else if ((*p_utf8 & 0xF8) == 0xF0) + } else if ((*p_utf8 & 0xF8) == 0xF0) { len = 4; - else if ((*p_utf8 & 0xFC) == 0xF8) + } else if ((*p_utf8 & 0xFC) == 0xF8) { len = 5; - else if ((*p_utf8 & 0xFE) == 0xFC) + } else if ((*p_utf8 & 0xFE) == 0xFC) { len = 6; - else { + } else { _UNICERROR("invalid len"); return true; //invalid UTF8 @@ -1523,14 +1482,12 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { uint32_t unichar = 0; - if (len == 1) + if (len == 1) { unichar = *p_utf8; - else { - + } else { unichar = (0xFF >> (len + 1)) & *p_utf8; for (int i = 1; i < len; i++) { - if ((p_utf8[i] & 0xC0) != 0x80) { _UNICERROR("invalid utf8"); return true; //invalid utf8 @@ -1557,19 +1514,18 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } CharString String::utf8() const { - int l = length(); - if (!l) + if (!l) { return CharString(); + } const CharType *d = &operator[](0); int fl = 0; for (int i = 0; i < l; i++) { - uint32_t c = d[i]; - if (c <= 0x7f) // 7 bits. + if (c <= 0x7f) { // 7 bits. fl += 1; - else if (c <= 0x7ff) { // 11 bits + } else if (c <= 0x7ff) { // 11 bits fl += 2; } else if (c <= 0xffff) { // 16 bits fl += 3; @@ -1594,12 +1550,11 @@ CharString String::utf8() const { #define APPEND_CHAR(m_c) *(cdst++) = m_c for (int i = 0; i < l; i++) { - uint32_t c = d[i]; - if (c <= 0x7f) // 7 bits. + if (c <= 0x7f) { // 7 bits. APPEND_CHAR(c); - else if (c <= 0x7ff) { // 11 bits + } else if (c <= 0x7ff) { // 11 bits APPEND_CHAR(uint32_t(0xc0 | ((c >> 6) & 0x1f))); // Top 5 bits. APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits. @@ -1643,30 +1598,30 @@ String::String(CharType p_char) { shared=nullptr; copy_from(p_char); } + + */ String::String(const char *p_str) { - copy_from(p_str); } String::String(const CharType *p_str, int p_clip_to_len) { - copy_from(p_str, p_clip_to_len); } String::String(const StrRange &p_range) { - - if (!p_range.c_str) + if (!p_range.c_str) { return; + } copy_from(p_range.c_str, p_range.len); } int String::hex_to_int(bool p_with_prefix) const { - - if (p_with_prefix && length() < 3) + if (p_with_prefix && length() < 3) { return 0; + } const CharType *s = ptr(); @@ -1677,15 +1632,15 @@ int String::hex_to_int(bool p_with_prefix) const { } if (p_with_prefix) { - if (s[0] != '0' || s[1] != 'x') + if (s[0] != '0' || s[1] != 'x') { return 0; + } s += 2; } int hex = 0; while (*s) { - CharType c = LOWERCASE(*s); int n; if (c >= '0' && c <= '9') { @@ -1706,9 +1661,9 @@ int String::hex_to_int(bool p_with_prefix) const { } int64_t String::hex_to_int64(bool p_with_prefix) const { - - if (p_with_prefix && length() < 3) + if (p_with_prefix && length() < 3) { return 0; + } const CharType *s = ptr(); @@ -1719,15 +1674,15 @@ int64_t String::hex_to_int64(bool p_with_prefix) const { } if (p_with_prefix) { - if (s[0] != '0' || s[1] != 'x') + if (s[0] != '0' || s[1] != 'x') { return 0; + } s += 2; } int64_t hex = 0; while (*s) { - CharType c = LOWERCASE(*s); int64_t n; if (c >= '0' && c <= '9') { @@ -1748,9 +1703,9 @@ int64_t String::hex_to_int64(bool p_with_prefix) const { } int64_t String::bin_to_int64(bool p_with_prefix) const { - - if (p_with_prefix && length() < 3) + if (p_with_prefix && length() < 3) { return 0; + } const CharType *s = ptr(); @@ -1761,15 +1716,15 @@ int64_t String::bin_to_int64(bool p_with_prefix) const { } if (p_with_prefix) { - if (s[0] != '0' || s[1] != 'b') + if (s[0] != '0' || s[1] != 'b') { return 0; + } s += 2; } int64_t binary = 0; while (*s) { - CharType c = LOWERCASE(*s); int64_t n; if (c == '0' || c == '1') { @@ -1788,9 +1743,9 @@ int64_t String::bin_to_int64(bool p_with_prefix) const { } int String::to_int() const { - - if (length() == 0) + if (length() == 0) { return 0; + } int to = (find(".") >= 0) ? find(".") : length(); @@ -1798,16 +1753,13 @@ int String::to_int() const { int sign = 1; for (int i = 0; i < to; i++) { - CharType c = operator[](i); if (c >= '0' && c <= '9') { - ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); integer *= 10; integer += c - '0'; } else if (integer == 0 && c == '-') { - sign = -sign; } } @@ -1816,9 +1768,9 @@ int String::to_int() const { } int64_t String::to_int64() const { - - if (length() == 0) + if (length() == 0) { return 0; + } int to = (find(".") >= 0) ? find(".") : length(); @@ -1826,16 +1778,13 @@ int64_t String::to_int64() const { int64_t sign = 1; for (int i = 0; i < to; i++) { - CharType c = operator[](i); if (c >= '0' && c <= '9') { - ERR_FAIL_COND_V_MSG(integer > INT64_MAX / 10, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); integer *= 10; integer += c - '0'; } else if (integer == 0 && c == '-') { - sign = -sign; } } @@ -1844,62 +1793,60 @@ int64_t String::to_int64() const { } int String::to_int(const char *p_str, int p_len) { - int to = 0; - if (p_len >= 0) + if (p_len >= 0) { to = p_len; - else { - while (p_str[to] != 0 && p_str[to] != '.') + } else { + while (p_str[to] != 0 && p_str[to] != '.') { to++; + } } int integer = 0; int sign = 1; for (int i = 0; i < to; i++) { - char c = p_str[i]; if (c >= '0' && c <= '9') { - ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); integer *= 10; integer += c - '0'; } else if (c == '-' && integer == 0) { - sign = -sign; - } else if (c != ' ') + } else if (c != ' ') { break; + } } return integer * sign; } bool String::is_numeric() const { - if (length() == 0) { return false; - }; + } int s = 0; - if (operator[](0) == '-') ++s; + if (operator[](0) == '-') { + ++s; + } bool dot = false; for (int i = s; i < length(); i++) { - CharType c = operator[](i); if (c == '.') { if (dot) { return false; - }; + } dot = true; } if (c < '0' || c > '9') { return false; - }; - }; + } + } return true; // TODO: Use the parser below for this instead -}; +} template <class C> static double built_in_strtod(const C *string, /* A decimal ASCII floating-point number, @@ -1916,7 +1863,6 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point C **endPtr = nullptr) /* If non-nullptr, store terminating Cacter's * address here. */ { - static const int maxExponent = 511; /* Largest possible base 10 exponent. Any * exponent larger than this will already * produce underflow or overflow, so there's @@ -2118,7 +2064,6 @@ done: #define READING_DONE 4 double String::to_double(const char *p_str) { - #ifndef NO_USE_STDLIB return built_in_strtod<char>(p_str); //return atof(p_str); DOES NOT WORK ON ANDROID(??) @@ -2128,19 +2073,17 @@ double String::to_double(const char *p_str) { } float String::to_float() const { - return to_double(); } double String::to_double(const CharType *p_str, const CharType **r_end) { - return built_in_strtod<CharType>(p_str, (CharType **)r_end); } -int64_t String::to_int(const CharType *p_str, int p_len) { - - if (p_len == 0 || !p_str[0]) +int64_t String::to_int(const CharType *p_str, int p_len, bool p_clamp) { + if (p_len == 0 || !p_str[0]) { return 0; + } ///@todo make more exact so saving and loading does not lose precision int64_t integer = 0; @@ -2151,7 +2094,6 @@ int64_t String::to_int(const CharType *p_str, int p_len) { const CharType *limit = &p_str[p_len]; while (*str && reading != READING_DONE && str != limit) { - CharType c = *(str++); switch (reading) { case READING_SIGN: { @@ -2172,16 +2114,22 @@ int64_t String::to_int(const CharType *p_str, int p_len) { [[fallthrough]]; } case READING_INT: { - if (c >= '0' && c <= '9') { - if (integer > INT64_MAX / 10) { String number(""); str = p_str; while (*str && str != limit) { number += *(str++); } - ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + if (p_clamp) { + if (sign == 1) { + return INT64_MAX; + } else { + return INT64_MIN; + } + } else { + ERR_FAIL_V_MSG(sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + number + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + } } integer *= 10; integer += c - '0'; @@ -2197,9 +2145,9 @@ int64_t String::to_int(const CharType *p_str, int p_len) { } double String::to_double() const { - - if (empty()) + if (empty()) { return 0; + } #ifndef NO_USE_STDLIB return built_in_strtod<CharType>(c_str()); //return wcstod(c_str(),nullptr ); DOES NOT WORK ON ANDROID :( @@ -2209,91 +2157,88 @@ double String::to_double() const { } bool operator==(const char *p_chr, const String &p_str) { - return p_str == p_chr; } String operator+(const char *p_chr, const String &p_str) { - String tmp = p_chr; tmp += p_str; return tmp; } -String operator+(CharType p_chr, const String &p_str) { +String operator+(CharType p_chr, const String &p_str) { return (String::chr(p_chr) + p_str); } uint32_t String::hash(const char *p_cstr) { - uint32_t hashv = 5381; uint32_t c; - while ((c = *p_cstr++)) + while ((c = *p_cstr++)) { hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } return hashv; } uint32_t String::hash(const char *p_cstr, int p_len) { - uint32_t hashv = 5381; - for (int i = 0; i < p_len; i++) + for (int i = 0; i < p_len; i++) { hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */ + } return hashv; } uint32_t String::hash(const CharType *p_cstr, int p_len) { - uint32_t hashv = 5381; - for (int i = 0; i < p_len; i++) + for (int i = 0; i < p_len; i++) { hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */ + } return hashv; } uint32_t String::hash(const CharType *p_cstr) { - uint32_t hashv = 5381; uint32_t c; - while ((c = *p_cstr++)) + while ((c = *p_cstr++)) { hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } return hashv; } uint32_t String::hash() const { - /* simple djb2 hashing */ const CharType *chr = c_str(); uint32_t hashv = 5381; uint32_t c; - while ((c = *chr++)) + while ((c = *chr++)) { hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } return hashv; } uint64_t String::hash64() const { - /* simple djb2 hashing */ const CharType *chr = c_str(); uint64_t hashv = 5381; uint64_t c; - while ((c = *chr++)) + while ((c = *chr++)) { hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } return hashv; } String String::md5_text() const { - CharString cs = utf8(); unsigned char hash[16]; CryptoCore::md5((unsigned char *)cs.ptr(), cs.length(), hash); @@ -2315,7 +2260,6 @@ String String::sha256_text() const { } Vector<uint8_t> String::md5_buffer() const { - CharString cs = utf8(); unsigned char hash[16]; CryptoCore::md5((unsigned char *)cs.ptr(), cs.length(), hash); @@ -2326,7 +2270,7 @@ Vector<uint8_t> String::md5_buffer() const { ret.write[i] = hash[i]; } return ret; -}; +} Vector<uint8_t> String::sha1_buffer() const { CharString cs = utf8(); @@ -2356,38 +2300,41 @@ Vector<uint8_t> String::sha256_buffer() const { } String String::insert(int p_at_pos, const String &p_string) const { - - if (p_at_pos < 0) + if (p_at_pos < 0) { return *this; + } - if (p_at_pos > length()) + if (p_at_pos > length()) { p_at_pos = length(); + } String pre; - if (p_at_pos > 0) + if (p_at_pos > 0) { pre = substr(0, p_at_pos); + } String post; - if (p_at_pos < length()) + if (p_at_pos < length()) { post = substr(p_at_pos, length() - p_at_pos); + } return pre + p_string + post; } -String String::substr(int p_from, int p_chars) const { - if (p_chars == -1) +String String::substr(int p_from, int p_chars) const { + if (p_chars == -1) { p_chars = length() - p_from; + } - if (empty() || p_from < 0 || p_from >= length() || p_chars <= 0) + if (empty() || p_from < 0 || p_from >= length() || p_chars <= 0) { return ""; + } if ((p_from + p_chars) > length()) { - p_chars = length() - p_from; } if (p_from == 0 && p_chars >= length()) { - return String(*this); } @@ -2397,12 +2344,10 @@ String String::substr(int p_from, int p_chars) const { } int String::find_last(const String &p_str) const { - int pos = -1; int findfrom = 0; int findres = -1; while ((findres = find(p_str, findfrom)) != -1) { - pos = findres; findfrom = pos + 1; } @@ -2411,32 +2356,30 @@ int String::find_last(const String &p_str) const { } int String::find(const String &p_str, int p_from) const { - - if (p_from < 0) + if (p_from < 0) { return -1; + } const int src_len = p_str.length(); const int len = length(); - if (src_len == 0 || len == 0) + if (src_len == 0 || len == 0) { return -1; // won't find anything! + } const CharType *src = c_str(); const CharType *str = p_str.c_str(); for (int i = p_from; i <= (len - src_len); i++) { - bool found = true; for (int j = 0; j < src_len; j++) { - int read_pos = i + j; if (read_pos >= len) { - ERR_PRINT("read_pos>=len"); return -1; - }; + } if (src[read_pos] != str[j]) { found = false; @@ -2444,54 +2387,51 @@ int String::find(const String &p_str, int p_from) const { } } - if (found) + if (found) { return i; + } } return -1; } int String::find(const char *p_str, int p_from) const { - - if (p_from < 0) + if (p_from < 0) { return -1; + } const int len = length(); - if (len == 0) + if (len == 0) { return -1; // won't find anything! + } const CharType *src = c_str(); int src_len = 0; - while (p_str[src_len] != '\0') + while (p_str[src_len] != '\0') { src_len++; + } if (src_len == 1) { - const char needle = p_str[0]; for (int i = p_from; i < len; i++) { - if (src[i] == needle) { return i; } } } else { - for (int i = p_from; i <= (len - src_len); i++) { - bool found = true; for (int j = 0; j < src_len; j++) { - int read_pos = i + j; if (read_pos >= len) { - ERR_PRINT("read_pos>=len"); return -1; - }; + } if (src[read_pos] != p_str[j]) { found = false; @@ -2499,8 +2439,9 @@ int String::find(const char *p_str, int p_from) const { } } - if (found) + if (found) { return i; + } } } @@ -2512,83 +2453,82 @@ int String::find_char(const CharType &p_char, int p_from) const { } int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const { - - if (p_from < 0) + if (p_from < 0) { return -1; - if (p_keys.size() == 0) + } + if (p_keys.size() == 0) { return -1; + } //int src_len=p_str.length(); const String *keys = &p_keys[0]; int key_count = p_keys.size(); int len = length(); - if (len == 0) + if (len == 0) { return -1; // won't find anything! + } const CharType *src = c_str(); for (int i = p_from; i < len; i++) { - bool found = true; for (int k = 0; k < key_count; k++) { - found = true; - if (r_key) + if (r_key) { *r_key = k; + } const CharType *cmp = keys[k].c_str(); int l = keys[k].length(); for (int j = 0; j < l; j++) { - int read_pos = i + j; if (read_pos >= len) { - found = false; break; - }; + } if (src[read_pos] != cmp[j]) { found = false; break; } } - if (found) + if (found) { break; + } } - if (found) + if (found) { return i; + } } return -1; } int String::findn(const String &p_str, int p_from) const { - - if (p_from < 0) + if (p_from < 0) { return -1; + } int src_len = p_str.length(); - if (src_len == 0 || length() == 0) + if (src_len == 0 || length() == 0) { return -1; // won't find anything! + } const CharType *srcd = c_str(); for (int i = p_from; i <= (length() - src_len); i++) { - bool found = true; for (int j = 0; j < src_len; j++) { - int read_pos = i + j; if (read_pos >= length()) { - ERR_PRINT("read_pos>=length()"); return -1; - }; + } CharType src = _find_lower(srcd[read_pos]); CharType dst = _find_lower(p_str[j]); @@ -2599,46 +2539,46 @@ int String::findn(const String &p_str, int p_from) const { } } - if (found) + if (found) { return i; + } } return -1; } int String::rfind(const String &p_str, int p_from) const { - // establish a limit int limit = length() - p_str.length(); - if (limit < 0) + if (limit < 0) { return -1; + } // establish a starting point - if (p_from < 0) + if (p_from < 0) { p_from = limit; - else if (p_from > limit) + } else if (p_from > limit) { p_from = limit; + } int src_len = p_str.length(); int len = length(); - if (src_len == 0 || len == 0) + if (src_len == 0 || len == 0) { return -1; // won't find anything! + } const CharType *src = c_str(); for (int i = p_from; i >= 0; i--) { - bool found = true; for (int j = 0; j < src_len; j++) { - int read_pos = i + j; if (read_pos >= len) { - ERR_PRINT("read_pos>=len"); return -1; - }; + } if (src[read_pos] != p_str[j]) { found = false; @@ -2646,45 +2586,46 @@ int String::rfind(const String &p_str, int p_from) const { } } - if (found) + if (found) { return i; + } } return -1; } -int String::rfindn(const String &p_str, int p_from) const { +int String::rfindn(const String &p_str, int p_from) const { // establish a limit int limit = length() - p_str.length(); - if (limit < 0) + if (limit < 0) { return -1; + } // establish a starting point - if (p_from < 0) + if (p_from < 0) { p_from = limit; - else if (p_from > limit) + } else if (p_from > limit) { p_from = limit; + } int src_len = p_str.length(); int len = length(); - if (src_len == 0 || len == 0) + if (src_len == 0 || len == 0) { return -1; // won't find anything! + } const CharType *src = c_str(); for (int i = p_from; i >= 0; i--) { - bool found = true; for (int j = 0; j < src_len; j++) { - int read_pos = i + j; if (read_pos >= len) { - ERR_PRINT("read_pos>=len"); return -1; - }; + } CharType srcc = _find_lower(src[read_pos]); CharType dstc = _find_lower(p_str[j]); @@ -2695,56 +2636,59 @@ int String::rfindn(const String &p_str, int p_from) const { } } - if (found) + if (found) { return i; + } } return -1; } bool String::ends_with(const String &p_string) const { - int pos = find_last(p_string); - if (pos == -1) + if (pos == -1) { return false; + } return pos + p_string.length() == length(); } bool String::begins_with(const String &p_string) const { - - if (p_string.length() > length()) + if (p_string.length() > length()) { return false; + } int l = p_string.length(); - if (l == 0) + if (l == 0) { return true; + } const CharType *src = &p_string[0]; const CharType *str = &operator[](0); int i = 0; for (; i < l; i++) { - - if (src[i] != str[i]) + if (src[i] != str[i]) { return false; + } } // only if i == l the p_string matches the beginning return i == l; } -bool String::begins_with(const char *p_string) const { +bool String::begins_with(const char *p_string) const { int l = length(); - if (l == 0 || !p_string) + if (l == 0 || !p_string) { return false; + } const CharType *str = &operator[](0); int i = 0; while (*p_string && i < l) { - - if (*p_string != str[i]) + if (*p_string != str[i]) { return false; + } i++; p_string++; } @@ -2753,22 +2697,18 @@ bool String::begins_with(const char *p_string) const { } 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); } 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("'"); } @@ -2818,7 +2758,6 @@ int String::countn(const String &p_string, int p_from, int p_to) const { } bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const { - int len = length(); if (len == 0) { // Technically an empty string is subsequence of any string @@ -2911,22 +2850,21 @@ static bool _wildcard_match(const CharType *p_pattern, const CharType *p_string, } bool String::match(const String &p_wildcard) const { - - if (!p_wildcard.length() || !length()) + if (!p_wildcard.length() || !length()) { return false; + } return _wildcard_match(p_wildcard.c_str(), c_str(), true); } bool String::matchn(const String &p_wildcard) const { - - if (!p_wildcard.length() || !length()) + if (!p_wildcard.length() || !length()) { return false; + } return _wildcard_match(p_wildcard.c_str(), c_str(), false); } String String::format(const Variant &values, String placeholder) const { - String new_string = String(this->ptr()); if (values.get_type() == Variant::ARRAY) { @@ -2998,20 +2936,17 @@ String String::format(const Variant &values, String placeholder) const { } String String::replace(const String &p_key, const String &p_with) const { - String new_string; int search_from = 0; int result = 0; while ((result = find(p_key, search_from)) >= 0) { - new_string += substr(search_from, result - search_from); new_string += p_with; search_from = result + p_key.length(); } if (search_from == 0) { - return *this; } @@ -3021,23 +2956,21 @@ String String::replace(const String &p_key, const String &p_with) const { } String String::replace(const char *p_key, const char *p_with) const { - String new_string; int search_from = 0; int result = 0; while ((result = find(p_key, search_from)) >= 0) { - new_string += substr(search_from, result - search_from); new_string += p_with; int k = 0; - while (p_key[k] != '\0') + while (p_key[k] != '\0') { k++; + } search_from = result + k; } if (search_from == 0) { - return *this; } @@ -3047,7 +2980,6 @@ String String::replace(const char *p_key, const char *p_with) const { } String String::replace_first(const String &p_key, const String &p_with) const { - int pos = find(p_key); if (pos >= 0) { return substr(0, pos) + p_with + substr(pos + p_key.length(), length()); @@ -3055,21 +2987,19 @@ String String::replace_first(const String &p_key, const String &p_with) const { return *this; } -String String::replacen(const String &p_key, const String &p_with) const { +String String::replacen(const String &p_key, const String &p_with) const { String new_string; int search_from = 0; int result = 0; while ((result = findn(p_key, search_from)) >= 0) { - new_string += substr(search_from, result - search_from); new_string += p_with; search_from = result + p_key.length(); } if (search_from == 0) { - return *this; } @@ -3078,7 +3008,6 @@ String String::replacen(const String &p_key, const String &p_with) const { } String String::repeat(int p_count) const { - ERR_FAIL_COND_V_MSG(p_count < 0, "", "Parameter count should be a positive number."); String new_string; @@ -3086,43 +3015,45 @@ String String::repeat(int p_count) const { new_string.resize(length() * p_count + 1); - for (int i = 0; i < p_count; i++) - for (int j = 0; j < length(); j++) + for (int i = 0; i < p_count; i++) { + for (int j = 0; j < length(); j++) { new_string[i * length() + j] = src[j]; + } + } return new_string; } String String::left(int p_pos) const { - - if (p_pos <= 0) + if (p_pos <= 0) { return ""; + } - if (p_pos >= length()) + if (p_pos >= length()) { return *this; + } return substr(0, p_pos); } String String::right(int p_pos) const { - - if (p_pos >= length()) + if (p_pos >= length()) { return ""; + } - if (p_pos <= 0) + if (p_pos <= 0) { return *this; + } return substr(p_pos, (length() - p_pos)); } CharType String::ord_at(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, length(), 0); return operator[](p_idx); } String String::dedent() const { - String new_string; String indent; bool has_indent = false; @@ -3131,11 +3062,11 @@ String String::dedent() const { int indent_stop = -1; for (int i = 0; i < length(); i++) { - CharType c = operator[](i); if (c == '\n') { - if (has_text) + if (has_text) { new_string += substr(indent_stop, i - indent_stop); + } new_string += "\n"; has_text = false; line_start = i + 1; @@ -3151,57 +3082,58 @@ String String::dedent() const { } if (has_indent && indent_stop < 0) { int j = i - line_start; - if (j >= indent.length() || c != indent[j]) + if (j >= indent.length() || c != indent[j]) { indent_stop = i; + } } } } - if (has_text) + if (has_text) { new_string += substr(indent_stop, length() - indent_stop); + } return new_string; } String String::strip_edges(bool left, bool right) const { - int len = length(); int beg = 0, end = len; if (left) { for (int i = 0; i < len; i++) { - - if (operator[](i) <= 32) + if (operator[](i) <= 32) { beg++; - else + } else { break; + } } } if (right) { for (int i = (int)(len - 1); i >= 0; i--) { - - if (operator[](i) <= 32) + if (operator[](i) <= 32) { end--; - else + } else { break; + } } } - if (beg == 0 && end == len) + if (beg == 0 && end == len) { return *this; + } return substr(beg, end - beg); } String String::strip_escapes() const { - String new_string; for (int i = 0; i < length(); i++) { - // Escape characters on first page of the ASCII table, before 32 (Space). - if (operator[](i) < 32) + if (operator[](i) < 32) { continue; + } new_string += operator[](i); } @@ -3209,65 +3141,60 @@ String String::strip_escapes() const { } String String::lstrip(const String &p_chars) const { - int len = length(); int beg; for (beg = 0; beg < len; beg++) { - - if (p_chars.find_char(get(beg)) == -1) + if (p_chars.find_char(get(beg)) == -1) { break; + } } - if (beg == 0) + if (beg == 0) { return *this; + } return substr(beg, len - beg); } String String::rstrip(const String &p_chars) const { - int len = length(); int end; for (end = len - 1; end >= 0; end--) { - - if (p_chars.find_char(get(end)) == -1) + if (p_chars.find_char(get(end)) == -1) { break; + } } - if (end == len - 1) + if (end == len - 1) { return *this; + } return substr(0, end + 1); } String String::simplify_path() const { - String s = *this; String drive; if (s.begins_with("local://")) { drive = "local://"; s = s.substr(8, s.length()); } else if (s.begins_with("res://")) { - drive = "res://"; s = s.substr(6, s.length()); } else if (s.begins_with("user://")) { - drive = "user://"; s = s.substr(7, s.length()); } else if (s.begins_with("/") || s.begins_with("\\")) { - drive = s.substr(0, 1); s = s.substr(1, s.length() - 1); } else { - int p = s.find(":/"); - if (p == -1) + if (p == -1) { p = s.find(":\\"); + } if (p != -1 && p < s.find("/")) { - drive = s.substr(0, p + 2); s = s.substr(p + 2, s.length()); } @@ -3276,21 +3203,20 @@ String String::simplify_path() const { s = s.replace("\\", "/"); while (true) { // in case of using 2 or more slash String compare = s.replace("//", "/"); - if (s == compare) + if (s == compare) { break; - else + } else { s = compare; + } } Vector<String> dirs = s.split("/", false); for (int i = 0; i < dirs.size(); i++) { - String d = dirs[i]; if (d == ".") { dirs.remove(i); i--; } else if (d == "..") { - if (i == 0) { dirs.remove(i); i--; @@ -3305,9 +3231,9 @@ String String::simplify_path() const { s = ""; for (int i = 0; i < dirs.size(); i++) { - - if (i > 0) + if (i > 0) { s += "/"; + } s += dirs[i]; } @@ -3315,17 +3241,16 @@ String String::simplify_path() const { } static int _humanize_digits(int p_num) { - - if (p_num < 100) + if (p_num < 100) { return 2; - else if (p_num < 1024) + } else if (p_num < 1024) { return 1; - else + } else { return 0; + } } String String::humanize_size(uint64_t p_size) { - uint64_t _div = 1; Vector<String> prefixes; prefixes.push_back(RTR("B")); @@ -3348,36 +3273,38 @@ String String::humanize_size(uint64_t p_size) { return String::num(p_size / divisor).pad_decimals(digits) + " " + prefixes[prefix_idx]; } -bool String::is_abs_path() const { - if (length() > 1) +bool String::is_abs_path() const { + if (length() > 1) { return (operator[](0) == '/' || operator[](0) == '\\' || find(":/") != -1 || find(":\\") != -1); - else if ((length()) == 1) + } else if ((length()) == 1) { return (operator[](0) == '/' || operator[](0) == '\\'); - else + } else { return false; + } } bool String::is_valid_identifier() const { - int len = length(); - if (len == 0) + if (len == 0) { return false; + } const wchar_t *str = &operator[](0); for (int i = 0; i < len; i++) { - if (i == 0) { - if (str[0] >= '0' && str[0] <= '9') + if (str[0] >= '0' && str[0] <= '9') { return false; // no start with number plz + } } bool valid_char = (str[i] >= '0' && str[i] <= '9') || (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || str[i] == '_'; - if (!valid_char) + if (!valid_char) { return false; + } } return true; @@ -3386,7 +3313,6 @@ bool String::is_valid_identifier() const { //kind of poor should be rewritten properly String String::word_wrap(int p_chars_per_line) const { - int from = 0; int last_space = 0; String ret; @@ -3463,7 +3389,6 @@ String String::http_unescape() const { } String String::c_unescape() const { - String escaped = *this; escaped = escaped.replace("\\a", "\a"); escaped = escaped.replace("\\b", "\b"); @@ -3481,7 +3406,6 @@ String String::c_unescape() const { } String String::c_escape() const { - String escaped = *this; escaped = escaped.replace("\\", "\\\\"); escaped = escaped.replace("\a", "\\a"); @@ -3499,7 +3423,6 @@ String String::c_escape() const { } String String::c_escape_multiline() const { - String escaped = *this; escaped = escaped.replace("\\", "\\\\"); escaped = escaped.replace("\"", "\\\""); @@ -3508,7 +3431,6 @@ String String::c_escape_multiline() const { } String String::json_escape() const { - String escaped = *this; escaped = escaped.replace("\\", "\\\\"); escaped = escaped.replace("\b", "\\b"); @@ -3523,7 +3445,6 @@ String String::json_escape() const { } String String::xml_escape(bool p_escape_quotes) const { - String str = *this; str = str.replace("&", "&"); str = str.replace("<", "<"); @@ -3533,29 +3454,24 @@ String String::xml_escape(bool p_escape_quotes) const { str = str.replace("\"", """); } /* - for (int i=1;i<32;i++) { +for (int i=1;i<32;i++) { - char chr[2]={i,0}; - str=str.replace(chr,"&#"+String::num(i)+";"); - }*/ + char chr[2]={i,0}; + str=str.replace(chr,"&#"+String::num(i)+";"); +}*/ return str; } static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src, int p_src_len, CharType *p_dst) { - int len = 0; while (p_src_len) { - if (*p_src == '&') { - int eat = 0; if (p_src_len >= 4 && p_src[1] == '#') { - CharType c = 0; for (int i = 2; i < p_src_len; i++) { - eat = i + 1; CharType ct = p_src[i]; if (ct == ';') { @@ -3573,49 +3489,50 @@ static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src, int p_src_len, Ch c |= ct; } - if (p_dst) + if (p_dst) { *p_dst = c; + } } else if (p_src_len >= 4 && p_src[1] == 'g' && p_src[2] == 't' && p_src[3] == ';') { - - if (p_dst) + if (p_dst) { *p_dst = '>'; + } eat = 4; } else if (p_src_len >= 4 && p_src[1] == 'l' && p_src[2] == 't' && p_src[3] == ';') { - - if (p_dst) + if (p_dst) { *p_dst = '<'; + } eat = 4; } else if (p_src_len >= 5 && p_src[1] == 'a' && p_src[2] == 'm' && p_src[3] == 'p' && p_src[4] == ';') { - - if (p_dst) + if (p_dst) { *p_dst = '&'; + } eat = 5; } else if (p_src_len >= 6 && p_src[1] == 'q' && p_src[2] == 'u' && p_src[3] == 'o' && p_src[4] == 't' && p_src[5] == ';') { - - if (p_dst) + if (p_dst) { *p_dst = '"'; + } eat = 6; } else if (p_src_len >= 6 && p_src[1] == 'a' && p_src[2] == 'p' && p_src[3] == 'o' && p_src[4] == 's' && p_src[5] == ';') { - - if (p_dst) + if (p_dst) { *p_dst = '\''; + } eat = 6; } else { - - if (p_dst) + if (p_dst) { *p_dst = *p_src; + } eat = 1; } - if (p_dst) + if (p_dst) { p_dst++; + } len++; p_src += eat; p_src_len -= eat; } else { - if (p_dst) { *p_dst = *p_src; p_dst++; @@ -3630,12 +3547,12 @@ static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src, int p_src_len, Ch } String String::xml_unescape() const { - String str; int l = length(); int len = _xml_unescape(c_str(), l, nullptr); - if (len == 0) + if (len == 0) { return String(); + } str.resize(len + 1); _xml_unescape(c_str(), l, str.ptrw()); str[len] = 0; @@ -3643,7 +3560,6 @@ String String::xml_unescape() const { } String String::pad_decimals(int p_digits) const { - String s = *this; int c = s.find("."); @@ -3670,7 +3586,6 @@ String String::pad_decimals(int p_digits) const { } String String::pad_zeros(int p_digits) const { - String s = *this; int end = s.find("."); @@ -3678,8 +3593,9 @@ String String::pad_zeros(int p_digits) const { end = s.length(); } - if (end == 0) + if (end == 0) { return s; + } int begin = 0; @@ -3687,11 +3603,11 @@ String String::pad_zeros(int p_digits) const { begin++; } - if (begin >= end) + if (begin >= end) { return s; + } while (end - begin < p_digits) { - s = s.insert(begin, "0"); end++; } @@ -3700,7 +3616,6 @@ String String::pad_zeros(int p_digits) const { } String String::trim_prefix(const String &p_prefix) const { - String s = *this; if (s.begins_with(p_prefix)) { return s.substr(p_prefix.length(), s.length() - p_prefix.length()); @@ -3709,7 +3624,6 @@ String String::trim_prefix(const String &p_prefix) const { } String String::trim_suffix(const String &p_suffix) const { - String s = *this; if (s.ends_with(p_suffix)) { return s.substr(0, s.length() - p_suffix.length()); @@ -3718,40 +3632,42 @@ String String::trim_suffix(const String &p_suffix) const { } bool String::is_valid_integer() const { - int len = length(); - if (len == 0) + if (len == 0) { return false; + } int from = 0; - if (len != 1 && (operator[](0) == '+' || operator[](0) == '-')) + if (len != 1 && (operator[](0) == '+' || operator[](0) == '-')) { from++; + } for (int i = from; i < len; i++) { - - if (operator[](i) < '0' || operator[](i) > '9') + if (operator[](i) < '0' || operator[](i) > '9') { return false; // no start with number plz + } } return true; } bool String::is_valid_hex_number(bool p_with_prefix) const { - int len = length(); - if (len == 0) + if (len == 0) { return false; + } int from = 0; - if (len != 1 && (operator[](0) == '+' || operator[](0) == '-')) + if (len != 1 && (operator[](0) == '+' || operator[](0) == '-')) { from++; + } if (p_with_prefix) { - - if (len < 3) + if (len < 3) { return false; + } if (operator[](from) != '0' || operator[](from + 1) != 'x') { return false; } @@ -3759,22 +3675,22 @@ bool String::is_valid_hex_number(bool p_with_prefix) const { } for (int i = from; i < len; i++) { - CharType c = operator[](i); - if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) + if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { continue; + } return false; } return true; -}; +} bool String::is_valid_float() const { - int len = length(); - if (len == 0) + if (len == 0) { return false; + } int from = 0; if (operator[](0) == '+' || operator[](0) == '-') { @@ -3788,71 +3704,70 @@ bool String::is_valid_float() const { bool numbers_found = false; for (int i = from; i < len; i++) { - if (operator[](i) >= '0' && operator[](i) <= '9') { - - if (exponent_found) + if (exponent_found) { exponent_values_found = true; - else + } else { numbers_found = true; + } } else if (numbers_found && !exponent_found && operator[](i) == 'e') { exponent_found = true; } else if (!period_found && !exponent_found && operator[](i) == '.') { period_found = true; } else if ((operator[](i) == '-' || operator[](i) == '+') && exponent_found && !exponent_values_found && !sign_found) { sign_found = true; - } else + } else { return false; // no start with number plz + } } return numbers_found; } String String::path_to_file(const String &p_path) const { - // Don't get base dir for src, this is expected to be a dir already. String src = this->replace("\\", "/"); String dst = p_path.replace("\\", "/").get_base_dir(); String rel = src.path_to(dst); - if (rel == dst) // failed + if (rel == dst) { // failed return p_path; - else + } else { return rel + p_path.get_file(); + } } String String::path_to(const String &p_path) const { - String src = this->replace("\\", "/"); String dst = p_path.replace("\\", "/"); - if (!src.ends_with("/")) + if (!src.ends_with("/")) { src += "/"; - if (!dst.ends_with("/")) + } + if (!dst.ends_with("/")) { dst += "/"; + } String base; if (src.begins_with("res://") && dst.begins_with("res://")) { - base = "res:/"; src = src.replace("res://", "/"); dst = dst.replace("res://", "/"); } else if (src.begins_with("user://") && dst.begins_with("user://")) { - base = "user:/"; src = src.replace("user://", "/"); dst = dst.replace("user://", "/"); } else if (src.begins_with("/") && dst.begins_with("/")) { - //nothing } else { //dos style String src_begin = src.get_slicec('/', 0); String dst_begin = dst.get_slicec('/', 0); - if (src_begin != dst_begin) + if (src_begin != dst_begin) { return p_path; //impossible to do this + } base = src_begin; src = src.substr(src_begin.length(), src.length()); @@ -3867,12 +3782,15 @@ String String::path_to(const String &p_path) const { int common_parent = 0; while (true) { - if (src_dirs.size() == common_parent) + if (src_dirs.size() == common_parent) { break; - if (dst_dirs.size() == common_parent) + } + if (dst_dirs.size() == common_parent) { break; - if (src_dirs[common_parent] != dst_dirs[common_parent]) + } + if (src_dirs[common_parent] != dst_dirs[common_parent]) { break; + } common_parent++; } @@ -3881,27 +3799,24 @@ String String::path_to(const String &p_path) const { String dir; for (int i = src_dirs.size() - 1; i > common_parent; i--) { - dir += "../"; } for (int i = common_parent + 1; i < dst_dirs.size(); i++) { - dir += dst_dirs[i] + "/"; } - if (dir.length() == 0) + if (dir.length() == 0) { dir = "./"; + } return dir; } bool String::is_valid_html_color() const { - return Color::html_is_valid(*this); } bool String::is_valid_filename() const { - String stripped = strip_edges(); if (*this != stripped) { return false; @@ -3915,55 +3830,54 @@ bool String::is_valid_filename() const { } bool String::is_valid_ip_address() const { - if (find(":") >= 0) { - Vector<String> ip = split(":"); for (int i = 0; i < ip.size(); i++) { - String n = ip[i]; - if (n.empty()) + if (n.empty()) { continue; + } if (n.is_valid_hex_number(false)) { int nint = n.hex_to_int(false); - if (nint < 0 || nint > 0xffff) + if (nint < 0 || nint > 0xffff) { return false; + } continue; - }; - if (!n.is_valid_ip_address()) + } + if (!n.is_valid_ip_address()) { return false; - }; + } + } } else { Vector<String> ip = split("."); - if (ip.size() != 4) + if (ip.size() != 4) { return false; + } for (int i = 0; i < ip.size(); i++) { - String n = ip[i]; - if (!n.is_valid_integer()) + if (!n.is_valid_integer()) { return false; + } int val = n.to_int(); - if (val < 0 || val > 255) + if (val < 0 || val > 255) { return false; + } } - }; + } return true; } bool String::is_resource_file() const { - return begins_with("res://") && find("::") == -1; } bool String::is_rel_path() const { - return !is_abs_path(); } String String::get_base_dir() const { - int basepos = find("://"); String rs; String base; @@ -3976,52 +3890,52 @@ String String::get_base_dir() const { rs = substr(1, length()); base = "/"; } else { - rs = *this; } } int sep = MAX(rs.find_last("/"), rs.find_last("\\")); - if (sep == -1) + if (sep == -1) { return base; + } return base + rs.substr(0, sep); } String String::get_file() const { - int sep = MAX(find_last("/"), find_last("\\")); - if (sep == -1) + if (sep == -1) { return *this; + } return substr(sep + 1, length()); } String String::get_extension() const { - int pos = find_last("."); - if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) + if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) { return ""; + } return substr(pos + 1, length()); } String String::plus_file(const String &p_file) const { - if (empty()) + if (empty()) { return p_file; - if (operator[](length() - 1) == '/' || (p_file.size() > 0 && p_file.operator[](0) == '/')) + } + if (operator[](length() - 1) == '/' || (p_file.size() > 0 && p_file.operator[](0) == '/')) { return *this + p_file; + } return *this + "/" + p_file; } String String::percent_encode() const { - CharString cs = utf8(); String encoded; for (int i = 0; i < cs.length(); i++) { uint8_t c = cs[i]; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '~' || c == '.') { - char p[2] = { (char)c, 0 }; encoded += p; } else { @@ -4036,34 +3950,34 @@ String String::percent_encode() const { return encoded; } -String String::percent_decode() const { +String String::percent_decode() const { CharString pe; CharString cs = utf8(); for (int i = 0; i < cs.length(); i++) { - uint8_t c = cs[i]; if (c == '%' && i < length() - 2) { - uint8_t a = LOWERCASE(cs[i + 1]); uint8_t b = LOWERCASE(cs[i + 2]); - if (a >= '0' && a <= '9') + if (a >= '0' && a <= '9') { c = (a - '0') << 4; - else if (a >= 'a' && a <= 'f') + } else if (a >= 'a' && a <= 'f') { c = (a - 'a' + 10) << 4; - else + } else { continue; + } uint8_t d = 0; - if (b >= '0' && b <= '9') + if (b >= '0' && b <= '9') { d = (b - '0'); - else if (b >= 'a' && b <= 'f') + } else if (b >= 'a' && b <= 'f') { d = (b - 'a' + 10); - else + } else { continue; + } c += d; i += 2; } @@ -4087,31 +4001,27 @@ String String::property_name_encode() const { } String String::get_basename() const { - int pos = find_last("."); - if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) + if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) { return *this; + } return substr(0, pos); } String itos(int64_t p_val) { - return String::num_int64(p_val); } String uitos(uint64_t p_val) { - return String::num_uint64(p_val); } String rtos(double p_val) { - return String::num(p_val); } String rtoss(double p_val) { - return String::num_scientific(p_val); } @@ -4120,19 +4030,22 @@ String String::rpad(int min_length, const String &character) const { String s = *this; int padding = min_length - s.length(); if (padding > 0) { - for (int i = 0; i < padding; i++) + for (int i = 0; i < padding; i++) { s = s + character; + } } return s; } + // Left-pad with a character. String String::lpad(int min_length, const String &character) const { String s = *this; int padding = min_length - s.length(); if (padding > 0) { - for (int i = 0; i < padding; i++) + for (int i = 0; i < padding; i++) { s = character + s; + } } return s; @@ -4182,9 +4095,14 @@ String String::sprintf(const Array &values, bool *error) const { int base = 16; bool capitalize = false; switch (c) { - case 'd': base = 10; break; - case 'o': base = 8; break; - case 'x': break; + case 'd': + base = 10; + break; + case 'o': + base = 8; + break; + case 'x': + break; case 'X': base = 16; capitalize = true; @@ -4225,27 +4143,40 @@ String String::sprintf(const Array &values, bool *error) const { } double value = values[value_index]; - String str = String::num(value, min_decimals); + bool is_negative = (value < 0); + String str = String::num(ABS(value), min_decimals); // Pad decimals out. str = str.pad_decimals(min_decimals); - // Show sign - if (show_sign && str.left(1) != "-") { - str = str.insert(0, "+"); - } + int initial_len = str.length(); - // Padding + // Padding. Leave room for sign later if required. + int pad_chars_count = (is_negative || show_sign) ? min_chars - 1 : min_chars; + String pad_char = pad_with_zeroes ? String("0") : String(" "); if (left_justified) { - str = str.rpad(min_chars); + if (pad_with_zeroes) { + return "left justification cannot be used with zeros as the padding"; + } else { + str = str.rpad(pad_chars_count, pad_char); + } } else { - str = str.lpad(min_chars); + str = str.lpad(pad_chars_count, pad_char); + } + + // Add sign if needed. + if (show_sign || is_negative) { + String sign_char = is_negative ? "-" : "+"; + if (left_justified) { + str = str.insert(0, sign_char); + } else { + str = str.insert(pad_with_zeroes ? 0 : str.length() - initial_len, sign_char); + } } formatted += str; ++value_index; in_format = false; - break; } case 's': { // String @@ -4420,13 +4351,14 @@ String TTR(const String &p_text) { } String DTR(const String &p_text) { + // Comes straight from the XML, so remove indentation and any trailing whitespace. + const String text = p_text.dedent().strip_edges(); + if (TranslationServer::get_singleton()) { - // Comes straight from the XML, so remove indentation and any trailing whitespace. - const String text = p_text.dedent().strip_edges(); return TranslationServer::get_singleton()->doc_translate(text); } - return p_text; + return text; } #endif diff --git a/core/ustring.h b/core/ustring.h index ee7e3b1e16..5b13a1c704 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -51,8 +51,9 @@ class CharProxy { public: _FORCE_INLINE_ operator T() const { - if (unlikely(_index == _cowdata.size())) + if (unlikely(_index == _cowdata.size())) { return _null; + } return _cowdata.get(_index); } @@ -71,7 +72,6 @@ public: }; class CharString { - CowData<char> _cowdata; static const char _null; @@ -84,8 +84,9 @@ public: _FORCE_INLINE_ char get(int p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ void set(int p_index, const char &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ const char &operator[](int p_index) const { - if (unlikely(p_index == _cowdata.size())) + if (unlikely(p_index == _cowdata.size())) { return _null; + } return _cowdata.get(p_index); } @@ -113,7 +114,6 @@ protected: typedef wchar_t CharType; struct StrRange { - const CharType *c_str; int len; @@ -124,7 +124,6 @@ struct StrRange { }; class String { - CowData<CharType> _cowdata; static const CharType _null; @@ -154,8 +153,9 @@ public: Error resize(int p_size) { return _cowdata.resize(p_size); } _FORCE_INLINE_ const CharType &operator[](int p_index) const { - if (unlikely(p_index == _cowdata.size())) + if (unlikely(p_index == _cowdata.size())) { return _null; + } return _cowdata.get(p_index); } @@ -254,7 +254,7 @@ public: static int to_int(const char *p_str, int p_len = -1); static double to_double(const char *p_str); static double to_double(const CharType *p_str, const CharType **r_end = nullptr); - static int64_t to_int(const CharType *p_str, int p_len = -1); + static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false); String capitalize() const; String camelcase_to_underscore(bool lowercase = true) const; @@ -377,36 +377,31 @@ String rtos(double p_val); String rtoss(double p_val); //scientific version struct NoCaseComparator { - bool operator()(const String &p_a, const String &p_b) const { - return p_a.nocasecmp_to(p_b) < 0; } }; struct NaturalNoCaseComparator { - bool operator()(const String &p_a, const String &p_b) const { - return p_a.naturalnocasecmp_to(p_b) < 0; } }; template <typename L, typename R> _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) { - while (true) { - - if (*l_ptr == 0 && *r_ptr == 0) + if (*l_ptr == 0 && *r_ptr == 0) { return false; - else if (*l_ptr == 0) + } else if (*l_ptr == 0) { return true; - else if (*r_ptr == 0) + } else if (*r_ptr == 0) { return false; - else if (*l_ptr < *r_ptr) + } else if (*l_ptr < *r_ptr) { return true; - else if (*l_ptr > *r_ptr) + } else if (*l_ptr > *r_ptr) { return false; + } l_ptr++; r_ptr++; diff --git a/core/variant.cpp b/core/variant.cpp index b3611536b8..21aaa0fe9e 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -41,177 +41,136 @@ #include "scene/main/node.h" String Variant::get_type_name(Variant::Type p_type) { - switch (p_type) { case NIL: { - return "Nil"; } break; // atomic types case BOOL: { - return "bool"; } break; case INT: { - return "int"; } break; case FLOAT: { - return "float"; } break; case STRING: { - return "String"; } break; // math types case VECTOR2: { - return "Vector2"; } break; case VECTOR2I: { - return "Vector2i"; } break; case RECT2: { - return "Rect2"; } break; case RECT2I: { - return "Rect2i"; } break; case TRANSFORM2D: { - return "Transform2D"; } break; case VECTOR3: { - return "Vector3"; } break; case VECTOR3I: { - return "Vector3i"; } break; case PLANE: { - return "Plane"; } break; - /* - case QUAT: { - - - } break;*/ case AABB: { - return "AABB"; } break; case QUAT: { - return "Quat"; } break; case BASIS: { - return "Basis"; } break; case TRANSFORM: { - return "Transform"; } break; // misc types case COLOR: { - return "Color"; } break; case _RID: { - return "RID"; } break; case OBJECT: { - return "Object"; } break; case CALLABLE: { - return "Callable"; } break; case SIGNAL: { - return "Signal"; } break; case STRING_NAME: { - return "StringName"; } break; case NODE_PATH: { - return "NodePath"; } break; case DICTIONARY: { - return "Dictionary"; } break; case ARRAY: { - return "Array"; } break; // arrays case PACKED_BYTE_ARRAY: { - return "PackedByteArray"; } break; case PACKED_INT32_ARRAY: { - return "PackedInt32Array"; } break; case PACKED_INT64_ARRAY: { - return "PackedInt64Array"; } break; case PACKED_FLOAT32_ARRAY: { - return "PackedFloat32Array"; } break; case PACKED_FLOAT64_ARRAY: { - return "PackedFloat64Array"; } break; case PACKED_STRING_ARRAY: { - return "PackedStringArray"; } break; case PACKED_VECTOR2_ARRAY: { - return "PackedVector2Array"; } break; case PACKED_VECTOR3_ARRAY: { - return "PackedVector3Array"; } break; case PACKED_COLOR_ARRAY: { - return "PackedColorArray"; } break; @@ -223,22 +182,22 @@ String Variant::get_type_name(Variant::Type p_type) { } bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { - - if (p_type_from == p_type_to) + if (p_type_from == p_type_to) { return true; - if (p_type_to == NIL && p_type_from != NIL) //nil can convert to anything + } + if (p_type_to == NIL && p_type_from != NIL) { //nil can convert to anything return true; + } if (p_type_from == NIL) { return (p_type_to == OBJECT); - }; + } const Type *valid_types = nullptr; const Type *invalid_types = nullptr; switch (p_type_to) { case BOOL: { - static const Type valid[] = { INT, FLOAT, @@ -249,7 +208,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case INT: { - static const Type valid[] = { BOOL, FLOAT, @@ -261,7 +219,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case FLOAT: { - static const Type valid[] = { BOOL, INT, @@ -273,7 +230,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case STRING: { - static const Type invalid[] = { OBJECT, NIL @@ -282,7 +238,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { invalid_types = invalid; } break; case VECTOR2: { - static const Type valid[] = { VECTOR2I, NIL, @@ -292,7 +247,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case VECTOR2I: { - static const Type valid[] = { VECTOR2, NIL, @@ -302,7 +256,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case RECT2: { - static const Type valid[] = { RECT2I, NIL, @@ -312,7 +265,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case RECT2I: { - static const Type valid[] = { RECT2, NIL, @@ -322,7 +274,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case TRANSFORM2D: { - static const Type valid[] = { TRANSFORM, NIL @@ -331,7 +282,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case VECTOR3: { - static const Type valid[] = { VECTOR3I, NIL, @@ -341,7 +291,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case VECTOR3I: { - static const Type valid[] = { VECTOR3, NIL, @@ -352,7 +301,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case QUAT: { - static const Type valid[] = { BASIS, NIL @@ -362,7 +310,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case BASIS: { - static const Type valid[] = { QUAT, VECTOR3, @@ -373,7 +320,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case TRANSFORM: { - static const Type valid[] = { TRANSFORM2D, QUAT, @@ -386,7 +332,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case COLOR: { - static const Type valid[] = { STRING, INT, @@ -398,7 +343,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case _RID: { - static const Type valid[] = { OBJECT, NIL @@ -407,7 +351,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case OBJECT: { - static const Type valid[] = { NIL }; @@ -415,7 +358,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case STRING_NAME: { - static const Type valid[] = { STRING, NIL @@ -424,7 +366,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case NODE_PATH: { - static const Type valid[] = { STRING, NIL @@ -433,7 +374,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case ARRAY: { - static const Type valid[] = { PACKED_BYTE_ARRAY, PACKED_INT32_ARRAY, @@ -451,7 +391,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; // arrays case PACKED_BYTE_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -460,7 +399,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case PACKED_INT32_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -468,7 +406,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case PACKED_INT64_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -476,7 +413,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case PACKED_FLOAT32_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -485,7 +421,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case PACKED_FLOAT64_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -494,7 +429,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case PACKED_STRING_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -502,7 +436,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { valid_types = valid; } break; case PACKED_VECTOR2_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -511,7 +444,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case PACKED_VECTOR3_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -520,7 +452,6 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; case PACKED_COLOR_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -534,22 +465,20 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } if (valid_types) { - int i = 0; while (valid_types[i] != NIL) { - - if (p_type_from == valid_types[i]) + if (p_type_from == valid_types[i]) { return true; + } i++; } } else if (invalid_types) { - int i = 0; while (invalid_types[i] != NIL) { - - if (p_type_from == invalid_types[i]) + if (p_type_from == invalid_types[i]) { return false; + } i++; } @@ -560,21 +489,21 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type_to) { - - if (p_type_from == p_type_to) + if (p_type_from == p_type_to) { return true; - if (p_type_to == NIL && p_type_from != NIL) //nil can convert to anything + } + if (p_type_to == NIL && p_type_from != NIL) { //nil can convert to anything return true; + } if (p_type_from == NIL) { return (p_type_to == OBJECT); - }; + } const Type *valid_types = nullptr; switch (p_type_to) { case BOOL: { - static const Type valid[] = { INT, FLOAT, @@ -585,7 +514,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case INT: { - static const Type valid[] = { BOOL, FLOAT, @@ -597,7 +525,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case FLOAT: { - static const Type valid[] = { BOOL, INT, @@ -609,7 +536,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case STRING: { - static const Type valid[] = { NODE_PATH, STRING_NAME, @@ -619,7 +545,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case VECTOR2: { - static const Type valid[] = { VECTOR2I, NIL, @@ -629,7 +554,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case VECTOR2I: { - static const Type valid[] = { VECTOR2, NIL, @@ -639,7 +563,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case RECT2: { - static const Type valid[] = { RECT2I, NIL, @@ -649,7 +572,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case RECT2I: { - static const Type valid[] = { RECT2, NIL, @@ -659,7 +581,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case TRANSFORM2D: { - static const Type valid[] = { TRANSFORM, NIL @@ -668,7 +589,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case VECTOR3: { - static const Type valid[] = { VECTOR3I, NIL, @@ -678,7 +598,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case VECTOR3I: { - static const Type valid[] = { VECTOR3, NIL, @@ -689,7 +608,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case QUAT: { - static const Type valid[] = { BASIS, NIL @@ -699,7 +617,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case BASIS: { - static const Type valid[] = { QUAT, VECTOR3, @@ -710,7 +627,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case TRANSFORM: { - static const Type valid[] = { TRANSFORM2D, QUAT, @@ -723,7 +639,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case COLOR: { - static const Type valid[] = { STRING, INT, @@ -735,7 +650,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case _RID: { - static const Type valid[] = { OBJECT, NIL @@ -744,7 +658,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case OBJECT: { - static const Type valid[] = { NIL }; @@ -752,7 +665,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case STRING_NAME: { - static const Type valid[] = { STRING, NIL @@ -761,7 +673,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case NODE_PATH: { - static const Type valid[] = { STRING, NIL @@ -770,7 +681,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case ARRAY: { - static const Type valid[] = { PACKED_BYTE_ARRAY, PACKED_INT32_ARRAY, @@ -788,7 +698,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; // arrays case PACKED_BYTE_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -797,7 +706,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case PACKED_INT32_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -805,7 +713,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case PACKED_INT64_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -813,7 +720,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case PACKED_FLOAT32_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -822,7 +728,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case PACKED_FLOAT64_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -831,7 +736,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case PACKED_STRING_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -839,7 +743,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type valid_types = valid; } break; case PACKED_VECTOR2_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -848,7 +751,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case PACKED_VECTOR3_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -857,7 +759,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; case PACKED_COLOR_ARRAY: { - static const Type valid[] = { ARRAY, NIL @@ -871,12 +772,11 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } if (valid_types) { - int i = 0; while (valid_types[i] != NIL) { - - if (p_type_from == valid_types[i]) + if (p_type_from == valid_types[i]) { return true; + } i++; } } @@ -885,9 +785,9 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } bool Variant::operator==(const Variant &p_variant) const { - - if (type != p_variant.type) //evaluation of operator== needs to be more strict + if (type != p_variant.type) { //evaluation of operator== needs to be more strict return false; + } bool v; Variant r; evaluate(OP_EQUAL, *this, p_variant, r, v); @@ -895,9 +795,9 @@ bool Variant::operator==(const Variant &p_variant) const { } bool Variant::operator!=(const Variant &p_variant) const { - - if (type != p_variant.type) //evaluation of operator== needs to be more strict + if (type != p_variant.type) { //evaluation of operator== needs to be more strict return true; + } bool v; Variant r; evaluate(OP_NOT_EQUAL, *this, p_variant, r, v); @@ -905,8 +805,9 @@ bool Variant::operator!=(const Variant &p_variant) const { } bool Variant::operator<(const Variant &p_variant) const { - if (type != p_variant.type) //if types differ, then order by type first + if (type != p_variant.type) { //if types differ, then order by type first return type < p_variant.type; + } bool v; Variant r; evaluate(OP_LESS, *this, p_variant, r, v); @@ -914,186 +815,145 @@ bool Variant::operator<(const Variant &p_variant) const { } bool Variant::is_zero() const { - switch (type) { case NIL: { - return true; } break; // atomic types case BOOL: { - return !(_data._bool); } break; case INT: { - return _data._int == 0; } break; case FLOAT: { - return _data._float == 0; } break; case STRING: { - return *reinterpret_cast<const String *>(_data._mem) == String(); } break; // math types case VECTOR2: { - return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2(); } break; case VECTOR2I: { - return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i(); } break; case RECT2: { - return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2(); } break; case RECT2I: { - return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i(); } break; case TRANSFORM2D: { - return *_data._transform2d == Transform2D(); } break; case VECTOR3: { - return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3(); } break; case VECTOR3I: { - return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(); } break; case PLANE: { - return *reinterpret_cast<const Plane *>(_data._mem) == Plane(); } break; - /* - case QUAT: { - - - } break;*/ case AABB: { - return *_data._aabb == ::AABB(); } break; case QUAT: { - return *reinterpret_cast<const Quat *>(_data._mem) == Quat(); } break; case BASIS: { - return *_data._basis == Basis(); } break; case TRANSFORM: { - return *_data._transform == Transform(); } break; // misc types case COLOR: { - return *reinterpret_cast<const Color *>(_data._mem) == Color(); } break; case _RID: { - return *reinterpret_cast<const RID *>(_data._mem) == RID(); } break; case OBJECT: { - return _get_obj().obj == nullptr; } break; case CALLABLE: { - return reinterpret_cast<const Callable *>(_data._mem)->is_null(); } break; case SIGNAL: { - return reinterpret_cast<const Signal *>(_data._mem)->is_null(); } break; case STRING_NAME: { - return *reinterpret_cast<const StringName *>(_data._mem) != StringName(); } break; case NODE_PATH: { - return reinterpret_cast<const NodePath *>(_data._mem)->is_empty(); } break; case DICTIONARY: { - return reinterpret_cast<const Dictionary *>(_data._mem)->empty(); } break; case ARRAY: { - return reinterpret_cast<const Array *>(_data._mem)->empty(); } break; // arrays case PACKED_BYTE_ARRAY: { - return PackedArrayRef<uint8_t>::get_array(_data.packed_array).size() == 0; } break; case PACKED_INT32_ARRAY: { - return PackedArrayRef<int32_t>::get_array(_data.packed_array).size() == 0; } break; case PACKED_INT64_ARRAY: { - return PackedArrayRef<int64_t>::get_array(_data.packed_array).size() == 0; } break; case PACKED_FLOAT32_ARRAY: { - return PackedArrayRef<float>::get_array(_data.packed_array).size() == 0; } break; case PACKED_FLOAT64_ARRAY: { - return PackedArrayRef<double>::get_array(_data.packed_array).size() == 0; } break; case PACKED_STRING_ARRAY: { - return PackedArrayRef<String>::get_array(_data.packed_array).size() == 0; } break; case PACKED_VECTOR2_ARRAY: { - return PackedArrayRef<Vector2>::get_array(_data.packed_array).size() == 0; } break; case PACKED_VECTOR3_ARRAY: { - return PackedArrayRef<Vector3>::get_array(_data.packed_array).size() == 0; } break; case PACKED_COLOR_ARRAY: { - return PackedArrayRef<Color>::get_array(_data.packed_array).size() == 0; } break; @@ -1105,65 +965,52 @@ bool Variant::is_zero() const { } bool Variant::is_one() const { - switch (type) { case NIL: { - return true; } break; // atomic types case BOOL: { - return _data._bool; } break; case INT: { - return _data._int == 1; } break; case FLOAT: { - return _data._float == 1; } break; case VECTOR2: { - return *reinterpret_cast<const Vector2 *>(_data._mem) == Vector2(1, 1); } break; case VECTOR2I: { - return *reinterpret_cast<const Vector2i *>(_data._mem) == Vector2i(1, 1); } break; case RECT2: { - return *reinterpret_cast<const Rect2 *>(_data._mem) == Rect2(1, 1, 1, 1); } break; case RECT2I: { - return *reinterpret_cast<const Rect2i *>(_data._mem) == Rect2i(1, 1, 1, 1); } break; case VECTOR3: { - return *reinterpret_cast<const Vector3 *>(_data._mem) == Vector3(1, 1, 1); } break; case VECTOR3I: { - return *reinterpret_cast<const Vector3i *>(_data._mem) == Vector3i(1, 1, 1); } break; case PLANE: { - return *reinterpret_cast<const Plane *>(_data._mem) == Plane(1, 1, 1, 1); } break; case COLOR: { - return *reinterpret_cast<const Color *>(_data._mem) == Color(1, 1, 1, 1); } break; @@ -1185,7 +1032,6 @@ bool Variant::is_null() const { } void Variant::reference(const Variant &p_variant) { - switch (type) { case NIL: case BOOL: @@ -1200,93 +1046,73 @@ void Variant::reference(const Variant &p_variant) { 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 FLOAT: { - _data._float = p_variant._data._float; } break; case STRING: { - memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem))); } break; // math types case VECTOR2: { - memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem))); } break; case VECTOR2I: { - memnew_placement(_data._mem, Vector2i(*reinterpret_cast<const Vector2i *>(p_variant._data._mem))); } break; case RECT2: { - memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem))); } break; case RECT2I: { - memnew_placement(_data._mem, Rect2i(*reinterpret_cast<const Rect2i *>(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 VECTOR3I: { - memnew_placement(_data._mem, Vector3i(*reinterpret_cast<const Vector3i *>(p_variant._data._mem))); } break; case PLANE: { - memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem))); } break; case AABB: { - _data._aabb = memnew(::AABB(*p_variant._data._aabb)); } break; case QUAT: { - memnew_placement(_data._mem, Quat(*reinterpret_cast<const Quat *>(p_variant._data._mem))); } break; case BASIS: { - _data._basis = memnew(Basis(*p_variant._data._basis)); } break; case TRANSFORM: { - _data._transform = memnew(Transform(*p_variant._data._transform)); } break; // misc types case COLOR: { - memnew_placement(_data._mem, Color(*reinterpret_cast<const Color *>(p_variant._data._mem))); } break; case _RID: { - memnew_placement(_data._mem, RID(*reinterpret_cast<const RID *>(p_variant._data._mem))); } break; case OBJECT: { - memnew_placement(_data._mem, ObjData); if (p_variant._get_obj().obj && p_variant._get_obj().id.is_reference()) { @@ -1303,37 +1129,30 @@ void Variant::reference(const Variant &p_variant) { } break; case CALLABLE: { - memnew_placement(_data._mem, Callable(*reinterpret_cast<const Callable *>(p_variant._data._mem))); } break; case SIGNAL: { - memnew_placement(_data._mem, Signal(*reinterpret_cast<const Signal *>(p_variant._data._mem))); } break; case STRING_NAME: { - memnew_placement(_data._mem, StringName(*reinterpret_cast<const StringName *>(p_variant._data._mem))); } break; case NODE_PATH: { - memnew_placement(_data._mem, NodePath(*reinterpret_cast<const NodePath *>(p_variant._data._mem))); } break; case DICTIONARY: { - memnew_placement(_data._mem, Dictionary(*reinterpret_cast<const Dictionary *>(p_variant._data._mem))); } break; case ARRAY: { - memnew_placement(_data._mem, Array(*reinterpret_cast<const Array *>(p_variant._data._mem))); } break; // arrays case PACKED_BYTE_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<uint8_t> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<uint8_t>::create(); @@ -1341,7 +1160,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_INT32_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<int32_t> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<int32_t>::create(); @@ -1349,7 +1167,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_INT64_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<int64_t> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<int64_t>::create(); @@ -1357,7 +1174,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_FLOAT32_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<float> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<float>::create(); @@ -1365,7 +1181,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_FLOAT64_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<double> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<double>::create(); @@ -1373,7 +1188,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_STRING_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<String> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<String>::create(); @@ -1381,7 +1195,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_VECTOR2_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<Vector2> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<Vector2>::create(); @@ -1389,7 +1202,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_VECTOR3_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<Vector3> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<Vector3>::create(); @@ -1397,7 +1209,6 @@ void Variant::reference(const Variant &p_variant) { } break; case PACKED_COLOR_ARRAY: { - _data.packed_array = static_cast<PackedArrayRef<Color> *>(p_variant._data.packed_array)->reference(); if (!_data.packed_array) { _data.packed_array = PackedArrayRef<Color>::create(); @@ -1411,28 +1222,53 @@ void Variant::reference(const Variant &p_variant) { void Variant::zero() { switch (type) { - case NIL: break; - case BOOL: this->_data._bool = false; break; - case INT: this->_data._int = 0; break; - case FLOAT: this->_data._float = 0; break; - case VECTOR2: *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); break; - case VECTOR2I: *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i(); break; - case RECT2: *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2(); break; - case RECT2I: *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i(); break; - case VECTOR3: *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3(); break; - case VECTOR3I: *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); break; - case PLANE: *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); break; - case QUAT: *reinterpret_cast<Quat *>(this->_data._mem) = Quat(); break; - case COLOR: *reinterpret_cast<Color *>(this->_data._mem) = Color(); break; - default: this->clear(); break; + case NIL: + break; + case BOOL: + this->_data._bool = false; + break; + case INT: + this->_data._int = 0; + break; + case FLOAT: + this->_data._float = 0; + break; + case VECTOR2: + *reinterpret_cast<Vector2 *>(this->_data._mem) = Vector2(); + break; + case VECTOR2I: + *reinterpret_cast<Vector2i *>(this->_data._mem) = Vector2i(); + break; + case RECT2: + *reinterpret_cast<Rect2 *>(this->_data._mem) = Rect2(); + break; + case RECT2I: + *reinterpret_cast<Rect2i *>(this->_data._mem) = Rect2i(); + break; + case VECTOR3: + *reinterpret_cast<Vector3 *>(this->_data._mem) = Vector3(); + break; + case VECTOR3I: + *reinterpret_cast<Vector3i *>(this->_data._mem) = Vector3i(); + break; + case PLANE: + *reinterpret_cast<Plane *>(this->_data._mem) = Plane(); + break; + case QUAT: + *reinterpret_cast<Quat *>(this->_data._mem) = Quat(); + break; + case COLOR: + *reinterpret_cast<Color *>(this->_data._mem) = Color(); + break; + default: + this->clear(); + break; } } void Variant::clear() { - switch (type) { case STRING: { - reinterpret_cast<String *>(_data._mem)->~String(); } break; /* @@ -1443,35 +1279,28 @@ void Variant::clear() { COLOR, VECTOR2, RECT2 - */ + */ case TRANSFORM2D: { - memdelete(_data._transform2d); } break; case AABB: { - memdelete(_data._aabb); } break; case BASIS: { - memdelete(_data._basis); } break; case TRANSFORM: { - memdelete(_data._transform); } break; // misc types case STRING_NAME: { - reinterpret_cast<StringName *>(_data._mem)->~StringName(); } break; case NODE_PATH: { - reinterpret_cast<NodePath *>(_data._mem)->~NodePath(); } break; case OBJECT: { - if (_get_obj().id.is_reference()) { //we are safe that there is a reference here Reference *reference = static_cast<Reference *>(_get_obj().obj); @@ -1487,56 +1316,43 @@ void Variant::clear() { reinterpret_cast<RID *>(_data._mem)->~RID(); } break; case CALLABLE: { - reinterpret_cast<Callable *>(_data._mem)->~Callable(); } break; case SIGNAL: { - reinterpret_cast<Signal *>(_data._mem)->~Signal(); } break; case DICTIONARY: { - reinterpret_cast<Dictionary *>(_data._mem)->~Dictionary(); } break; case ARRAY: { - reinterpret_cast<Array *>(_data._mem)->~Array(); } break; // arrays case PACKED_BYTE_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_INT32_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_INT64_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_FLOAT32_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_FLOAT64_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_STRING_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_VECTOR2_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_VECTOR3_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; case PACKED_COLOR_ARRAY: { - PackedArrayRefBase::destroy(_data.packed_array); } break; default: { @@ -1547,83 +1363,72 @@ void Variant::clear() { } Variant::operator signed int() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } } -Variant::operator unsigned int() const { +Variant::operator unsigned int() const { switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } } Variant::operator int64_t() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int64(); - default: { - + case NIL: return 0; - } - } -} - -/* -Variant::operator long unsigned int() const { - - switch( type ) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._real; - case STRING: return operator String().to_int(); + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int64(); default: { - return 0; } } - - return 0; -}; -*/ +} Variant::operator uint64_t() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } @@ -1641,141 +1446,159 @@ Variant::operator ObjectID() const { #ifdef NEED_LONG_INT Variant::operator signed long() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._real; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._real; + case STRING: + return operator String().to_int(); default: { - return 0; } } return 0; -}; +} Variant::operator unsigned long() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._real; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._real; + case STRING: + return operator String().to_int(); default: { - return 0; } } return 0; -}; +} #endif Variant::operator signed short() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } } -Variant::operator unsigned short() const { +Variant::operator unsigned short() const { switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } } -Variant::operator signed char() const { +Variant::operator signed char() const { switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } } -Variant::operator unsigned char() const { +Variant::operator unsigned char() const { switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1 : 0; - case INT: return _data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_int(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1 : 0; + case INT: + return _data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_int(); default: { - return 0; } } } Variant::operator CharType() const { - return operator unsigned int(); } Variant::operator float() const { - switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1.0 : 0.0; - case INT: return (float)_data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_double(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1.0 : 0.0; + case INT: + return (float)_data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_double(); default: { - return 0; } } } -Variant::operator double() const { +Variant::operator double() const { switch (type) { - - case NIL: return 0; - case BOOL: return _data._bool ? 1.0 : 0.0; - case INT: return (double)_data._int; - case FLOAT: return _data._float; - case STRING: return operator String().to_double(); + case NIL: + return 0; + case BOOL: + return _data._bool ? 1.0 : 0.0; + case INT: + return (double)_data._int; + case FLOAT: + return _data._float; + case STRING: + return operator String().to_double(); default: { - return 0; } } } Variant::operator StringName() const { - if (type == STRING_NAME) { return *reinterpret_cast<const StringName *>(_data._mem); } else if (type == STRING) { @@ -1786,12 +1609,10 @@ Variant::operator StringName() const { } struct _VariantStrPair { - String key; String value; bool operator<(const _VariantStrPair &p) const { - return key < p.key; } }; @@ -1804,44 +1625,54 @@ Variant::operator String() const { String Variant::stringify(List<const void *> &stack) const { switch (type) { - - case NIL: return "Null"; - case BOOL: return _data._bool ? "True" : "False"; - case INT: return itos(_data._int); - case FLOAT: return rtos(_data._float); - case STRING: return *reinterpret_cast<const String *>(_data._mem); - case VECTOR2: return "(" + operator Vector2() + ")"; - case VECTOR2I: return "(" + operator Vector2i() + ")"; - case RECT2: return "(" + operator Rect2() + ")"; - case RECT2I: return "(" + operator Rect2i() + ")"; + case NIL: + return "Null"; + case BOOL: + return _data._bool ? "True" : "False"; + case INT: + return itos(_data._int); + case FLOAT: + return rtos(_data._float); + case STRING: + return *reinterpret_cast<const String *>(_data._mem); + case VECTOR2: + return "(" + operator Vector2() + ")"; + case VECTOR2I: + return "(" + operator Vector2i() + ")"; + case RECT2: + return "(" + operator Rect2() + ")"; + case RECT2I: + return "(" + operator Rect2i() + ")"; case TRANSFORM2D: { - Transform2D mat32 = operator Transform2D(); return "(" + Variant(mat32.elements[0]).operator String() + ", " + Variant(mat32.elements[1]).operator String() + ", " + Variant(mat32.elements[2]).operator String() + ")"; } break; - case VECTOR3: return "(" + operator Vector3() + ")"; - case VECTOR3I: return "(" + operator Vector3i() + ")"; + case VECTOR3: + return "(" + operator Vector3() + ")"; + case VECTOR3I: + return "(" + operator Vector3i() + ")"; case PLANE: return operator Plane(); //case QUAT: - case AABB: return operator ::AABB(); - case QUAT: return "(" + operator Quat() + ")"; + case AABB: + return operator ::AABB(); + case QUAT: + return "(" + operator Quat() + ")"; case BASIS: { - Basis mat3 = operator Basis(); String mtx("("); for (int i = 0; i < 3; i++) { - - if (i != 0) + if (i != 0) { mtx += ", "; + } mtx += "("; for (int j = 0; j < 3; j++) { - - if (j != 0) + if (j != 0) { mtx += ", "; + } mtx += Variant(mat3.elements[i][j]).operator String(); } @@ -1851,12 +1682,15 @@ String Variant::stringify(List<const void *> &stack) const { return mtx + ")"; } break; - case TRANSFORM: return operator Transform(); - case STRING_NAME: return operator StringName(); - case NODE_PATH: return operator NodePath(); - case COLOR: return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a); + case TRANSFORM: + return operator Transform(); + case STRING_NAME: + return operator StringName(); + case NODE_PATH: + return operator NodePath(); + case COLOR: + return String::num(operator Color().r) + "," + String::num(operator Color().g) + "," + String::num(operator Color().b) + "," + String::num(operator Color().a); case DICTIONARY: { - const Dictionary &d = *reinterpret_cast<const Dictionary *>(_data._mem); if (stack.find(d.id())) { return "{...}"; @@ -1872,7 +1706,6 @@ String Variant::stringify(List<const void *> &stack) const { Vector<_VariantStrPair> pairs; for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - _VariantStrPair sp; sp.key = E->get().stringify(stack); sp.value = d[E->get()].stringify(stack); @@ -1883,8 +1716,9 @@ String Variant::stringify(List<const void *> &stack) const { pairs.sort(); for (int i = 0; i < pairs.size(); i++) { - if (i > 0) + if (i > 0) { str += ", "; + } str += pairs[i].key + ":" + pairs[i].value; } str += "}"; @@ -1892,98 +1726,90 @@ String Variant::stringify(List<const void *> &stack) const { return str; } break; case PACKED_VECTOR2_ARRAY: { - Vector<Vector2> vec = operator Vector<Vector2>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + Variant(vec[i]); } str += "]"; return str; } break; case PACKED_VECTOR3_ARRAY: { - Vector<Vector3> vec = operator Vector<Vector3>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + Variant(vec[i]); } str += "]"; return str; } break; case PACKED_STRING_ARRAY: { - Vector<String> vec = operator Vector<String>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + vec[i]; } str += "]"; return str; } break; case PACKED_INT32_ARRAY: { - Vector<int32_t> vec = operator Vector<int32_t>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + itos(vec[i]); } str += "]"; return str; } break; case PACKED_INT64_ARRAY: { - Vector<int64_t> vec = operator Vector<int64_t>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + itos(vec[i]); } str += "]"; return str; } break; case PACKED_FLOAT32_ARRAY: { - Vector<float> vec = operator Vector<float>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + rtos(vec[i]); } str += "]"; return str; } break; case PACKED_FLOAT64_ARRAY: { - Vector<double> vec = operator Vector<double>(); String str("["); for (int i = 0; i < vec.size(); i++) { - - if (i > 0) + if (i > 0) { str += ", "; + } str = str + rtos(vec[i]); } str += "]"; return str; } break; case ARRAY: { - Array arr = operator Array(); if (stack.find(arr.id())) { return "[...]"; @@ -1992,8 +1818,9 @@ String Variant::stringify(List<const void *> &stack) const { String str("["); for (int i = 0; i < arr.size(); i++) { - if (i) + if (i) { str += ", "; + } str += arr[i].stringify(stack); } @@ -2003,16 +1830,15 @@ String Variant::stringify(List<const void *> &stack) const { } break; case OBJECT: { - if (_get_obj().obj) { - if (!_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { return "[Freed Object]"; - }; + } return _get_obj().obj->to_string(); - } else + } else { return "[Object:null]"; + } } break; case CALLABLE: { @@ -2036,131 +1862,131 @@ String Variant::stringify(List<const void *> &stack) const { } Variant::operator Vector2() const { - - if (type == VECTOR2) + if (type == VECTOR2) { return *reinterpret_cast<const Vector2 *>(_data._mem); - else if (type == VECTOR2I) + } else if (type == VECTOR2I) { return *reinterpret_cast<const Vector2i *>(_data._mem); - else if (type == VECTOR3) + } else if (type == VECTOR3) { return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y); - else if (type == VECTOR3I) + } else if (type == VECTOR3I) { return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y); - else + } else { return Vector2(); + } } Variant::operator Vector2i() const { - - if (type == VECTOR2I) + if (type == VECTOR2I) { return *reinterpret_cast<const Vector2i *>(_data._mem); - else if (type == VECTOR2) + } else if (type == VECTOR2) { return *reinterpret_cast<const Vector2 *>(_data._mem); - else if (type == VECTOR3) + } else if (type == VECTOR3) { return Vector2(reinterpret_cast<const Vector3 *>(_data._mem)->x, reinterpret_cast<const Vector3 *>(_data._mem)->y); - else if (type == VECTOR3I) + } else if (type == VECTOR3I) { return Vector2(reinterpret_cast<const Vector3i *>(_data._mem)->x, reinterpret_cast<const Vector3i *>(_data._mem)->y); - else + } else { return Vector2i(); + } } Variant::operator Rect2() const { - - if (type == RECT2) + if (type == RECT2) { return *reinterpret_cast<const Rect2 *>(_data._mem); - else if (type == RECT2I) + } else if (type == RECT2I) { return *reinterpret_cast<const Rect2i *>(_data._mem); - else + } else { return Rect2(); + } } Variant::operator Rect2i() const { - - if (type == RECT2I) + if (type == RECT2I) { return *reinterpret_cast<const Rect2i *>(_data._mem); - else if (type == RECT2) + } else if (type == RECT2) { return *reinterpret_cast<const Rect2 *>(_data._mem); - else + } else { return Rect2i(); + } } Variant::operator Vector3() const { - - if (type == VECTOR3) + if (type == VECTOR3) { return *reinterpret_cast<const Vector3 *>(_data._mem); - else if (type == VECTOR3I) + } else if (type == VECTOR3I) { return *reinterpret_cast<const Vector3i *>(_data._mem); - else if (type == VECTOR2) + } else if (type == VECTOR2) { return Vector3(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0); - else if (type == VECTOR2I) + } else if (type == VECTOR2I) { return Vector3(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0); - else + } else { return Vector3(); + } } Variant::operator Vector3i() const { - - if (type == VECTOR3I) + if (type == VECTOR3I) { return *reinterpret_cast<const Vector3i *>(_data._mem); - else if (type == VECTOR3) + } else if (type == VECTOR3) { return *reinterpret_cast<const Vector3 *>(_data._mem); - else if (type == VECTOR2) + } else if (type == VECTOR2) { return Vector3i(reinterpret_cast<const Vector2 *>(_data._mem)->x, reinterpret_cast<const Vector2 *>(_data._mem)->y, 0.0); - else if (type == VECTOR2I) + } else if (type == VECTOR2I) { return Vector3i(reinterpret_cast<const Vector2i *>(_data._mem)->x, reinterpret_cast<const Vector2i *>(_data._mem)->y, 0.0); - else + } else { return Vector3i(); + } } Variant::operator Plane() const { - - if (type == PLANE) + if (type == PLANE) { return *reinterpret_cast<const Plane *>(_data._mem); - else + } else { return Plane(); + } } -Variant::operator ::AABB() const { - if (type == AABB) +Variant::operator ::AABB() const { + if (type == AABB) { return *_data._aabb; - else + } else { return ::AABB(); + } } Variant::operator Basis() const { - - if (type == BASIS) + if (type == BASIS) { return *_data._basis; - else if (type == QUAT) + } else if (type == QUAT) { return *reinterpret_cast<const Quat *>(_data._mem); - else if (type == VECTOR3) { + } else if (type == VECTOR3) { return Basis(*reinterpret_cast<const Vector3 *>(_data._mem)); - } else if (type == TRANSFORM) // unexposed in Variant::can_convert? + } else if (type == TRANSFORM) { // unexposed in Variant::can_convert? return _data._transform->basis; - else + } else { return Basis(); + } } Variant::operator Quat() const { - - if (type == QUAT) + if (type == QUAT) { return *reinterpret_cast<const Quat *>(_data._mem); - else if (type == BASIS) + } else if (type == BASIS) { return *_data._basis; - else if (type == TRANSFORM) + } else if (type == TRANSFORM) { return _data._transform->basis; - else + } else { return Quat(); + } } Variant::operator Transform() const { - - if (type == TRANSFORM) + if (type == TRANSFORM) { return *_data._transform; - else if (type == BASIS) + } else if (type == BASIS) { return Transform(*_data._basis, Vector3()); - else if (type == QUAT) + } else if (type == QUAT) { return Transform(Basis(*reinterpret_cast<const Quat *>(_data._mem)), Vector3()); - else if (type == TRANSFORM2D) { + } else if (type == TRANSFORM2D) { const Transform2D &t = *_data._transform2d; Transform m; m.basis.elements[0][0] = t.elements[0][0]; @@ -2170,12 +1996,12 @@ Variant::operator Transform() const { m.origin[0] = t.elements[2][0]; m.origin[1] = t.elements[2][1]; return m; - } else + } else { return Transform(); + } } Variant::operator Transform2D() const { - if (type == TRANSFORM2D) { return *_data._transform2d; } else if (type == TRANSFORM) { @@ -2188,43 +2014,43 @@ Variant::operator Transform2D() const { m.elements[2][0] = t.origin[0]; m.elements[2][1] = t.origin[1]; return m; - } else + } else { return Transform2D(); + } } Variant::operator Color() const { - - if (type == COLOR) + if (type == COLOR) { return *reinterpret_cast<const Color *>(_data._mem); - else if (type == STRING) + } else if (type == STRING) { return Color::html(operator String()); - else if (type == INT) + } else if (type == INT) { return Color::hex(operator int()); - else + } else { return Color(); + } } Variant::operator NodePath() const { - - if (type == NODE_PATH) + if (type == NODE_PATH) { return *reinterpret_cast<const NodePath *>(_data._mem); - else if (type == STRING) + } else if (type == STRING) { return NodePath(operator String()); - else + } else { return NodePath(); + } } Variant::operator RID() const { - - if (type == _RID) + if (type == _RID) { return *reinterpret_cast<const RID *>(_data._mem); - else if (type == OBJECT && _get_obj().obj == nullptr) { + } else if (type == OBJECT && _get_obj().obj == nullptr) { return RID(); } else if (type == OBJECT && _get_obj().obj) { #ifdef DEBUG_ENABLED if (EngineDebugger::is_active()) { ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed)."); - }; + } #endif Callable::CallError ce; Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce); @@ -2238,11 +2064,11 @@ Variant::operator RID() const { } Variant::operator Object *() const { - - if (type == OBJECT) + if (type == OBJECT) { return _get_obj().obj; - else + } else { return nullptr; + } } Object *Variant::get_validated_object_with_check(bool &r_previously_freed) const { @@ -2257,59 +2083,59 @@ Object *Variant::get_validated_object_with_check(bool &r_previously_freed) const } Object *Variant::get_validated_object() const { - if (type == OBJECT) + if (type == OBJECT) { return ObjectDB::get_instance(_get_obj().id); - else + } else { return nullptr; + } } Variant::operator Node *() const { - - if (type == OBJECT) + if (type == OBJECT) { return Object::cast_to<Node>(_get_obj().obj); - else + } else { return nullptr; + } } -Variant::operator Control *() const { - if (type == OBJECT) +Variant::operator Control *() const { + if (type == OBJECT) { return Object::cast_to<Control>(_get_obj().obj); - else + } else { return nullptr; + } } Variant::operator Dictionary() const { - - if (type == DICTIONARY) + if (type == DICTIONARY) { return *reinterpret_cast<const Dictionary *>(_data._mem); - else + } else { return Dictionary(); + } } Variant::operator Callable() const { - - if (type == CALLABLE) + if (type == CALLABLE) { return *reinterpret_cast<const Callable *>(_data._mem); - else + } else { return Callable(); + } } Variant::operator Signal() const { - - if (type == SIGNAL) + if (type == SIGNAL) { return *reinterpret_cast<const Signal *>(_data._mem); - else + } else { return Signal(); + } } template <class DA, class SA> inline DA _convert_array(const SA &p_array) { - DA da; da.resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { - da.set(i, Variant(p_array.get(i))); } @@ -2318,9 +2144,7 @@ inline DA _convert_array(const SA &p_array) { template <class DA> inline DA _convert_array_from_variant(const Variant &p_variant) { - switch (p_variant.get_type()) { - case Variant::ARRAY: { return _convert_array<DA, Array>(p_variant.operator Array()); } @@ -2358,169 +2182,172 @@ inline DA _convert_array_from_variant(const Variant &p_variant) { } Variant::operator Array() const { - - if (type == ARRAY) + if (type == ARRAY) { return *reinterpret_cast<const Array *>(_data._mem); - else + } else { return _convert_array_from_variant<Array>(*this); + } } Variant::operator Vector<uint8_t>() const { - - if (type == PACKED_BYTE_ARRAY) + if (type == PACKED_BYTE_ARRAY) { return static_cast<PackedArrayRef<uint8_t> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<uint8_t>>(*this); + } } -Variant::operator Vector<int32_t>() const { - if (type == PACKED_INT32_ARRAY) +Variant::operator Vector<int32_t>() const { + if (type == PACKED_INT32_ARRAY) { return static_cast<PackedArrayRef<int32_t> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<int>>(*this); + } } -Variant::operator Vector<int64_t>() const { - if (type == PACKED_INT64_ARRAY) +Variant::operator Vector<int64_t>() const { + if (type == PACKED_INT64_ARRAY) { return static_cast<PackedArrayRef<int64_t> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<int64_t>>(*this); + } } Variant::operator Vector<float>() const { - - if (type == PACKED_FLOAT32_ARRAY) + if (type == PACKED_FLOAT32_ARRAY) { return static_cast<PackedArrayRef<float> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<float>>(*this); + } } Variant::operator Vector<double>() const { - - if (type == PACKED_FLOAT64_ARRAY) + if (type == PACKED_FLOAT64_ARRAY) { return static_cast<PackedArrayRef<double> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<double>>(*this); + } } Variant::operator Vector<String>() const { - - if (type == PACKED_STRING_ARRAY) + if (type == PACKED_STRING_ARRAY) { return static_cast<PackedArrayRef<String> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<String>>(*this); + } } -Variant::operator Vector<Vector3>() const { - if (type == PACKED_VECTOR3_ARRAY) +Variant::operator Vector<Vector3>() const { + if (type == PACKED_VECTOR3_ARRAY) { return static_cast<PackedArrayRef<Vector3> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<Vector3>>(*this); + } } -Variant::operator Vector<Vector2>() const { - if (type == PACKED_VECTOR2_ARRAY) +Variant::operator Vector<Vector2>() const { + if (type == PACKED_VECTOR2_ARRAY) { return static_cast<PackedArrayRef<Vector2> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<Vector2>>(*this); + } } Variant::operator Vector<Color>() const { - - if (type == PACKED_COLOR_ARRAY) + if (type == PACKED_COLOR_ARRAY) { return static_cast<PackedArrayRef<Color> *>(_data.packed_array)->array; - else + } else { return _convert_array_from_variant<Vector<Color>>(*this); + } } /* helpers */ Variant::operator Vector<RID>() const { - Array va = operator Array(); Vector<RID> rids; rids.resize(va.size()); - for (int i = 0; i < rids.size(); i++) + for (int i = 0; i < rids.size(); i++) { rids.write[i] = va[i]; + } return rids; } Variant::operator Vector<Plane>() const { - Array va = operator Array(); Vector<Plane> planes; int va_size = va.size(); - if (va_size == 0) + if (va_size == 0) { return planes; + } planes.resize(va_size); Plane *w = planes.ptrw(); - for (int i = 0; i < va_size; i++) + for (int i = 0; i < va_size; i++) { w[i] = va[i]; + } return planes; } Variant::operator Vector<Face3>() const { - Vector<Vector3> va = operator Vector<Vector3>(); Vector<Face3> faces; int va_size = va.size(); - if (va_size == 0) + if (va_size == 0) { return faces; + } faces.resize(va_size / 3); Face3 *w = faces.ptrw(); const Vector3 *r = va.ptr(); - for (int i = 0; i < va_size; i++) + for (int i = 0; i < va_size; i++) { w[i / 3].vertex[i % 3] = r[i]; + } return faces; } Variant::operator Vector<Variant>() const { - Array va = operator Array(); Vector<Variant> variants; int va_size = va.size(); - if (va_size == 0) + if (va_size == 0) { return variants; + } variants.resize(va_size); Variant *w = variants.ptrw(); - for (int i = 0; i < va_size; i++) + for (int i = 0; i < va_size; i++) { w[i] = va[i]; + } return variants; } -Variant::operator Vector<StringName>() const { +Variant::operator Vector<StringName>() const { Vector<String> from = operator Vector<String>(); Vector<StringName> to; int len = from.size(); to.resize(len); for (int i = 0; i < len; i++) { - to.write[i] = from[i]; } return to; } Variant::operator Margin() const { - return (Margin) operator int(); } -Variant::operator Orientation() const { +Variant::operator Orientation() const { return (Orientation) operator int(); } Variant::operator IP_Address() const { - if (type == PACKED_FLOAT32_ARRAY || type == PACKED_INT32_ARRAY || type == PACKED_FLOAT64_ARRAY || type == PACKED_INT64_ARRAY || type == PACKED_BYTE_ARRAY) { - Vector<int> addr = operator Vector<int>(); if (addr.size() == 4) { return IP_Address(addr.get(0), addr.get(1), addr.get(2), addr.get(3)); @@ -2531,26 +2358,16 @@ Variant::operator IP_Address() const { } Variant::Variant(bool p_bool) { - type = BOOL; _data._bool = p_bool; } -/* -Variant::Variant(long unsigned int p_long) { - - type=INT; - _data._int=p_long; -}; -*/ - Variant::Variant(signed int p_int) { - type = INT; _data._int = p_int; } -Variant::Variant(unsigned int p_int) { +Variant::Variant(unsigned int p_int) { type = INT; _data._int = p_int; } @@ -2558,56 +2375,52 @@ Variant::Variant(unsigned int p_int) { #ifdef NEED_LONG_INT Variant::Variant(signed long p_int) { - type = INT; _data._int = p_int; } -Variant::Variant(unsigned long p_int) { +Variant::Variant(unsigned long p_int) { type = INT; _data._int = p_int; } #endif Variant::Variant(int64_t p_int) { - type = INT; _data._int = p_int; } Variant::Variant(uint64_t p_int) { - type = INT; _data._int = p_int; } Variant::Variant(signed short p_short) { - type = INT; _data._int = p_short; } -Variant::Variant(unsigned short p_short) { +Variant::Variant(unsigned short p_short) { type = INT; _data._int = p_short; } -Variant::Variant(signed char p_char) { +Variant::Variant(signed char p_char) { type = INT; _data._int = p_char; } -Variant::Variant(unsigned char p_char) { +Variant::Variant(unsigned char p_char) { type = INT; _data._int = p_char; } -Variant::Variant(float p_float) { +Variant::Variant(float p_float) { type = FLOAT; _data._float = p_float; } -Variant::Variant(double p_double) { +Variant::Variant(double p_double) { type = FLOAT; _data._float = p_double; } @@ -2618,121 +2431,106 @@ Variant::Variant(const ObjectID &p_id) { } Variant::Variant(const StringName &p_string) { - type = STRING_NAME; memnew_placement(_data._mem, StringName(p_string)); } -Variant::Variant(const String &p_string) { +Variant::Variant(const String &p_string) { type = STRING; memnew_placement(_data._mem, String(p_string)); } Variant::Variant(const char *const p_cstring) { - type = STRING; memnew_placement(_data._mem, String((const char *)p_cstring)); } Variant::Variant(const CharType *p_wstring) { - type = STRING; memnew_placement(_data._mem, String(p_wstring)); } -Variant::Variant(const Vector3 &p_vector3) { +Variant::Variant(const Vector3 &p_vector3) { type = VECTOR3; memnew_placement(_data._mem, Vector3(p_vector3)); } -Variant::Variant(const Vector3i &p_vector3i) { +Variant::Variant(const Vector3i &p_vector3i) { type = VECTOR3I; memnew_placement(_data._mem, Vector3i(p_vector3i)); } Variant::Variant(const Vector2 &p_vector2) { - type = VECTOR2; memnew_placement(_data._mem, Vector2(p_vector2)); } Variant::Variant(const Vector2i &p_vector2i) { - type = VECTOR2I; memnew_placement(_data._mem, Vector2i(p_vector2i)); } Variant::Variant(const Rect2 &p_rect2) { - type = RECT2; memnew_placement(_data._mem, Rect2(p_rect2)); } Variant::Variant(const Rect2i &p_rect2i) { - type = RECT2I; memnew_placement(_data._mem, Rect2i(p_rect2i)); } Variant::Variant(const Plane &p_plane) { - type = PLANE; memnew_placement(_data._mem, Plane(p_plane)); } -Variant::Variant(const ::AABB &p_aabb) { +Variant::Variant(const ::AABB &p_aabb) { type = AABB; _data._aabb = memnew(::AABB(p_aabb)); } Variant::Variant(const Basis &p_matrix) { - type = BASIS; _data._basis = memnew(Basis(p_matrix)); } Variant::Variant(const Quat &p_quat) { - type = QUAT; memnew_placement(_data._mem, Quat(p_quat)); } -Variant::Variant(const Transform &p_transform) { +Variant::Variant(const Transform &p_transform) { type = TRANSFORM; _data._transform = memnew(Transform(p_transform)); } Variant::Variant(const Transform2D &p_transform) { - type = TRANSFORM2D; _data._transform2d = memnew(Transform2D(p_transform)); } -Variant::Variant(const Color &p_color) { +Variant::Variant(const Color &p_color) { type = COLOR; memnew_placement(_data._mem, Color(p_color)); } Variant::Variant(const NodePath &p_node_path) { - type = NODE_PATH; memnew_placement(_data._mem, NodePath(p_node_path)); } Variant::Variant(const RID &p_rid) { - type = _RID; memnew_placement(_data._mem, RID(p_rid)); } Variant::Variant(const Object *p_object) { - type = OBJECT; memnew_placement(_data._mem, ObjData); if (p_object) { - if (p_object->is_reference()) { Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(p_object)); if (!reference->init_ref()) { @@ -2751,30 +2549,26 @@ Variant::Variant(const Object *p_object) { } Variant::Variant(const Callable &p_callable) { - type = CALLABLE; memnew_placement(_data._mem, Callable(p_callable)); } -Variant::Variant(const Signal &p_callable) { +Variant::Variant(const Signal &p_callable) { type = SIGNAL; memnew_placement(_data._mem, Signal(p_callable)); } Variant::Variant(const Dictionary &p_dictionary) { - type = DICTIONARY; memnew_placement(_data._mem, Dictionary(p_dictionary)); } Variant::Variant(const Array &p_array) { - type = ARRAY; memnew_placement(_data._mem, Array(p_array)); } Variant::Variant(const Vector<Plane> &p_array) { - type = ARRAY; Array *plane_array = memnew_placement(_data._mem, Array); @@ -2782,13 +2576,11 @@ Variant::Variant(const Vector<Plane> &p_array) { plane_array->resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { - plane_array->operator[](i) = Variant(p_array[i]); } } Variant::Variant(const Vector<RID> &p_array) { - type = ARRAY; Array *rid_array = memnew_placement(_data._mem, Array); @@ -2796,65 +2588,57 @@ Variant::Variant(const Vector<RID> &p_array) { rid_array->resize(p_array.size()); for (int i = 0; i < p_array.size(); i++) { - rid_array->set(i, Variant(p_array[i])); } } Variant::Variant(const Vector<uint8_t> &p_byte_array) { - type = PACKED_BYTE_ARRAY; _data.packed_array = PackedArrayRef<uint8_t>::create(p_byte_array); } -Variant::Variant(const Vector<int32_t> &p_int32_array) { +Variant::Variant(const Vector<int32_t> &p_int32_array) { type = PACKED_INT32_ARRAY; _data.packed_array = PackedArrayRef<int32_t>::create(p_int32_array); } Variant::Variant(const Vector<int64_t> &p_int64_array) { - type = PACKED_INT64_ARRAY; _data.packed_array = PackedArrayRef<int64_t>::create(p_int64_array); } Variant::Variant(const Vector<float> &p_float32_array) { - type = PACKED_FLOAT32_ARRAY; _data.packed_array = PackedArrayRef<float>::create(p_float32_array); } Variant::Variant(const Vector<double> &p_float64_array) { - type = PACKED_FLOAT64_ARRAY; _data.packed_array = PackedArrayRef<double>::create(p_float64_array); } Variant::Variant(const Vector<String> &p_string_array) { - type = PACKED_STRING_ARRAY; _data.packed_array = PackedArrayRef<String>::create(p_string_array); } -Variant::Variant(const Vector<Vector3> &p_vector3_array) { +Variant::Variant(const Vector<Vector3> &p_vector3_array) { type = PACKED_VECTOR3_ARRAY; _data.packed_array = PackedArrayRef<Vector3>::create(p_vector3_array); } Variant::Variant(const Vector<Vector2> &p_vector2_array) { - type = PACKED_VECTOR2_ARRAY; _data.packed_array = PackedArrayRef<Vector2>::create(p_vector2_array); } -Variant::Variant(const Vector<Color> &p_color_array) { +Variant::Variant(const Vector<Color> &p_color_array) { type = PACKED_COLOR_ARRAY; _data.packed_array = PackedArrayRef<Color>::create(p_color_array); } Variant::Variant(const Vector<Face3> &p_face_array) { - Vector<Vector3> vertices; int face_count = p_face_array.size(); vertices.resize(face_count * 3); @@ -2864,9 +2648,9 @@ Variant::Variant(const Vector<Face3> &p_face_array) { Vector3 *w = vertices.ptrw(); for (int i = 0; i < face_count; i++) { - - for (int j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) { w[i * 3 + j] = r[i].vertex[j]; + } } } @@ -2887,20 +2671,20 @@ Variant::Variant(const Vector<Variant> &p_array) { } Variant::Variant(const Vector<StringName> &p_array) { - type = NIL; Vector<String> v; int len = p_array.size(); v.resize(len); - for (int i = 0; i < len; i++) + for (int i = 0; i < len; i++) { v.set(i, p_array[i]); + } *this = v; } void Variant::operator=(const Variant &p_variant) { - - if (unlikely(this == &p_variant)) + if (unlikely(this == &p_variant)) { return; + } if (unlikely(type != p_variant.type)) { reference(p_variant); @@ -2909,90 +2693,70 @@ void Variant::operator=(const Variant &p_variant) { 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 FLOAT: { - _data._float = p_variant._data._float; } 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 VECTOR2I: { - *reinterpret_cast<Vector2i *>(_data._mem) = *reinterpret_cast<const Vector2i *>(p_variant._data._mem); } break; case RECT2: { - *reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem); } break; case RECT2I: { - *reinterpret_cast<Rect2i *>(_data._mem) = *reinterpret_cast<const Rect2i *>(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 VECTOR3I: { - *reinterpret_cast<Vector3i *>(_data._mem) = *reinterpret_cast<const Vector3i *>(p_variant._data._mem); } break; case PLANE: { - *reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem); } break; case AABB: { - *_data._aabb = *(p_variant._data._aabb); } 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: { - if (_get_obj().id.is_reference()) { //we are safe that there is a reference here Reference *reference = static_cast<Reference *>(_get_obj().obj); @@ -3015,66 +2779,51 @@ void Variant::operator=(const Variant &p_variant) { } break; case CALLABLE: { - *reinterpret_cast<Callable *>(_data._mem) = *reinterpret_cast<const Callable *>(p_variant._data._mem); } break; case SIGNAL: { - *reinterpret_cast<Signal *>(_data._mem) = *reinterpret_cast<const Signal *>(p_variant._data._mem); } break; case STRING_NAME: { - *reinterpret_cast<StringName *>(_data._mem) = *reinterpret_cast<const StringName *>(p_variant._data._mem); } 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 PACKED_BYTE_ARRAY: { - _data.packed_array = PackedArrayRef<uint8_t>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_INT32_ARRAY: { - _data.packed_array = PackedArrayRef<int32_t>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_INT64_ARRAY: { - _data.packed_array = PackedArrayRef<int64_t>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_FLOAT32_ARRAY: { - _data.packed_array = PackedArrayRef<float>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_FLOAT64_ARRAY: { - _data.packed_array = PackedArrayRef<double>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_STRING_ARRAY: { - _data.packed_array = PackedArrayRef<String>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_VECTOR2_ARRAY: { - _data.packed_array = PackedArrayRef<Vector2>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_VECTOR3_ARRAY: { - _data.packed_array = PackedArrayRef<Vector3>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; case PACKED_COLOR_ARRAY: { - _data.packed_array = PackedArrayRef<Color>::reference_from(_data.packed_array, p_variant._data.packed_array); } break; default: { @@ -3083,77 +2832,56 @@ void Variant::operator=(const Variant &p_variant) { } Variant::Variant(const IP_Address &p_address) { - type = STRING; memnew_placement(_data._mem, String(p_address)); } Variant::Variant(const Variant &p_variant) { - - type = NIL; reference(p_variant); } -/* -Variant::~Variant() { - - clear(); -}*/ - uint32_t Variant::hash() const { - switch (type) { case NIL: { - return 0; } break; case BOOL: { - return _data._bool ? 1 : 0; } break; case INT: { - return _data._int; } break; case FLOAT: { - return hash_djb2_one_float(_data._float); } break; case STRING: { - return reinterpret_cast<const String *>(_data._mem)->hash(); } break; // math types case VECTOR2: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->x); return hash_djb2_one_float(reinterpret_cast<const Vector2 *>(_data._mem)->y, hash); } break; case VECTOR2I: { - uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Vector2i *>(_data._mem)->x); return hash_djb2_one_32(reinterpret_cast<const Vector2i *>(_data._mem)->y, hash); } break; case RECT2: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.x); hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->position.y, hash); hash = hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.x, hash); return hash_djb2_one_float(reinterpret_cast<const Rect2 *>(_data._mem)->size.y, hash); } break; case RECT2I: { - uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->position.x); hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->position.y, hash); hash = hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->size.x, hash); return hash_djb2_one_32(reinterpret_cast<const Rect2i *>(_data._mem)->size.y, hash); } break; case TRANSFORM2D: { - uint32_t hash = 5831; for (int i = 0; i < 3; i++) { - for (int j = 0; j < 2; j++) { hash = hash_djb2_one_float(_data._transform2d->elements[i][j], hash); } @@ -3162,35 +2890,25 @@ uint32_t Variant::hash() const { return hash; } break; case VECTOR3: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->x); hash = hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->y, hash); return hash_djb2_one_float(reinterpret_cast<const Vector3 *>(_data._mem)->z, hash); } break; case VECTOR3I: { - uint32_t hash = hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->x); hash = hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->y, hash); return hash_djb2_one_32(reinterpret_cast<const Vector3i *>(_data._mem)->z, hash); } break; case PLANE: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.x); hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.y, hash); hash = hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->normal.z, hash); return hash_djb2_one_float(reinterpret_cast<const Plane *>(_data._mem)->d, hash); } break; - /* - case QUAT: { - - - } break;*/ case AABB: { - uint32_t hash = 5831; for (int i = 0; i < 3; i++) { - hash = hash_djb2_one_float(_data._aabb->position[i], hash); hash = hash_djb2_one_float(_data._aabb->size[i], hash); } @@ -3199,7 +2917,6 @@ uint32_t Variant::hash() const { } break; case QUAT: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->x); hash = hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->y, hash); hash = hash_djb2_one_float(reinterpret_cast<const Quat *>(_data._mem)->z, hash); @@ -3207,10 +2924,8 @@ uint32_t Variant::hash() const { } break; case BASIS: { - uint32_t hash = 5831; for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { hash = hash_djb2_one_float(_data._basis->elements[i][j], hash); } @@ -3220,10 +2935,8 @@ uint32_t Variant::hash() const { } break; case TRANSFORM: { - uint32_t hash = 5831; for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { hash = hash_djb2_one_float(_data._transform->basis.elements[i][j], hash); } @@ -3236,7 +2949,6 @@ uint32_t Variant::hash() const { // misc types case COLOR: { - uint32_t hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->r); hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->g, hash); hash = hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->b, hash); @@ -3244,45 +2956,36 @@ uint32_t Variant::hash() const { } break; case _RID: { - return hash_djb2_one_64(reinterpret_cast<const RID *>(_data._mem)->get_id()); } break; case OBJECT: { - return hash_djb2_one_64(make_uint64_t(_get_obj().obj)); } break; case STRING_NAME: { - return reinterpret_cast<const StringName *>(_data._mem)->hash(); } break; case NODE_PATH: { - return reinterpret_cast<const NodePath *>(_data._mem)->hash(); } break; case DICTIONARY: { - return reinterpret_cast<const Dictionary *>(_data._mem)->hash(); } break; case CALLABLE: { - return reinterpret_cast<const Callable *>(_data._mem)->hash(); } break; case SIGNAL: { - const Signal &s = *reinterpret_cast<const Signal *>(_data._mem); uint32_t hash = s.get_name().hash(); return hash_djb2_one_64(s.get_object_id(), hash); } break; case ARRAY: { - const Array &arr = *reinterpret_cast<const Array *>(_data._mem); return arr.hash(); } break; case PACKED_BYTE_ARRAY: { - const Vector<uint8_t> &arr = PackedArrayRef<uint8_t>::get_array(_data.packed_array); int len = arr.size(); if (likely(len)) { @@ -3294,7 +2997,6 @@ uint32_t Variant::hash() const { } break; case PACKED_INT32_ARRAY: { - const Vector<int32_t> &arr = PackedArrayRef<int32_t>::get_array(_data.packed_array); int len = arr.size(); if (likely(len)) { @@ -3306,7 +3008,6 @@ uint32_t Variant::hash() const { } break; case PACKED_INT64_ARRAY: { - const Vector<int64_t> &arr = PackedArrayRef<int64_t>::get_array(_data.packed_array); int len = arr.size(); if (likely(len)) { @@ -3318,7 +3019,6 @@ uint32_t Variant::hash() const { } break; case PACKED_FLOAT32_ARRAY: { - const Vector<float> &arr = PackedArrayRef<float>::get_array(_data.packed_array); int len = arr.size(); @@ -3331,7 +3031,6 @@ uint32_t Variant::hash() const { } break; case PACKED_FLOAT64_ARRAY: { - const Vector<double> &arr = PackedArrayRef<double>::get_array(_data.packed_array); int len = arr.size(); @@ -3344,7 +3043,6 @@ uint32_t Variant::hash() const { } break; case PACKED_STRING_ARRAY: { - uint32_t hash = 5831; const Vector<String> &arr = PackedArrayRef<String>::get_array(_data.packed_array); int len = arr.size(); @@ -3360,7 +3058,6 @@ uint32_t Variant::hash() const { return hash; } break; case PACKED_VECTOR2_ARRAY: { - uint32_t hash = 5831; const Vector<Vector2> &arr = PackedArrayRef<Vector2>::get_array(_data.packed_array); int len = arr.size(); @@ -3377,7 +3074,6 @@ uint32_t Variant::hash() const { return hash; } break; case PACKED_VECTOR3_ARRAY: { - uint32_t hash = 5831; const Vector<Vector3> &arr = PackedArrayRef<Vector3>::get_array(_data.packed_array); int len = arr.size(); @@ -3395,7 +3091,6 @@ uint32_t Variant::hash() const { return hash; } break; case PACKED_COLOR_ARRAY: { - uint32_t hash = 5831; const Vector<Color> &arr = PackedArrayRef<Color>::get_array(_data.packed_array); int len = arr.size(); @@ -3462,8 +3157,9 @@ uint32_t Variant::hash() const { return true bool Variant::hash_compare(const Variant &p_variant) const { - if (type != p_variant.type) + if (type != p_variant.type) { return false; + } switch (type) { case FLOAT: { @@ -3501,8 +3197,9 @@ bool Variant::hash_compare(const Variant &p_variant) const { Transform2D *r = p_variant._data._transform2d; for (int i = 0; i < 3; i++) { - if (!(hash_compare_vector2(l->elements[i], r->elements[i]))) + if (!(hash_compare_vector2(l->elements[i], r->elements[i]))) { return false; + } } return true; @@ -3550,8 +3247,9 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Basis *r = p_variant._data._basis; for (int i = 0; i < 3; i++) { - if (!(hash_compare_vector3(l->elements[i], r->elements[i]))) + if (!(hash_compare_vector3(l->elements[i], r->elements[i]))) { return false; + } } return true; @@ -3562,8 +3260,9 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Transform *r = p_variant._data._transform; for (int i = 0; i < 3; i++) { - if (!(hash_compare_vector3(l->basis.elements[i], r->basis.elements[i]))) + if (!(hash_compare_vector3(l->basis.elements[i], r->basis.elements[i]))) { return false; + } } return hash_compare_vector3(l->origin, r->origin); @@ -3580,12 +3279,14 @@ bool Variant::hash_compare(const Variant &p_variant) const { const Array &l = *(reinterpret_cast<const Array *>(_data._mem)); const Array &r = *(reinterpret_cast<const Array *>(p_variant._data._mem)); - if (l.size() != r.size()) + if (l.size() != r.size()) { return false; + } for (int i = 0; i < l.size(); ++i) { - if (!l[i].hash_compare(r[i])) + if (!l[i].hash_compare(r[i])) { return false; + } } return true; @@ -3623,38 +3324,35 @@ bool Variant::hash_compare(const Variant &p_variant) const { } bool Variant::is_ref() const { - return type == OBJECT && _get_obj().id.is_reference(); } Vector<Variant> varray() { - return Vector<Variant>(); } Vector<Variant> varray(const Variant &p_arg1) { - Vector<Variant> v; v.push_back(p_arg1); return v; } -Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2) { +Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2) { Vector<Variant> v; v.push_back(p_arg1); v.push_back(p_arg2); return v; } -Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3) { +Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3) { Vector<Variant> v; v.push_back(p_arg1); v.push_back(p_arg2); v.push_back(p_arg3); return v; } -Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4) { +Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4) { Vector<Variant> v; v.push_back(p_arg1); v.push_back(p_arg2); @@ -3664,7 +3362,6 @@ Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Varia } Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5) { - Vector<Variant> v; v.push_back(p_arg1); v.push_back(p_arg2); @@ -3678,12 +3375,13 @@ void Variant::static_assign(const Variant &p_variant) { } bool Variant::is_shared() const { - switch (type) { - - case OBJECT: return true; - case ARRAY: return true; - case DICTIONARY: return true; + case OBJECT: + return true; + case ARRAY: + return true; + case DICTIONARY: + return true; default: { } } @@ -3695,8 +3393,9 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { VARIANT_ARGPTRS; int argc = 0; for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) + if (argptr[i]->get_type() == Variant::NIL) { break; + } argc++; } @@ -3705,20 +3404,16 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { Variant ret = call(p_method, argptr, argc, error); switch (error.error) { - case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { - String err = "Invalid type for argument #" + itos(error.argument) + ", expected '" + Variant::get_type_name(Variant::Type(error.expected)) + "'."; ERR_PRINT(err.utf8().get_data()); } break; case Callable::CallError::CALL_ERROR_INVALID_METHOD: { - String err = "Invalid method '" + p_method + "' for type '" + Variant::get_type_name(type) + "'."; ERR_PRINT(err.utf8().get_data()); } break; case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: { - String err = "Too many arguments for method '" + p_method + "'"; ERR_PRINT(err.utf8().get_data()); } break; @@ -3730,12 +3425,10 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { } void Variant::construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct, void *p_construct_ud) { - r_value = Variant(); } String Variant::get_construct_string() const { - String vars; VariantWriter::write_to_string(*this, vars); @@ -3743,7 +3436,6 @@ String Variant::get_construct_string() const { } String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { - String err_text; if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { @@ -3768,14 +3460,12 @@ String Variant::get_call_error_text(Object *p_base, const StringName &p_method, String class_name = p_base->get_class(); Ref<Script> script = p_base->get_script(); if (script.is_valid() && script->get_path().is_resource_file()) { - class_name += "(" + script->get_path().get_file() + ")"; } return "'" + class_name + "::" + String(p_method) + "': " + err_text; } String Variant::get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { - String err_text; if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { @@ -3801,26 +3491,20 @@ String Variant::get_callable_error_text(const Callable &p_callable, const Varian } String vformat(const String &p_text, const Variant &p1, const Variant &p2, const Variant &p3, const Variant &p4, const Variant &p5) { - Array args; if (p1.get_type() != Variant::NIL) { - args.push_back(p1); if (p2.get_type() != Variant::NIL) { - args.push_back(p2); if (p3.get_type() != Variant::NIL) { - args.push_back(p3); if (p4.get_type() != Variant::NIL) { - args.push_back(p4); if (p5.get_type() != Variant::NIL) { - args.push_back(p5); } } diff --git a/core/variant.h b/core/variant.h index a832f7ccf8..50b7a21eda 100644 --- a/core/variant.h +++ b/core/variant.h @@ -67,13 +67,6 @@ typedef Vector<Vector2> PackedVector2Array; typedef Vector<Vector3> PackedVector3Array; typedef Vector<Color> PackedColorArray; -// Temporary workaround until c++11 alignas() -#ifdef __GNUC__ -#define GCC_ALIGNED_8 __attribute__((aligned(8))) -#else -#define GCC_ALIGNED_8 -#endif - class Variant { public: // If this changes the table in variant_op must be updated @@ -130,10 +123,9 @@ private: // Variant takes 20 bytes when real_t is float, and 36 if double // it only allocates extra memory for aabb/matrix. - Type type; + Type type = NIL; struct ObjData { - ObjectID id; Object *obj; }; @@ -211,7 +203,7 @@ private: PackedArrayRefBase *packed_array; void *_ptr; //generic pointer uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]; - } _data GCC_ALIGNED_8; + } _data alignas(8); void reference(const Variant &p_variant); void clear(); @@ -227,10 +219,10 @@ public: bool is_ref() const; _FORCE_INLINE_ bool is_num() const { return type == INT || type == FLOAT; - }; + } _FORCE_INLINE_ bool is_array() const { return type >= ARRAY; - }; + } bool is_shared() const; bool is_zero() const; bool is_one() const; @@ -410,7 +402,6 @@ public: static String get_operator_name(Operator p_op); static void evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid); static _FORCE_INLINE_ Variant evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b) { - bool valid = true; Variant res; evaluate(p_op, p_a, p_b, res, valid); @@ -476,12 +467,13 @@ public: static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr); void operator=(const Variant &p_variant); // only this is enough for all the other types + Variant(const Variant &p_variant); - _FORCE_INLINE_ Variant() { - type = NIL; - } + _FORCE_INLINE_ Variant() {} _FORCE_INLINE_ ~Variant() { - if (type != Variant::NIL) clear(); + if (type != Variant::NIL) { + clear(); + } } }; @@ -496,22 +488,18 @@ Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Varia Vector<Variant> varray(const Variant &p_arg1, const Variant &p_arg2, const Variant &p_arg3, const Variant &p_arg4, const Variant &p_arg5); struct VariantHasher { - static _FORCE_INLINE_ uint32_t hash(const Variant &p_variant) { return p_variant.hash(); } }; struct VariantComparator { - static _FORCE_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) { return p_lhs.hash_compare(p_rhs); } }; Variant::ObjData &Variant::_get_obj() { - return *reinterpret_cast<ObjData *>(&_data._mem[0]); } const Variant::ObjData &Variant::_get_obj() const { - return *reinterpret_cast<const ObjData *>(&_data._mem[0]); } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 391c293810..a8beac1e44 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -42,14 +42,11 @@ typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_a typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); struct _VariantCall { - static void Vector3_dot(Variant &r_ret, Variant &p_self, const Variant **p_args) { - r_ret = reinterpret_cast<Vector3 *>(p_self._data._mem)->dot(*reinterpret_cast<const Vector3 *>(p_args[0]->_data._mem)); } struct FuncData { - int arg_count; Vector<Variant> default_args; Vector<Variant::Type> arg_types; @@ -62,16 +59,16 @@ struct _VariantCall { VariantFunc func; _FORCE_INLINE_ bool verify_arguments(const Variant **p_args, Callable::CallError &r_error) { - - if (arg_count == 0) + if (arg_count == 0) { return true; + } const Variant::Type *tptr = &arg_types[0]; for (int i = 0; i < arg_count; i++) { - - if (tptr[i] == Variant::NIL || tptr[i] == p_args[i]->type) + if (tptr[i] == Variant::NIL || tptr[i] == p_args[i]->type) { continue; // all good + } if (!Variant::can_convert(p_args[i]->type, tptr[i])) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = i; @@ -102,21 +99,25 @@ struct _VariantCall { #endif ERR_FAIL_COND(p_argcount > VARIANT_ARG_MAX); const Variant *newargs[VARIANT_ARG_MAX]; - for (int i = 0; i < p_argcount; i++) + for (int i = 0; i < p_argcount; i++) { newargs[i] = p_args[i]; + } // fill in any remaining parameters with defaults int first_default_arg = arg_count - def_argcount; - for (int i = p_argcount; i < arg_count; i++) + for (int i = p_argcount; i < arg_count; i++) { newargs[i] = &default_args[i - first_default_arg]; + } #ifdef DEBUG_ENABLED - if (!verify_arguments(newargs, r_error)) + if (!verify_arguments(newargs, r_error)) { return; + } #endif func(r_ret, p_self, newargs); } else { #ifdef DEBUG_ENABLED - if (!verify_arguments(p_args, r_error)) + if (!verify_arguments(p_args, r_error)) { return; + } #endif func(r_ret, p_self, p_args); } @@ -124,7 +125,6 @@ struct _VariantCall { }; struct TypeFunc { - Map<StringName, FuncData> functions; }; @@ -143,14 +143,12 @@ struct _VariantCall { //void addfunc(Variant::Type p_type, const StringName& p_name,VariantFunc p_func); static void make_func_return_variant(Variant::Type p_type, const StringName &p_name) { - #ifdef DEBUG_ENABLED type_funcs[p_type].functions[p_name].returns = true; #endif } 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; @@ -164,8 +162,9 @@ struct _VariantCall { funcdata.arg_names.push_back(p_argtype1.name); #endif - } else + } else { goto end; + } if (p_argtype2.name) { funcdata.arg_types.push_back(p_argtype2.type); @@ -173,8 +172,9 @@ struct _VariantCall { funcdata.arg_names.push_back(p_argtype2.name); #endif - } else + } else { goto end; + } if (p_argtype3.name) { funcdata.arg_types.push_back(p_argtype3.type); @@ -182,24 +182,27 @@ struct _VariantCall { funcdata.arg_names.push_back(p_argtype3.name); #endif - } else + } else { goto end; + } if (p_argtype4.name) { funcdata.arg_types.push_back(p_argtype4.type); #ifdef DEBUG_ENABLED funcdata.arg_names.push_back(p_argtype4.name); #endif - } else + } else { goto end; + } if (p_argtype5.name) { funcdata.arg_types.push_back(p_argtype5.type); #ifdef DEBUG_ENABLED funcdata.arg_names.push_back(p_argtype5.name); #endif - } else + } else { goto end; + } end: @@ -262,6 +265,7 @@ struct _VariantCall { VCALL_LOCALMEM3R(String, split); VCALL_LOCALMEM3R(String, rsplit); VCALL_LOCALMEM2R(String, split_floats); + VCALL_LOCALMEM1R(String, join); VCALL_LOCALMEM0R(String, to_upper); VCALL_LOCALMEM0R(String, to_lower); VCALL_LOCALMEM1R(String, left); @@ -314,7 +318,6 @@ struct _VariantCall { VCALL_LOCALMEM1R(String, trim_suffix); static void _call_String_to_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { - String *s = reinterpret_cast<String *>(p_self._data._mem); if (s->empty()) { r_ret = PackedByteArray(); @@ -332,7 +335,6 @@ struct _VariantCall { } static void _call_String_to_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { - String *s = reinterpret_cast<String *>(p_self._data._mem); if (s->empty()) { r_ret = PackedByteArray(); @@ -362,7 +364,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(Vector2, angle_to); VCALL_LOCALMEM1R(Vector2, angle_to_point); VCALL_LOCALMEM1R(Vector2, direction_to); - VCALL_LOCALMEM2R(Vector2, linear_interpolate); + VCALL_LOCALMEM2R(Vector2, lerp); VCALL_LOCALMEM2R(Vector2, slerp); VCALL_LOCALMEM4R(Vector2, cubic_interpolate); VCALL_LOCALMEM2R(Vector2, move_toward); @@ -426,7 +428,7 @@ struct _VariantCall { VCALL_LOCALMEM0R(Vector3, inverse); VCALL_LOCALMEM1R(Vector3, snapped); VCALL_LOCALMEM2R(Vector3, rotated); - VCALL_LOCALMEM2R(Vector3, linear_interpolate); + VCALL_LOCALMEM2R(Vector3, lerp); VCALL_LOCALMEM2R(Vector3, slerp); VCALL_LOCALMEM4R(Vector3, cubic_interpolate); VCALL_LOCALMEM2R(Vector3, move_toward); @@ -464,26 +466,29 @@ struct _VariantCall { //return vector3 if intersected, nil if not static void _call_Plane_intersect_3(Variant &r_ret, Variant &p_self, const Variant **p_args) { Vector3 result; - if (reinterpret_cast<Plane *>(p_self._data._mem)->intersect_3(*p_args[0], *p_args[1], &result)) + if (reinterpret_cast<Plane *>(p_self._data._mem)->intersect_3(*p_args[0], *p_args[1], &result)) { r_ret = result; - else + } else { r_ret = Variant(); + } } static void _call_Plane_intersects_ray(Variant &r_ret, Variant &p_self, const Variant **p_args) { Vector3 result; - if (reinterpret_cast<Plane *>(p_self._data._mem)->intersects_ray(*p_args[0], *p_args[1], &result)) + if (reinterpret_cast<Plane *>(p_self._data._mem)->intersects_ray(*p_args[0], *p_args[1], &result)) { r_ret = result; - else + } else { r_ret = Variant(); + } } static void _call_Plane_intersects_segment(Variant &r_ret, Variant &p_self, const Variant **p_args) { Vector3 result; - if (reinterpret_cast<Plane *>(p_self._data._mem)->intersects_segment(*p_args[0], *p_args[1], &result)) + if (reinterpret_cast<Plane *>(p_self._data._mem)->intersects_segment(*p_args[0], *p_args[1], &result)) { r_ret = result; - else + } else { r_ret = Variant(); + } } VCALL_LOCALMEM0R(Quat, length); @@ -509,7 +514,7 @@ struct _VariantCall { VCALL_LOCALMEM0R(Color, to_rgba64); VCALL_LOCALMEM0R(Color, inverted); VCALL_LOCALMEM0R(Color, contrasted); - VCALL_LOCALMEM2R(Color, linear_interpolate); + VCALL_LOCALMEM2R(Color, lerp); VCALL_LOCALMEM1R(Color, blend); VCALL_LOCALMEM1R(Color, lightened); VCALL_LOCALMEM1R(Color, darkened); @@ -591,7 +596,6 @@ struct _VariantCall { VCALL_LOCALMEM0R(Array, min); static void _call_PackedByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); String s; if (ba->size() > 0) { @@ -607,7 +611,6 @@ struct _VariantCall { } static void _call_PackedByteArray_get_string_from_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); String s; if (ba->size() > 0) { @@ -618,7 +621,6 @@ struct _VariantCall { } static void _call_PackedByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); PackedByteArray compressed; if (ba->size() > 0) { @@ -634,7 +636,6 @@ struct _VariantCall { } static void _call_PackedByteArray_decompress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); PackedByteArray decompressed; Compression::Mode mode = (Compression::Mode)(int)(*p_args[1]); @@ -860,42 +861,58 @@ struct _VariantCall { VCALL_PTR1R(Transform2D, is_equal_approx); static void _call_Transform2D_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); return; - case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); return; - case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); return; - default: r_ret = Variant(); + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); + return; + case Variant::RECT2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); + return; + case Variant::PACKED_VECTOR2_ARRAY: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); + return; + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); } } static void _call_Transform2D_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); return; - case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); return; - case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); return; - default: r_ret = Variant(); + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); + return; + case Variant::RECT2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); + return; + case Variant::PACKED_VECTOR2_ARRAY: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); + return; + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); } } static void _call_Transform2D_basis_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform(p_args[0]->operator Vector2()); return; - default: r_ret = Variant(); + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform(p_args[0]->operator Vector2()); + return; + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'basis_xform' in base 'Transform2D'. Only Vector2 is valid."); } } static void _call_Transform2D_basis_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform_inv(p_args[0]->operator Vector2()); return; - default: r_ret = Variant(); + case Variant::VECTOR2: + r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform_inv(p_args[0]->operator Vector2()); + return; + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'basis_xform_inv' in base 'Transform2D'. Only Vector2 is valid."); } } @@ -906,6 +923,18 @@ struct _VariantCall { VCALL_PTR1R(Basis, scaled); VCALL_PTR0R(Basis, get_scale); VCALL_PTR0R(Basis, get_euler); + VCALL_PTR0R(Basis, get_euler_xyz); + VCALL_PTR1(Basis, set_euler_xyz); + VCALL_PTR0R(Basis, get_euler_xzy); + VCALL_PTR1(Basis, set_euler_xzy); + VCALL_PTR0R(Basis, get_euler_yzx); + VCALL_PTR1(Basis, set_euler_yzx); + VCALL_PTR0R(Basis, get_euler_yxz); + VCALL_PTR1(Basis, set_euler_yxz); + VCALL_PTR0R(Basis, get_euler_zxy); + VCALL_PTR1(Basis, set_euler_zxy); + VCALL_PTR0R(Basis, get_euler_zyx); + VCALL_PTR1(Basis, set_euler_zyx); VCALL_PTR1R(Basis, tdotx); VCALL_PTR1R(Basis, tdoty); VCALL_PTR1R(Basis, tdotz); @@ -928,39 +957,46 @@ struct _VariantCall { VCALL_PTR1R(Transform, is_equal_approx); static void _call_Transform_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - - case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); return; - case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); return; - case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); return; - case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); return; - default: r_ret = Variant(); + case Variant::VECTOR3: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); + return; + case Variant::PLANE: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); + return; + case Variant::AABB: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); + return; + case Variant::PACKED_VECTOR3_ARRAY: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); + return; + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); } } static void _call_Transform_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - - case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); return; - case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); return; - case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); return; - case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); return; - default: r_ret = Variant(); + case Variant::VECTOR3: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); + return; + case Variant::PLANE: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); + return; + case Variant::AABB: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); + return; + case Variant::PACKED_VECTOR3_ARRAY: + r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); + return; + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); } } - /* - VCALL_PTR0( Transform, invert ); - VCALL_PTR0( Transform, affine_invert ); - VCALL_PTR2( Transform, rotate ); - VCALL_PTR1( Transform, scale ); - VCALL_PTR1( Transform, translate ); - VCALL_PTR0( Transform, orthonormalize ); */ - struct ConstructData { - int arg_count; Vector<Variant::Type> arg_types; Vector<String> arg_names; @@ -968,50 +1004,41 @@ struct _VariantCall { }; struct ConstructFunc { - List<ConstructData> constructors; }; static ConstructFunc *construct_funcs; static void Vector2_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector2(*p_args[0], *p_args[1]); } static void Vector2i_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector2i(*p_args[0], *p_args[1]); } static void Rect2_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2(*p_args[0], *p_args[1]); } static void Rect2_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } static void Rect2i_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2i(*p_args[0], *p_args[1]); } static void Rect2i_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2i(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } static void Transform2D_init2(Variant &r_ret, const Variant **p_args) { - Transform2D m(*p_args[0], *p_args[1]); r_ret = m; } static void Transform2D_init3(Variant &r_ret, const Variant **p_args) { - Transform2D m; m[0] = *p_args[0]; m[1] = *p_args[1]; @@ -1020,76 +1047,65 @@ struct _VariantCall { } static void Vector3_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector3(*p_args[0], *p_args[1], *p_args[2]); } static void Vector3i_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector3i(*p_args[0], *p_args[1], *p_args[2]); } static void Plane_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } static void Plane_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(*p_args[0], *p_args[1], *p_args[2]); } static void Plane_init3(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator real_t()); } static void Plane_init4(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator Vector3()); } static void Quat_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Quat(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } static void Quat_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Quat(((Vector3)(*p_args[0])), ((real_t)(*p_args[1]))); } static void Quat_init3(Variant &r_ret, const Variant **p_args) { - r_ret = Quat(((Vector3)(*p_args[0]))); } static void Color_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Color(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } static void Color_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Color(*p_args[0], *p_args[1], *p_args[2]); } static void Color_init3(Variant &r_ret, const Variant **p_args) { - r_ret = Color::html(*p_args[0]); } static void Color_init4(Variant &r_ret, const Variant **p_args) { - r_ret = Color::hex(*p_args[0]); } - static void AABB_init1(Variant &r_ret, const Variant **p_args) { + static void Color_init5(Variant &r_ret, const Variant **p_args) { + r_ret = Color(((Color)(*p_args[0])), *p_args[1]); + } + static void AABB_init1(Variant &r_ret, const Variant **p_args) { r_ret = ::AABB(*p_args[0], *p_args[1]); } static void Basis_init1(Variant &r_ret, const Variant **p_args) { - Basis m; m.set_axis(0, *p_args[0]); m.set_axis(1, *p_args[1]); @@ -1098,12 +1114,10 @@ struct _VariantCall { } static void Basis_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Basis(p_args[0]->operator Vector3(), p_args[1]->operator real_t()); } static void Transform_init1(Variant &r_ret, const Variant **p_args) { - Transform t; t.basis.set_axis(0, *p_args[0]); t.basis.set_axis(1, *p_args[1]); @@ -1113,17 +1127,14 @@ struct _VariantCall { } static void Transform_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Transform(p_args[0]->operator Basis(), p_args[1]->operator Vector3()); } static void Callable_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Callable(p_args[0]->operator ObjectID(), p_args[1]->operator String()); } static void Signal_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Signal(p_args[0]->operator ObjectID(), p_args[1]->operator String()); } @@ -1132,31 +1143,34 @@ struct _VariantCall { const String &p_name2 = "", const Variant::Type p_type2 = Variant::NIL, const String &p_name3 = "", const Variant::Type p_type3 = Variant::NIL, const String &p_name4 = "", const Variant::Type p_type4 = Variant::NIL) { - ConstructData cd; cd.func = p_func; cd.arg_count = 0; - if (p_name1 == "") + if (p_name1 == "") { goto end; + } cd.arg_count++; cd.arg_names.push_back(p_name1); cd.arg_types.push_back(p_type1); - if (p_name2 == "") + if (p_name2 == "") { goto end; + } cd.arg_count++; cd.arg_names.push_back(p_name2); cd.arg_types.push_back(p_type2); - if (p_name3 == "") + if (p_name3 == "") { goto end; + } cd.arg_count++; cd.arg_names.push_back(p_name3); cd.arg_types.push_back(p_type3); - if (p_name4 == "") + if (p_name4 == "") { goto end; + } cd.arg_count++; cd.arg_names.push_back(p_name4); cd.arg_types.push_back(p_type4); @@ -1167,18 +1181,19 @@ struct _VariantCall { } struct ConstantData { - Map<StringName, int> value; #ifdef DEBUG_ENABLED List<StringName> value_ordered; #endif Map<StringName, Variant> variant_value; +#ifdef DEBUG_ENABLED + List<StringName> variant_value_ordered; +#endif }; static ConstantData *constant_data; static void add_constant(int p_type, StringName p_constant_name, int p_constant_value) { - constant_data[p_type].value[p_constant_name] = p_constant_value; #ifdef DEBUG_ENABLED constant_data[p_type].value_ordered.push_back(p_constant_name); @@ -1186,8 +1201,10 @@ struct _VariantCall { } static void add_variant_constant(int p_type, StringName p_constant_name, const Variant &p_constant_value) { - constant_data[p_type].variant_value[p_constant_name] = p_constant_value; +#ifdef DEBUG_ENABLED + constant_data[p_type].variant_value_ordered.push_back(p_constant_name); +#endif } }; @@ -1196,7 +1213,6 @@ _VariantCall::ConstructFunc *_VariantCall::construct_funcs = nullptr; _VariantCall::ConstantData *_VariantCall::constant_data = nullptr; Variant Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - Variant ret; call_ptr(p_method, p_args, p_argcount, &ret, r_error); return ret; @@ -1224,13 +1240,11 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p //else if (type==Variant::METHOD) { } else { - r_error.error = Callable::CallError::CALL_OK; Map<StringName, _VariantCall::FuncData>::Element *E = _VariantCall::type_funcs[type].functions.find(p_method); if (E) { - _VariantCall::FuncData &funcdata = E->get(); funcdata.call(ret, *this, p_args, p_argcount, r_error); @@ -1239,7 +1253,6 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p bool valid = false; if (type == CALLABLE) { if (p_method == CoreStringNames::get_singleton()->call) { - reinterpret_cast<const Callable *>(_data._mem)->call(p_args, p_argcount, ret, r_error); valid = true; } @@ -1264,14 +1277,14 @@ void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p } } - if (r_error.error == Callable::CallError::CALL_OK && r_ret) + if (r_error.error == Callable::CallError::CALL_OK && r_ret) { *r_ret = ret; + } } #define VCALL(m_type, m_method) _VariantCall::_call_##m_type##_##m_method Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, Variant()); @@ -1283,50 +1296,80 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i return Variant(); // atomic types - case BOOL: return Variant(false); - case INT: return 0; - case FLOAT: return 0.0f; + case BOOL: + return Variant(false); + case INT: + return 0; + case FLOAT: + return 0.0f; case STRING: return String(); // math types case VECTOR2: return Vector2(); - case RECT2: return Rect2(); - case VECTOR3: return Vector3(); - case TRANSFORM2D: return Transform2D(); - case PLANE: return Plane(); - case QUAT: return Quat(); + case VECTOR2I: + return Vector2i(); + case RECT2: + return Rect2(); + case RECT2I: + return Rect2i(); + case VECTOR3: + return Vector3(); + case VECTOR3I: + return Vector3i(); + case TRANSFORM2D: + return Transform2D(); + case PLANE: + return Plane(); + case QUAT: + return Quat(); case AABB: return ::AABB(); - case BASIS: return Basis(); + case BASIS: + return Basis(); case TRANSFORM: return Transform(); // misc types - case COLOR: return Color(); + case COLOR: + return Color(); case STRING_NAME: return StringName(); case NODE_PATH: return NodePath(); - case _RID: return RID(); - case OBJECT: return (Object *)nullptr; - case CALLABLE: return Callable(); - case SIGNAL: return Signal(); - case DICTIONARY: return Dictionary(); + case _RID: + return RID(); + case OBJECT: + return (Object *)nullptr; + case CALLABLE: + return Callable(); + case SIGNAL: + return Signal(); + case DICTIONARY: + return Dictionary(); case ARRAY: return Array(); - case PACKED_BYTE_ARRAY: return PackedByteArray(); - case PACKED_INT32_ARRAY: return PackedInt32Array(); - case PACKED_INT64_ARRAY: return PackedInt64Array(); - case PACKED_FLOAT32_ARRAY: return PackedFloat32Array(); - case PACKED_FLOAT64_ARRAY: return PackedFloat64Array(); - case PACKED_STRING_ARRAY: return PackedStringArray(); + case PACKED_BYTE_ARRAY: + return PackedByteArray(); + case PACKED_INT32_ARRAY: + return PackedInt32Array(); + case PACKED_INT64_ARRAY: + return PackedInt64Array(); + case PACKED_FLOAT32_ARRAY: + return PackedFloat32Array(); + case PACKED_FLOAT64_ARRAY: + return PackedFloat64Array(); + case PACKED_STRING_ARRAY: + return PackedStringArray(); case PACKED_VECTOR2_ARRAY: return PackedVector2Array(); - case PACKED_VECTOR3_ARRAY: return PackedVector3Array(); - case PACKED_COLOR_ARRAY: return PackedColorArray(); - default: return Variant(); + case PACKED_VECTOR3_ARRAY: + return PackedVector3Array(); + case PACKED_COLOR_ARRAY: + return PackedColorArray(); + default: + return Variant(); } } else if (p_argcount == 1 && p_args[0]->type == p_type) { @@ -1336,7 +1379,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i switch (p_type) { case NIL: { - return Variant(); } break; case BOOL: { @@ -1357,54 +1399,78 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i case VECTOR2I: { return Vector2i(*p_args[0]); } - case RECT2: return (Rect2(*p_args[0])); - case RECT2I: return (Rect2i(*p_args[0])); - case VECTOR3: return (Vector3(*p_args[0])); - case VECTOR3I: return (Vector3i(*p_args[0])); - case PLANE: return (Plane(*p_args[0])); - case QUAT: return (p_args[0]->operator Quat()); + case RECT2: + return (Rect2(*p_args[0])); + case RECT2I: + return (Rect2i(*p_args[0])); + case VECTOR3: + return (Vector3(*p_args[0])); + case VECTOR3I: + return (Vector3i(*p_args[0])); + case TRANSFORM2D: + return (Transform2D(p_args[0]->operator Transform2D())); + case PLANE: + return (Plane(*p_args[0])); + case QUAT: + return (p_args[0]->operator Quat()); case AABB: return (::AABB(*p_args[0])); - case BASIS: return (Basis(p_args[0]->operator Basis())); + case BASIS: + return (Basis(p_args[0]->operator Basis())); case TRANSFORM: return (Transform(p_args[0]->operator Transform())); // misc types - case COLOR: return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]); + case COLOR: + return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]); case STRING_NAME: return (StringName(p_args[0]->operator StringName())); case NODE_PATH: return (NodePath(p_args[0]->operator NodePath())); - case _RID: return (RID(*p_args[0])); - case OBJECT: return ((Object *)(p_args[0]->operator Object *())); - case CALLABLE: return ((Callable)(p_args[0]->operator Callable())); - case SIGNAL: return ((Signal)(p_args[0]->operator Signal())); - case DICTIONARY: return p_args[0]->operator Dictionary(); + case _RID: + return (RID(*p_args[0])); + case OBJECT: + return ((Object *)(p_args[0]->operator Object *())); + case CALLABLE: + return ((Callable)(p_args[0]->operator Callable())); + case SIGNAL: + return ((Signal)(p_args[0]->operator Signal())); + case DICTIONARY: + return p_args[0]->operator Dictionary(); case ARRAY: return p_args[0]->operator Array(); // arrays - case PACKED_BYTE_ARRAY: return (PackedByteArray(*p_args[0])); - case PACKED_INT32_ARRAY: return (PackedInt32Array(*p_args[0])); - case PACKED_INT64_ARRAY: return (PackedInt64Array(*p_args[0])); - case PACKED_FLOAT32_ARRAY: return (PackedFloat32Array(*p_args[0])); - case PACKED_FLOAT64_ARRAY: return (PackedFloat64Array(*p_args[0])); - case PACKED_STRING_ARRAY: return (PackedStringArray(*p_args[0])); + case PACKED_BYTE_ARRAY: + return (PackedByteArray(*p_args[0])); + case PACKED_INT32_ARRAY: + return (PackedInt32Array(*p_args[0])); + case PACKED_INT64_ARRAY: + return (PackedInt64Array(*p_args[0])); + case PACKED_FLOAT32_ARRAY: + return (PackedFloat32Array(*p_args[0])); + case PACKED_FLOAT64_ARRAY: + return (PackedFloat64Array(*p_args[0])); + case PACKED_STRING_ARRAY: + return (PackedStringArray(*p_args[0])); case PACKED_VECTOR2_ARRAY: return (PackedVector2Array(*p_args[0])); - case PACKED_VECTOR3_ARRAY: return (PackedVector3Array(*p_args[0])); - case PACKED_COLOR_ARRAY: return (PackedColorArray(*p_args[0])); - default: return Variant(); + case PACKED_VECTOR3_ARRAY: + return (PackedVector3Array(*p_args[0])); + case PACKED_COLOR_ARRAY: + return (PackedColorArray(*p_args[0])); + default: + return Variant(); } } else if (p_argcount >= 1) { - _VariantCall::ConstructFunc &c = _VariantCall::construct_funcs[p_type]; for (List<_VariantCall::ConstructData>::Element *E = c.constructors.front(); E; E = E->next()) { const _VariantCall::ConstructData &cd = E->get(); - if (cd.arg_count != p_argcount) + if (cd.arg_count != p_argcount) { continue; + } //validate parameters for (int i = 0; i < cd.arg_count; i++) { @@ -1426,11 +1492,11 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i } bool Variant::has_method(const StringName &p_method) const { - if (type == OBJECT) { Object *obj = get_validated_object(); - if (!obj) + if (!obj) { return false; + } return obj->has_method(p_method); } @@ -1440,69 +1506,68 @@ bool Variant::has_method(const StringName &p_method) const { } Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) + if (!E) { return Vector<Variant::Type>(); + } return E->get().arg_types; } bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) + 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 &tf = _VariantCall::type_funcs[p_type]; const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) + if (!E) { return Vector<StringName>(); + } return E->get().arg_names; } Variant::Type Variant::get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) + if (!E) { return Variant::NIL; + } - if (r_has_return) + if (r_has_return) { *r_has_return = E->get().returns; + } return E->get().return_type; } Vector<Variant> Variant::get_method_default_arguments(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) + if (!E) { return Vector<Variant>(); + } return E->get().default_args; } void Variant::get_method_list(List<MethodInfo> *p_list) const { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type]; for (const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.front(); E; E = E->next()) { - const _VariantCall::FuncData &fd = E->get(); MethodInfo mi; @@ -1513,7 +1578,6 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { } for (int i = 0; i < fd.arg_types.size(); i++) { - PropertyInfo pi; pi.type = fd.arg_types[i]; #ifdef DEBUG_ENABLED @@ -1528,8 +1592,9 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { ret.type = fd.return_type; if (fd.returns) { ret.name = "ret"; - if (fd.return_type == Variant::NIL) + if (fd.return_type == Variant::NIL) { ret.usage = PROPERTY_USAGE_NIL_IS_VARIANT; + } } mi.return_val = ret; #endif @@ -1538,7 +1603,6 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { } if (type == CALLABLE) { - MethodInfo mi; mi.name = "call"; mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT; @@ -1553,7 +1617,6 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { } if (type == SIGNAL) { - MethodInfo mi; mi.name = "emit"; mi.flags |= METHOD_FLAG_VARARG; @@ -1563,18 +1626,15 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const { } void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list) { - ERR_FAIL_INDEX(p_type, VARIANT_MAX); //custom constructors for (const List<_VariantCall::ConstructData>::Element *E = _VariantCall::construct_funcs[p_type].constructors.front(); E; E = E->next()) { - const _VariantCall::ConstructData &cd = E->get(); MethodInfo mi; mi.name = Variant::get_type_name(p_type); mi.return_val.type = p_type; for (int i = 0; i < cd.arg_count; i++) { - PropertyInfo pi; pi.name = cd.arg_names[i]; pi.type = cd.arg_types[i]; @@ -1584,10 +1644,12 @@ void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_lis } //default constructors for (int i = 0; i < VARIANT_MAX; i++) { - if (i == p_type) + if (i == p_type) { continue; - if (!Variant::can_convert(Variant::Type(i), p_type)) + } + if (!Variant::can_convert(Variant::Type(i), p_type)) { continue; + } MethodInfo mi; mi.name = Variant::get_type_name(p_type); @@ -1601,39 +1663,39 @@ void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_lis } void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants) { - ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; #ifdef DEBUG_ENABLED for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) { - p_constants->push_back(E->get()); #else for (Map<StringName, int>::Element *E = cd.value.front(); E; E = E->next()) { - p_constants->push_back(E->key()); #endif } +#ifdef DEBUG_ENABLED + for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) { + p_constants->push_back(E->get()); +#else for (Map<StringName, Variant>::Element *E = cd.variant_value.front(); E; E = E->next()) { - p_constants->push_back(E->key()); +#endif } } bool Variant::has_constant(Variant::Type p_type, const StringName &p_value) { - ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; return cd.value.has(p_value) || cd.variant_value.has(p_value); } Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid) { - - if (r_valid) + if (r_valid) { *r_valid = false; + } ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; @@ -1642,21 +1704,22 @@ Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_va if (!E) { Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value); if (F) { - if (r_valid) + if (r_valid) { *r_valid = true; + } return F->get(); } else { return -1; } } - if (r_valid) + if (r_valid) { *r_valid = true; + } return E->get(); } void register_variant_methods() { - _VariantCall::type_funcs = memnew_arr(_VariantCall::TypeFunc, Variant::VARIANT_MAX); _VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX); @@ -1739,6 +1802,7 @@ void register_variant_methods() { ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, split, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, rsplit, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); ADDFUNC2R(STRING, PACKED_FLOAT32_ARRAY, String, split_floats, STRING, "delimiter", BOOL, "allow_empty", varray(true)); + ADDFUNC1R(STRING, STRING, String, join, PACKED_STRING_ARRAY, "parts", varray()); ADDFUNC0R(STRING, STRING, String, to_upper, varray()); ADDFUNC0R(STRING, STRING, String, to_lower, varray()); @@ -1809,7 +1873,7 @@ void register_variant_methods() { ADDFUNC1R(VECTOR2, VECTOR2, Vector2, posmod, FLOAT, "mod", varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, posmodv, VECTOR2, "modv", varray()); ADDFUNC1R(VECTOR2, VECTOR2, Vector2, project, VECTOR2, "b", varray()); - ADDFUNC2R(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", FLOAT, "t", varray()); + ADDFUNC2R(VECTOR2, VECTOR2, Vector2, lerp, VECTOR2, "b", FLOAT, "t", varray()); ADDFUNC2R(VECTOR2, VECTOR2, Vector2, slerp, VECTOR2, "b", FLOAT, "t", varray()); ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", FLOAT, "t", varray()); ADDFUNC2R(VECTOR2, VECTOR2, Vector2, move_toward, VECTOR2, "to", FLOAT, "delta", varray()); @@ -1874,7 +1938,7 @@ void register_variant_methods() { ADDFUNC0R(VECTOR3, VECTOR3, Vector3, inverse, varray()); ADDFUNC1R(VECTOR3, VECTOR3, Vector3, snapped, VECTOR3, "by", varray()); ADDFUNC2R(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", FLOAT, "phi", varray()); - ADDFUNC2R(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", FLOAT, "t", varray()); + ADDFUNC2R(VECTOR3, VECTOR3, Vector3, lerp, VECTOR3, "b", FLOAT, "t", varray()); ADDFUNC2R(VECTOR3, VECTOR3, Vector3, slerp, VECTOR3, "b", FLOAT, "t", varray()); ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", FLOAT, "t", varray()); ADDFUNC2R(VECTOR3, VECTOR3, Vector3, move_toward, VECTOR3, "to", FLOAT, "delta", varray()); @@ -1933,7 +1997,7 @@ void register_variant_methods() { ADDFUNC0R(COLOR, INT, Color, to_rgba64, varray()); ADDFUNC0R(COLOR, COLOR, Color, inverted, varray()); ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray()); - ADDFUNC2R(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", FLOAT, "t", varray()); + ADDFUNC2R(COLOR, COLOR, Color, lerp, COLOR, "b", FLOAT, "t", varray()); ADDFUNC1R(COLOR, COLOR, Color, blend, COLOR, "over", varray()); ADDFUNC1R(COLOR, COLOR, Color, lightened, FLOAT, "amount", varray()); ADDFUNC1R(COLOR, COLOR, Color, darkened, FLOAT, "amount", varray()); @@ -2217,6 +2281,8 @@ void register_variant_methods() { _VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT, "a", Variant::FLOAT); _VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT); + // init3 and init4 are the constructors for HTML hex strings and integers respectively which don't need binding here, so we skip to init5. + _VariantCall::add_constructor(_VariantCall::Color_init5, Variant::COLOR, "c", Variant::COLOR, "a", Variant::FLOAT); _VariantCall::add_constructor(_VariantCall::AABB_init1, Variant::AABB, "position", Variant::VECTOR3, "size", Variant::VECTOR3); @@ -2314,7 +2380,6 @@ void register_variant_methods() { } void unregister_variant_methods() { - memdelete_arr(_VariantCall::type_funcs); memdelete_arr(_VariantCall::construct_funcs); memdelete_arr(_VariantCall::constant_data); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index f173c88054..2c79e2029e 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -78,43 +78,44 @@ #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, FLOAT), \ - TYPE(PREFIX, OP, STRING), \ - TYPE(PREFIX, OP, VECTOR2), \ - TYPE(PREFIX, OP, VECTOR2I), \ - TYPE(PREFIX, OP, RECT2), \ - TYPE(PREFIX, OP, RECT2I), \ - TYPE(PREFIX, OP, VECTOR3), \ - TYPE(PREFIX, OP, VECTOR3I), \ - TYPE(PREFIX, OP, TRANSFORM2D), \ - TYPE(PREFIX, OP, PLANE), \ - TYPE(PREFIX, OP, QUAT), \ - TYPE(PREFIX, OP, AABB), \ - TYPE(PREFIX, OP, BASIS), \ - TYPE(PREFIX, OP, TRANSFORM), \ - TYPE(PREFIX, OP, COLOR), \ +#define TYPES(PREFIX, OP) { \ + TYPE(PREFIX, OP, NIL), \ + TYPE(PREFIX, OP, BOOL), \ + TYPE(PREFIX, OP, INT), \ + TYPE(PREFIX, OP, FLOAT), \ + TYPE(PREFIX, OP, STRING), \ + TYPE(PREFIX, OP, VECTOR2), \ + TYPE(PREFIX, OP, VECTOR2I), \ + TYPE(PREFIX, OP, RECT2), \ + TYPE(PREFIX, OP, RECT2I), \ + TYPE(PREFIX, OP, VECTOR3), \ + TYPE(PREFIX, OP, VECTOR3I), \ + TYPE(PREFIX, OP, TRANSFORM2D), \ + TYPE(PREFIX, OP, PLANE), \ + TYPE(PREFIX, OP, QUAT), \ + TYPE(PREFIX, OP, AABB), \ + TYPE(PREFIX, OP, BASIS), \ + TYPE(PREFIX, OP, TRANSFORM), \ + TYPE(PREFIX, OP, COLOR), \ TYPE(PREFIX, OP, STRING_NAME), \ - TYPE(PREFIX, OP, NODE_PATH), \ - TYPE(PREFIX, OP, _RID), \ - TYPE(PREFIX, OP, OBJECT), \ + TYPE(PREFIX, OP, NODE_PATH), \ + TYPE(PREFIX, OP, _RID), \ + TYPE(PREFIX, OP, OBJECT), \ TYPE(PREFIX, OP, CALLABLE), \ - TYPE(PREFIX, OP, SIGNAL), \ - TYPE(PREFIX, OP, DICTIONARY), \ - TYPE(PREFIX, OP, ARRAY), \ + TYPE(PREFIX, OP, SIGNAL), \ + TYPE(PREFIX, OP, DICTIONARY), \ + TYPE(PREFIX, OP, ARRAY), \ TYPE(PREFIX, OP, PACKED_BYTE_ARRAY), \ - TYPE(PREFIX, OP, PACKED_INT32_ARRAY), \ - TYPE(PREFIX, OP, PACKED_INT64_ARRAY), \ - TYPE(PREFIX, OP, PACKED_FLOAT32_ARRAY), \ - TYPE(PREFIX, OP, PACKED_FLOAT64_ARRAY), \ + TYPE(PREFIX, OP, PACKED_INT32_ARRAY), \ + TYPE(PREFIX, OP, PACKED_INT64_ARRAY), \ + TYPE(PREFIX, OP, PACKED_FLOAT32_ARRAY), \ + TYPE(PREFIX, OP, PACKED_FLOAT64_ARRAY), \ TYPE(PREFIX, OP, PACKED_STRING_ARRAY), \ TYPE(PREFIX, OP, PACKED_VECTOR2_ARRAY), \ TYPE(PREFIX, OP, PACKED_VECTOR3_ARRAY), \ TYPE(PREFIX, OP, PACKED_COLOR_ARRAY), \ } + /* clang-format on */ #define CASES(PREFIX) static const void *switch_table_##PREFIX[25][Variant::VARIANT_MAX] = { \ @@ -159,7 +160,6 @@ #endif Variant::operator bool() const { - return booleanize(); } @@ -181,22 +181,27 @@ bool Variant::booleanize() const { 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 == FLOAT) _RETURN(p_a._data.m_type m_op p_b._data._float); \ - \ - _RETURN_FAIL \ - }; - -#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 == FLOAT) _RETURN(p_a._data.m_type m_op p_b._data._float); \ - if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - }; +#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 == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + \ + _RETURN_FAIL \ + } + +#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 == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + if (p_b.type == NIL) \ + _RETURN(!(p_b.type m_op NIL)); \ + \ + _RETURN_FAIL \ + } #ifdef DEBUG_ENABLED #define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ @@ -217,84 +222,108 @@ bool Variant::booleanize() const { } \ \ _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 == FLOAT) _RETURN(p_a._data.m_type / p_b._data._float); \ - \ - _RETURN_FAIL \ - }; +#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 == FLOAT) \ + _RETURN(p_a._data.m_type / p_b._data._float); \ + \ + _RETURN_FAIL \ + } #endif #define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \ CASE_TYPE(m_prefix, m_op_name, m_name) { \ _RETURN(-p_a._data.m_type); \ - }; + } #define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \ CASE_TYPE(m_prefix, m_op_name, m_name) { \ _RETURN(p_a._data.m_type); \ - }; - -#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) _RETURN(p_a._data.m_type m_op p_b._data._float); \ - 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)); \ - if (p_b.type == VECTOR2I) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3I) _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 == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const StringName *>(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 == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(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 == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(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_STR_NULL_NP(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_STR_NULL_SN(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 == STRING_NAME) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NIL) _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - }; + } + +#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 == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + 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)); \ + if (p_b.type == VECTOR2I) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ + if (p_b.type == VECTOR3I) \ + _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 == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const StringName *>(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 == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(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 == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(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_STR_NULL_NP(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_STR_NULL_SN(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 == STRING_NAME) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ + if (p_b.type == NIL) \ + _RETURN(!(p_b.type m_op NIL)); \ + \ + _RETURN_FAIL \ + } #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) { \ @@ -302,7 +331,7 @@ bool Variant::booleanize() const { _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) { \ @@ -310,7 +339,7 @@ bool Variant::booleanize() const { _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) { \ @@ -320,7 +349,7 @@ bool Variant::booleanize() const { _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) { \ @@ -332,13 +361,16 @@ bool Variant::booleanize() const { _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ } -#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 == FLOAT) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._float); \ - \ - _RETURN_FAIL \ +#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 == FLOAT) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._float); \ + \ + _RETURN_FAIL \ } #define DEFAULT_OP_PTR(m_op, m_name, m_sub) \ @@ -403,7 +435,6 @@ bool Variant::booleanize() const { if (a_len m_opa array_b.size()) { \ _RETURN(m_ret_s); \ } else { \ - \ const m_type *ra = array_a.ptr(); \ const m_type *rb = array_b.ptr(); \ \ @@ -429,14 +460,14 @@ bool Variant::booleanize() const { 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(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 == NIL) + _RETURN(true); if (p_b.type == OBJECT) _RETURN(p_b._get_obj().obj == nullptr); @@ -532,7 +563,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, 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 == NIL) + _RETURN(false); if (p_b.type == OBJECT) _RETURN(p_b._get_obj().obj != nullptr); @@ -884,10 +916,12 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, int asize = array_a.size(); int bsize = array_b.size(); sum.resize(asize + bsize); - for (int i = 0; i < asize; i++) + for (int i = 0; i < asize; i++) { sum[i] = array_a[i]; - for (int i = 0; i < bsize; i++) + } + for (int i = 0; i < bsize; i++) { sum[i + asize] = array_b[i]; + } _RETURN(sum); } @@ -981,7 +1015,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case VECTOR2: { _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -996,7 +1031,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case FLOAT: { _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._float); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -1008,7 +1044,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case BASIS: { _RETURN(*p_a._data._basis * *p_b._data._basis); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -1020,7 +1057,8 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, case TRANSFORM: { _RETURN(*p_a._data._transform * *p_b._data._transform); } - default: _RETURN_FAIL; + default: + _RETURN_FAIL; } } @@ -1380,7 +1418,6 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, } void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) { - bool valid = false; switch (type) { case VECTOR2: { @@ -1428,7 +1465,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case RECT2: { - if (p_value.type == Variant::VECTOR2) { Rect2 *v = reinterpret_cast<Rect2 *>(_data._mem); //scalar name @@ -1445,7 +1481,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } } break; case RECT2I: { - if (p_value.type == Variant::VECTOR2I) { Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem); //scalar name @@ -1462,7 +1497,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } } break; case TRANSFORM2D: { - if (p_value.type == Variant::VECTOR2) { Transform2D *v = _data._transform2d; if (p_index == CoreStringNames::singleton->x) { @@ -1479,7 +1513,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case VECTOR3: { - if (p_value.type == Variant::INT) { Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { @@ -1508,7 +1541,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case VECTOR3I: { - if (p_value.type == Variant::INT) { Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { @@ -1537,7 +1569,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case PLANE: { - if (p_value.type == Variant::INT) { Plane *v = reinterpret_cast<Plane *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { @@ -1579,7 +1610,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case QUAT: { - if (p_value.type == Variant::INT) { Quat *v = reinterpret_cast<Quat *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { @@ -1614,7 +1644,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case AABB: { - if (p_value.type == Variant::VECTOR3) { ::AABB *v = _data._aabb; //scalar name @@ -1631,7 +1660,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } } break; case BASIS: { - if (p_value.type == Variant::VECTOR3) { Basis *v = _data._basis; //scalar name @@ -1648,7 +1676,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } } break; case TRANSFORM: { - if (p_value.type == Variant::BASIS && p_index == CoreStringNames::singleton->basis) { _data._transform->basis = *p_value._data._basis; valid = true; @@ -1659,7 +1686,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } break; case COLOR: { - if (p_value.type == Variant::INT) { Color *v = reinterpret_cast<Color *>(_data._mem); if (p_index == CoreStringNames::singleton->r) { @@ -1735,7 +1761,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } } break; case OBJECT: { - #ifdef DEBUG_ENABLED if (!_get_obj().obj) { break; @@ -1758,7 +1783,6 @@ void Variant::set_named(const StringName &p_index, const Variant &p_value, bool } Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { - if (r_valid) { *r_valid = true; } @@ -1782,7 +1806,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case RECT2: { - const Rect2 *v = reinterpret_cast<const Rect2 *>(_data._mem); //scalar name if (p_index == CoreStringNames::singleton->position) { @@ -1794,7 +1817,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } } break; case RECT2I: { - const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem); //scalar name if (p_index == CoreStringNames::singleton->position) { @@ -1806,7 +1828,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } } break; case TRANSFORM2D: { - const Transform2D *v = _data._transform2d; if (p_index == CoreStringNames::singleton->x) { return v->elements[0]; @@ -1818,7 +1839,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case VECTOR3: { - const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { return v->x; @@ -1830,7 +1850,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case VECTOR3I: { - const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { return v->x; @@ -1842,7 +1861,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case PLANE: { - const Plane *v = reinterpret_cast<const Plane *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { return v->normal.x; @@ -1858,7 +1876,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case QUAT: { - const Quat *v = reinterpret_cast<const Quat *>(_data._mem); if (p_index == CoreStringNames::singleton->x) { return v->x; @@ -1872,7 +1889,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case AABB: { - const ::AABB *v = _data._aabb; //scalar name if (p_index == CoreStringNames::singleton->position) { @@ -1884,7 +1900,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } } break; case BASIS: { - const Basis *v = _data._basis; //scalar name if (p_index == CoreStringNames::singleton->x) { @@ -1897,7 +1912,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case TRANSFORM: { - if (p_index == CoreStringNames::singleton->basis) { return _data._transform->basis; } else if (p_index == CoreStringNames::singleton->origin) { @@ -1906,7 +1920,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; case COLOR: { - const Color *v = reinterpret_cast<const Color *>(_data._mem); if (p_index == CoreStringNames::singleton->r) { return v->r; @@ -1933,17 +1946,17 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } } break; case OBJECT: { - #ifdef DEBUG_ENABLED if (!_get_obj().obj) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return "Instance base is null."; } else { - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - if (r_valid) + if (r_valid) { *r_valid = false; + } return "Attempted use of stray pointer object."; } } @@ -1983,7 +1996,8 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { #define DEFAULT_OP_DVECTOR_SET(m_name, m_type, skip_cond) \ case m_name: { \ - if (skip_cond) return; \ + if (skip_cond) \ + return; \ \ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ int index = p_index; \ @@ -2000,7 +2014,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { #define DEFAULT_OP_DVECTOR_GET(m_name, m_type) \ case m_name: { \ - \ if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ int index = p_index; \ const Vector<m_type> *arr = &PackedArrayRef<m_type>::get_array(_data.packed_array); \ @@ -2015,7 +2028,6 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { } break; void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) { - static bool _dummy = false; bool &valid = r_valid ? *r_valid : _dummy; @@ -2035,24 +2047,24 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } break; case STRING: { - - if (p_index.type != Variant::INT && p_index.type != Variant::FLOAT) + if (p_index.type != Variant::INT && p_index.type != Variant::FLOAT) { return; + } int idx = p_index; String *str = reinterpret_cast<String *>(_data._mem); int len = str->length(); - if (idx < 0) + if (idx < 0) { idx += len; - if (idx < 0 || idx >= len) + } + if (idx < 0 || idx >= len) { return; + } String chr; if (p_value.type == Variant::INT || p_value.type == Variant::FLOAT) { - chr = String::chr(p_value); } else if (p_value.type == Variant::STRING) { - chr = p_value; } else { return; @@ -2064,18 +2076,18 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case VECTOR2: { - - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { // scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 2; + } if (idx >= 0 && idx < 2) { - Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem); valid = true; (*v)[idx] = p_value; @@ -2099,18 +2111,18 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case VECTOR2I: { - - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { // scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 2; + } if (idx >= 0 && idx < 2) { - Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem); valid = true; (*v)[idx] = p_value; @@ -2134,9 +2146,9 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case RECT2: { - - if (p_value.type != Variant::VECTOR2) + if (p_value.type != Variant::VECTOR2) { return; + } if (p_index.get_type() == Variant::STRING) { //scalar name @@ -2159,9 +2171,9 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } } break; case RECT2I: { - - if (p_value.type != Variant::VECTOR2I) + if (p_value.type != Variant::VECTOR2I) { return; + } if (p_index.get_type() == Variant::STRING) { //scalar name @@ -2184,16 +2196,16 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } } break; case TRANSFORM2D: { - - if (p_value.type != Variant::VECTOR2) + if (p_value.type != Variant::VECTOR2) { return; + } if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) + if (index < 0) { index += 3; + } if (index >= 0 && index < 3) { Transform2D *v = _data._transform2d; @@ -2202,7 +2214,6 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } } else if (p_index.get_type() == Variant::STRING && p_value.get_type() == Variant::VECTOR2) { - //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); Transform2D *v = _data._transform2d; @@ -2223,24 +2234,23 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case VECTOR3: { - - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { //scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 3; + } if (idx >= 0 && idx < 3) { - Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); valid = true; (*v)[idx] = p_value; return; } } else if (p_index.get_type() == Variant::STRING) { - //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); @@ -2261,24 +2271,23 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case VECTOR3I: { - - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { //scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 3; + } if (idx >= 0 && idx < 3) { - Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); valid = true; (*v)[idx] = p_value; return; } } else if (p_index.get_type() == Variant::STRING) { - //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); @@ -2299,35 +2308,38 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case PLANE: { - if (p_index.get_type() == Variant::STRING) { //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); Plane *v = reinterpret_cast<Plane *>(_data._mem); if (*str == "x") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } valid = true; v->normal.x = p_value; return; } else if (*str == "y") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } valid = true; v->normal.y = p_value; return; } else if (*str == "z") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } valid = true; v->normal.z = p_value; return; } else if (*str == "normal") { - if (p_value.type != Variant::VECTOR3) + if (p_value.type != Variant::VECTOR3) { return; + } valid = true; v->normal = p_value; @@ -2341,12 +2353,11 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case QUAT: { - - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); Quat *v = reinterpret_cast<Quat *>(_data._mem); if (*str == "x") { @@ -2370,9 +2381,9 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case AABB: { - - if (p_value.type != Variant::VECTOR3) + if (p_value.type != Variant::VECTOR3) { return; + } if (p_index.get_type() == Variant::STRING) { //scalar name @@ -2395,16 +2406,16 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } } break; case BASIS: { - - if (p_value.type != Variant::VECTOR3) + if (p_value.type != Variant::VECTOR3) { return; + } if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) + if (index < 0) { index += 3; + } if (index >= 0 && index < 3) { Basis *v = _data._basis; @@ -2413,7 +2424,6 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } } else if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); Basis *v = _data._basis; @@ -2434,41 +2444,42 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case TRANSFORM: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - - if (p_value.type != Variant::VECTOR3) + if (p_value.type != Variant::VECTOR3) { return; + } int index = p_index; - if (index < 0) + if (index < 0) { index += 4; + } if (index >= 0 && index < 4) { Transform *v = _data._transform; valid = true; - if (index == 3) + if (index == 3) { v->origin = p_value; - else + } else { v->basis.set_axis(index, p_value); + } return; } } else if (p_index.get_type() == Variant::STRING) { - Transform *v = _data._transform; const String *str = reinterpret_cast<const String *>(p_index._data._mem); if (*str == "basis") { - - if (p_value.type != Variant::BASIS) + if (p_value.type != Variant::BASIS) { return; + } valid = true; v->basis = p_value; return; } if (*str == "origin") { - if (p_value.type != Variant::VECTOR3) + if (p_value.type != Variant::VECTOR3) { return; + } valid = true; v->origin = p_value; return; @@ -2477,12 +2488,11 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } break; case COLOR: { - - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) + if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { return; + } if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); Color *v = reinterpret_cast<Color *>(_data._mem); if (*str == "r") { @@ -2531,10 +2541,10 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) return; } } else if (p_index.get_type() == Variant::INT) { - int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 4; + } if (idx >= 0 && idx < 4) { Color *v = reinterpret_cast<Color *>(_data._mem); (*v)[idx] = p_value; @@ -2550,14 +2560,12 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) case _RID: { } break; case OBJECT: { - Object *obj = _get_obj().obj; //only if debugging! if (obj) { #ifdef DEBUG_ENABLED if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - WARN_PRINT("Attempted use of previously freed pointer object."); valid = false; return; @@ -2574,7 +2582,6 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } } break; case DICTIONARY: { - Dictionary *dic = reinterpret_cast<Dictionary *>(_data._mem); dic->operator[](p_index) = p_value; valid = true; //always valid, i guess? should this really be ok? @@ -2596,7 +2603,6 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) } Variant Variant::get(const Variant &p_index, bool *r_valid) const { - static bool _dummy = false; bool &valid = r_valid ? *r_valid : _dummy; @@ -2617,16 +2623,15 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { return Variant(); } break; case STRING: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { //string index int idx = p_index; const String *str = reinterpret_cast<const String *>(_data._mem); - if (idx < 0) + if (idx < 0) { idx += str->length(); + } if (idx >= 0 && idx < str->length()) { - valid = true; return str->substr(idx, 1); } @@ -2634,14 +2639,13 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case VECTOR2: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { // scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 2; + } if (idx >= 0 && idx < 2) { - const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem); valid = true; return (*v)[idx]; @@ -2662,14 +2666,13 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case VECTOR2I: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { // scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 2; + } if (idx >= 0 && idx < 2) { - const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem); valid = true; return (*v)[idx]; @@ -2690,7 +2693,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case RECT2: { - if (p_index.get_type() == Variant::STRING) { //scalar name @@ -2709,7 +2711,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } } break; case RECT2I: { - if (p_index.get_type() == Variant::STRING) { //scalar name @@ -2728,20 +2729,18 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } } break; case VECTOR3: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { //scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 3; + } if (idx >= 0 && idx < 3) { - const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem); valid = true; return (*v)[idx]; } } else if (p_index.get_type() == Variant::STRING) { - //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem); @@ -2759,20 +2758,18 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case VECTOR3I: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { //scalar index int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 3; + } if (idx >= 0 && idx < 3) { - const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem); valid = true; return (*v)[idx]; } } else if (p_index.get_type() == Variant::STRING) { - //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem); @@ -2790,13 +2787,12 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case TRANSFORM2D: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) + if (index < 0) { index += 3; + } if (index >= 0 && index < 3) { const Transform2D *v = _data._transform2d; @@ -2804,7 +2800,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { return v->elements[index]; } } else if (p_index.get_type() == Variant::STRING) { - //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Transform2D *v = _data._transform2d; @@ -2822,7 +2817,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case PLANE: { - if (p_index.get_type() == Variant::STRING) { //scalar name const String *str = reinterpret_cast<const String *>(p_index._data._mem); @@ -2847,9 +2841,7 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case QUAT: { - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Quat *v = reinterpret_cast<const Quat *>(_data._mem); if (*str == "x") { @@ -2869,7 +2861,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case AABB: { - if (p_index.get_type() == Variant::STRING) { //scalar name @@ -2888,12 +2879,11 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } } break; case BASIS: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) + if (index < 0) { index += 3; + } if (index >= 0 && index < 3) { const Basis *v = _data._basis; @@ -2901,7 +2891,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { return v->get_axis(index); } } else if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Basis *v = _data._basis; @@ -2919,19 +2908,17 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case TRANSFORM: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) + if (index < 0) { index += 4; + } if (index >= 0 && index < 4) { const Transform *v = _data._transform; valid = true; return index == 3 ? v->origin : v->basis.get_axis(index); } } else if (p_index.get_type() == Variant::STRING) { - const Transform *v = _data._transform; const String *str = reinterpret_cast<const String *>(p_index._data._mem); @@ -2947,9 +2934,7 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case COLOR: { - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); const Color *v = reinterpret_cast<const Color *>(_data._mem); if (*str == "r") { @@ -2987,10 +2972,10 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { return (int)Math::round(v->a * 255.0); } } else if (p_index.get_type() == Variant::INT) { - int idx = p_index; - if (idx < 0) + if (idx < 0) { idx += 4; + } if (idx >= 0 && idx < 4) { const Color *v = reinterpret_cast<const Color *>(_data._mem); valid = true; @@ -3008,7 +2993,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { case OBJECT: { Object *obj = _get_obj().obj; if (obj) { - #ifdef DEBUG_ENABLED if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { @@ -3026,7 +3010,6 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } break; case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); const Variant *res = dic->getptr(p_index); if (res) { @@ -3052,14 +3035,12 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { } bool Variant::in(const Variant &p_index, bool *r_valid) const { - - if (r_valid) + if (r_valid) { *r_valid = true; + } switch (type) { - case STRING: { - if (p_index.get_type() == Variant::STRING) { //string index String idx = p_index; @@ -3072,7 +3053,6 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { case OBJECT: { Object *obj = _get_obj().obj; if (obj) { - bool valid = false; #ifdef DEBUG_ENABLED @@ -3093,26 +3073,25 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { return valid; } else { - if (r_valid) + if (r_valid) { *r_valid = false; + } } return false; } break; case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); return dic->has(p_index); } break; case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); int l = arr->size(); if (l) { for (int i = 0; i < l; i++) { - - if (evaluate(OP_EQUAL, (*arr)[i], p_index)) + if (evaluate(OP_EQUAL, (*arr)[i], p_index)) { return true; + } } } @@ -3121,15 +3100,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_BYTE_ARRAY: { if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); int l = arr->size(); if (l) { const uint8_t *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3139,15 +3118,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_INT32_ARRAY: { if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int32_t index = p_index; const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); int32_t l = arr->size(); if (l) { const int32_t *r = arr->ptr(); for (int32_t i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3156,15 +3135,15 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_INT64_ARRAY: { if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int64_t index = p_index; const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); int64_t l = arr->size(); if (l) { const int64_t *r = arr->ptr(); for (int64_t i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3172,17 +3151,16 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } break; case PACKED_FLOAT32_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - real_t index = p_index; const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); int l = arr->size(); if (l) { const float *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3191,17 +3169,16 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_FLOAT64_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - real_t index = p_index; const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); int l = arr->size(); if (l) { const double *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3211,7 +3188,6 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_STRING_ARRAY: { if (p_index.get_type() == Variant::STRING) { - String index = p_index; const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); @@ -3219,8 +3195,9 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { if (l) { const String *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3230,7 +3207,6 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; //25 case PACKED_VECTOR2_ARRAY: { if (p_index.get_type() == Variant::VECTOR2) { - Vector2 index = p_index; const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); @@ -3238,8 +3214,9 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { if (l) { const Vector2 *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3249,7 +3226,6 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_VECTOR3_ARRAY: { if (p_index.get_type() == Variant::VECTOR3) { - Vector3 index = p_index; const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); @@ -3257,8 +3233,9 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { if (l) { const Vector3 *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3267,9 +3244,7 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } break; case PACKED_COLOR_ARRAY: { - if (p_index.get_type() == Variant::COLOR) { - Color index = p_index; const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); @@ -3277,8 +3252,9 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { if (l) { const Color *r = arr->ptr(); for (int i = 0; i < l; i++) { - if (r[i] == index) + if (r[i] == index) { return true; + } } } @@ -3289,63 +3265,55 @@ bool Variant::in(const Variant &p_index, bool *r_valid) const { } } - if (r_valid) + if (r_valid) { *r_valid = false; + } return false; } void Variant::get_property_list(List<PropertyInfo> *p_list) const { - switch (type) { case VECTOR2: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); } break; case VECTOR2I: { - p_list->push_back(PropertyInfo(Variant::INT, "x")); p_list->push_back(PropertyInfo(Variant::INT, "y")); } break; case RECT2: { - p_list->push_back(PropertyInfo(Variant::VECTOR2, "position")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "size")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "end")); } break; case RECT2I: { - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "position")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "end")); } break; case VECTOR3: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); } break; case VECTOR3I: { - p_list->push_back(PropertyInfo(Variant::INT, "x")); p_list->push_back(PropertyInfo(Variant::INT, "y")); p_list->push_back(PropertyInfo(Variant::INT, "z")); } break; case TRANSFORM2D: { - p_list->push_back(PropertyInfo(Variant::VECTOR2, "x")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "y")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "origin")); } break; case PLANE: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "normal")); p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); @@ -3354,7 +3322,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { } break; case QUAT: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); @@ -3367,14 +3334,12 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::VECTOR3, "end")); } break; case BASIS: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "x")); p_list->push_back(PropertyInfo(Variant::VECTOR3, "y")); p_list->push_back(PropertyInfo(Variant::VECTOR3, "z")); } break; case TRANSFORM: { - p_list->push_back(PropertyInfo(Variant::BASIS, "basis")); p_list->push_back(PropertyInfo(Variant::VECTOR3, "origin")); @@ -3400,7 +3365,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { case _RID: { } break; case OBJECT: { - Object *obj = _get_obj().obj; if (obj) { #ifdef DEBUG_ENABLED @@ -3417,7 +3381,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { } break; case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); List<Variant> keys; dic->get_key_list(&keys); @@ -3437,7 +3400,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { case PACKED_VECTOR2_ARRAY: case PACKED_VECTOR3_ARRAY: case PACKED_COLOR_ARRAY: { - //nothing } break; default: { @@ -3446,7 +3408,6 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const { } bool Variant::iter_init(Variant &r_iter, bool &valid) const { - valid = true; switch (type) { case INT: { @@ -3458,17 +3419,25 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return _data._float > 0.0; } break; case VECTOR2: { - int64_t from = reinterpret_cast<const Vector2 *>(_data._mem)->x; - int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + double from = reinterpret_cast<const Vector2 *>(_data._mem)->x; + double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + + r_iter = from; + + return from < to; + } break; + case VECTOR2I: { + int64_t from = reinterpret_cast<const Vector2i *>(_data._mem)->x; + int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; r_iter = from; return from < to; } break; case VECTOR3: { - int64_t from = reinterpret_cast<const Vector3 *>(_data._mem)->x; - int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y; - int64_t step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + double from = reinterpret_cast<const Vector3 *>(_data._mem)->x; + double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; r_iter = from; @@ -3476,13 +3445,24 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return false; } else if (from < to) { return step > 0; - } else { - return step < 0; } - //return true; + return step < 0; } break; - case OBJECT: { + case VECTOR3I: { + int64_t from = reinterpret_cast<const Vector3i *>(_data._mem)->x; + int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; + int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; + + r_iter = from; + if (from == to) { + return false; + } else if (from < to) { + return step > 0; + } + return step < 0; + } break; + case OBJECT: { if (!_get_obj().obj) { valid = false; return false; @@ -3514,18 +3494,18 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { } break; case STRING: { - const String *str = reinterpret_cast<const String *>(_data._mem); - if (str->empty()) + if (str->empty()) { return false; + } r_iter = 0; return true; } break; case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); - if (dic->empty()) + if (dic->empty()) { return false; + } const Variant *next = dic->next(nullptr); r_iter = *next; @@ -3533,81 +3513,87 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { } break; case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); - if (arr->empty()) + if (arr->empty()) { return false; + } r_iter = 0; return true; } break; case PACKED_BYTE_ARRAY: { const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_INT32_ARRAY: { const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_INT64_ARRAY: { const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_FLOAT32_ARRAY: { const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_FLOAT64_ARRAY: { const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_STRING_ARRAY: { const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; } break; case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); - if (arr->size() == 0) + if (arr->size() == 0) { return false; + } r_iter = 0; return true; @@ -3619,56 +3605,91 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { valid = false; return false; } -bool Variant::iter_next(Variant &r_iter, bool &valid) const { +bool Variant::iter_next(Variant &r_iter, bool &valid) const { valid = true; switch (type) { case INT: { int64_t idx = r_iter; idx++; - if (idx >= _data._int) + if (idx >= _data._int) { return false; + } r_iter = idx; return true; } break; case FLOAT: { int64_t idx = r_iter; idx++; - if (idx >= _data._float) + if (idx >= _data._float) { return false; + } r_iter = idx; return true; } break; case VECTOR2: { - int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + + double idx = r_iter; + idx++; + + if (idx >= to) { + return false; + } + + r_iter = idx; + return true; + } break; + case VECTOR2I: { + int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; int64_t idx = r_iter; idx++; - if (idx >= to) + if (idx >= to) { return false; + } r_iter = idx; return true; } break; case VECTOR3: { - int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y; - int64_t step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + + double idx = r_iter; + idx += step; + + if (step < 0 && idx <= to) { + return false; + } + + if (step > 0 && idx >= to) { + return false; + } + + r_iter = idx; + return true; + } break; + case VECTOR3I: { + int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; + int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; int64_t idx = r_iter; idx += step; - if (step < 0 && idx <= to) + if (step < 0 && idx <= to) { return false; + } - if (step > 0 && idx >= to) + if (step > 0 && idx >= to) { return false; + } r_iter = idx; return true; } break; case OBJECT: { - if (!_get_obj().obj) { valid = false; return false; @@ -3701,33 +3722,33 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { } break; case STRING: { - const String *str = reinterpret_cast<const String *>(_data._mem); int idx = r_iter; idx++; - if (idx >= str->length()) + if (idx >= str->length()) { return false; + } r_iter = idx; return true; } break; case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); const Variant *next = dic->next(&r_iter); - if (!next) + if (!next) { return false; + } r_iter = *next; return true; } break; case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; } break; @@ -3735,8 +3756,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; @@ -3745,8 +3767,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); int32_t idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; @@ -3755,8 +3778,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); int64_t idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; @@ -3765,8 +3789,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; @@ -3775,8 +3800,9 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; @@ -3785,38 +3811,39 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; } break; case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; } break; case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; } break; case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); int idx = r_iter; idx++; - if (idx >= arr->size()) + if (idx >= arr->size()) { return false; + } r_iter = idx; return true; } break; @@ -3829,27 +3856,27 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { } Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { - r_valid = true; switch (type) { case INT: { - return r_iter; } break; case FLOAT: { - return r_iter; } break; case VECTOR2: { - + return r_iter; + } break; + case VECTOR2I: { return r_iter; } break; case VECTOR3: { - + return r_iter; + } break; + case VECTOR3I: { return r_iter; } break; case OBJECT: { - if (!_get_obj().obj) { r_valid = false; return Variant(); @@ -3877,17 +3904,14 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { } break; case STRING: { - const String *str = reinterpret_cast<const String *>(_data._mem); return str->substr(r_iter, 1); } break; case DICTIONARY: { - return r_iter; //iterator is the same as the key } break; case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); int idx = r_iter; #ifdef DEBUG_ENABLED @@ -3965,7 +3989,6 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { return arr->get(idx); } break; case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); int idx = r_iter; #ifdef DEBUG_ENABLED @@ -3977,7 +4000,6 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { return arr->get(idx); } break; case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); int idx = r_iter; #ifdef DEBUG_ENABLED @@ -3989,7 +4011,6 @@ Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { return arr->get(idx); } break; case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); int idx = r_iter; #ifdef DEBUG_ENABLED @@ -4142,7 +4163,6 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) } void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) { - if (a.type != b.type) { if (a.is_num() && b.is_num()) { //not as efficient but.. @@ -4157,7 +4177,6 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } switch (a.type) { - case NIL: { r_dst = Variant(); } @@ -4195,22 +4214,21 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & int split = csize / 2; for (int i = 0; i < csize; i++) { - CharType chr = ' '; if (i < split) { - - if (i < sa.length()) + if (i < sa.length()) { chr = sa[i]; - else if (i < sb.length()) + } else if (i < sb.length()) { chr = sb[i]; + } } else { - - if (i < sb.length()) + if (i < sb.length()) { chr = sb[i]; - else if (i < sa.length()) + } else if (i < sa.length()) { chr = sa[i]; + } } dst[i] = chr; @@ -4220,7 +4238,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case VECTOR2: { - r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Vector2 *>(b._data._mem), c); + r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector2 *>(b._data._mem), c); } return; case VECTOR2I: { @@ -4233,7 +4251,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & return; case RECT2: { - r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.linear_interpolate(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.linear_interpolate(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c)); + r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c)); } return; case RECT2I: { @@ -4254,7 +4272,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & return; case VECTOR3: { - r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Vector3 *>(b._data._mem), c); + r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector3 *>(b._data._mem), c); } return; case VECTOR3I: { @@ -4281,7 +4299,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case AABB: { - r_dst = ::AABB(a._data._aabb->position.linear_interpolate(b._data._aabb->position, c), a._data._aabb->size.linear_interpolate(b._data._aabb->size, c)); + r_dst = ::AABB(a._data._aabb->position.lerp(b._data._aabb->position, c), a._data._aabb->size.lerp(b._data._aabb->size, c)); } return; case BASIS: { @@ -4293,7 +4311,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case COLOR: { - r_dst = reinterpret_cast<const Color *>(a._data._mem)->linear_interpolate(*reinterpret_cast<const Color *>(b._data._mem), c); + r_dst = reinterpret_cast<const Color *>(a._data._mem)->lerp(*reinterpret_cast<const Color *>(b._data._mem), c); } return; case STRING_NAME: { @@ -4328,10 +4346,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector<int32_t> *arr_b = &PackedArrayRef<int32_t>::get_array(b._data.packed_array); int32_t sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<int32_t> v; v.resize(sz); { @@ -4354,10 +4370,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector<int64_t> *arr_b = &PackedArrayRef<int64_t>::get_array(b._data.packed_array); int64_t sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<int64_t> v; v.resize(sz); { @@ -4380,10 +4394,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector<float> *arr_b = &PackedArrayRef<float>::get_array(b._data.packed_array); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<float> v; v.resize(sz); { @@ -4406,10 +4418,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector<double> *arr_b = &PackedArrayRef<double>::get_array(b._data.packed_array); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<double> v; v.resize(sz); { @@ -4436,10 +4446,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<Vector2> v; v.resize(sz); { @@ -4448,7 +4456,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector2 *br = arr_b->ptr(); for (int i = 0; i < sz; i++) { - vw[i] = ar[i].linear_interpolate(br[i], c); + vw[i] = ar[i].lerp(br[i], c); } } r_dst = v; @@ -4456,15 +4464,12 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array); const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<Vector3> v; v.resize(sz); { @@ -4473,7 +4478,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector3 *br = arr_b->ptr(); for (int i = 0; i < sz; i++) { - vw[i] = ar[i].linear_interpolate(br[i], c); + vw[i] = ar[i].lerp(br[i], c); } } r_dst = v; @@ -4485,10 +4490,8 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array); int sz = arr_a->size(); if (sz == 0 || arr_b->size() != sz) { - r_dst = a; } else { - Vector<Color> v; v.resize(sz); { @@ -4497,7 +4500,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & const Color *br = arr_b->ptr(); for (int i = 0; i < sz; i++) { - vw[i] = ar[i].linear_interpolate(br[i], c); + vw[i] = ar[i].lerp(br[i], c); } } r_dst = v; @@ -4505,7 +4508,6 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & } return; default: { - r_dst = a; } } @@ -4541,7 +4543,6 @@ static const char *_op_names[Variant::OP_MAX] = { }; String Variant::get_operator_name(Operator p_op) { - ERR_FAIL_INDEX_V(p_op, OP_MAX, ""); return _op_names[p_op]; } diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 0a578faf78..74f4f32c0e 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -36,21 +36,18 @@ #include "core/string_buffer.h" CharType VariantParser::StreamFile::get_char() { - return f->get_8(); } bool VariantParser::StreamFile::is_utf8() const { - return true; } -bool VariantParser::StreamFile::is_eof() const { +bool VariantParser::StreamFile::is_eof() const { return f->eof_reached(); } CharType VariantParser::StreamString::get_char() { - if (pos > s.length()) { return 0; } else if (pos == s.length()) { @@ -66,6 +63,7 @@ CharType VariantParser::StreamString::get_char() { bool VariantParser::StreamString::is_utf8() const { return false; } + bool VariantParser::StreamString::is_eof() const { return pos > s.length(); } @@ -93,11 +91,9 @@ const char *VariantParser::tk_name[TK_MAX] = { }; Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, String &r_err_str) { - bool string_name = false; while (true) { - CharType cchar; if (p_stream->saved) { cchar = p_stream->saved; @@ -111,82 +107,69 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } switch (cchar) { - case '\n': { - line++; break; - }; + } case 0: { r_token.type = TK_EOF; return OK; } break; case '{': { - r_token.type = TK_CURLY_BRACKET_OPEN; return OK; - }; + } case '}': { - r_token.type = TK_CURLY_BRACKET_CLOSE; return OK; - }; + } case '[': { - r_token.type = TK_BRACKET_OPEN; return OK; - }; + } case ']': { - r_token.type = TK_BRACKET_CLOSE; return OK; - }; + } case '(': { - r_token.type = TK_PARENTHESIS_OPEN; return OK; - }; + } case ')': { - r_token.type = TK_PARENTHESIS_CLOSE; return OK; - }; + } case ':': { - r_token.type = TK_COLON; return OK; - }; + } case ';': { - while (true) { CharType ch = p_stream->get_char(); if (p_stream->is_eof()) { r_token.type = TK_EOF; return OK; } - if (ch == '\n') + if (ch == '\n') { break; + } } break; - }; + } case ',': { - r_token.type = TK_COMMA; return OK; - }; + } case '.': { - r_token.type = TK_PERIOD; return OK; - }; + } case '=': { - r_token.type = TK_EQUAL; return OK; - }; + } case '#': { - StringBuffer<> color_str; color_str += '#'; while (true) { @@ -206,7 +189,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri r_token.value = Color::html(color_str.as_string()); r_token.type = TK_COLOR; return OK; - }; + } case '@': { cchar = p_stream->get_char(); if (cchar != '"') { @@ -219,10 +202,8 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri [[fallthrough]]; } case '"': { - String str; while (true) { - CharType ch = p_stream->get_char(); if (ch == 0) { @@ -242,12 +223,21 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri CharType res = 0; switch (next) { - - case 'b': res = 8; break; - case 't': res = 9; break; - case 'n': res = 10; break; - case 'f': res = 12; break; - case 'r': res = 13; break; + case 'b': + res = 8; + break; + case 't': + res = 9; + break; + case 'n': + res = 10; + break; + case 'f': + res = 12; + break; + case 'r': + res = 13; + break; case 'u': { //hex number for (int j = 0; j < 4; j++) { @@ -258,7 +248,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri return ERR_PARSE_ERROR; } if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { - r_err_str = "Malformed hex constant in string"; r_token.type = TK_ERROR; return ERR_PARSE_ERROR; @@ -290,8 +279,9 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri str += res; } else { - if (ch == '\n') + if (ch == '\n') { line++; + } str += ch; } } @@ -311,7 +301,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } break; default: { - if (cchar <= 32) { break; } @@ -338,10 +327,8 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri bool is_float = false; while (true) { - switch (reading) { case READING_INT: { - if (c >= '0' && c <= '9') { //pass } else if (c == '.') { @@ -356,9 +343,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } break; case READING_DEC: { - if (c >= '0' && c <= '9') { - } else if (c == 'e') { reading = READING_EXP; } else { @@ -367,7 +352,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } break; case READING_EXP: { - if (c >= '0' && c <= '9') { exp_beg = true; @@ -380,8 +364,9 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } break; } - if (reading == READING_DONE) + if (reading == READING_DONE) { break; + } num += c; c = p_stream->get_char(); } @@ -390,19 +375,18 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri r_token.type = TK_NUMBER; - if (is_float) + if (is_float) { r_token.value = num.as_double(); - else + } else { r_token.value = num.as_int(); + } return OK; } else if ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_') { - StringBuffer<> id; bool first = true; while ((cchar >= 'A' && cchar <= 'Z') || (cchar >= 'a' && cchar <= 'z') || cchar == '_' || (!first && cchar >= '0' && cchar <= '9')) { - id += cchar; cchar = p_stream->get_char(); first = false; @@ -427,7 +411,6 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings, int &line, String &r_err_str) { - Token token; get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { @@ -438,7 +421,6 @@ Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings, String accum; while (true) { - CharType c = p_stream->get_char(); if (p_stream->is_eof()) { @@ -460,7 +442,6 @@ Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings, template <class T> Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct, int &line, String &r_err_str) { - Token token; get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { @@ -470,7 +451,6 @@ Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct, bool first = true; while (true) { - if (!first) { get_token(p_stream, token, line, r_err_str); if (token.type == TK_COMMA) { @@ -499,221 +479,208 @@ Error VariantParser::_parse_construct(Stream *p_stream, Vector<T> &r_construct, } Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { - - /* { - Error err = get_token(p_stream,token,line,r_err_str); - if (err) - return err; - }*/ - if (token.type == TK_CURLY_BRACKET_OPEN) { - Dictionary d; Error err = _parse_dictionary(d, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } value = d; return OK; } else if (token.type == TK_BRACKET_OPEN) { - Array a; Error err = _parse_array(a, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } value = a; return OK; - } else if (token.type == TK_IDENTIFIER) { - String id = token.value; - if (id == "true") + if (id == "true") { value = true; - else if (id == "false") + } else if (id == "false") { value = false; - else if (id == "null" || id == "nil") + } else if (id == "null" || id == "nil") { value = Variant(); - else if (id == "inf") + } else if (id == "inf") { value = Math_INF; - else if (id == "nan") + } else if (id == "nan") { value = Math_NAN; - else if (id == "Vector2") { - + } else if (id == "Vector2") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 2) { r_err_str = "Expected 2 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Vector2(args[0], args[1]); - return OK; } else if (id == "Vector2i") { - Vector<int32_t> args; Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 2) { r_err_str = "Expected 2 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Vector2i(args[0], args[1]); - return OK; } else if (id == "Rect2") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 4) { r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Rect2(args[0], args[1], args[2], args[3]); - return OK; } else if (id == "Rect2i") { - Vector<int32_t> args; Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 4) { r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Rect2i(args[0], args[1], args[2], args[3]); - return OK; } else if (id == "Vector3") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 3) { r_err_str = "Expected 3 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Vector3(args[0], args[1], args[2]); - return OK; } else if (id == "Vector3i") { - Vector<int32_t> args; Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 3) { r_err_str = "Expected 3 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Vector3i(args[0], args[1], args[2]); - return OK; } else if (id == "Transform2D" || id == "Matrix32") { //compatibility - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 6) { r_err_str = "Expected 6 arguments for constructor"; + return ERR_PARSE_ERROR; } + Transform2D m; m[0] = Vector2(args[0], args[1]); m[1] = Vector2(args[2], args[3]); m[2] = Vector2(args[4], args[5]); value = m; - return OK; } else if (id == "Plane") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 4) { r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Plane(args[0], args[1], args[2], args[3]); - return OK; } else if (id == "Quat") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 4) { r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Quat(args[0], args[1], args[2], args[3]); - return OK; - } else if (id == "AABB" || id == "Rect3") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 6) { r_err_str = "Expected 6 arguments for constructor"; + return ERR_PARSE_ERROR; } value = AABB(Vector3(args[0], args[1], args[2]), Vector3(args[3], args[4], args[5])); - return OK; - } else if (id == "Basis" || id == "Matrix3") { //compatibility - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 9) { r_err_str = "Expected 9 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - return OK; } else if (id == "Transform") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 12) { r_err_str = "Expected 12 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Transform(Basis(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]), Vector3(args[9], args[10], args[11])); - return OK; - } else if (id == "Color") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } if (args.size() != 4) { r_err_str = "Expected 4 arguments for constructor"; + return ERR_PARSE_ERROR; } value = Color(args[0], args[1], args[2], args[3]); - return OK; - } else if (id == "NodePath") { - get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -733,9 +700,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, r_err_str = "Expected ')'"; return ERR_PARSE_ERROR; } - } else if (id == "RID") { - get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -755,10 +720,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, r_err_str = "Expected ')'"; return ERR_PARSE_ERROR; } - - return OK; } else if (id == "Object") { - get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -793,17 +755,16 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, bool need_comma = false; while (true) { - if (p_stream->is_eof()) { r_err_str = "Unexpected End of File while parsing Object()"; return ERR_FILE_CORRUPT; } if (at_key) { - Error err = get_token(p_stream, token2, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token2.type == TK_PARENTHESIS_CLOSE) { Reference *reference = Object::cast_to<Reference>(obj); @@ -816,9 +777,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } if (need_comma) { - if (token2.type != TK_COMMA) { - r_err_str = "Expected '}' or ','"; return ERR_PARSE_ERROR; } else { @@ -836,32 +795,31 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, err = get_token(p_stream, token2, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token2.type != TK_COLON) { - r_err_str = "Expected ':'"; return ERR_PARSE_ERROR; } at_key = false; } else { - Error err = get_token(p_stream, token2, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } Variant v; err = parse_value(token2, v, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } obj->set(key, v); need_comma = true; at_key = true; } } - } else if (id == "Resource" || id == "SubResource" || id == "ExtResource") { - get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -869,37 +827,30 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } if (p_res_parser && id == "Resource" && p_res_parser->func) { - RES res; Error err = p_res_parser->func(p_res_parser->userdata, p_stream, res, line, r_err_str); - if (err) + if (err) { return err; + } value = res; - - return OK; } else if (p_res_parser && id == "ExtResource" && p_res_parser->ext_func) { - RES res; Error err = p_res_parser->ext_func(p_res_parser->userdata, p_stream, res, line, r_err_str); - if (err) + if (err) { return err; + } value = res; - - return OK; } else if (p_res_parser && id == "SubResource" && p_res_parser->sub_func) { - RES res; Error err = p_res_parser->sub_func(p_res_parser->userdata, p_stream, res, line, r_err_str); - if (err) + if (err) { return err; + } value = res; - - return OK; } else { - get_token(p_stream, token, line, r_err_str); if (token.type == TK_STRING) { String path = token.value; @@ -916,20 +867,17 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = res; - return OK; - } else { r_err_str = "Expected string as argument for Resource()."; return ERR_PARSE_ERROR; } } - } else if (id == "PackedByteArray" || id == "PoolByteArray" || id == "ByteArray") { - Vector<uint8_t> args; Error err = _parse_construct<uint8_t>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<uint8_t> arr; { @@ -942,15 +890,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; - } else if (id == "PackedInt32Array" || id == "PackedIntArray" || id == "PoolIntArray" || id == "IntArray") { - Vector<int32_t> args; Error err = _parse_construct<int32_t>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<int32_t> arr; { @@ -963,15 +908,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; - } else if (id == "PackedInt64Array") { - Vector<int64_t> args; Error err = _parse_construct<int64_t>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<int64_t> arr; { @@ -984,15 +926,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; - } else if (id == "PackedFloat32Array" || id == "PackedRealArray" || id == "PoolRealArray" || id == "FloatArray") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<float> arr; { @@ -1005,14 +944,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; } else if (id == "PackedFloat64Array") { - Vector<double> args; Error err = _parse_construct<double>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<double> arr; { @@ -1025,10 +962,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; } else if (id == "PackedStringArray" || id == "PoolStringArray" || id == "StringArray") { - get_token(p_stream, token, line, r_err_str); if (token.type != TK_PARENTHESIS_OPEN) { r_err_str = "Expected '('"; @@ -1039,7 +973,6 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, bool first = true; while (true) { - if (!first) { get_token(p_stream, token, line, r_err_str); if (token.type == TK_COMMA) { @@ -1075,15 +1008,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; - } else if (id == "PackedVector2Array" || id == "PoolVector2Array" || id == "Vector2Array") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<Vector2> arr; { @@ -1096,15 +1026,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; - } else if (id == "PackedVector3Array" || id == "PoolVector3Array" || id == "Vector3Array") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<Vector3> arr; { @@ -1117,15 +1044,12 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; - } else if (id == "PackedColorArray" || id == "PoolColorArray" || id == "ColorArray") { - Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); - if (err) + if (err) { return err; + } Vector<Color> arr; { @@ -1138,29 +1062,23 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } value = arr; - - return OK; } else { r_err_str = "Unexpected identifier: '" + id + "'."; return ERR_PARSE_ERROR; } + // All above branches end up here unless they had an early return. return OK; - } else if (token.type == TK_NUMBER) { - value = token.value; return OK; } else if (token.type == TK_STRING) { - value = token.value; return OK; } else if (token.type == TK_STRING_NAME) { - value = token.value; return OK; } else if (token.type == TK_COLOR) { - value = token.value; return OK; } else { @@ -1170,30 +1088,26 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { - Token token; bool need_comma = false; while (true) { - if (p_stream->is_eof()) { r_err_str = "Unexpected End of File while parsing array"; return ERR_FILE_CORRUPT; } Error err = get_token(p_stream, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token.type == TK_BRACKET_CLOSE) { - return OK; } if (need_comma) { - if (token.type != TK_COMMA) { - r_err_str = "Expected ','"; return ERR_PARSE_ERROR; } else { @@ -1204,8 +1118,9 @@ Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, Str Variant v; err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } array.push_back(v); need_comma = true; @@ -1213,34 +1128,29 @@ Error VariantParser::_parse_array(Array &array, Stream *p_stream, int &line, Str } Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int &line, String &r_err_str, ResourceParser *p_res_parser) { - bool at_key = true; Variant key; Token token; bool need_comma = false; while (true) { - if (p_stream->is_eof()) { r_err_str = "Unexpected End of File while parsing dictionary"; return ERR_FILE_CORRUPT; } if (at_key) { - Error err = get_token(p_stream, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token.type == TK_CURLY_BRACKET_CLOSE) { - return OK; } if (need_comma) { - if (token.type != TK_COMMA) { - r_err_str = "Expected '}' or ','"; return ERR_PARSE_ERROR; } else { @@ -1251,29 +1161,31 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int err = parse_value(token, key, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } err = get_token(p_stream, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } if (token.type != TK_COLON) { - r_err_str = "Expected ':'"; return ERR_PARSE_ERROR; } at_key = false; } else { - Error err = get_token(p_stream, token, line, r_err_str); - if (err != OK) + if (err != OK) { return err; + } Variant v; err = parse_value(token, v, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } object[key] = v; need_comma = true; at_key = true; @@ -1282,7 +1194,6 @@ Error VariantParser::_parse_dictionary(Dictionary &object, Stream *p_stream, int } Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) { - r_tag.fields.clear(); if (token.type != TK_BRACKET_OPEN) { @@ -1291,19 +1202,18 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin } if (p_simple_tag) { - r_tag.name = ""; r_tag.fields.clear(); while (true) { - CharType c = p_stream->get_char(); if (p_stream->is_eof()) { r_err_str = "Unexpected EOF while parsing simple tag"; return ERR_PARSE_ERROR; } - if (c == ']') + if (c == ']') { break; + } r_tag.name += String::chr(c); } @@ -1323,15 +1233,15 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin bool parsing_tag = true; while (true) { - if (p_stream->is_eof()) { r_err_str = "Unexpected End of File while parsing tag: " + r_tag.name; return ERR_FILE_CORRUPT; } get_token(p_stream, token, line, r_err_str); - if (token.type == TK_BRACKET_CLOSE) + if (token.type == TK_BRACKET_CLOSE) { break; + } if (parsing_tag && token.type == TK_PERIOD) { r_tag.name += "."; //support tags such as [someprop.Android] for specific platforms @@ -1363,8 +1273,9 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin get_token(p_stream, token, line, r_err_str); Variant value; Error err = parse_value(token, value, p_stream, line, r_err_str, p_res_parser); - if (err) + if (err) { return err; + } r_tag.fields[id] = value; } @@ -1373,7 +1284,6 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin } Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, ResourceParser *p_res_parser, bool p_simple_tag) { - Token token; get_token(p_stream, token, line, r_err_str); @@ -1390,13 +1300,11 @@ Error VariantParser::parse_tag(Stream *p_stream, int &line, String &r_err_str, T } Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r_err_str, Tag &r_tag, String &r_assign, Variant &r_value, ResourceParser *p_res_parser, bool p_simple_tag) { - //assign.. r_assign = ""; String what; while (true) { - CharType c; if (p_stream->saved) { c = p_stream->saved; @@ -1406,8 +1314,9 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r c = p_stream->get_char(); } - if (p_stream->is_eof()) + if (p_stream->is_eof()) { return ERR_FILE_EOF; + } if (c == ';') { //comment while (true) { @@ -1415,8 +1324,9 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r if (p_stream->is_eof()) { return ERR_FILE_EOF; } - if (ch == '\n') + if (ch == '\n') { break; + } } continue; } @@ -1435,8 +1345,9 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r p_stream->saved = '"'; Token tk; Error err = get_token(p_stream, tk, line, r_err_str); - if (err) + if (err) { return err; + } if (tk.type != TK_STRING) { r_err_str = "Error reading quoted string"; return ERR_INVALID_DATA; @@ -1460,11 +1371,11 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r } Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, int &r_err_line, ResourceParser *p_res_parser) { - Token token; Error err = get_token(p_stream, token, r_err_line, r_err_str); - if (err) + if (err) { return err; + } if (token.type == TK_EOF) { return ERR_FILE_EOF; @@ -1478,103 +1389,88 @@ Error VariantParser::parse(Stream *p_stream, Variant &r_ret, String &r_err_str, //////////////////////////////////////////////////////////////////////////////// static String rtosfix(double p_value) { - - if (p_value == 0.0) + if (p_value == 0.0) { return "0"; //avoid negative zero (-0) being written, which may annoy git, svn, etc. for changes when they don't exist. - else + } else { return rtoss(p_value); + } } Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_string_func, void *p_store_string_ud, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) { - switch (p_variant.get_type()) { - case Variant::NIL: { p_store_string_func(p_store_string_ud, "null"); } break; case Variant::BOOL: { - p_store_string_func(p_store_string_ud, p_variant.operator bool() ? "true" : "false"); } break; case Variant::INT: { - p_store_string_func(p_store_string_ud, itos(p_variant.operator int64_t())); } break; case Variant::FLOAT: { - String s = rtosfix(p_variant.operator real_t()); if (s != "inf" && s != "nan") { - if (s.find(".") == -1 && s.find("e") == -1) + if (s.find(".") == -1 && s.find("e") == -1) { s += ".0"; + } } p_store_string_func(p_store_string_ud, s); } break; case Variant::STRING: { - String str = p_variant; str = "\"" + str.c_escape_multiline() + "\""; p_store_string_func(p_store_string_ud, str); } break; case Variant::VECTOR2: { - Vector2 v = p_variant; p_store_string_func(p_store_string_ud, "Vector2( " + rtosfix(v.x) + ", " + rtosfix(v.y) + " )"); } break; case Variant::VECTOR2I: { - Vector2i v = p_variant; p_store_string_func(p_store_string_ud, "Vector2i( " + itos(v.x) + ", " + itos(v.y) + " )"); } break; case Variant::RECT2: { - Rect2 aabb = p_variant; p_store_string_func(p_store_string_ud, "Rect2( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + " )"); } break; case Variant::RECT2I: { - Rect2i aabb = p_variant; p_store_string_func(p_store_string_ud, "Rect2i( " + itos(aabb.position.x) + ", " + itos(aabb.position.y) + ", " + itos(aabb.size.x) + ", " + itos(aabb.size.y) + " )"); } break; case Variant::VECTOR3: { - Vector3 v = p_variant; p_store_string_func(p_store_string_ud, "Vector3( " + rtosfix(v.x) + ", " + rtosfix(v.y) + ", " + rtosfix(v.z) + " )"); } break; case Variant::VECTOR3I: { - Vector3i v = p_variant; p_store_string_func(p_store_string_ud, "Vector3i( " + itos(v.x) + ", " + itos(v.y) + ", " + itos(v.z) + " )"); } break; case Variant::PLANE: { - Plane p = p_variant; p_store_string_func(p_store_string_ud, "Plane( " + rtosfix(p.normal.x) + ", " + rtosfix(p.normal.y) + ", " + rtosfix(p.normal.z) + ", " + rtosfix(p.d) + " )"); } break; case Variant::AABB: { - AABB aabb = p_variant; p_store_string_func(p_store_string_ud, "AABB( " + rtosfix(aabb.position.x) + ", " + rtosfix(aabb.position.y) + ", " + rtosfix(aabb.position.z) + ", " + rtosfix(aabb.size.x) + ", " + rtosfix(aabb.size.y) + ", " + rtosfix(aabb.size.z) + " )"); } break; case Variant::QUAT: { - Quat quat = p_variant; p_store_string_func(p_store_string_ud, "Quat( " + rtosfix(quat.x) + ", " + rtosfix(quat.y) + ", " + rtosfix(quat.z) + ", " + rtosfix(quat.w) + " )"); } break; case Variant::TRANSFORM2D: { - String s = "Transform2D( "; Transform2D m3 = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 2; j++) { - - if (i != 0 || j != 0) + if (i != 0 || j != 0) { s += ", "; + } s += rtosfix(m3.elements[i][j]); } } @@ -1583,14 +1479,13 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::BASIS: { - String s = "Basis( "; Basis m3 = p_variant; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - - if (i != 0 || j != 0) + if (i != 0 || j != 0) { s += ", "; + } s += rtosfix(m3.elements[i][j]); } } @@ -1599,15 +1494,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::TRANSFORM: { - String s = "Transform( "; Transform t = p_variant; Basis &m3 = t.basis; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - - if (i != 0 || j != 0) + if (i != 0 || j != 0) { s += ", "; + } s += rtosfix(m3.elements[i][j]); } } @@ -1619,13 +1513,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str // misc types case Variant::COLOR: { - Color c = p_variant; p_store_string_func(p_store_string_ud, "Color( " + rtosfix(c.r) + ", " + rtosfix(c.g) + ", " + rtosfix(c.b) + ", " + rtosfix(c.a) + " )"); } break; case Variant::STRING_NAME: { - String str = p_variant; str = "@\"" + str.c_escape() + "\""; @@ -1633,7 +1525,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::NODE_PATH: { - String str = p_variant; str = "NodePath(\"" + str.c_escape() + "\")"; @@ -1642,7 +1533,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::OBJECT: { - Object *obj = p_variant; if (!obj) { @@ -1657,13 +1547,11 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str //try external function if (p_encode_res_func) { - res_text = p_encode_res_func(p_encode_res_ud, res); } //try path because it's a file if (res_text == String() && res->get_path().is_resource_file()) { - //external resource String path = res->get_path(); res_text = "Resource( \"" + path + "\")"; @@ -1684,7 +1572,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str obj->get_property_list(&props); bool first = true; for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { - if (E->get().usage & PROPERTY_USAGE_STORAGE || E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE) { //must be serialized @@ -1704,7 +1591,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::DICTIONARY: { - Dictionary dict = p_variant; List<Variant> keys; @@ -1713,7 +1599,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str p_store_string_func(p_store_string_ud, "{\n"); for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - /* if (!_check_type(dict[E->get()])) continue; @@ -1721,22 +1606,22 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud); p_store_string_func(p_store_string_ud, ": "); write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud); - if (E->next()) + if (E->next()) { p_store_string_func(p_store_string_ud, ",\n"); + } } p_store_string_func(p_store_string_ud, "\n}"); } break; case Variant::ARRAY: { - p_store_string_func(p_store_string_ud, "[ "); Array array = p_variant; int len = array.size(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } write(array[i], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud); } p_store_string_func(p_store_string_ud, " ]"); @@ -1744,7 +1629,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_BYTE_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedByteArray( "); String s; Vector<uint8_t> data = p_variant; @@ -1752,9 +1636,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str const uint8_t *ptr = data.ptr(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, itos(ptr[i])); } @@ -1763,16 +1647,15 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_INT32_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedInt32Array( "); Vector<int32_t> data = p_variant; int32_t len = data.size(); const int32_t *ptr = data.ptr(); for (int32_t i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, itos(ptr[i])); } @@ -1781,16 +1664,15 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_INT64_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedInt64Array( "); Vector<int64_t> data = p_variant; int64_t len = data.size(); const int64_t *ptr = data.ptr(); for (int64_t i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, itos(ptr[i])); } @@ -1799,16 +1681,15 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_FLOAT32_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedFloat32Array( "); Vector<float> data = p_variant; int len = data.size(); const float *ptr = data.ptr(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, rtosfix(ptr[i])); } @@ -1816,16 +1697,15 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_FLOAT64_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedFloat64Array( "); Vector<double> data = p_variant; int len = data.size(); const double *ptr = data.ptr(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, rtosfix(ptr[i])); } @@ -1833,7 +1713,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_STRING_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedStringArray( "); Vector<String> data = p_variant; int len = data.size(); @@ -1843,9 +1722,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str //write_string("\n"); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } String str = ptr[i]; p_store_string_func(p_store_string_ud, "\"" + str.c_escape() + "\""); } @@ -1854,16 +1733,15 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_VECTOR2_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedVector2Array( "); Vector<Vector2> data = p_variant; int len = data.size(); const Vector2 *ptr = data.ptr(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y)); } @@ -1871,16 +1749,15 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_VECTOR3_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedVector3Array( "); Vector<Vector3> data = p_variant; int len = data.size(); const Vector3 *ptr = data.ptr(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, rtosfix(ptr[i].x) + ", " + rtosfix(ptr[i].y) + ", " + rtosfix(ptr[i].z)); } @@ -1888,7 +1765,6 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::PACKED_COLOR_ARRAY: { - p_store_string_func(p_store_string_ud, "PackedColorArray( "); Vector<Color> data = p_variant; @@ -1896,9 +1772,9 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str const Color *ptr = data.ptr(); for (int i = 0; i < len; i++) { - - if (i > 0) + if (i > 0) { p_store_string_func(p_store_string_ud, ", "); + } p_store_string_func(p_store_string_ud, rtosfix(ptr[i].r) + ", " + rtosfix(ptr[i].g) + ", " + rtosfix(ptr[i].b) + ", " + rtosfix(ptr[i].a)); } @@ -1913,14 +1789,12 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } static Error _write_to_str(void *ud, const String &p_string) { - String *str = (String *)ud; (*str) += p_string; return OK; } Error VariantWriter::write_to_string(const Variant &p_variant, String &r_string, EncodeResourceFunc p_encode_res_func, void *p_encode_res_ud) { - r_string = String(); return write(p_variant, _write_to_str, &r_string, p_encode_res_func, p_encode_res_ud); diff --git a/core/variant_parser.h b/core/variant_parser.h index 63ed51bcc9..b55d7b2df0 100644 --- a/core/variant_parser.h +++ b/core/variant_parser.h @@ -38,45 +38,40 @@ class VariantParser { public: struct Stream { - virtual CharType get_char() = 0; virtual bool is_utf8() const = 0; virtual bool is_eof() const = 0; - CharType saved; + CharType saved = 0; - Stream() : - saved(0) {} + Stream() {} virtual ~Stream() {} }; struct StreamFile : public Stream { - - FileAccess *f; + FileAccess *f = nullptr; virtual CharType get_char(); virtual bool is_utf8() const; virtual bool is_eof() const; - StreamFile() { f = nullptr; } + StreamFile() {} }; struct StreamString : public Stream { - String s; - int pos; + int pos = 0; virtual CharType get_char(); virtual bool is_utf8() const; virtual bool is_eof() const; - StreamString() { pos = 0; } + StreamString() {} }; typedef Error (*ParseResourceFunc)(void *p_self, Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str); struct ResourceParser { - void *userdata = nullptr; ParseResourceFunc func; ParseResourceFunc ext_func; @@ -113,13 +108,11 @@ public: }; struct Token { - TokenType type; Variant value; }; struct Tag { - String name; Map<String, Variant> fields; }; diff --git a/core/vector.h b/core/vector.h index 7277179621..4c152fb084 100644 --- a/core/vector.h +++ b/core/vector.h @@ -39,6 +39,7 @@ #include "core/cowdata.h" #include "core/error_macros.h" +#include "core/os/copymem.h" #include "core/os/memory.h" #include "core/sort_array.h" @@ -69,7 +70,9 @@ public: void remove(int p_index) { _cowdata.remove(p_index); } void erase(const T &p_val) { int idx = find(p_val); - if (idx >= 0) remove(idx); + if (idx >= 0) { + remove(idx); + } } void invert(); @@ -91,10 +94,10 @@ public: template <class C> void sort_custom() { - int len = _cowdata.size(); - if (len == 0) + if (len == 0) { return; + } T *data = ptrw(); SortArray<T, C> sorter; @@ -102,30 +105,32 @@ public: } void sort() { - sort_custom<_DefaultComparator<T>>(); } void ordered_insert(const T &p_val) { int i; for (i = 0; i < _cowdata.size(); i++) { - if (p_val < operator[](i)) { break; - }; - }; + } + } insert(i, p_val); } - _FORCE_INLINE_ Vector() {} - _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } inline Vector &operator=(const Vector &p_from) { _cowdata._ref(p_from._cowdata); return *this; } - Vector<T> subarray(int p_from, int p_to) const { + Vector<uint8_t> to_byte_array() const { + Vector<uint8_t> ret; + ret.resize(size() * sizeof(T)); + copymem(ret.ptrw(), ptr(), sizeof(T) * size()); + return ret; + } + Vector<T> subarray(int p_from, int p_to) const { if (p_from < 0) { p_from = size() + p_from; } @@ -148,12 +153,14 @@ public: return slice; } + _FORCE_INLINE_ Vector() {} + _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } + _FORCE_INLINE_ ~Vector() {} }; template <class T> void Vector<T>::invert() { - for (int i = 0; i < size() / 2; i++) { T *p = ptrw(); SWAP(p[i], p[size() - i - 1]); @@ -163,17 +170,18 @@ void Vector<T>::invert() { template <class T> void Vector<T>::append_array(Vector<T> p_other) { const int ds = p_other.size(); - if (ds == 0) + if (ds == 0) { return; + } const int bs = size(); resize(bs + ds); - for (int i = 0; i < ds; ++i) + for (int i = 0; i < ds; ++i) { ptrw()[bs + i] = p_other[i]; + } } template <class T> bool Vector<T>::push_back(T p_elem) { - Error err = resize(size() + 1); ERR_FAIL_COND_V(err, true); set(size() - 1, p_elem); diff --git a/core/vmap.h b/core/vmap.h index 84ae1aaf66..c91ea9b3c9 100644 --- a/core/vmap.h +++ b/core/vmap.h @@ -38,14 +38,12 @@ template <class T, class V> class VMap { public: struct Pair { - T key; V value; _FORCE_INLINE_ Pair() {} _FORCE_INLINE_ Pair(const T &p_key, const V &p_value) { - key = p_key; value = p_value; } @@ -55,10 +53,10 @@ private: CowData<Pair> _cowdata; _FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const { - r_exact = false; - if (_cowdata.empty()) + if (_cowdata.empty()) { return 0; + } int low = 0; int high = _cowdata.size() - 1; @@ -66,8 +64,9 @@ private: int middle = 0; #ifdef DEBUG_ENABLED - if (low > high) + if (low > high) { ERR_PRINT("low > high, this may be a bug"); + } #endif while (low <= high) { middle = (low + high) / 2; @@ -83,15 +82,16 @@ private: } //return the position where this would be inserted - if (a[middle].key < p_val) + if (a[middle].key < p_val) { middle++; + } return middle; } _FORCE_INLINE_ int _find_exact(const T &p_val) const { - - if (_cowdata.empty()) + if (_cowdata.empty()) { return -1; + } int low = 0; int high = _cowdata.size() - 1; @@ -115,7 +115,6 @@ private: public: int insert(const T &p_key, const V &p_val) { - bool exact; int pos = _find(p_key, exact); if (exact) { @@ -127,25 +126,22 @@ public: } bool has(const T &p_val) const { - return _find_exact(p_val) != -1; } void erase(const T &p_val) { - int pos = _find_exact(p_val); - if (pos < 0) + if (pos < 0) { return; + } _cowdata.remove(pos); } int find(const T &p_val) const { - return _find_exact(p_val); } int find_nearest(const T &p_val) const { - bool exact; return _find(p_val, exact); } @@ -154,37 +150,30 @@ public: _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } const Pair *get_array() const { - return _cowdata.ptr(); } Pair *get_array() { - return _cowdata.ptrw(); } const V &getv(int p_index) const { - return _cowdata.get(p_index).value; } V &getv(int p_index) { - return _cowdata.get_m(p_index).value; } const T &getk(int p_index) const { - return _cowdata.get(p_index).key; } T &getk(int p_index) { - return _cowdata.get_m(p_index).key; } inline const V &operator[](const T &p_key) const { - int pos = _find_exact(p_key); CRASH_COND(pos < 0); @@ -193,7 +182,6 @@ public: } inline V &operator[](const T &p_key) { - int pos = _find_exact(p_key); if (pos < 0) { pos = insert(p_key, V()); @@ -202,11 +190,13 @@ public: return _cowdata.get_m(pos).value; } - _FORCE_INLINE_ VMap(){}; + _FORCE_INLINE_ VMap() {} _FORCE_INLINE_ VMap(const VMap &p_from) { _cowdata._ref(p_from._cowdata); } + inline VMap &operator=(const VMap &p_from) { _cowdata._ref(p_from._cowdata); return *this; } }; + #endif // VMAP_H diff --git a/core/vset.h b/core/vset.h index b96a115d21..034b8fe851 100644 --- a/core/vset.h +++ b/core/vset.h @@ -36,14 +36,13 @@ template <class T> class VSet { - Vector<T> _data; _FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const { - r_exact = false; - if (_data.empty()) + if (_data.empty()) { return 0; + } int low = 0; int high = _data.size() - 1; @@ -51,8 +50,9 @@ class VSet { int middle = 0; #ifdef DEBUG_ENABLED - if (low > high) + if (low > high) { ERR_PRINT("low > high, this may be a bug"); + } #endif while (low <= high) { @@ -69,15 +69,16 @@ class VSet { } //return the position where this would be inserted - if (a[middle] < p_val) + if (a[middle] < p_val) { middle++; + } return middle; } _FORCE_INLINE_ int _find_exact(const T &p_val) const { - - if (_data.empty()) + if (_data.empty()) { return -1; + } int low = 0; int high = _data.size() - 1; @@ -101,29 +102,27 @@ class VSet { public: void insert(const T &p_val) { - bool exact; int pos = _find(p_val, exact); - if (exact) + if (exact) { return; + } _data.insert(pos, p_val); } bool has(const T &p_val) const { - return _find_exact(p_val) != -1; } void erase(const T &p_val) { - int pos = _find_exact(p_val); - if (pos < 0) + if (pos < 0) { return; + } _data.remove(pos); } int find(const T &p_val) const { - return _find_exact(p_val); } @@ -132,12 +131,10 @@ public: _FORCE_INLINE_ int size() const { return _data.size(); } inline T &operator[](int p_index) { - return _data.write[p_index]; } inline const T &operator[](int p_index) const { - return _data[p_index]; } }; |