diff options
241 files changed, 7153 insertions, 2320 deletions
diff --git a/SConstruct b/SConstruct index bc89aa7540..f2f1ea57f3 100644 --- a/SConstruct +++ b/SConstruct @@ -367,13 +367,13 @@ if selected_platform in platform_list: if (config.can_build(selected_platform)): config.configure(env) env.module_list.append(x) - try: - doc_classes = config.get_doc_classes() - doc_path = config.get_doc_path() - for c in doc_classes: - env.doc_class_path[c]="modules/"+x+"/"+doc_path - except: - pass + try: + doc_classes = config.get_doc_classes() + doc_path = config.get_doc_path() + for c in doc_classes: + env.doc_class_path[c]="modules/"+x+"/"+doc_path + except: + pass sys.path.remove(tmppath) diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 0f217c8235..cfd7677d6b 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -33,6 +33,7 @@ #include "geometry.h" #include "io/file_access_compressed.h" #include "io/file_access_encrypted.h" +#include "io/json.h" #include "io/marshalls.h" #include "os/keyboard.h" #include "os/os.h" @@ -440,8 +441,8 @@ bool _OS::is_vsync_enabled() const { return OS::get_singleton()->is_vsync_enabled(); } -PowerState _OS::get_power_state() { - return OS::get_singleton()->get_power_state(); +_OS::PowerState _OS::get_power_state() { + return _OS::PowerState(OS::get_singleton()->get_power_state()); } int _OS::get_power_seconds_left() { @@ -2600,3 +2601,76 @@ _Engine *_Engine::singleton = NULL; _Engine::_Engine() { singleton = this; } + +void JSONParseResult::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_error"), &JSONParseResult::get_error); + ClassDB::bind_method(D_METHOD("get_error_string"), &JSONParseResult::get_error_string); + ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParseResult::get_error_line); + ClassDB::bind_method(D_METHOD("get_result"), &JSONParseResult::get_result); + + ClassDB::bind_method(D_METHOD("set_error", "error"), &JSONParseResult::set_error); + ClassDB::bind_method(D_METHOD("set_error_string", "error_string"), &JSONParseResult::set_error_string); + ClassDB::bind_method(D_METHOD("set_error_line", "error_line"), &JSONParseResult::set_error_line); + ClassDB::bind_method(D_METHOD("set_result", "result"), &JSONParseResult::set_result); + + ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error"); + ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line"); + ADD_PROPERTYNZ(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result"); +} + +void JSONParseResult::set_error(Error p_error) { + error = p_error; +} + +Error JSONParseResult::get_error() const { + return error; +} + +void JSONParseResult::set_error_string(const String &p_error_string) { + error_string = p_error_string; +} + +String JSONParseResult::get_error_string() const { + return error_string; +} + +void JSONParseResult::set_error_line(int p_error_line) { + error_line = p_error_line; +} + +int JSONParseResult::get_error_line() const { + return error_line; +} + +void JSONParseResult::set_result(const Variant &p_result) { + result = p_result; +} + +Variant JSONParseResult::get_result() const { + return result; +} + +void _JSON::_bind_methods() { + ClassDB::bind_method(D_METHOD("print", "value"), &_JSON::print); + ClassDB::bind_method(D_METHOD("parse", "json"), &_JSON::parse); +} + +String _JSON::print(const Variant &p_value) { + return JSON::print(p_value); +} + +Ref<JSONParseResult> _JSON::parse(const String &p_json) { + Ref<JSONParseResult> result; + result.instance(); + + result->error = JSON::parse(p_json, result->result, result->error_string, result->error_line); + + return result; +} + +_JSON *_JSON::singleton = NULL; + +_JSON::_JSON() { + singleton = this; +} diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 1a3782c471..721acf657f 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -36,7 +36,7 @@ #include "io/resource_saver.h" #include "os/dir_access.h" #include "os/file_access.h" -#include "os/power.h" +#include "os/os.h" #include "os/semaphore.h" #include "os/thread.h" @@ -97,6 +97,14 @@ protected: static _OS *singleton; public: + enum PowerState { + POWERSTATE_UNKNOWN, /**< cannot determine power status */ + POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */ + POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */ + POWERSTATE_CHARGING, /**< Plugged in, charging battery */ + POWERSTATE_CHARGED /**< Plugged in, battery charged */ + }; + enum Weekday { DAY_SUNDAY, DAY_MONDAY, @@ -312,6 +320,7 @@ public: _OS(); }; +VARIANT_ENUM_CAST(_OS::PowerState); VARIANT_ENUM_CAST(_OS::Weekday); VARIANT_ENUM_CAST(_OS::Month); VARIANT_ENUM_CAST(_OS::SystemDir); @@ -660,4 +669,50 @@ public: _Engine(); }; +class _JSON; + +class JSONParseResult : public Reference { + GDCLASS(JSONParseResult, Reference) + + friend class _JSON; + + Error error; + String error_string; + int error_line; + + Variant result; + +protected: + static void _bind_methods(); + +public: + void set_error(Error p_error); + Error get_error() const; + + void set_error_string(const String &p_error_string); + String get_error_string() const; + + void set_error_line(int p_error_line); + int get_error_line() const; + + void set_result(const Variant &p_result); + Variant get_result() const; +}; + +class _JSON : public Object { + GDCLASS(_JSON, Object) + +protected: + static void _bind_methods(); + static _JSON *singleton; + +public: + static _JSON *get_singleton() { return singleton; } + + String print(const Variant &p_value); + Ref<JSONParseResult> parse(const String &p_json); + + _JSON(); +}; + #endif // CORE_BIND_H diff --git a/core/color.cpp b/core/color.cpp index 259a4988b1..78b11a84df 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -250,6 +250,14 @@ Color Color::html(const String &p_color) { return Color(); if (color[0] == '#') color = color.substr(1, color.length() - 1); + if (color.length() == 3 || color.length() == 4) { + String exp_color; + for (int i = 0; i < color.length(); i++) { + exp_color += color[i]; + exp_color += color[i]; + } + color = exp_color; + } bool alpha = false; @@ -400,3 +408,122 @@ Color::operator String() const { return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a); } + +Color Color::operator+(const Color &p_color) const { + + return Color( + CLAMP(r + p_color.r, 0.0, 1.0), + CLAMP(g + p_color.g, 0.0, 1.0), + CLAMP(b + p_color.b, 0.0, 1.0), + CLAMP(a + p_color.a, 0.0, 1.0)); +} + +void Color::operator+=(const Color &p_color) { + + r = CLAMP(r + p_color.r, 0.0, 1.0); + g = CLAMP(g + p_color.g, 0.0, 1.0); + b = CLAMP(b + p_color.b, 0.0, 1.0); + a = CLAMP(a + p_color.a, 0.0, 1.0); +} + +Color Color::operator-(const Color &p_color) const { + + return Color( + CLAMP(r - p_color.r, 0.0, 1.0), + CLAMP(g - p_color.g, 0.0, 1.0), + CLAMP(b - p_color.b, 0.0, 1.0), + CLAMP(a - p_color.a, 0.0, 1.0)); +} + +void Color::operator-=(const Color &p_color) { + + r = CLAMP(r - p_color.r, 0.0, 1.0); + g = CLAMP(g - p_color.g, 0.0, 1.0); + b = CLAMP(b - p_color.b, 0.0, 1.0); + a = CLAMP(a - p_color.a, 0.0, 1.0); +} + +Color Color::operator*(const Color &p_color) const { + + return Color( + CLAMP(r * p_color.r, 0.0, 1.0), + CLAMP(g * p_color.g, 0.0, 1.0), + CLAMP(b * p_color.b, 0.0, 1.0), + CLAMP(a * p_color.a, 0.0, 1.0)); +} + +Color Color::operator*(const real_t &rvalue) const { + + return Color( + CLAMP(r * rvalue, 0.0, 1.0), + CLAMP(g * rvalue, 0.0, 1.0), + CLAMP(b * rvalue, 0.0, 1.0), + CLAMP(a * rvalue, 0.0, 1.0)); +} + +void Color::operator*=(const Color &p_color) { + + r = CLAMP(r * p_color.r, 0.0, 1.0); + g = CLAMP(g * p_color.g, 0.0, 1.0); + b = CLAMP(b * p_color.b, 0.0, 1.0); + a = CLAMP(a * p_color.a, 0.0, 1.0); +} + +void Color::operator*=(const real_t &rvalue) { + + r = CLAMP(r * rvalue, 0.0, 1.0); + g = CLAMP(g * rvalue, 0.0, 1.0); + b = CLAMP(b * rvalue, 0.0, 1.0); + a = CLAMP(a * rvalue, 0.0, 1.0); +}; + +Color Color::operator/(const Color &p_color) const { + + return Color( + p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0), + p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0), + p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0), + p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0)); +} + +Color Color::operator/(const real_t &rvalue) const { + + if (rvalue == 0) return Color(1.0, 1.0, 1.0, 1.0); + return Color( + CLAMP(r / rvalue, 0.0, 1.0), + CLAMP(g / rvalue, 0.0, 1.0), + CLAMP(b / rvalue, 0.0, 1.0), + CLAMP(a / rvalue, 0.0, 1.0)); +} + +void Color::operator/=(const Color &p_color) { + + r = p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0); + g = p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0); + b = p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0); + a = p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0); +} + +void Color::operator/=(const real_t &rvalue) { + + if (rvalue == 0) { + r = 1.0; + g = 1.0; + b = 1.0; + a = 1.0; + } else { + r = CLAMP(r / rvalue, 0.0, 1.0); + g = CLAMP(g / rvalue, 0.0, 1.0); + b = CLAMP(b / rvalue, 0.0, 1.0); + a = CLAMP(a / rvalue, 0.0, 1.0); + } +}; + +Color Color::operator-() const { + + return Color( + CLAMP(1.0 - r, 0.0, 1.0), + CLAMP(1.0 - g, 0.0, 1.0), + CLAMP(1.0 - b, 0.0, 1.0), + CLAMP(1.0 - a, 0.0, 1.0)); +} diff --git a/core/color.h b/core/color.h index d3d5db09f9..972b6a1b33 100644 --- a/core/color.h +++ b/core/color.h @@ -67,6 +67,23 @@ struct Color { return components[idx]; } + Color operator+(const Color &p_color) const; + void operator+=(const Color &p_color); + + Color operator-() const; + Color operator-(const Color &p_color) const; + void operator-=(const Color &p_color); + + Color operator*(const Color &p_color) const; + Color operator*(const real_t &rvalue) const; + void operator*=(const Color &p_color); + void operator*=(const real_t &rvalue); + + Color operator/(const Color &p_color) const; + Color operator/(const real_t &rvalue) const; + void operator/=(const Color &p_color); + void operator/=(const real_t &rvalue); + void invert(); void contrast(); Color inverted() const; diff --git a/core/hash_map.h b/core/hash_map.h index 37391a4c83..e100d7a904 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -37,39 +37,6 @@ #include "os/memory.h" #include "ustring.h" -struct HashMapHasherDefault { - static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } - static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } - static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } - - static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } - static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); } - static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } - static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } - static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; } - //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } -}; - -template <typename T> -struct HashMapComparatorDefault { - static bool compare(const T &p_lhs, const T &p_rhs) { - return p_lhs == p_rhs; - } - - bool compare(const float &p_lhs, const float &p_rhs) { - return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); - } - - bool compare(const double &p_lhs, const double &p_rhs) { - return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); - } -}; - /** * @class HashMap * @author Juan Linietsky <reduzio@gmail.com> diff --git a/core/hashfuncs.h b/core/hashfuncs.h index 56d40f1dd7..2880cc451e 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -33,6 +33,7 @@ #include "math_defs.h" #include "math_funcs.h" #include "typedefs.h" +#include "ustring.h" /** * Hashing functions @@ -128,4 +129,37 @@ static inline uint64_t make_uint64_t(T p_in) { return _u._u64; } +struct HashMapHasherDefault { + static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } + static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } + static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } + + static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash(uint64_t(p_int)); } + static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_djb2_one_float(p_float); } + static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_djb2_one_float(p_double); } + static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return p_int; } + static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return (uint32_t)p_int; } + static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return p_int; } + static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return (uint32_t)p_int; } + static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } + static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } + static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; } + //static _FORCE_INLINE_ uint32_t hash(const void* p_ptr) { return uint32_t(uint64_t(p_ptr))*(0x9e3779b1L); } +}; + +template <typename T> +struct HashMapComparatorDefault { + static bool compare(const T &p_lhs, const T &p_rhs) { + return p_lhs == p_rhs; + } + + bool compare(const float &p_lhs, const float &p_rhs) { + return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); + } + + bool compare(const double &p_lhs, const double &p_rhs) { + return (p_lhs == p_rhs) || (Math::is_nan(p_lhs) && Math::is_nan(p_rhs)); + } +}; + #endif diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 7132b6573e..2c587762e8 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -577,7 +577,7 @@ real_t CameraMatrix::get_fov() const { if ((matrix[8] == 0) && (matrix[9] == 0)) { return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0; } else { - // our frustum is asymetrical need to calculate the left planes angle seperately.. + // our frustum is asymmetrical need to calculate the left planes angle separately.. Plane left_plane = Plane(matrix[3] + matrix[0], matrix[7] + matrix[4], matrix[11] + matrix[8], diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h new file mode 100644 index 0000000000..66a1e348a1 --- /dev/null +++ b/core/oa_hash_map.h @@ -0,0 +1,593 @@ +/*************************************************************************/ +/* oa_hash_map.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef OA_HASH_MAP_H +#define OA_HASH_MAP_H + +#include "hashfuncs.h" +#include "math_funcs.h" +#include "os/copymem.h" +#include "os/memory.h" + +// uncomment this to disable intial local storage. +#define OA_HASH_MAP_INITIAL_LOCAL_STORAGE + +/** + * This class implements a hash map datastructure that uses open addressing with + * local probing. + * + * It can give huge performance improvements over a chained HashMap because of + * the increased data locality. + * + * Because of that locality property it's important to not use "large" value + * types as the "TData" type. If TData values are too big it can cause more + * cache misses then chaining. If larger values are needed then storing those + * in a separate array and using pointers or indices to reference them is the + * better solution. + * + * This hash map also implements real-time incremental rehashing. + * + */ +template <class TKey, class TData, + uint16_t INITIAL_NUM_ELEMENTS = 64, + class Hasher = HashMapHasherDefault, + class Comparator = HashMapComparatorDefault<TKey> > +class OAHashMap { + +private: +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + TData local_data[INITIAL_NUM_ELEMENTS]; + TKey local_keys[INITIAL_NUM_ELEMENTS]; + uint32_t local_hashes[INITIAL_NUM_ELEMENTS]; + uint8_t local_flags[INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)]; +#endif + + struct { + TData *data; + TKey *keys; + uint32_t *hashes; + + // This is actually an array of bits, 4 bit pairs per octet. + // | ba ba ba ba | ba ba ba ba | .... + // + // if a is set it means that there is an element present. + // if b is set it means that an element was deleted. This is needed for + // the local probing to work without relocating any succeeding and + // colliding entries. + uint8_t *flags; + + uint32_t capacity; + } table, old_table; + + bool is_rehashing; + uint32_t rehash_position; + uint32_t rehash_amount; + + uint32_t elements; + + /* Methods */ + + // returns true if the value already existed, false if it's a new entry + bool _raw_set_with_hash(uint32_t p_hash, const TKey &p_key, const TData &p_data) { + for (int i = 0; i < table.capacity; i++) { + + int pos = (p_hash + i) % table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset)); + bool is_deleted_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1)); + + if (is_filled_flag) { + if (table.hashes[pos] == p_hash && Comparator::compare(table.keys[pos], p_key)) { + table.data[pos] = p_data; + return true; + } + continue; + } + + table.keys[pos] = p_key; + table.data[pos] = p_data; + table.hashes[pos] = p_hash; + + table.flags[flags_pos] |= (1 << (2 * flags_pos_offset)); + table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset + 1)); + + return false; + } + return false; + } + +public: + _FORCE_INLINE_ uint32_t get_capacity() const { return table.capacity; } + _FORCE_INLINE_ uint32_t get_num_elements() const { return elements; } + + void set(const TKey &p_key, const TData &p_data) { + + uint32_t hash = Hasher::hash(p_key); + + // We don't progress the rehashing if the table just got resized + // to keep the cost of this function low. + if (is_rehashing) { + + // rehash progress + + for (int i = 0; i <= rehash_amount && rehash_position < old_table.capacity; rehash_position++) { + + int flags_pos = rehash_position / 4; + int flags_pos_offset = rehash_position % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + _raw_set_with_hash(old_table.hashes[rehash_position], old_table.keys[rehash_position], old_table.data[rehash_position]); + + old_table.keys[rehash_position].~TKey(); + old_table.data[rehash_position].~TData(); + + memnew_placement(&old_table.keys[rehash_position], TKey); + memnew_placement(&old_table.data[rehash_position], TData); + + old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); + old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); + } + } + + if (rehash_position >= old_table.capacity) { + + // wohooo, we can get rid of the old table. + is_rehashing = false; + +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + if (old_table.data == local_data) { + // Everything is local, so no cleanup :P + } else +#endif + { + memdelete_arr(old_table.data); + memdelete_arr(old_table.keys); + memdelete_arr(old_table.hashes); + memdelete_arr(old_table.flags); + } + } + } + + // Table is almost full, resize and start rehashing process. + if (elements >= table.capacity * 0.7) { + + old_table.capacity = table.capacity; + old_table.data = table.data; + old_table.flags = table.flags; + old_table.hashes = table.hashes; + old_table.keys = table.keys; + + table.capacity = old_table.capacity * 2; + + table.data = memnew_arr(TData, table.capacity); + table.flags = memnew_arr(uint8_t, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0)); + table.hashes = memnew_arr(uint32_t, table.capacity); + table.keys = memnew_arr(TKey, table.capacity); + + zeromem(table.flags, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0)); + + is_rehashing = true; + rehash_position = 0; + rehash_amount = (elements * 2) / (table.capacity * 0.7 - old_table.capacity); + } + + if (!_raw_set_with_hash(hash, p_key, p_data)) + elements++; + } + + /** + * returns true if the value was found, false otherwise. + * + * if r_data is not NULL then the value will be written to the object + * it points to. + */ + bool lookup(const TKey &p_key, TData *r_data) { + + uint32_t hash = Hasher::hash(p_key); + + bool check_old_table = is_rehashing; + bool check_new_table = true; + + // search for the key and return the value associated with it + // + // if we're rehashing we need to check both the old and the + // current table. If we find a value in the old table we still + // need to continue searching in the new table as it might have + // been added after + + TData *value = NULL; + + for (int i = 0; i < table.capacity; i++) { + + if (!check_new_table && !check_old_table) { + + break; + } + + // if we're rehashing check the old table + if (check_old_table && i < old_table.capacity) { + + int pos = (hash + i) % old_table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) { + value = &old_table.data[pos]; + check_old_table = false; + } + } else if (!is_deleted_flag) { + + // we hit an empty field here, we don't + // need to further check this old table + // because we know it's not in here. + + check_old_table = false; + } + } + + if (check_new_table) { + + int pos = (hash + i) % table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) { + if (r_data != NULL) + *r_data = table.data[pos]; + return true; + } + continue; + } else if (is_deleted_flag) { + continue; + } else if (value != NULL) { + + // We found a value in the old table + if (r_data != NULL) + *r_data = *value; + return true; + } else { + check_new_table = false; + } + } + } + + if (value != NULL) { + if (r_data != NULL) + *r_data = *value; + return true; + } + return false; + } + + _FORCE_INLINE_ bool has(const TKey &p_key) { + return lookup(p_key, NULL); + } + + void remove(const TKey &p_key) { + uint32_t hash = Hasher::hash(p_key); + + bool check_old_table = is_rehashing; + bool check_new_table = true; + + for (int i = 0; i < table.capacity; i++) { + + if (!check_new_table && !check_old_table) { + return; + } + + // if we're rehashing check the old table + if (check_old_table && i < old_table.capacity) { + + int pos = (hash + i) % old_table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) { + old_table.keys[pos].~TKey(); + old_table.data[pos].~TData(); + + memnew_placement(&old_table.keys[pos], TKey); + memnew_placement(&old_table.data[pos], TData); + + old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); + old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); + + elements--; + return; + } + } else if (!is_deleted_flag) { + + // we hit an empty field here, we don't + // need to further check this old table + // because we know it's not in here. + + check_old_table = false; + } + } + + if (check_new_table) { + + int pos = (hash + i) % table.capacity; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0; + + if (is_filled_flag) { + // found our entry? + if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) { + table.keys[pos].~TKey(); + table.data[pos].~TData(); + + memnew_placement(&table.keys[pos], TKey); + memnew_placement(&table.data[pos], TData); + + table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset)); + table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1)); + + // don't return here, this value might still be in the old table + // if it was already relocated. + + elements--; + return; + } + continue; + } else if (is_deleted_flag) { + continue; + } else { + check_new_table = false; + } + } + } + } + + struct Iterator { + bool valid; + + uint32_t hash; + + const TKey *key; + const TData *data; + + private: + friend class OAHashMap; + bool was_from_old_table; + }; + + Iterator iter() const { + Iterator it; + + it.valid = false; + it.was_from_old_table = false; + + bool check_old_table = is_rehashing; + + for (int i = 0; i < table.capacity; i++) { + + // if we're rehashing check the old table first + if (check_old_table && i < old_table.capacity) { + + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = old_table.hashes[pos]; + it.data = &old_table.data[pos]; + it.key = &old_table.keys[pos]; + + it.was_from_old_table = true; + + return it; + } + } + + { + + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = table.hashes[pos]; + it.data = &table.data[pos]; + it.key = &table.keys[pos]; + + return it; + } + } + } + + return it; + } + + Iterator next_iter(const Iterator &p_iter) const { + if (!p_iter.valid) { + return p_iter; + } + + Iterator it; + + it.valid = false; + it.was_from_old_table = false; + + bool check_old_table = is_rehashing; + + // we use this to skip the first check or not + bool was_from_old_table = p_iter.was_from_old_table; + + int prev_index = (p_iter.data - (p_iter.was_from_old_table ? old_table.data : table.data)); + + if (!was_from_old_table) { + prev_index++; + } + + for (int i = prev_index; i < table.capacity; i++) { + + // if we're rehashing check the old table first + if (check_old_table && i < old_table.capacity && !was_from_old_table) { + + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = old_table.hashes[pos]; + it.data = &old_table.data[pos]; + it.key = &old_table.keys[pos]; + + it.was_from_old_table = true; + + return it; + } + } + + was_from_old_table = false; + + { + int pos = i; + + int flags_pos = pos / 4; + int flags_pos_offset = pos % 4; + + bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0; + + if (is_filled_flag) { + it.valid = true; + it.hash = table.hashes[pos]; + it.data = &table.data[pos]; + it.key = &table.keys[pos]; + + return it; + } + } + } + + return it; + } + + OAHashMap(uint32_t p_initial_capacity = INITIAL_NUM_ELEMENTS) { + +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + + if (p_initial_capacity <= INITIAL_NUM_ELEMENTS) { + table.data = local_data; + table.keys = local_keys; + table.hashes = local_hashes; + table.flags = local_flags; + + zeromem(table.flags, INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)); + + table.capacity = INITIAL_NUM_ELEMENTS; + elements = 0; + } else +#endif + { + table.data = memnew_arr(TData, p_initial_capacity); + table.keys = memnew_arr(TKey, p_initial_capacity); + table.hashes = memnew_arr(uint32_t, p_initial_capacity); + table.flags = memnew_arr(uint8_t, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0)); + + zeromem(table.flags, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0)); + + table.capacity = p_initial_capacity; + elements = 0; + } + + is_rehashing = false; + rehash_position = 0; + } + + ~OAHashMap() { +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + if (table.capacity <= INITIAL_NUM_ELEMENTS) { + return; // Everything is local, so no cleanup :P + } +#endif + if (is_rehashing) { + +#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE + if (old_table.data == local_data) { + // Everything is local, so no cleanup :P + } else +#endif + { + memdelete_arr(old_table.data); + memdelete_arr(old_table.keys); + memdelete_arr(old_table.hashes); + memdelete_arr(old_table.flags); + } + } + + memdelete_arr(table.data); + memdelete_arr(table.keys); + memdelete_arr(table.hashes); + memdelete_arr(table.flags); + } +}; + +#endif diff --git a/core/object.cpp b/core/object.cpp index 23e32a214a..b1770f1d7a 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -277,32 +277,32 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name) : name(p_name), flags(METHOD_FLAG_NORMAL), + return_val(p_ret), id(0) { - return_val = p_ret; } MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1) : name(p_name), + return_val(p_ret), flags(METHOD_FLAG_NORMAL), id(0) { - return_val = p_ret; arguments.push_back(p_param1); } MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2) : name(p_name), + return_val(p_ret), flags(METHOD_FLAG_NORMAL), id(0) { - return_val = p_ret; arguments.push_back(p_param1); arguments.push_back(p_param2); } MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3) : name(p_name), + return_val(p_ret), flags(METHOD_FLAG_NORMAL), id(0) { - return_val = p_ret; arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -310,9 +310,9 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4) : name(p_name), + return_val(p_ret), flags(METHOD_FLAG_NORMAL), id(0) { - return_val = p_ret; arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); @@ -321,9 +321,9 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5) : name(p_name), + return_val(p_ret), flags(METHOD_FLAG_NORMAL), id(0) { - return_val = p_ret; arguments.push_back(p_param1); arguments.push_back(p_param2); arguments.push_back(p_param3); diff --git a/core/object.h b/core/object.h index 644e2b8270..3070439138 100644 --- a/core/object.h +++ b/core/object.h @@ -148,6 +148,7 @@ struct PropertyInfo { hint(PROPERTY_HINT_NONE), usage(PROPERTY_USAGE_DEFAULT) { } + PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = StringName()) : type(p_type), name(p_name), @@ -161,12 +162,12 @@ struct PropertyInfo { class_name = p_class_name; } } + PropertyInfo(const StringName &p_class_name) : type(Variant::OBJECT), + class_name(p_class_name), hint(PROPERTY_HINT_NONE), usage(PROPERTY_USAGE_DEFAULT) { - - class_name = p_class_name; } bool operator<(const PropertyInfo &p_info) const { diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index f24d6d16ca..1437e7cdfc 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -292,7 +292,7 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) { return full; } -Error DirAccess::copy(String p_from, String p_to) { +Error DirAccess::copy(String p_from, String p_to, int chmod_flags) { //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; @@ -329,6 +329,11 @@ Error DirAccess::copy(String p_from, String p_to) { fdst->store_8(fsrc->get_8()); } + if (err == OK && chmod_flags != -1) { + fdst->close(); + err = fdst->_chmod(p_to, chmod_flags); + } + memdelete(fsrc); memdelete(fdst); diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 6ad8b4c49b..7fa3ce5cf1 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -89,7 +89,7 @@ public: static bool exists(String p_dir); virtual size_t get_space_left() = 0; - virtual Error copy(String p_from, String p_to); + virtual Error copy(String p_from, String p_to, int chmod_flags = -1); virtual Error rename(String p_from, String p_to) = 0; virtual Error remove(String p_name) = 0; diff --git a/core/os/file_access.h b/core/os/file_access.h index 8e5728f525..63692cb290 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -140,6 +140,8 @@ public: virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType + virtual Error _chmod(const String &p_path, int p_mod) { return FAILED; } + static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files. static FileAccess *create_for_path(const String &p_path); static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files. diff --git a/core/os/os.cpp b/core/os/os.cpp index 764f7fe6e6..437ce01a5e 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -485,7 +485,7 @@ bool OS::is_vsync_enabled() const { return true; } -PowerState OS::get_power_state() { +OS::PowerState OS::get_power_state() { return POWERSTATE_UNKNOWN; } int OS::get_power_seconds_left() { diff --git a/core/os/os.h b/core/os/os.h index c378d36a35..2fc87e44a0 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -34,7 +34,6 @@ #include "image.h" #include "list.h" #include "os/main_loop.h" -#include "power.h" #include "ustring.h" #include "vector.h" #include <stdarg.h> @@ -65,6 +64,14 @@ class OS { public: typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection); + enum PowerState { + POWERSTATE_UNKNOWN, /**< cannot determine power status */ + POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */ + POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */ + POWERSTATE_CHARGING, /**< Plugged in, charging battery */ + POWERSTATE_CHARGED /**< Plugged in, battery charged */ + }; + enum RenderThreadMode { RENDER_THREAD_UNSAFE, @@ -413,7 +420,7 @@ public: virtual void set_use_vsync(bool p_enable); virtual bool is_vsync_enabled() const; - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); @@ -431,6 +438,6 @@ public: virtual ~OS(); }; -VARIANT_ENUM_CAST(PowerState); +VARIANT_ENUM_CAST(OS::PowerState); #endif diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 72d40b42c3..7ea0d563a6 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -307,8 +307,8 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) { if (exec_path != "") { bool found = false; - // get our filename without our path (note, not using exec_path.get_basename anymore because not all file systems have dots in their file names!) - String filebase_name = exec_path.get_file(); + // get our filename without our path (note, using exec_path.get_file before get_basename anymore because not all file systems have dots in their file names!) + String filebase_name = exec_path.get_file().get_basename(); // try to open at the location of executable String datapack_name = exec_path.get_base_dir().plus_file(filebase_name) + ".pck"; diff --git a/core/reference.cpp b/core/reference.cpp index bb70628cbe..7f93922d22 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -33,7 +33,7 @@ bool Reference::init_ref() { - if (refcount.ref()) { + if (reference()) { // this may fail in the scenario of two threads assigning the pointer for the FIRST TIME // at the same time, which is never likely to happen (would be crazy to do) @@ -41,7 +41,7 @@ bool Reference::init_ref() { if (refcount_init.get() > 0) { refcount_init.unref(); - refcount.unref(); // first referencing is already 1, so compensate for the ref above + unreference(); // first referencing is already 1, so compensate for the ref above } return true; @@ -62,13 +62,16 @@ int Reference::reference_get_count() const { return refcount.get(); } -void Reference::reference() { +bool Reference::reference() { + bool success = refcount.ref(); - refcount.ref(); - if (get_script_instance()) { + if (success && get_script_instance()) { get_script_instance()->refcount_incremented(); } + + return success; } + bool Reference::unreference() { bool die = refcount.unref(); diff --git a/core/reference.h b/core/reference.h index ca3ae60418..bafc164276 100644 --- a/core/reference.h +++ b/core/reference.h @@ -51,7 +51,7 @@ protected: public: _FORCE_INLINE_ bool is_referenced() const { return refcount_init.get() < 1; } bool init_ref(); - void reference(); + bool reference(); // returns false if refcount is at zero and didn't get increased bool unreference(); int reference_get_count() const; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 27c31127a4..0e34a3eea5 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -68,6 +68,7 @@ static _Engine *_engine = NULL; static _ClassDB *_classdb = NULL; static _Marshalls *_marshalls = NULL; static TranslationLoaderPO *resource_format_po = NULL; +static _JSON *_json = NULL; static IP *ip = NULL; @@ -162,6 +163,8 @@ void register_core_types() { ClassDB::register_class<AStar>(); ClassDB::register_class<EncodedObjectAsID>(); + ClassDB::register_class<JSONParseResult>(); + ip = IP::create(); _geometry = memnew(_Geometry); @@ -172,6 +175,7 @@ void register_core_types() { _engine = memnew(_Engine); _classdb = memnew(_ClassDB); _marshalls = memnew(_Marshalls); + _json = memnew(_JSON); } void register_core_settings() { @@ -193,6 +197,7 @@ void register_core_singletons() { ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("TranslationServer", TranslationServer::get_singleton())); ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Input", Input::get_singleton())); ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("InputMap", InputMap::get_singleton())); + ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JSON", _JSON::get_singleton())); } void unregister_core_types() { @@ -203,6 +208,7 @@ void unregister_core_types() { memdelete(_engine); memdelete(_classdb); memdelete(_marshalls); + memdelete(_json); memdelete(_geometry); diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 4760047959..27fc73ec63 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -503,6 +503,10 @@ void UndoRedo::_bind_methods() { ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history); ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name); ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version); + ClassDB::bind_method(D_METHOD("set_max_steps", "max_steps"), &UndoRedo::set_max_steps); + ClassDB::bind_method(D_METHOD("get_max_steps"), &UndoRedo::get_max_steps); + ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo); + ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo); BIND_ENUM_CONSTANT(MERGE_DISABLE); BIND_ENUM_CONSTANT(MERGE_ENDS); diff --git a/core/variant.cpp b/core/variant.cpp index 74f6b6a711..52bdd4e22d 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -903,9 +903,6 @@ bool Variant::is_one() const { void Variant::reference(const Variant &p_variant) { - if (this == &p_variant) - return; - clear(); type = p_variant.type; @@ -924,17 +921,14 @@ void Variant::reference(const Variant &p_variant) { case INT: { _data._int = p_variant._data._int; - } break; case REAL: { _data._real = p_variant._data._real; - } break; case STRING: { memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem))); - } break; // math types @@ -942,33 +936,24 @@ void Variant::reference(const Variant &p_variant) { case VECTOR2: { memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem))); - } break; case RECT2: { memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem))); - } break; case TRANSFORM2D: { _data._transform2d = memnew(Transform2D(*p_variant._data._transform2d)); - } break; case VECTOR3: { memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem))); - } break; case PLANE: { memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem))); - } break; - /* - case QUAT: { - - } break;*/ case RECT3: { _data._rect3 = memnew(Rect3(*p_variant._data._rect3)); @@ -986,7 +971,6 @@ void Variant::reference(const Variant &p_variant) { case TRANSFORM: { _data._transform = memnew(Transform(*p_variant._data._transform)); - } break; // misc types @@ -1058,6 +1042,7 @@ void Variant::reference(const Variant &p_variant) { default: {} } } + void Variant::zero() { switch (type) { case NIL: break; @@ -1073,6 +1058,7 @@ void Variant::zero() { default: this->clear(); break; } } + void Variant::clear() { switch (type) { @@ -1092,12 +1078,10 @@ void Variant::clear() { case TRANSFORM2D: { memdelete(_data._transform2d); - } break; case RECT3: { memdelete(_data._rect3); - } break; case BASIS: { @@ -1106,14 +1090,12 @@ void Variant::clear() { case TRANSFORM: { memdelete(_data._transform); - } break; // misc types case NODE_PATH: { reinterpret_cast<NodePath *>(_data._mem)->~NodePath(); - } break; case OBJECT: { @@ -1127,48 +1109,39 @@ void Variant::clear() { case DICTIONARY: { reinterpret_cast<Dictionary *>(_data._mem)->~Dictionary(); - } break; case ARRAY: { reinterpret_cast<Array *>(_data._mem)->~Array(); - } break; // arrays case POOL_BYTE_ARRAY: { reinterpret_cast<PoolVector<uint8_t> *>(_data._mem)->~PoolVector<uint8_t>(); - } break; case POOL_INT_ARRAY: { reinterpret_cast<PoolVector<int> *>(_data._mem)->~PoolVector<int>(); - } break; case POOL_REAL_ARRAY: { reinterpret_cast<PoolVector<real_t> *>(_data._mem)->~PoolVector<real_t>(); - } break; case POOL_STRING_ARRAY: { reinterpret_cast<PoolVector<String> *>(_data._mem)->~PoolVector<String>(); - } break; case POOL_VECTOR2_ARRAY: { reinterpret_cast<PoolVector<Vector2> *>(_data._mem)->~PoolVector<Vector2>(); - } break; case POOL_VECTOR3_ARRAY: { reinterpret_cast<PoolVector<Vector3> *>(_data._mem)->~PoolVector<Vector3>(); - } break; case POOL_COLOR_ARRAY: { reinterpret_cast<PoolVector<Color> *>(_data._mem)->~PoolVector<Color>(); - } break; default: {} /* not needed */ } @@ -2259,8 +2232,8 @@ Variant::Variant(const RefPtr &p_resource) { type = OBJECT; memnew_placement(_data._mem, ObjData); - REF ref = p_resource; - _get_obj().obj = ref.ptr(); + REF *ref = reinterpret_cast<REF *>(p_resource.get_data()); + _get_obj().obj = ref->ptr(); _get_obj().ref = p_resource; } @@ -2496,7 +2469,135 @@ Variant::Variant(const Vector<Color> &p_array) { void Variant::operator=(const Variant &p_variant) { - reference(p_variant); + if (this == &p_variant) + return; + + if (type != p_variant.type) { + reference(p_variant); + return; + } + + switch (p_variant.type) { + case NIL: { + + // none + } break; + + // atomic types + case BOOL: { + + _data._bool = p_variant._data._bool; + } break; + case INT: { + + _data._int = p_variant._data._int; + } break; + case REAL: { + + _data._real = p_variant._data._real; + } break; + case STRING: { + + *reinterpret_cast<String *>(_data._mem) = *reinterpret_cast<const String *>(p_variant._data._mem); + } break; + + // math types + + case VECTOR2: { + + *reinterpret_cast<Vector2 *>(_data._mem) = *reinterpret_cast<const Vector2 *>(p_variant._data._mem); + } break; + case RECT2: { + + *reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem); + } break; + case TRANSFORM2D: { + + *_data._transform2d = *(p_variant._data._transform2d); + } break; + case VECTOR3: { + + *reinterpret_cast<Vector3 *>(_data._mem) = *reinterpret_cast<const Vector3 *>(p_variant._data._mem); + } break; + case PLANE: { + + *reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem); + } break; + + case RECT3: { + + *_data._rect3 = *(p_variant._data._rect3); + } break; + case QUAT: { + + *reinterpret_cast<Quat *>(_data._mem) = *reinterpret_cast<const Quat *>(p_variant._data._mem); + } break; + case BASIS: { + + *_data._basis = *(p_variant._data._basis); + } break; + case TRANSFORM: { + + *_data._transform = *(p_variant._data._transform); + } break; + + // misc types + case COLOR: { + + *reinterpret_cast<Color *>(_data._mem) = *reinterpret_cast<const Color *>(p_variant._data._mem); + } break; + case _RID: { + + *reinterpret_cast<RID *>(_data._mem) = *reinterpret_cast<const RID *>(p_variant._data._mem); + } break; + case OBJECT: { + + *reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj(); + } break; + case NODE_PATH: { + + *reinterpret_cast<NodePath *>(_data._mem) = *reinterpret_cast<const NodePath *>(p_variant._data._mem); + } break; + case DICTIONARY: { + + *reinterpret_cast<Dictionary *>(_data._mem) = *reinterpret_cast<const Dictionary *>(p_variant._data._mem); + } break; + case ARRAY: { + + *reinterpret_cast<Array *>(_data._mem) = *reinterpret_cast<const Array *>(p_variant._data._mem); + } break; + + // arrays + case POOL_BYTE_ARRAY: { + + *reinterpret_cast<PoolVector<uint8_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<uint8_t> *>(p_variant._data._mem); + } break; + case POOL_INT_ARRAY: { + + *reinterpret_cast<PoolVector<int> *>(_data._mem) = *reinterpret_cast<const PoolVector<int> *>(p_variant._data._mem); + } break; + case POOL_REAL_ARRAY: { + + *reinterpret_cast<PoolVector<real_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<real_t> *>(p_variant._data._mem); + } break; + case POOL_STRING_ARRAY: { + + *reinterpret_cast<PoolVector<String> *>(_data._mem) = *reinterpret_cast<const PoolVector<String> *>(p_variant._data._mem); + } break; + case POOL_VECTOR2_ARRAY: { + + *reinterpret_cast<PoolVector<Vector2> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector2> *>(p_variant._data._mem); + } break; + case POOL_VECTOR3_ARRAY: { + + *reinterpret_cast<PoolVector<Vector3> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector3> *>(p_variant._data._mem); + } break; + case POOL_COLOR_ARRAY: { + + *reinterpret_cast<PoolVector<Color> *>(_data._mem) = *reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem); + } break; + default: {} + } } Variant::Variant(const IP_Address &p_address) { diff --git a/core/variant.h b/core/variant.h index c44608ebfa..5ea540a63f 100644 --- a/core/variant.h +++ b/core/variant.h @@ -43,7 +43,6 @@ #include "math_2d.h" #include "matrix3.h" #include "node_path.h" -#include "os/power.h" #include "plane.h" #include "quat.h" #include "rect3.h" @@ -71,6 +70,7 @@ typedef PoolVector<Color> PoolColorArray; class Variant { public: + // If this changes the table in variant_op must be updated enum Type { NIL, @@ -289,6 +289,7 @@ public: Variant(const IP_Address &p_address); + // If this changes the table in variant_op must be updated enum Operator { //comparation @@ -300,7 +301,7 @@ public: OP_GREATER_EQUAL, //mathematic OP_ADD, - OP_SUBSTRACT, + OP_SUBTRACT, OP_MULTIPLY, OP_DIVIDE, OP_NEGATE, @@ -389,7 +390,7 @@ public: uint32_t hash() const; bool hash_compare(const Variant &p_variant) const; - bool booleanize(bool &valid) const; + bool booleanize() const; void static_assign(const Variant &p_variant); static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index b6e114b853..5d47936679 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -33,49 +33,123 @@ #include "object.h" #include "script_language.h" -Variant::operator bool() const { - - bool b; - return booleanize(b); +#define CASE_TYPE_ALL(PREFIX, OP) \ + CASE_TYPE(PREFIX, OP, INT) \ + CASE_TYPE_ALL_BUT_INT(PREFIX, OP) + +#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \ + CASE_TYPE(PREFIX, OP, NIL) \ + CASE_TYPE(PREFIX, OP, BOOL) \ + CASE_TYPE(PREFIX, OP, REAL) \ + CASE_TYPE(PREFIX, OP, STRING) \ + CASE_TYPE(PREFIX, OP, VECTOR2) \ + CASE_TYPE(PREFIX, OP, RECT2) \ + CASE_TYPE(PREFIX, OP, VECTOR3) \ + CASE_TYPE(PREFIX, OP, TRANSFORM2D) \ + CASE_TYPE(PREFIX, OP, PLANE) \ + CASE_TYPE(PREFIX, OP, QUAT) \ + CASE_TYPE(PREFIX, OP, RECT3) \ + CASE_TYPE(PREFIX, OP, BASIS) \ + CASE_TYPE(PREFIX, OP, TRANSFORM) \ + CASE_TYPE(PREFIX, OP, COLOR) \ + CASE_TYPE(PREFIX, OP, NODE_PATH) \ + CASE_TYPE(PREFIX, OP, _RID) \ + CASE_TYPE(PREFIX, OP, OBJECT) \ + CASE_TYPE(PREFIX, OP, DICTIONARY) \ + CASE_TYPE(PREFIX, OP, ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_BYTE_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_INT_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_REAL_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_STRING_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY) \ + CASE_TYPE(PREFIX, OP, POOL_COLOR_ARRAY) + +#ifdef __GNUC__ +#define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE + +/* clang-format off */ +#define TYPES(PREFIX, OP) { \ + TYPE(PREFIX, OP, NIL), \ + TYPE(PREFIX, OP, BOOL), \ + TYPE(PREFIX, OP, INT), \ + TYPE(PREFIX, OP, REAL), \ + TYPE(PREFIX, OP, STRING), \ + TYPE(PREFIX, OP, VECTOR2), \ + TYPE(PREFIX, OP, RECT2), \ + TYPE(PREFIX, OP, VECTOR3), \ + TYPE(PREFIX, OP, TRANSFORM2D), \ + TYPE(PREFIX, OP, PLANE), \ + TYPE(PREFIX, OP, QUAT), \ + TYPE(PREFIX, OP, RECT3), \ + TYPE(PREFIX, OP, BASIS), \ + TYPE(PREFIX, OP, TRANSFORM), \ + TYPE(PREFIX, OP, COLOR), \ + TYPE(PREFIX, OP, NODE_PATH), \ + TYPE(PREFIX, OP, _RID), \ + TYPE(PREFIX, OP, OBJECT), \ + TYPE(PREFIX, OP, DICTIONARY), \ + TYPE(PREFIX, OP, ARRAY), \ + TYPE(PREFIX, OP, POOL_BYTE_ARRAY), \ + TYPE(PREFIX, OP, POOL_INT_ARRAY), \ + TYPE(PREFIX, OP, POOL_REAL_ARRAY), \ + TYPE(PREFIX, OP, POOL_STRING_ARRAY), \ + TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY), \ + TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY), \ + TYPE(PREFIX, OP, POOL_COLOR_ARRAY), \ +} +/* clang-format on */ + +#define CASES(PREFIX) static void *switch_table_##PREFIX[25][27] = { \ + TYPES(PREFIX, OP_EQUAL), \ + TYPES(PREFIX, OP_NOT_EQUAL), \ + TYPES(PREFIX, OP_LESS), \ + TYPES(PREFIX, OP_LESS_EQUAL), \ + TYPES(PREFIX, OP_GREATER), \ + TYPES(PREFIX, OP_GREATER_EQUAL), \ + TYPES(PREFIX, OP_ADD), \ + TYPES(PREFIX, OP_SUBTRACT), \ + TYPES(PREFIX, OP_MULTIPLY), \ + TYPES(PREFIX, OP_DIVIDE), \ + TYPES(PREFIX, OP_NEGATE), \ + TYPES(PREFIX, OP_POSITIVE), \ + TYPES(PREFIX, OP_MODULE), \ + TYPES(PREFIX, OP_STRING_CONCAT), \ + TYPES(PREFIX, OP_SHIFT_LEFT), \ + TYPES(PREFIX, OP_SHIFT_RIGHT), \ + TYPES(PREFIX, OP_BIT_AND), \ + TYPES(PREFIX, OP_BIT_OR), \ + TYPES(PREFIX, OP_BIT_XOR), \ + TYPES(PREFIX, OP_BIT_NEGATE), \ + TYPES(PREFIX, OP_AND), \ + TYPES(PREFIX, OP_OR), \ + TYPES(PREFIX, OP_XOR), \ + TYPES(PREFIX, OP_NOT), \ + TYPES(PREFIX, OP_IN), \ } -bool Variant::booleanize(bool &r_valid) const { +#define SWITCH(PREFIX, op, val) goto *switch_table_##PREFIX[op][val]; +#define SWITCH_OP(PREFIX, OP, val) +#define CASE_TYPE(PREFIX, OP, TYPE) PREFIX##_##OP##_##TYPE: + +#else +#define CASES(PREFIX) +#define SWITCH(PREFIX, op, val) switch (op) +#define SWITCH_OP(PREFIX, OP, val) \ + case OP: \ + switch (val) +#define CASE_TYPE(PREFIX, OP, TYPE) case TYPE: +#endif - r_valid = true; - switch (type) { - case NIL: return false; - case BOOL: return _data._bool; - case INT: return _data._int; - case REAL: return _data._real; - case STRING: return (*reinterpret_cast<const String *>(_data._mem)) != ""; - case VECTOR2: - case RECT2: - case TRANSFORM2D: - case VECTOR3: - case PLANE: - case RECT3: - case QUAT: - case BASIS: - case TRANSFORM: - case COLOR: - case _RID: return (*reinterpret_cast<const RID *>(_data._mem)).is_valid(); - case OBJECT: return _get_obj().obj; - case NODE_PATH: return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath(); - case DICTIONARY: - case ARRAY: - case POOL_BYTE_ARRAY: - case POOL_INT_ARRAY: - case POOL_REAL_ARRAY: - case POOL_STRING_ARRAY: - case POOL_VECTOR2_ARRAY: - case POOL_VECTOR3_ARRAY: - case POOL_COLOR_ARRAY: - r_valid = false; - return false; - default: {} - } +Variant::operator bool() const { - return false; + return booleanize(); +} + +// We consider all unitialized or empty types to be false based on the type's +// zeroiness. +bool Variant::booleanize() const { + return !is_zero(); } #define _RETURN(m_what) \ @@ -84,10 +158,15 @@ bool Variant::booleanize(bool &r_valid) const { return; \ } -#define DEFAULT_OP_NUM(m_op, m_name, m_type) \ - case m_name: { \ +#define _RETURN_FAIL \ + { \ + r_valid = false; \ + return; \ + } + +#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ - case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \ case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \ case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \ default: {} \ @@ -96,22 +175,55 @@ bool Variant::booleanize(bool &r_valid) const { return; \ }; -#define DEFAULT_OP_NUM_NEG(m_name, m_type) \ - case m_name: { \ - \ - _RETURN(-p_a._data.m_type); \ +#ifdef DEBUG_ENABLED +#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + switch (p_b.type) { \ + case INT: { \ + if (p_b._data._int == 0) { \ + r_valid = false; \ + _RETURN("Division By Zero"); \ + } \ + _RETURN(p_a._data.m_type / p_b._data._int); \ + } \ + case REAL: { \ + if (p_b._data._real == 0) { \ + r_valid = false; \ + _RETURN("Division By Zero"); \ + } \ + _RETURN(p_a._data.m_type / p_b._data._real); \ + } \ + default: {} \ + } \ + r_valid = false; \ + return; \ + }; +#else +#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + switch (p_b.type) { \ + case INT: _RETURN(p_a._data.m_type / p_b._data._int); \ + case REAL: _RETURN(p_a._data.m_type / p_b._data._real); \ + default: {} \ + } \ + r_valid = false; \ + return; \ }; +#endif -#define DEFAULT_OP_NUM_POS(m_name, m_type) \ - case m_name: { \ - \ - _RETURN(p_a._data.m_type); \ +#define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + _RETURN(-p_a._data.m_type); \ }; -#define DEFAULT_OP_NUM_VEC(m_op, m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + _RETURN(p_a._data.m_type); \ + }; + +#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ - case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \ case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \ case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \ case VECTOR2: _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ @@ -122,8 +234,19 @@ bool Variant::booleanize(bool &r_valid) const { return; \ }; -#define DEFAULT_OP_STR(m_op, m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + switch (p_b.type) { \ + case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \ + case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \ + default: {} \ + } \ + r_valid = false; \ + return; \ + }; + +#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ @@ -133,31 +256,36 @@ bool Variant::booleanize(bool &r_valid) const { return; \ }; -#define DEFAULT_OP_LOCALMEM(m_op, m_name, m_type) \ - case m_name: { \ - switch (p_b.type) { \ - case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - default: {} \ - } \ - r_valid = false; \ - return; \ - } +#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const m_type *>(p_a._data._mem)); \ + r_valid = false; \ + return; \ + }; + +#define DEFAULT_OP_LOCALMEM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ + r_valid = false; \ + return; \ + }; -#define DEFAULT_OP_LOCALMEM_NEG(m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_LOCALMEM_NEG(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ _RETURN(-*reinterpret_cast<const m_type *>(p_a._data._mem)); \ } -#define DEFAULT_OP_LOCALMEM_POS(m_name, m_type) \ - case m_name: { \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ +#define DEFAULT_OP_LOCALMEM_POS(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ } -#define DEFAULT_OP_LOCALMEM_NUM(m_op, m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ switch (p_b.type) { \ case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - case BOOL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._bool); \ case INT: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \ case REAL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._real); \ default: {} \ @@ -176,50 +304,51 @@ bool Variant::booleanize(bool &r_valid) const { return; \ } -#define DEFAULT_OP_PTRREF(m_op, m_name, m_sub) \ - case m_name: { \ - switch (p_b.type) { \ - case m_name: _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ - default: {} \ - } \ - r_valid = false; \ - return; \ +#define DEFAULT_OP_PTRREF(m_prefix, m_op_name, m_name, m_op, m_sub) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == m_name) \ + _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ + r_valid = false; \ + return; \ } -#define DEFAULT_OP_ARRAY_EQ(m_name, m_type) \ - DEFAULT_OP_ARRAY_OP(m_name, m_type, !=, !=, true, false, false) - -#define DEFAULT_OP_ARRAY_LT(m_name, m_type) \ - DEFAULT_OP_ARRAY_OP(m_name, m_type, <, !=, false, a_len < array_b.size(), true) - -#define DEFAULT_OP_ARRAY_OP(m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ - case m_name: { \ - if (p_a.type != p_b.type) { \ - r_valid = false; \ - return; \ - } \ - const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \ - const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \ - \ - int a_len = array_a.size(); \ - if (a_len m_opa array_b.size()) { \ - _RETURN(m_ret_s); \ - } else { \ - \ - PoolVector<m_type>::Read ra = array_a.read(); \ - PoolVector<m_type>::Read rb = array_b.read(); \ - \ - for (int i = 0; i < a_len; i++) { \ - if (ra[i] m_opb rb[i]) \ - _RETURN(m_ret_f); \ - } \ - \ - _RETURN(m_ret_def); \ - } \ +#define DEFAULT_OP_ARRAY_EQ(m_prefix, m_op_name, m_name, m_type) \ + DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, !=, !=, true, false, false) + +#define DEFAULT_OP_ARRAY_LT(m_prefix, m_op_name, m_name, m_type) \ + DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, <, !=, false, a_len < array_b.size(), true) + +#define DEFAULT_OP_ARRAY_GT(m_prefix, m_op_name, m_name, m_type) \ + DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, >, !=, false, a_len < array_b.size(), true) + +#define DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_a.type != p_b.type) { \ + r_valid = false; \ + return; \ + } \ + const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \ + const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \ + \ + int a_len = array_a.size(); \ + if (a_len m_opa array_b.size()) { \ + _RETURN(m_ret_s); \ + } else { \ + \ + PoolVector<m_type>::Read ra = array_a.read(); \ + PoolVector<m_type>::Read rb = array_b.read(); \ + \ + for (int i = 0; i < a_len; i++) { \ + if (ra[i] m_opb rb[i]) \ + _RETURN(m_ret_f); \ + } \ + \ + _RETURN(m_ret_def); \ + } \ } -#define DEFAULT_OP_ARRAY_ADD(m_name, m_type) \ - case m_name: { \ +#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ if (p_a.type != p_b.type) { \ r_valid = false; \ _RETURN(NIL); \ @@ -231,595 +360,646 @@ bool Variant::booleanize(bool &r_valid) const { _RETURN(sum); \ } -#define DEFAULT_OP_FAIL(m_name) \ - case m_name: { \ - r_valid = false; \ - return; \ - } - -void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid) { +void Variant::evaluate(const Operator &p_op, const Variant &p_a, + const Variant &p_b, Variant &r_ret, bool &r_valid) { + CASES(math); r_valid = true; - switch (p_op) { + SWITCH(math, p_op, p_a.type) { + SWITCH_OP(math, OP_EQUAL, p_a.type) { + CASE_TYPE(math, OP_EQUAL, NIL) { + if (p_b.type == NIL) _RETURN(true); + if (p_b.type == OBJECT) + _RETURN(p_b._get_obj().obj == NULL); + _RETURN_FAIL; + } - case OP_EQUAL: { + CASE_TYPE(math, OP_EQUAL, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; + _RETURN(p_a._data._bool == p_b._data._bool); + } - if ((int(p_a.type) * int(p_b.type)) == 0) { - //null case is an exception, one of both is null - if (p_a.type == p_b.type) //null against null is true - _RETURN(true); - //only against object is allowed - if (p_a.type == Variant::OBJECT) { + CASE_TYPE(math, OP_EQUAL, OBJECT) { + if (p_b.type == OBJECT) + _RETURN((p_a._get_obj().obj == p_b._get_obj().obj)); + if (p_b.type == NIL) _RETURN(p_a._get_obj().obj == NULL); - } else if (p_b.type == Variant::OBJECT) { - _RETURN(p_b._get_obj().obj == NULL); - } - //otherwise, always false - _RETURN(false); + _RETURN_FAIL; } - switch (p_a.type) { + CASE_TYPE(math, OP_EQUAL, DICTIONARY) { + if (p_b.type != DICTIONARY) + _RETURN_FAIL; + + const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); + const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); + + _RETURN(*arr_a == *arr_b); + } - case NIL: { + CASE_TYPE(math, OP_EQUAL, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - _RETURN(p_b.type == NIL || (p_b.type == Variant::OBJECT && !p_b._get_obj().obj)); - } break; + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - DEFAULT_OP_NUM(==, BOOL, _bool); - DEFAULT_OP_NUM(==, INT, _int); - DEFAULT_OP_NUM(==, REAL, _real); - DEFAULT_OP_STR(==, STRING, String); - DEFAULT_OP_LOCALMEM(==, VECTOR2, Vector2); - DEFAULT_OP_LOCALMEM(==, RECT2, Rect2); - DEFAULT_OP_PTRREF(==, TRANSFORM2D, _transform2d); - DEFAULT_OP_LOCALMEM(==, VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM(==, PLANE, Plane); - DEFAULT_OP_LOCALMEM(==, QUAT, Quat); - DEFAULT_OP_PTRREF(==, RECT3, _rect3); - DEFAULT_OP_PTRREF(==, BASIS, _basis); - DEFAULT_OP_PTRREF(==, TRANSFORM, _transform); + int l = arr_a->size(); + if (arr_b->size() != l) + _RETURN(false); + for (int i = 0; i < l; i++) { + if (!((*arr_a)[i] == (*arr_b)[i])) { + _RETURN(false); + } + } - DEFAULT_OP_LOCALMEM(==, COLOR, Color); - DEFAULT_OP_STR(==, NODE_PATH, NodePath); - DEFAULT_OP_LOCALMEM(==, _RID, RID); - case OBJECT: { + _RETURN(true); + } + + DEFAULT_OP_NUM(math, OP_EQUAL, INT, ==, _int); + DEFAULT_OP_NUM(math, OP_EQUAL, REAL, ==, _real); + DEFAULT_OP_STR(math, OP_EQUAL, STRING, ==, String); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, VECTOR2, ==, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, RECT2, ==, Rect2); + DEFAULT_OP_PTRREF(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, VECTOR3, ==, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, PLANE, ==, Plane); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, QUAT, ==, Quat); + DEFAULT_OP_PTRREF(math, OP_EQUAL, RECT3, ==, _rect3); + DEFAULT_OP_PTRREF(math, OP_EQUAL, BASIS, ==, _basis); + DEFAULT_OP_PTRREF(math, OP_EQUAL, TRANSFORM, ==, _transform); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, COLOR, ==, Color); + DEFAULT_OP_STR(math, OP_EQUAL, NODE_PATH, ==, NodePath); + DEFAULT_OP_LOCALMEM(math, OP_EQUAL, _RID, ==, RID); + + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_COLOR_ARRAY, Color); + } - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj == p_b._get_obj().obj)); - if (p_b.type == NIL) - _RETURN(!p_a._get_obj().obj); - } break; + SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) { + CASE_TYPE(math, OP_NOT_EQUAL, NIL) { + if (p_b.type == NIL) _RETURN(false); + if (p_b.type == OBJECT) + _RETURN(p_b._get_obj().obj != NULL); + _RETURN_FAIL; + } - case DICTIONARY: { + CASE_TYPE(math, OP_NOT_EQUAL, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; + _RETURN(p_a._data._bool != p_b._data._bool); + } - if (p_b.type != DICTIONARY) - _RETURN(false); + CASE_TYPE(math, OP_NOT_EQUAL, OBJECT) { + if (p_b.type == OBJECT) + _RETURN((p_a._get_obj().obj != p_b._get_obj().obj)); + if (p_b.type == NIL) + _RETURN(p_a._get_obj().obj != NULL); + _RETURN_FAIL; + } - const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); - const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); + CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) { + if (p_b.type != DICTIONARY) + _RETURN_FAIL; - _RETURN(*arr_a == *arr_b); + const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); + const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); - } break; - case ARRAY: { + _RETURN((*arr_a == *arr_b) == false); + } - if (p_b.type != ARRAY) - _RETURN(false); + CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - int l = arr_a->size(); - if (arr_b->size() != l) + int l = arr_a->size(); + if (arr_b->size() != l) + _RETURN(true); + for (int i = 0; i < l; i++) { + if (((*arr_a)[i] == (*arr_b)[i])) { _RETURN(false); - for (int i = 0; i < l; i++) { - if (!((*arr_a)[i] == (*arr_b)[i])) { - _RETURN(false); - } } + } - _RETURN(true); + _RETURN(true); + } + + DEFAULT_OP_NUM(math, OP_NOT_EQUAL, INT, !=, _int); + DEFAULT_OP_NUM(math, OP_NOT_EQUAL, REAL, !=, _real); + DEFAULT_OP_STR(math, OP_NOT_EQUAL, STRING, !=, String); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, RECT2, !=, Rect2); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, PLANE, !=, Plane); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, QUAT, !=, Quat); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, RECT3, !=, _rect3); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, BASIS, !=, _basis); + DEFAULT_OP_PTRREF(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, COLOR, !=, Color); + DEFAULT_OP_STR(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath); + DEFAULT_OP_LOCALMEM(math, OP_NOT_EQUAL, _RID, !=, RID); + + CASE_TYPE(math, OP_NOT_EQUAL, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_INT_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_NOT_EQUAL, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; + SWITCH_OP(math, OP_LESS, p_a.type) { + CASE_TYPE(math, OP_LESS, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; - DEFAULT_OP_ARRAY_EQ(POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_EQ(POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_EQ(POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_EQ(POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_EQ(POOL_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_EQ(POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_EQ(POOL_COLOR_ARRAY, Color); + if (p_a._data._bool == p_b._data._bool) + _RETURN(false); - case VARIANT_MAX: { - r_valid = false; - return; + if (p_a._data._bool && !p_b._data._bool) + _RETURN(false); - } break; + _RETURN(true); } - } break; - case OP_NOT_EQUAL: { - Variant res; - evaluate(OP_EQUAL, p_a, p_b, res, r_valid); - if (!r_valid) - return; - if (res.type == BOOL) - res._data._bool = !res._data._bool; - _RETURN(res); - - } break; - case OP_LESS: { - - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(<, BOOL, _bool); - DEFAULT_OP_NUM(<, INT, _int); - DEFAULT_OP_NUM(<, REAL, _real); - DEFAULT_OP_STR(<, STRING, String); - DEFAULT_OP_LOCALMEM(<, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(<, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_FAIL(QUAT); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_LOCALMEM(<, _RID, RID); - case OBJECT: { - - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj < p_b._get_obj().obj)); - } break; - DEFAULT_OP_FAIL(DICTIONARY); - case ARRAY: { - - if (p_b.type != ARRAY) - _RETURN(false); - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - - int l = arr_a->size(); - if (arr_b->size() < l) - _RETURN(false); - for (int i = 0; i < l; i++) { - if (!((*arr_a)[i] < (*arr_b)[i])) { - _RETURN(true); - } - } + CASE_TYPE(math, OP_LESS, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj < p_b._get_obj().obj)); + } - _RETURN(false); + CASE_TYPE(math, OP_LESS, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - } break; - DEFAULT_OP_ARRAY_LT(POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_LT(POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_LT(POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_LT(POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_LT(POOL_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(POOL_COLOR_ARRAY, Color); - case VARIANT_MAX: { - r_valid = false; - return; + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - } break; - } - - } break; - case OP_LESS_EQUAL: { - - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(<=, BOOL, _bool); - DEFAULT_OP_NUM(<=, INT, _int); - DEFAULT_OP_NUM(<=, REAL, _real); - DEFAULT_OP_STR(<=, STRING, String); - DEFAULT_OP_LOCALMEM(<=, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(<=, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_FAIL(QUAT); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_LOCALMEM(<=, _RID, RID); - case OBJECT: { - - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj)); - } break; - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + int l = arr_a->size(); + if (arr_b->size() < l) + _RETURN(false); + for (int i = 0; i < l; i++) { + if (!((*arr_a)[i] < (*arr_b)[i])) { + _RETURN(true); + } + } - } break; + _RETURN(false); } - } break; - case OP_GREATER: { + DEFAULT_OP_NUM(math, OP_LESS, INT, <, _int); + DEFAULT_OP_NUM(math, OP_LESS, REAL, <, _real); + DEFAULT_OP_STR(math, OP_LESS, STRING, <, String); + DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR2_ARRAY, Vector3); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_COLOR_ARRAY, Color); + + CASE_TYPE(math, OP_LESS, NIL) + CASE_TYPE(math, OP_LESS, RECT2) + CASE_TYPE(math, OP_LESS, TRANSFORM2D) + CASE_TYPE(math, OP_LESS, PLANE) + CASE_TYPE(math, OP_LESS, QUAT) + CASE_TYPE(math, OP_LESS, RECT3) + CASE_TYPE(math, OP_LESS, BASIS) + CASE_TYPE(math, OP_LESS, TRANSFORM) + CASE_TYPE(math, OP_LESS, COLOR) + CASE_TYPE(math, OP_LESS, NODE_PATH) + CASE_TYPE(math, OP_LESS, DICTIONARY) + _RETURN_FAIL; + } - Variant res; - evaluate(OP_LESS, p_b, p_a, res, r_valid); - if (!r_valid) - return; - _RETURN(res); + SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) { + CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj)); + } + + DEFAULT_OP_NUM(math, OP_LESS_EQUAL, INT, <=, _int); + DEFAULT_OP_NUM(math, OP_LESS_EQUAL, REAL, <=, _real); + DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String); + DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID); + + CASE_TYPE(math, OP_LESS_EQUAL, NIL) + CASE_TYPE(math, OP_LESS_EQUAL, BOOL) + CASE_TYPE(math, OP_LESS_EQUAL, RECT2) + CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D) + CASE_TYPE(math, OP_LESS_EQUAL, PLANE) + CASE_TYPE(math, OP_LESS_EQUAL, QUAT) + CASE_TYPE(math, OP_LESS_EQUAL, RECT3) + CASE_TYPE(math, OP_LESS_EQUAL, BASIS) + CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM) + CASE_TYPE(math, OP_LESS_EQUAL, COLOR) + CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH) + CASE_TYPE(math, OP_LESS_EQUAL, DICTIONARY) + CASE_TYPE(math, OP_LESS_EQUAL, ARRAY) + CASE_TYPE(math, OP_LESS_EQUAL, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_INT_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_LESS_EQUAL, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; - case OP_GREATER_EQUAL: { + SWITCH_OP(math, OP_GREATER, p_a.type) { + CASE_TYPE(math, OP_GREATER, BOOL) { + if (p_b.type != BOOL) + _RETURN_FAIL; - Variant res; - evaluate(OP_LESS_EQUAL, p_b, p_a, res, r_valid); - if (!r_valid) - return; - _RETURN(res); - } break; - //mathematic - case OP_ADD: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(+, BOOL, _bool); - DEFAULT_OP_NUM(+, INT, _int); - DEFAULT_OP_NUM(+, REAL, _real); - DEFAULT_OP_STR(+, STRING, String); - DEFAULT_OP_LOCALMEM(+, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(+, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_LOCALMEM(+, QUAT, Quat); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - - case ARRAY: { - if (p_a.type != p_b.type) { - r_valid = false; - return; - } - const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem); - const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem); - Array sum; - int asize = array_a.size(); - int bsize = array_b.size(); - sum.resize(asize + bsize); - for (int i = 0; i < asize; i++) - sum[i] = array_a[i]; - for (int i = 0; i < bsize; i++) - sum[i + asize] = array_b[i]; - _RETURN(sum); - } - DEFAULT_OP_ARRAY_ADD(POOL_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_ADD(POOL_INT_ARRAY, int); - DEFAULT_OP_ARRAY_ADD(POOL_REAL_ARRAY, real_t); - DEFAULT_OP_ARRAY_ADD(POOL_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_ADD(POOL_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_ADD(POOL_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_ADD(POOL_COLOR_ARRAY, Color); - case VARIANT_MAX: { - r_valid = false; - return; + if (p_a._data._bool == p_b._data._bool) + _RETURN(false); - } break; - } - } break; - case OP_SUBSTRACT: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(-, BOOL, _bool); - DEFAULT_OP_NUM(-, INT, _int); - DEFAULT_OP_NUM(-, REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM(-, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM(-, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - DEFAULT_OP_LOCALMEM(-, QUAT, Quat); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + if (!p_a._data._bool && p_b._data._bool) + _RETURN(false); - } break; + _RETURN(true); } - } break; - case OP_MULTIPLY: { - switch (p_a.type) { - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(*, BOOL, _bool); - DEFAULT_OP_NUM_VEC(*, INT, _int); - DEFAULT_OP_NUM_VEC(*, REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM_NUM(*, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - case TRANSFORM2D: { + CASE_TYPE(math, OP_GREATER, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj > p_b._get_obj().obj)); + } - if (p_b.type == TRANSFORM2D) { - _RETURN(*p_a._data._transform2d * *p_b._data._transform2d); - }; - if (p_b.type == VECTOR2) { - _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); - }; - r_valid = false; - return; - } break; - DEFAULT_OP_LOCALMEM_NUM(*, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - case QUAT: { - - switch (p_b.type) { - case VECTOR3: { - - _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem)); - } break; - case QUAT: { - - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem)); - } break; - case REAL: { - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real); - } break; - default: {} - }; - r_valid = false; - return; - } break; - DEFAULT_OP_FAIL(RECT3); - case BASIS: { + CASE_TYPE(math, OP_GREATER, ARRAY) { + if (p_b.type != ARRAY) + _RETURN_FAIL; - switch (p_b.type) { - case VECTOR3: { + const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); + const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem)); - }; - case BASIS: { + int l = arr_a->size(); + if (arr_b->size() > l) + _RETURN(false); + for (int i = 0; i < l; i++) { + if (((*arr_a)[i] < (*arr_b)[i])) { + _RETURN(false); + } + } - _RETURN(*p_a._data._basis * *p_b._data._basis); - }; - default: {} - }; - r_valid = false; - return; - } break; - case TRANSFORM: { + _RETURN(true); + } + + DEFAULT_OP_NUM(math, OP_GREATER, INT, >, _int); + DEFAULT_OP_NUM(math, OP_GREATER, REAL, >, _real); + DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR2_ARRAY, Vector3); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_COLOR_ARRAY, Color); + + CASE_TYPE(math, OP_GREATER, NIL) + CASE_TYPE(math, OP_GREATER, RECT2) + CASE_TYPE(math, OP_GREATER, TRANSFORM2D) + CASE_TYPE(math, OP_GREATER, PLANE) + CASE_TYPE(math, OP_GREATER, QUAT) + CASE_TYPE(math, OP_GREATER, RECT3) + CASE_TYPE(math, OP_GREATER, BASIS) + CASE_TYPE(math, OP_GREATER, TRANSFORM) + CASE_TYPE(math, OP_GREATER, COLOR) + CASE_TYPE(math, OP_GREATER, NODE_PATH) + CASE_TYPE(math, OP_GREATER, DICTIONARY) + _RETURN_FAIL; + } - switch (p_b.type) { - case VECTOR3: { + SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) { + CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) { + if (p_b.type != OBJECT) + _RETURN_FAIL; + _RETURN((p_a._get_obj().obj >= p_b._get_obj().obj)); + } + + DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, INT, >=, _int); + DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, REAL, >=, _real); + DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3); + DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID); + + CASE_TYPE(math, OP_GREATER_EQUAL, NIL) + CASE_TYPE(math, OP_GREATER_EQUAL, BOOL) + CASE_TYPE(math, OP_GREATER_EQUAL, RECT2) + CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D) + CASE_TYPE(math, OP_GREATER_EQUAL, PLANE) + CASE_TYPE(math, OP_GREATER_EQUAL, QUAT) + CASE_TYPE(math, OP_GREATER_EQUAL, RECT3) + CASE_TYPE(math, OP_GREATER_EQUAL, BASIS) + CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM) + CASE_TYPE(math, OP_GREATER_EQUAL, COLOR) + CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH) + CASE_TYPE(math, OP_GREATER_EQUAL, DICTIONARY) + CASE_TYPE(math, OP_GREATER_EQUAL, ARRAY) + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_INT_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_GREATER_EQUAL, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem)); - }; - case TRANSFORM: { + SWITCH_OP(math, OP_ADD, p_a.type) { + CASE_TYPE(math, OP_ADD, ARRAY) { + if (p_a.type != p_b.type) + _RETURN_FAIL; + + const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem); + const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem); + Array sum; + int asize = array_a.size(); + int bsize = array_b.size(); + sum.resize(asize + bsize); + for (int i = 0; i < asize; i++) + sum[i] = array_a[i]; + for (int i = 0; i < bsize; i++) + sum[i + asize] = array_b[i]; + _RETURN(sum); + } + + DEFAULT_OP_NUM(math, OP_ADD, INT, +, _int); + DEFAULT_OP_NUM(math, OP_ADD, REAL, +, _real); + DEFAULT_OP_STR(math, OP_ADD, STRING, +, String); + DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat); + DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color); + + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_BYTE_ARRAY, uint8_t); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_INT_ARRAY, int); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_REAL_ARRAY, real_t); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_STRING_ARRAY, String); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR2_ARRAY, Vector2); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR3_ARRAY, Vector3); + DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_COLOR_ARRAY, Color); + + CASE_TYPE(math, OP_ADD, NIL) + CASE_TYPE(math, OP_ADD, BOOL) + CASE_TYPE(math, OP_ADD, RECT2) + CASE_TYPE(math, OP_ADD, TRANSFORM2D) + CASE_TYPE(math, OP_ADD, PLANE) + CASE_TYPE(math, OP_ADD, RECT3) + CASE_TYPE(math, OP_ADD, BASIS) + CASE_TYPE(math, OP_ADD, TRANSFORM) + CASE_TYPE(math, OP_ADD, NODE_PATH) + CASE_TYPE(math, OP_ADD, _RID) + CASE_TYPE(math, OP_ADD, OBJECT) + CASE_TYPE(math, OP_ADD, DICTIONARY) + _RETURN_FAIL; + } - _RETURN(*p_a._data._transform * *p_b._data._transform); - }; - default: {} - }; - r_valid = false; - return; - } break; - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + SWITCH_OP(math, OP_SUBTRACT, p_a.type) { + DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int); + DEFAULT_OP_NUM(math, OP_SUBTRACT, REAL, -, _real); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat); + DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color); + + CASE_TYPE(math, OP_SUBTRACT, NIL) + CASE_TYPE(math, OP_SUBTRACT, BOOL) + CASE_TYPE(math, OP_SUBTRACT, STRING) + CASE_TYPE(math, OP_SUBTRACT, RECT2) + CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D) + CASE_TYPE(math, OP_SUBTRACT, PLANE) + CASE_TYPE(math, OP_SUBTRACT, RECT3) + CASE_TYPE(math, OP_SUBTRACT, BASIS) + CASE_TYPE(math, OP_SUBTRACT, TRANSFORM) + CASE_TYPE(math, OP_SUBTRACT, NODE_PATH) + CASE_TYPE(math, OP_SUBTRACT, _RID) + CASE_TYPE(math, OP_SUBTRACT, OBJECT) + CASE_TYPE(math, OP_SUBTRACT, DICTIONARY) + CASE_TYPE(math, OP_SUBTRACT, ARRAY) + CASE_TYPE(math, OP_SUBTRACT, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_INT_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_SUBTRACT, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; + SWITCH_OP(math, OP_MULTIPLY, p_a.type) { + CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) { + switch (p_b.type) { + case TRANSFORM2D: { + _RETURN(*p_a._data._transform2d * *p_b._data._transform2d); + } + case VECTOR2: { + _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); + } + default: _RETURN_FAIL; + } } - } break; - case OP_DIVIDE: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM(/, BOOL, _bool); - case INT: { - switch (p_b.type) { - case BOOL: { - int64_t b = p_b._data._bool; - if (b == 0) { - r_valid = false; - _RETURN("Division By False"); - } - _RETURN(p_a._data._int / b); - - } break; - case INT: { - int64_t b = p_b._data._int; - if (b == 0) { + CASE_TYPE(math, OP_MULTIPLY, QUAT) { + switch (p_b.type) { + case VECTOR3: { + _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem)); + } + case QUAT: { + _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem)); + } + case REAL: { + _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real); + } + default: _RETURN_FAIL; + } + } - r_valid = false; - _RETURN("Division By Zero"); - } - _RETURN(p_a._data._int / b); + CASE_TYPE(math, OP_MULTIPLY, BASIS) { + switch (p_b.type) { + case VECTOR3: { + _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem)); + } + case BASIS: { + _RETURN(*p_a._data._basis * *p_b._data._basis); + } + default: _RETURN_FAIL; + } + } - } break; - case REAL: _RETURN(p_a._data._int / p_b._data._real); - default: {} + CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) { + switch (p_b.type) { + case VECTOR3: { + _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem)); } - r_valid = false; - return; - }; - DEFAULT_OP_NUM(/, REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM_NUM(/, VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM_NUM(/, VECTOR3, Vector3); - DEFAULT_OP_FAIL(PLANE); - case QUAT: { - if (p_b.type != REAL) { - r_valid = false; - return; + case TRANSFORM: { + _RETURN(*p_a._data._transform * *p_b._data._transform); } - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real); - } break; - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + default: _RETURN_FAIL; + } + } - } break; - } - - } break; - case OP_POSITIVE: { - // Simple case when user defines variable as +value. - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - DEFAULT_OP_NUM_POS(BOOL, _bool); - DEFAULT_OP_NUM_POS(INT, _int); - DEFAULT_OP_NUM_POS(REAL, _real); - DEFAULT_OP_LOCALMEM_POS(VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM_POS(PLANE, Plane); - DEFAULT_OP_LOCALMEM_POS(QUAT, Quat); - DEFAULT_OP_LOCALMEM_POS(VECTOR2, Vector2); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { - r_valid = false; - return; + DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int); + DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, REAL, *, _real); + DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2); + DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3); + DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color); + + CASE_TYPE(math, OP_MULTIPLY, NIL) + CASE_TYPE(math, OP_MULTIPLY, BOOL) + CASE_TYPE(math, OP_MULTIPLY, STRING) + CASE_TYPE(math, OP_MULTIPLY, RECT2) + CASE_TYPE(math, OP_MULTIPLY, PLANE) + CASE_TYPE(math, OP_MULTIPLY, RECT3) + CASE_TYPE(math, OP_MULTIPLY, NODE_PATH) + CASE_TYPE(math, OP_MULTIPLY, _RID) + CASE_TYPE(math, OP_MULTIPLY, OBJECT) + CASE_TYPE(math, OP_MULTIPLY, DICTIONARY) + CASE_TYPE(math, OP_MULTIPLY, ARRAY) + CASE_TYPE(math, OP_MULTIPLY, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_INT_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_MULTIPLY, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; - } - } break; - case OP_NEGATE: { - switch (p_a.type) { - - DEFAULT_OP_FAIL(NIL); - DEFAULT_OP_NUM_NEG(BOOL, _bool); - DEFAULT_OP_NUM_NEG(INT, _int); - DEFAULT_OP_NUM_NEG(REAL, _real); - DEFAULT_OP_FAIL(STRING); - DEFAULT_OP_LOCALMEM_NEG(VECTOR2, Vector2); - DEFAULT_OP_FAIL(RECT2); - DEFAULT_OP_FAIL(TRANSFORM2D); - DEFAULT_OP_LOCALMEM_NEG(VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM_NEG(PLANE, Plane); - DEFAULT_OP_LOCALMEM_NEG(QUAT, Quat); - DEFAULT_OP_FAIL(RECT3); - DEFAULT_OP_FAIL(BASIS); - DEFAULT_OP_FAIL(TRANSFORM); - - DEFAULT_OP_FAIL(COLOR); - - DEFAULT_OP_FAIL(NODE_PATH); - DEFAULT_OP_FAIL(_RID); - DEFAULT_OP_FAIL(OBJECT); - DEFAULT_OP_FAIL(DICTIONARY); - DEFAULT_OP_FAIL(ARRAY); - DEFAULT_OP_FAIL(POOL_BYTE_ARRAY); - DEFAULT_OP_FAIL(POOL_INT_ARRAY); - DEFAULT_OP_FAIL(POOL_REAL_ARRAY); - DEFAULT_OP_FAIL(POOL_STRING_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY); - DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY); - DEFAULT_OP_FAIL(POOL_COLOR_ARRAY); - case VARIANT_MAX: { + SWITCH_OP(math, OP_DIVIDE, p_a.type) { + CASE_TYPE(math, OP_DIVIDE, QUAT) { + if (p_b.type != REAL) + _RETURN_FAIL; +#ifdef DEBUG_ENABLED + if (p_b._data._real == 0) { r_valid = false; - return; + _RETURN("Division By Zero"); + } +#endif + _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real); + } + + DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int); + DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, REAL, _real); + DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2); + DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3); + DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color); + + CASE_TYPE(math, OP_DIVIDE, NIL) + CASE_TYPE(math, OP_DIVIDE, BOOL) + CASE_TYPE(math, OP_DIVIDE, STRING) + CASE_TYPE(math, OP_DIVIDE, RECT2) + CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D) + CASE_TYPE(math, OP_DIVIDE, PLANE) + CASE_TYPE(math, OP_DIVIDE, RECT3) + CASE_TYPE(math, OP_DIVIDE, BASIS) + CASE_TYPE(math, OP_DIVIDE, TRANSFORM) + CASE_TYPE(math, OP_DIVIDE, NODE_PATH) + CASE_TYPE(math, OP_DIVIDE, _RID) + CASE_TYPE(math, OP_DIVIDE, OBJECT) + CASE_TYPE(math, OP_DIVIDE, DICTIONARY) + CASE_TYPE(math, OP_DIVIDE, ARRAY) + CASE_TYPE(math, OP_DIVIDE, POOL_BYTE_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_INT_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_REAL_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_STRING_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR2_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR3_ARRAY); + CASE_TYPE(math, OP_DIVIDE, POOL_COLOR_ARRAY); + _RETURN_FAIL; + } - } break; - } - } break; - case OP_MODULE: { - if (p_a.type == INT && p_b.type == INT) { + SWITCH_OP(math, OP_POSITIVE, p_a.type) { + DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int); + DEFAULT_OP_NUM_POS(math, OP_POSITIVE, REAL, _real); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat); + DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2); + + CASE_TYPE(math, OP_POSITIVE, NIL) + CASE_TYPE(math, OP_POSITIVE, BOOL) + CASE_TYPE(math, OP_POSITIVE, STRING) + CASE_TYPE(math, OP_POSITIVE, RECT2) + CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D) + CASE_TYPE(math, OP_POSITIVE, RECT3) + CASE_TYPE(math, OP_POSITIVE, BASIS) + CASE_TYPE(math, OP_POSITIVE, TRANSFORM) + CASE_TYPE(math, OP_POSITIVE, COLOR) + CASE_TYPE(math, OP_POSITIVE, NODE_PATH) + CASE_TYPE(math, OP_POSITIVE, _RID) + CASE_TYPE(math, OP_POSITIVE, OBJECT) + CASE_TYPE(math, OP_POSITIVE, DICTIONARY) + CASE_TYPE(math, OP_POSITIVE, ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_BYTE_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_INT_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_REAL_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_STRING_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR2_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR3_ARRAY) + CASE_TYPE(math, OP_POSITIVE, POOL_COLOR_ARRAY) + _RETURN_FAIL; + } + + SWITCH_OP(math, OP_NEGATE, p_a.type) { + DEFAULT_OP_NUM_NEG(math, OP_NEGATE, INT, _int); + DEFAULT_OP_NUM_NEG(math, OP_NEGATE, REAL, _real); + + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat); + DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color); + + CASE_TYPE(math, OP_NEGATE, NIL) + CASE_TYPE(math, OP_NEGATE, BOOL) + CASE_TYPE(math, OP_NEGATE, STRING) + CASE_TYPE(math, OP_NEGATE, RECT2) + CASE_TYPE(math, OP_NEGATE, TRANSFORM2D) + CASE_TYPE(math, OP_NEGATE, RECT3) + CASE_TYPE(math, OP_NEGATE, BASIS) + CASE_TYPE(math, OP_NEGATE, TRANSFORM) + CASE_TYPE(math, OP_NEGATE, NODE_PATH) + CASE_TYPE(math, OP_NEGATE, _RID) + CASE_TYPE(math, OP_NEGATE, OBJECT) + CASE_TYPE(math, OP_NEGATE, DICTIONARY) + CASE_TYPE(math, OP_NEGATE, ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_BYTE_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_INT_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_REAL_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_STRING_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_VECTOR2_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_VECTOR3_ARRAY) + CASE_TYPE(math, OP_NEGATE, POOL_COLOR_ARRAY) + _RETURN_FAIL; + } + + SWITCH_OP(math, OP_MODULE, p_a.type) { + CASE_TYPE(math, OP_MODULE, INT) { + if (p_b.type != INT) + _RETURN_FAIL; #ifdef DEBUG_ENABLED if (p_b._data._int == 0) { r_valid = false; @@ -827,8 +1007,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant & } #endif _RETURN(p_a._data._int % p_b._data._int); + } - } else if (p_a.type == STRING) { + CASE_TYPE(math, OP_MODULE, STRING) { const String *format = reinterpret_cast<const String *>(p_a._data._mem); String result; @@ -847,119 +1028,143 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant & _RETURN(result); } - r_valid = false; - return; + CASE_TYPE(math, OP_MODULE, NIL) + CASE_TYPE(math, OP_MODULE, BOOL) + CASE_TYPE(math, OP_MODULE, REAL) + CASE_TYPE(math, OP_MODULE, VECTOR2) + CASE_TYPE(math, OP_MODULE, RECT2) + CASE_TYPE(math, OP_MODULE, VECTOR3) + CASE_TYPE(math, OP_MODULE, TRANSFORM2D) + CASE_TYPE(math, OP_MODULE, PLANE) + CASE_TYPE(math, OP_MODULE, QUAT) + CASE_TYPE(math, OP_MODULE, RECT3) + CASE_TYPE(math, OP_MODULE, BASIS) + CASE_TYPE(math, OP_MODULE, TRANSFORM) + CASE_TYPE(math, OP_MODULE, COLOR) + CASE_TYPE(math, OP_MODULE, NODE_PATH) + CASE_TYPE(math, OP_MODULE, _RID) + CASE_TYPE(math, OP_MODULE, OBJECT) + CASE_TYPE(math, OP_MODULE, DICTIONARY) + CASE_TYPE(math, OP_MODULE, ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_BYTE_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_INT_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_REAL_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_STRING_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_VECTOR2_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_VECTOR3_ARRAY) + CASE_TYPE(math, OP_MODULE, POOL_COLOR_ARRAY) + _RETURN_FAIL; + } - } break; - case OP_STRING_CONCAT: { + SWITCH_OP(math, OP_STRING_CONCAT, p_a.type) { + CASE_TYPE_ALL(math, OP_STRING_CONCAT) _RETURN(p_a.operator String() + p_b.operator String()); - } break; - //bitwise - case OP_SHIFT_LEFT: { - if (p_a.type == INT && p_b.type == INT) + } + + SWITCH_OP(math, OP_SHIFT_LEFT, p_a.type) { + CASE_TYPE(math, OP_SHIFT_LEFT, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int << p_b._data._int); + } - r_valid = false; - return; + CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT) + _RETURN_FAIL; + } - } break; - case OP_SHIFT_RIGHT: { - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_SHIFT_RIGHT, p_a.type) { + CASE_TYPE(math, OP_SHIFT_RIGHT, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int >> p_b._data._int); + } - r_valid = false; - return; + CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT) + _RETURN_FAIL; + } - } break; - case OP_BIT_AND: { - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_BIT_AND, p_a.type) { + CASE_TYPE(math, OP_BIT_AND, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int & p_b._data._int); + } - r_valid = false; - return; - - } break; - case OP_BIT_OR: { + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND) + _RETURN_FAIL; + } - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_BIT_OR, p_a.type) { + CASE_TYPE(math, OP_BIT_OR, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int | p_b._data._int); + } - r_valid = false; - return; - - } break; - case OP_BIT_XOR: { + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR) + _RETURN_FAIL; + } - if (p_a.type == INT && p_b.type == INT) + SWITCH_OP(math, OP_BIT_XOR, p_a.type) { + CASE_TYPE(math, OP_BIT_XOR, INT) { + if (p_b.type != INT) + _RETURN_FAIL; _RETURN(p_a._data._int ^ p_b._data._int); + } - r_valid = false; - return; - - } break; - case OP_BIT_NEGATE: { + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR) + _RETURN_FAIL; + } - if (p_a.type == INT) + SWITCH_OP(math, OP_BIT_NEGATE, p_a.type) { + CASE_TYPE(math, OP_BIT_NEGATE, INT) { _RETURN(~p_a._data._int); + } - r_valid = false; - return; + CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE) + _RETURN_FAIL; + } - } break; - //logic - case OP_AND: { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - bool r = p_b.booleanize(r_valid); - if (!r_valid) - return; + SWITCH_OP(math, OP_AND, p_a.type) { + CASE_TYPE_ALL(math, OP_AND) { + bool l = p_a.booleanize(); + bool r = p_b.booleanize(); - _RETURN(l && r); - } break; - case OP_OR: { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - bool r = p_b.booleanize(r_valid); - if (!r_valid) - return; + _RETURN(l && r); + } + } - _RETURN(l || r); + SWITCH_OP(math, OP_OR, p_a.type) { + CASE_TYPE_ALL(math, OP_OR) { + bool l = p_a.booleanize(); + bool r = p_b.booleanize(); - } break; - case OP_XOR: { - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - bool r = p_b.booleanize(r_valid); - if (!r_valid) - return; + _RETURN(l || r); + } + } - _RETURN((l || r) && !(l && r)); - } break; - case OP_NOT: { + SWITCH_OP(math, OP_XOR, p_a.type) { + CASE_TYPE_ALL(math, OP_XOR) { + bool l = p_a.booleanize(); + bool r = p_b.booleanize(); - bool l = p_a.booleanize(r_valid); - if (!r_valid) - return; - _RETURN(!l); + _RETURN((l || r) && !(l && r)); + } + } - } break; - case OP_IN: { + SWITCH_OP(math, OP_NOT, p_a.type) { + CASE_TYPE_ALL(math, OP_NOT) { + bool l = p_a.booleanize(); + _RETURN(!l); + } + } + SWITCH_OP(math, OP_IN, p_a.type) { + CASE_TYPE_ALL(math, OP_IN) _RETURN(p_b.in(p_a, &r_valid)); - - } break; - case OP_MAX: { - - r_valid = false; - ERR_FAIL(); } } - - r_valid = false; } void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) { @@ -1512,7 +1717,8 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) DEFAULT_OP_DVECTOR_SET(POOL_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) // 25 DEFAULT_OP_DVECTOR_SET(POOL_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3) DEFAULT_OP_DVECTOR_SET(POOL_COLOR_ARRAY, Color, p_value.type != Variant::COLOR) - default: return; + default: + return; } } @@ -1885,7 +2091,8 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const { DEFAULT_OP_DVECTOR_GET(POOL_VECTOR2_ARRAY, Vector2) // 25 DEFAULT_OP_DVECTOR_GET(POOL_VECTOR3_ARRAY, Vector3) DEFAULT_OP_DVECTOR_GET(POOL_COLOR_ARRAY, Color) - default: return Variant(); + default: + return Variant(); } return Variant(); @@ -2374,7 +2581,8 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const { return true; } break; - default: {} + default: { + } } valid = false; @@ -2401,7 +2609,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const { return true; } break; case VECTOR2: { - int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y; int64_t idx = r_iter; idx++; @@ -2793,7 +3001,9 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) r_dst = Color(r, g, b, a); } return; - default: { r_dst = c < 0.5 ? a : b; } + default: { + r_dst = c < 0.5 ? a : b; + } return; } } diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index 52df939fc5..b61cf93ef7 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -23,11 +23,11 @@ <argument index="3" name="a8" type="int"> </argument> <description> - Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8bits of information ranging from 0 to 255. - 'r8' red channel - 'g8' green channel - 'b8' blue channel - 'a8' alpha channel + Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8 bits of information ranging from 0 to 255. + [code]r8[/code] red channel + [code]g8[/code] green channel + [code]b8[/code] blue channel + [code]a8[/code] alpha channel [codeblock] red = Color8(255, 0, 0) [/codeblock] @@ -41,7 +41,7 @@ <argument index="1" name="alpha" type="float"> </argument> <description> - Returns color 'name' with alpha ranging from 0 to 1. Note: 'name' is defined in color_names.inc. + Returns color [code]name[/code] with [code]alpha[/code] ranging from 0 to 1. Note: [code]name[/code] is defined in color_names.inc. [codeblock] red = ColorN('red') [/codeblock] @@ -53,7 +53,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the absolute value of parameter 's' (i.e. unsigned value, works for integer and float). + Returns the absolute value of parameter [code]s[/code] (i.e. unsigned value, works for integer and float). [codeblock] # a is 1 a = abs(-1) @@ -66,7 +66,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the arc cosine of 's' in radians. Use to get the angle of cosine 's'. + Returns the arc cosine of [code]s[/code] in radians. Use to get the angle of cosine [code]s[/code]. [codeblock] # c is 0.523599 or 30 degrees if converted with rad2deg(s) c = acos(0.866025) @@ -79,10 +79,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the arc sine of 's' in radians. Use to get the angle of sine 's'. + Returns the arc sine of [code]s[/code] in radians. Use to get the angle of sine [code]s[/code]. [codeblock] # s is 0.523599 or 30 degrees if converted with rad2deg(s) - s = asin(0.5) + s = asin(0.5) [/codeblock] </description> </method> @@ -92,6 +92,14 @@ <argument index="0" name="condition" type="bool"> </argument> <description> + Assert that the [code]condition[/code] is true. If the [code]condition[/code] is false a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always true. + [codeblock] + # Speed should always be between 0 and 20 + speed = -10 + assert(speed < 20) # Is true and program continues + assert(speed >= 0) # Is false and program stops + assert(speed >= 0 && speed < 20) # Or combined + [/codeblock] </description> </method> <method name="atan"> @@ -100,6 +108,11 @@ <argument index="0" name="s" type="float"> </argument> <description> + Returns the arc tangent of [code]s[/code] in radians. Use it to get the angle from an angle's tangent in trigonometry: [code]atan(tan(angle)) == angle[/code]. + The method cannot know in which quadrant the angle should fall. See [method atan2] if you always want an exact angle. + [codeblock] + a = atan(0.5) # a is 0.463648 + [/codeblock] </description> </method> <method name="atan2"> @@ -110,10 +123,9 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the arc tangent of y/x in radians. Use to get the angle of tangent y/x. To compute the value, the function takes into account the sign of both arguments in order to determine the quadrant. + Returns the arc tangent of [code]y/x[/code] in radians. Use to get the angle of tangent [code]y/x[/code]. To compute the value, the method takes into account the sign of both arguments in order to determine the quadrant. [codeblock] - # a is 3.141593 - a = atan(0,-1) + a = atan(0,-1) # a is 3.141593 [/codeblock] </description> </method> @@ -123,7 +135,7 @@ <argument index="0" name="bytes" type="PoolByteArray"> </argument> <description> - Decode a byte array back to a value. + Decodes a byte array back to a value. </description> </method> <method name="ceil"> @@ -132,12 +144,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Rounds 's' upward, returning the smallest integral value that is not less than 's'. + Rounds [code]s[/code] upward, returning the smallest integral value that is not less than [code]s[/code]. [codeblock] - # i is 2 - i = ceil(1.45) - # i is 2 - i = ceil(1.001) + i = ceil(1.45) # i is 2 + i = ceil(1.001) # i is 2 [/codeblock] </description> </method> @@ -147,7 +157,7 @@ <argument index="0" name="ascii" type="int"> </argument> <description> - Returns a character as String of the given ASCII code. + Returns a character as a String of the given ASCII code. [codeblock] # a is 'A' a = char(65) @@ -166,7 +176,7 @@ <argument index="2" name="max" type="float"> </argument> <description> - Clamp 'val' and return a value not less than 'min' and not more than 'max'. + Clamps [code]val[/code] and returns a value not less than [code]min[/code] and not more than [code]max[/code]. [codeblock] speed = 1000 # a is 20 @@ -186,7 +196,7 @@ <argument index="1" name="type" type="int"> </argument> <description> - Convert from a type to another in the best way possible. The "type" parameter uses the enum TYPE_* in [@Global Scope]. + Converts from a type to another in the best way possible. The [code]type[/code] parameter uses the enum TYPE_* in [@Global Scope]. [codeblock] a = Vector2(1, 0) # prints 1 @@ -204,7 +214,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the cosine of angle 's' in radians. + Returns the cosine of angle [code]s[/code] in radians. [codeblock] # prints 1 and -1 print(cos(PI*2)) @@ -218,7 +228,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the hyperbolic cosine of 's' in radians. + Returns the hyperbolic cosine of [code]s[/code] in radians. [codeblock] # prints 1.543081 print(cosh(1)) @@ -231,7 +241,7 @@ <argument index="0" name="db" type="float"> </argument> <description> - Convert from decibels to linear energy (audio). + Converts from decibels to linear energy (audio). </description> </method> <method name="decimals"> @@ -240,7 +250,7 @@ <argument index="0" name="step" type="float"> </argument> <description> - Returns the number of digit places after the decimal that the first non-zero digit occurs. + Returns the position of the first non-zero digit, after the decimal point. [codeblock] # n is 2 n = decimals(0.035) @@ -257,7 +267,7 @@ <argument index="2" name="step" type="float"> </argument> <description> - Returns the result of 'value' decreased by 'step' * 'amount'. + Returns the result of [code]value[/code] decreased by [code]step[/code] * [code]amount[/code]. [codeblock] # a = 59 a = dectime(60, 10, 0.1)) @@ -283,7 +293,7 @@ <argument index="0" name="dict" type="Dictionary"> </argument> <description> - Convert a previously converted instance to dictionary back into an instance. Useful for deserializing. + Converts a previously converted instance to a dictionary, back into an instance. Useful for deserializing. </description> </method> <method name="ease"> @@ -303,7 +313,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns [b]e[/b] raised to the power of 's'. [b]e[/b] sometimes called "Euler's number" is a mathematical constant whose value is approximately 2.71828. + Raises the Euler's constant [b]e[/b] to the power of [code]s[/code] and returns it. [b]e[/b] has an approximate value of 2.71828. + [codeblock] + a = exp(2) # approximately 7.39 + [/codeblock] </description> </method> <method name="floor"> @@ -312,7 +325,13 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the largest integer value (rounded down) that is less than or equal to 's'. + Rounds [code]s[/code] to the closest smaller integer and returns it. + [codeblock] + # a is 2 + a = floor(2.99) + # a is -3 + a = floor(-2.99) + [/codeblock] </description> </method> <method name="fmod"> @@ -323,11 +342,11 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the floating-point remainder of x/y (rounded towards zero): + Returns the floating-point remainder of [code]x/y[/code]. [codeblock] - fmod = x - tquot * y + # remainder is 1.5 + var remainder = fmod(7, 5.5) [/codeblock] - Where tquot is the truncated (i.e., rounded towards zero) result of: x/y. </description> </method> <method name="fposmod"> @@ -338,6 +357,26 @@ <argument index="1" name="y" type="float"> </argument> <description> + Returns the floating-point remainder of [code]x/y[/code] that wraps equally in positive and negative. + [codeblock] + var i = -10; + while i < 0: + prints(i, fposmod(i, 10)) + i += 1 + [/codeblock] + Produces: + [codeblock] + -10 10 + -9 1 + -8 2 + -7 3 + -6 4 + -5 5 + -4 6 + -3 7 + -2 8 + -1 9 + [/codeblock] </description> </method> <method name="funcref"> @@ -348,6 +387,14 @@ <argument index="1" name="funcname" type="String"> </argument> <description> + Returns a reference to the specified function [code]funcname[/code] in the [code]instance[/code] node. As functions aren't first-class objects in GDscript, use [code]funcref[/code] to store a [FuncRef] in a variable and call it later. + [codeblock] + func foo(): + return("bar") + + a = funcref(self, "foo") + print(a.call_func()) # prints bar + [/codeblock] </description> </method> <method name="hash"> @@ -358,8 +405,7 @@ <description> Returns the integer hash of the variable passed. [codeblock] - # print 177670 - print(hash("a")) + print(hash("a")) # prints 177670 [/codeblock] </description> </method> @@ -369,7 +415,7 @@ <argument index="0" name="inst" type="Object"> </argument> <description> - Returns the passed instance converted a dictionary (useful for serializing). + Returns the passed instance converted to a dictionary (useful for serializing). [codeblock] var foo = "bar" func _ready(): @@ -390,15 +436,14 @@ <argument index="0" name="instance_id" type="int"> </argument> <description> - Returns the Object that corresponds to 'instance_id'. All Objects have a unique instance ID. + Returns the Object that corresponds to [code]instance_id[/code]. All Objects have a unique instance ID. [codeblock] var foo = "bar" func _ready(): var id = get_instance_id() var inst = instance_from_id(id) - print(inst.foo) + print(inst.foo) # prints bar [/codeblock] - Prints "bar" </description> </method> <method name="inverse_lerp"> @@ -413,7 +458,7 @@ <description> Returns a normalized value considering the given range. [codeblock] - inverse_lerp(3, 5, 4) # return 0.5 + inverse_lerp(3, 5, 4) # returns 0.5 [/codeblock] </description> </method> @@ -423,7 +468,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns True/False whether 's' is an infinity value (either positive infinity or negative infinity). + Returns True/False whether [code]s[/code] is an infinity value (either positive infinity or negative infinity). </description> </method> <method name="is_nan"> @@ -432,7 +477,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns True/False whether 's' is a NaN (Not-A-Number) value. + Returns True/False whether [code]s[/code] is a NaN (Not-A-Number) value. </description> </method> <method name="len"> @@ -441,12 +486,11 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Returns length of Variant 'var'. Length is the character count of String, element count of Array, size of Dictionary, etc. Note: Generates a fatal error if Variant can not provide a length. + Returns length of Variant [code]var[/code]. Length is the character count of String, element count of Array, size of Dictionary, etc. Note: Generates a fatal error if Variant can not provide a length. [codeblock] a = [1, 2, 3, 4] - print(len(a)) + len(a) # returns 4 [/codeblock] - Prints 4 </description> </method> <method name="lerp"> @@ -459,7 +503,10 @@ <argument index="2" name="weight" type="float"> </argument> <description> - Linear interpolates between two values by a normalized value. + Linearly interpolates between two values by a normalized value. + [codeblock] + lerp(1, 3, 0.5) # returns 2 + [/codeblock] </description> </method> <method name="linear2db"> @@ -468,7 +515,7 @@ <argument index="0" name="nrg" type="float"> </argument> <description> - Convert from linear energy to decibels (audio). + Converts from linear energy to decibels (audio). </description> </method> <method name="load"> @@ -477,7 +524,7 @@ <argument index="0" name="path" type="String"> </argument> <description> - Load a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Pannel and choosing "Copy Path". + Loads a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". [codeblock] # load a scene called main located in the root of the project directory var main = load("res://main.tscn") @@ -490,10 +537,9 @@ <argument index="0" name="s" type="float"> </argument> <description> - Natural logarithm. The amount of time needed to reach a certain level of continuous growth. Note: This is not the same as the log funcation on your calculator which is a base 10 logarithm. + Natural logarithm. The amount of time needed to reach a certain level of continuous growth. Note: This is not the same as the log function on your calculator which is a base 10 logarithm. [codeblock] - # a is 2.302585 - a = log(10) + log(10) # returns 2.302585 [/codeblock] </description> </method> @@ -507,10 +553,8 @@ <description> Returns the maximum of two values. [codeblock] - # a is 2 - a = max(1,2) - # a is -3.99 - a = max(-3.99, -4) + max(1,2) # returns 2 + max(-3.99, -4) # returns -3.99 [/codeblock] </description> </method> @@ -524,10 +568,8 @@ <description> Returns the minimum of two values. [codeblock] - # a is 1 - a = min(1,2) - # a is -4 - a = min(-3.99, -4) + min(1,2) # returns 1 + min(-3.99, -4) # returns -4 [/codeblock] </description> </method> @@ -537,14 +579,11 @@ <argument index="0" name="val" type="int"> </argument> <description> - Returns the nearest larger power of 2 for an integer. + Returns the nearest larger power of 2 for integer [code]val[/code]. [codeblock] - # a is 4 - a = nearest_po2(3) - # a is 4 - a = nearest_po2(4) - # a is 8 - a = nearest_po2(5) + nearest_po2(3) # returns 4 + nearest_po2(4) # returns 4 + nearest_po2(5) # returns 8 [/codeblock] </description> </method> @@ -555,11 +594,11 @@ </argument> <description> Parse JSON text to a Variant (use [method typeof] to check if it is what you expect). - Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert every numerical values to [float] types. + Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to [float] types. [codeblock] p = parse_json('["a", "b", "c"]') if typeof(p) == TYPE_ARRAY: - print(p[0]) + print(p[0]) # prints a else: print("unexpected results") [/codeblock] @@ -573,10 +612,9 @@ <argument index="1" name="y" type="float"> </argument> <description> - Returns the result of 'x' raised to the power of 'y'. + Returns the result of [code]x[/code] raised to the power of [code]y[/code]. [codeblock] - # a is 32 - a = pow(2,5) + pow(2,5) # returns 32 [/codeblock] </description> </method> @@ -586,10 +624,11 @@ <argument index="0" name="path" type="String"> </argument> <description> - Returns a resource from the filesystem that is loaded during script parsing. Note: resource paths can be obtained by right clicking on a resource in the Assets Pannel and choosing "Copy Path". + Returns a resource from the filesystem that is loaded during script parsing. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". [codeblock] # load a scene called main located in the root of the project directory var main = preload("res://main.tscn") + [/codeblock] </description> </method> <method name="print" qualifiers="vararg"> @@ -599,44 +638,61 @@ Converts one or more arguments to strings in the best way possible and prints them to the console. [codeblock] a = [1,2,3] - print("a","b",a) + print("a","b",a) # prints ab[1, 2, 3] [/codeblock] - Prints ab[1, 2, 3] </description> </method> <method name="print_stack"> <return type="void"> </return> <description> - Print a stack track at code location, only works when running with debugger turned on. + Prints a stack track at code location, only works when running with debugger turned on. + Output in the console would look something like this: + [codeblock] + Frame 0 - res://test.gd:16 in function '_process' + [/codeblock] </description> </method> <method name="printerr" qualifiers="vararg"> <return type="void"> </return> <description> - Print one or more arguments to strings in the best way possible to standard error line. + Prints one or more arguments to strings in the best way possible to standard error line. + [codeblock] + printerr("prints to stderr") + [/codeblock] </description> </method> <method name="printraw" qualifiers="vararg"> <return type="void"> </return> <description> - Print one or more arguments to strings in the best way possible to console. No newline is added at the end. + Prints one or more arguments to strings in the best way possible to console. No newline is added at the end. + [codeblock] + printraw("A") + printraw("B") + # prints AB + [/codeblock] </description> </method> <method name="prints" qualifiers="vararg"> <return type="void"> </return> <description> - Print one or more arguments to the console with a space between each argument. + Prints one or more arguments to the console with a space between each argument. + [codeblock] + prints("A", "B", "C") # prints A B C + [/codeblock] </description> </method> <method name="printt" qualifiers="vararg"> <return type="void"> </return> <description> - Print one or more arguments to the console with a tab between each argument. + Prints one or more arguments to the console with a tab between each argument. + [codeblock] + printt("A", "B", "C") # prints A B C + [/codeblock] </description> </method> <method name="rad2deg"> @@ -645,7 +701,10 @@ <argument index="0" name="rad" type="float"> </argument> <description> - Convert from radians to degrees. + Converts from radians to degrees. + [codeblock] + rad2deg(0.523599) # returns 30 + [/codeblock] </description> </method> <method name="rand_range"> @@ -656,7 +715,10 @@ <argument index="1" name="to" type="float"> </argument> <description> - Random range, any floating point value between 'from' and 'to'. + Random range, any floating point value between [code]from[/code] and [code]to[/code]. + [codeblock] + prints(rand_range(0, 1), rand_range(0, 1)) # prints 0.135591 0.405263 + [/codeblock] </description> </method> <method name="rand_seed"> @@ -665,35 +727,70 @@ <argument index="0" name="seed" type="int"> </argument> <description> - Random from seed: pass a seed, and an array with both number and new seed is returned. "Seed" here refers to the internal state of the pseudo random number generator. The internal state of the current implementation is 64 bits. + Random from seed: pass a [code]seed[/code], and an array with both number and new seed is returned. "Seed" here refers to the internal state of the pseudo random number generator. The internal state of the current implementation is 64 bits. </description> </method> <method name="randf"> <return type="float"> </return> <description> - Return a random floating point value between 0 and 1. + Returns a random floating point value between 0 and 1. + [codeblock] + randf() # returns 0.375671 + [/codeblock] </description> </method> <method name="randi"> <return type="int"> </return> <description> - Return a random 32 bits integer value. To obtain a random value between 0 to N (where N is smaller than 2^32 - 1), you can use remainder. For example, to get a random integer between 0 and 19 inclusive, you can use randi() % 20. + Returns a random 32 bit integer. Use remainder to obtain a random value between 0 and N (where N is smaller than 2^32 -1). + [codeblock] + randi() % 20 # returns random number between 0 and 19 + randi() % 100 # returns random number between 0 and 99 + randi() % 100 + 1 # returns random number between 1 and 100 + [/codeblock] </description> </method> <method name="randomize"> <return type="void"> </return> <description> - Randomize the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time. + Randomizes the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time. + [codeblock] + func _ready(): + randomize() + [/codeblock] </description> </method> <method name="range" qualifiers="vararg"> <return type="Array"> </return> <description> - Return an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment). + Returns an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment). + [codeblock] + for i in range(4): + print(i) + for i in range(2, 5): + print(i) + for i in range(0, 6, 2): + print(i) + [/codeblock] + Output: + [codeblock] + 0 + 1 + 2 + 3 + + 2 + 3 + 4 + + 0 + 2 + 4 + [/codeblock] </description> </method> <method name="range_lerp"> @@ -710,7 +807,7 @@ <argument index="4" name="ostop" type="float"> </argument> <description> - Maps a value from range [istart, istop] to [ostart, ostop]. + Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code]. [codeblock] range_lerp(75, 0, 100, -1, 1) # returns 0.5 [/codeblock] @@ -722,7 +819,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the integral value that is nearest to s, with halfway cases rounded away from zero. + Returns the integral value that is nearest to [code]s[/code], with halfway cases rounded away from zero. + [codeblock] + round(2.6) # returns 3 + [/codeblock] </description> </method> <method name="seed"> @@ -731,7 +831,11 @@ <argument index="0" name="seed" type="int"> </argument> <description> - Set seed for the random number generator. + Sets seed for the random number generator. + [codeblock] + my_seed = "Godot Rocks" + seed(my_seed.hash()) + [/codeblock] </description> </method> <method name="sign"> @@ -740,7 +844,11 @@ <argument index="0" name="s" type="float"> </argument> <description> - Return sign (-1 or +1). + Returns sign of [code]s[/code] -1 or 1. + [codeblock] + sign(-6) # returns -1 + sign(6) # returns 1 + [/codeblock] </description> </method> <method name="sin"> @@ -749,7 +857,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the sine of an angle of s radians. + Returns the sine of angle [code]s[/code] in radians. + [codeblock] + sin(0.523599) # returns 0.5 + [/codeblock] </description> </method> <method name="sinh"> @@ -758,7 +869,11 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the hyperbolic sine of s. + Returns the hyperbolic sine of [code]s[/code]. + [codeblock] + a = log(2.0) # returns 0.693147 + sinh(a) # returns 0.75 + [/codeblock] </description> </method> <method name="sqrt"> @@ -767,7 +882,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the square root of s. + Returns the square root of [code]s[/code]. + [codeblock] + sqrt(9) # returns 3 + [/codeblock] </description> </method> <method name="stepify"> @@ -778,14 +896,20 @@ <argument index="1" name="step" type="float"> </argument> <description> - Snap float value to a given step. + Snaps float value [code]s[/code] to a given [code]step[/code]. </description> </method> <method name="str" qualifiers="vararg"> <return type="String"> </return> <description> - Convert one or more arguments to string in the best way possible. + Converts one or more arguments to string in the best way possible. + [codeblock] + var a = [10, 20, 30] + var b = str(a); + len(a) # returns 3 + len(b) # returns 12 + [/codeblock] </description> </method> <method name="str2var"> @@ -794,7 +918,12 @@ <argument index="0" name="string" type="String"> </argument> <description> - Convert a formatted string that was returned by [method var2str] to the original value. + Converts a formatted string that was returned by [method var2str] to the original value. + [codeblock] + a = '{ "a": 1, "b": 2 }' + b = str2var(a) + print(b['a']) # prints 1 + [/codeblock] </description> </method> <method name="tan"> @@ -803,7 +932,10 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the tangent of an angle of s radians. + Returns the tangent of angle [code]s[/code] in radians. + [codeblock] + tan( deg2rad(45) ) # returns 1 + [/codeblock] </description> </method> <method name="tanh"> @@ -812,7 +944,11 @@ <argument index="0" name="s" type="float"> </argument> <description> - Returns the hyperbolic tangent of s. + Returns the hyperbolic tangent of [code]s[/code]. + [codeblock] + a = log(2.0) # returns 0.693147 + tanh(a) # returns 0.6 + [/codeblock] </description> </method> <method name="to_json"> @@ -821,7 +957,12 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Convert a Variant to json text. + Converts a Variant [code]var[/code] to JSON text and return the result. Useful for serializing data to store or send over the network. + [codeblock] + a = { 'a': 1, 'b': 2 } + b = to_json(a) + print(b) # {"a":1, "b":2} + [/codeblock] </description> </method> <method name="type_exists"> @@ -830,7 +971,7 @@ <argument index="0" name="type" type="String"> </argument> <description> - Returns whether the given class is exist in [ClassDB]. + Returns whether the given class exists in [ClassDB]. [codeblock] type_exists("Sprite") # returns true type_exists("Variant") # returns false @@ -843,7 +984,14 @@ <argument index="0" name="what" type="Variant"> </argument> <description> - Return the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope]. + Returns the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope]. + [codeblock] + p = parse_json('["a", "b", "c"]') + if typeof(p) == TYPE_ARRAY: + print(p[0]) # prints a + else: + print("unexpected results") + [/codeblock] </description> </method> <method name="validate_json"> @@ -852,7 +1000,15 @@ <argument index="0" name="json" type="String"> </argument> <description> - This method is used to validate the structure and data types of a piece of JSON, similar to XML Schema for XML. + Checks that [code]json[/code] is valid JSON data. Returns empty string if valid. Returns error message if not valid. + [codeblock] + j = to_json([1, 2, 3]) + v = validate_json(j) + if not v: + print("valid") + else: + prints("invalid", v) + [/codeblock] </description> </method> <method name="var2bytes"> @@ -861,7 +1017,7 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Encode a variable value to a byte array. + Encodes a variable value to a byte array. </description> </method> <method name="var2str"> @@ -870,7 +1026,18 @@ <argument index="0" name="var" type="Variant"> </argument> <description> - Convert a value to a formatted string that can later be parsed using [method str2var]. + Converts a Variant [code]var[/code] to a formatted string that can later be parsed using [method str2var]. + [codeblock] + a = { 'a': 1, 'b': 2 } + print(var2str(a)) + [/codeblock] + prints + [codeblock] + { + "a": 1, + "b": 2 + } + [/codeblock] </description> </method> <method name="weakref"> @@ -879,7 +1046,7 @@ <argument index="0" name="obj" type="Object"> </argument> <description> - Return a weak reference to an object. + Returns a weak reference to an object. A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it. </description> </method> @@ -891,7 +1058,7 @@ <argument index="1" name="signal" type="String"> </argument> <description> - Stop the function execution and return the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state. + Stops the function execution and returns the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state. Returns anything that was passed to the resume function call. If passed an object and a signal, the execution is resumed when the object's signal is emitted. </description> </method> diff --git a/doc/classes/@Global Scope.xml b/doc/classes/@Global Scope.xml index 4044c4ed1f..a8fd377ecf 100644 --- a/doc/classes/@Global Scope.xml +++ b/doc/classes/@Global Scope.xml @@ -38,6 +38,8 @@ <member name="InputMap" type="InputMap" setter="" getter=""> [InputMap] singleton </member> + <member name="JSON" type="JSON" setter="" getter=""> + </member> <member name="Marshalls" type="Reference" setter="" getter=""> [Marshalls] singleton </member> diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml index 8821a450e5..4244e66a35 100644 --- a/doc/classes/AcceptDialog.xml +++ b/doc/classes/AcceptDialog.xml @@ -21,8 +21,8 @@ <argument index="2" name="action" type="String" default=""""> </argument> <description> - Add custom button to the dialog and return the created button. - The button titled with [i]text[/i] and the [i]action[/i] will be passed to [custom_action] signal when it is pressed. + Adds a button with label [i]text[/i] and a custom [i]action[/i] to the dialog and returns the created button. [i]action[/i] will be passed to the [custom_action] signal when pressed. + If [code]true[/code], [i]right[/i] will place the button to the right of any sibling buttons. Default value: [code]false[/code]. </description> </method> <method name="add_cancel"> @@ -31,7 +31,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Add custom cancel button to the dialog and return the created button. + Adds a button with label [i]name[/i] and a cancel action to the dialog and returns the created button. </description> </method> <method name="get_hide_on_ok" qualifiers="const"> @@ -68,7 +68,7 @@ <argument index="0" name="line_edit" type="Node"> </argument> <description> - Register a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted. + Registers a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted. </description> </method> <method name="set_hide_on_ok"> @@ -99,14 +99,14 @@ <signals> <signal name="confirmed"> <description> - Emitted when accepted. + Emitted when the dialog is accepted. </description> </signal> <signal name="custom_action"> <argument index="0" name="action" type="String"> </argument> <description> - Emitted with a custom button is added. + Emitted when a custom button is pressed. See [method add_button]. </description> </signal> </signals> diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml index ad9bc922e4..e128b4d865 100644 --- a/doc/classes/AnimationTreePlayer.xml +++ b/doc/classes/AnimationTreePlayer.xml @@ -659,5 +659,9 @@ <constant name="NODE_TRANSITION" value="9"> Transition node. </constant> + <constant name="ANIMATION_PROCESS_FIXED" value="0"> + </constant> + <constant name="ANIMATION_PROCESS_IDLE" value="1"> + </constant> </constants> </class> diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml index 4e366e124e..c59bbee084 100644 --- a/doc/classes/Area.xml +++ b/doc/classes/Area.xml @@ -493,5 +493,15 @@ </signal> </signals> <constants> + <constant name="SPACE_OVERRIDE_DISABLED" value="0"> + </constant> + <constant name="SPACE_OVERRIDE_COMBINE" value="1"> + </constant> + <constant name="SPACE_OVERRIDE_COMBINE_REPLACE" value="2"> + </constant> + <constant name="SPACE_OVERRIDE_REPLACE" value="3"> + </constant> + <constant name="SPACE_OVERRIDE_REPLACE_COMBINE" value="4"> + </constant> </constants> </class> diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml index d8b9dee9dc..e5c5a3b50e 100644 --- a/doc/classes/AudioEffectDistortion.xml +++ b/doc/classes/AudioEffectDistortion.xml @@ -93,5 +93,15 @@ </member> </members> <constants> + <constant name="MODE_CLIP" value="0"> + </constant> + <constant name="MODE_ATAN" value="1"> + </constant> + <constant name="MODE_LOFI" value="2"> + </constant> + <constant name="MODE_OVERDRIVE" value="3"> + </constant> + <constant name="MODE_WAVESHAPE" value="4"> + </constant> </constants> </class> diff --git a/doc/classes/AudioEffectFilter.xml b/doc/classes/AudioEffectFilter.xml index 6285539a61..17aa01d60a 100644 --- a/doc/classes/AudioEffectFilter.xml +++ b/doc/classes/AudioEffectFilter.xml @@ -77,5 +77,13 @@ </member> </members> <constants> + <constant name="FILTER_6DB" value="0"> + </constant> + <constant name="FILTER_12DB" value="1"> + </constant> + <constant name="FILTER_18DB" value="2"> + </constant> + <constant name="FILTER_24DB" value="3"> + </constant> </constants> </class> diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml index 7856537804..dc30c0c5f9 100644 --- a/doc/classes/AudioServer.xml +++ b/doc/classes/AudioServer.xml @@ -307,5 +307,11 @@ </signal> </signals> <constants> + <constant name="SPEAKER_MODE_STEREO" value="0"> + </constant> + <constant name="SPEAKER_SURROUND_51" value="2"> + </constant> + <constant name="SPEAKER_SURROUND_71" value="3"> + </constant> </constants> </class> diff --git a/doc/classes/AudioStreamOGGVorbis.xml b/doc/classes/AudioStreamOGGVorbis.xml index fd9018764d..679438b66b 100644 --- a/doc/classes/AudioStreamOGGVorbis.xml +++ b/doc/classes/AudioStreamOGGVorbis.xml @@ -56,10 +56,13 @@ </methods> <members> <member name="data" type="PoolByteArray" setter="set_data" getter="get_data"> + Raw audio data. </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop"> + If [code]true[/code], audio will loop continuously. Default value: [code]false[/code]. </member> <member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset"> + If loop is [code]true[/code], loop starts from this position, in seconds. </member> </members> <constants> diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml index 64823c3be5..edf5dd619b 100644 --- a/doc/classes/AudioStreamPlayer.xml +++ b/doc/classes/AudioStreamPlayer.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamPlayer" inherits="Node" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Plays back audio. </brief_description> <description> + Plays background audio. </description> <tutorials> </tutorials> @@ -57,6 +59,7 @@ <argument index="0" name="from_pos" type="float" default="0.0"> </argument> <description> + Plays the audio from the given position 'from_pos', in seconds. </description> </method> <method name="seek"> @@ -65,6 +68,7 @@ <argument index="0" name="to_pos" type="float"> </argument> <description> + Sets the position from which audio will be played, in seconds. </description> </method> <method name="set_autoplay"> @@ -111,29 +115,42 @@ <return type="void"> </return> <description> + Stops the audio. </description> </method> </methods> <members> <member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled"> + If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code]. </member> <member name="bus" type="String" setter="set_bus" getter="get_bus"> + Bus on which this audio is playing. </member> <member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget"> </member> <member name="playing" type="bool" setter="_set_playing" getter="is_playing"> + If [code]true[/code], audio is playing. </member> <member name="stream" type="AudioStream" setter="set_stream" getter="get_stream"> + The [AudioStream] object to be played. </member> <member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db"> + Volume of sound, in dB. </member> </members> <signals> <signal name="finished"> <description> + Emitted when the audio stops playing. </description> </signal> </signals> <constants> + <constant name="MIX_TARGET_STEREO" value="0"> + </constant> + <constant name="MIX_TARGET_SURROUND" value="1"> + </constant> + <constant name="MIX_TARGET_CENTER" value="2"> + </constant> </constants> </class> diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml index f2464ddac4..e31f2dd941 100644 --- a/doc/classes/AudioStreamPlayer2D.xml +++ b/doc/classes/AudioStreamPlayer2D.xml @@ -1,10 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamPlayer2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Plays audio in 2D. </brief_description> <description> + Plays audio that dampens with distance from screen center. </description> <tutorials> + http://docs.godotengine.org/en/latest/learning/features/audio/index.html </tutorials> <demos> </demos> @@ -69,6 +72,7 @@ <argument index="0" name="from_pos" type="float" default="0.0"> </argument> <description> + Plays the audio from the given position 'from_pos', in seconds. </description> </method> <method name="seek"> @@ -77,6 +81,7 @@ <argument index="0" name="to_pos" type="float"> </argument> <description> + Sets the position from which audio will be played, in seconds. </description> </method> <method name="set_area_mask"> @@ -139,30 +144,40 @@ <return type="void"> </return> <description> + Stops the audio. </description> </method> </methods> <members> <member name="area_mask" type="int" setter="set_area_mask" getter="get_area_mask"> + Areas in which this sound plays. </member> <member name="attenuation" type="float" setter="set_attenuation" getter="get_attenuation"> + Dampens audio over distance with this as an exponent. </member> <member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled"> + If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code]. </member> <member name="bus" type="String" setter="set_bus" getter="get_bus"> + Bus on which this audio is playing. </member> <member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance"> + Maximum distance from which audio is still hearable. </member> <member name="playing" type="bool" setter="_set_playing" getter="is_playing"> + If [code]true[/code], audio is playing. </member> <member name="stream" type="AudioStream" setter="set_stream" getter="get_stream"> + The [AudioStream] object to be played. </member> <member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db"> + Base volume without dampening. </member> </members> <signals> <signal name="finished"> <description> + Emitted when the audio stops playing. </description> </signal> </signals> diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml index 668e0cc0d2..3aad0ea87a 100644 --- a/doc/classes/AudioStreamPlayer3D.xml +++ b/doc/classes/AudioStreamPlayer3D.xml @@ -1,10 +1,13 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamPlayer3D" inherits="Spatial" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Plays 3D sound in 3D space </brief_description> <description> + Plays a sound effect with directed sound effects, dampens with distance if needed, generates effect of hearable position in space. </description> <tutorials> + http://docs.godotengine.org/en/latest/learning/features/audio/index.html </tutorials> <demos> </demos> @@ -123,6 +126,7 @@ <argument index="0" name="from_pos" type="float" default="0.0"> </argument> <description> + Plays the audio from the given position 'from_pos', in seconds. </description> </method> <method name="seek"> @@ -131,6 +135,7 @@ <argument index="0" name="to_pos" type="float"> </argument> <description> + Sets the position from which audio will be played, in seconds. </description> </method> <method name="set_area_mask"> @@ -265,67 +270,94 @@ <return type="void"> </return> <description> + Stops the audio. </description> </method> </methods> <members> <member name="area_mask" type="int" setter="set_area_mask" getter="get_area_mask"> + Areas in which this sound plays. </member> <member name="attenuation_filter_cutoff_hz" type="float" setter="set_attenuation_filter_cutoff_hz" getter="get_attenuation_filter_cutoff_hz"> + Dampens audio above this frequency, in Hz. </member> <member name="attenuation_filter_db" type="float" setter="set_attenuation_filter_db" getter="get_attenuation_filter_db"> + Amount how much the filter affects the loudness, in dB. </member> <member name="attenuation_model" type="int" setter="set_attenuation_model" getter="get_attenuation_model" enum="AudioStreamPlayer3D.AttenuationModel"> + Decides if audio should get quieter with distance linearly, quadratically or logarithmically. </member> <member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled"> + If [code]true[/code], audio plays audio plays when added to scene tree. Default value: [code]false[/code]. </member> <member name="bus" type="String" setter="set_bus" getter="get_bus"> + Bus on which this audio is playing. </member> <member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioStreamPlayer3D.DopplerTracking"> + Decides in which step the Doppler effect should be calculated. </member> <member name="emission_angle_degrees" type="float" setter="set_emission_angle" getter="get_emission_angle"> + The angle in which the audio reaches cameras undampened. </member> <member name="emission_angle_enabled" type="bool" setter="set_emission_angle_enabled" getter="is_emission_angle_enabled"> + If [code]true[/code], the audio should be dampened according to the direction of the sound. </member> <member name="emission_angle_filter_attenuation_db" type="float" setter="set_emission_angle_filter_attenuation_db" getter="get_emission_angle_filter_attenuation_db"> + dampens audio if camera is outside of 'emission_angle_degrees' and 'emission_angle_enabled' is set by this factor, in dB. </member> <member name="max_db" type="float" setter="set_max_db" getter="get_max_db"> + Sets the absolute maximum of the soundlevel, in dB. </member> <member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance"> + Sets the distance from wich the 'out_of_range_mode' takes effect. Has no effect if set to 0. </member> <member name="out_of_range_mode" type="int" setter="set_out_of_range_mode" getter="get_out_of_range_mode" enum="AudioStreamPlayer3D.OutOfRangeMode"> + Decides if audio should pause when source is outside of 'max_distance' range. </member> <member name="playing" type="bool" setter="_set_playing" getter="is_playing"> + If [code]true[/code], audio is playing. </member> <member name="stream" type="AudioStream" setter="set_stream" getter="get_stream"> + The [AudioStream] object to be played. </member> <member name="unit_db" type="float" setter="set_unit_db" getter="get_unit_db"> + Base sound level unaffected by dampening, in dB. </member> <member name="unit_size" type="float" setter="set_unit_size" getter="get_unit_size"> + Factor for the attenuation effect. </member> </members> <signals> <signal name="finished"> <description> + Fires when the audio stops playing. </description> </signal> </signals> <constants> <constant name="ATTENUATION_INVERSE_DISTANCE" value="0"> + Linear dampening of loudness according to distance. </constant> <constant name="ATTENUATION_INVERSE_SQUARE_DISTANCE" value="1"> + Squared dampening of loudness according to distance. </constant> <constant name="ATTENUATION_LOGARITHMIC" value="2"> + Logarithmic dampening of loudness according to distance. </constant> <constant name="OUT_OF_RANGE_MIX" value="0"> + Mix this audio in, even when it's out of range. </constant> <constant name="OUT_OF_RANGE_PAUSE" value="1"> + Pause this audio when it gets out of range. </constant> <constant name="DOPPLER_TRACKING_DISABLED" value="0"> + Disables doppler tracking. </constant> <constant name="DOPPLER_TRACKING_IDLE_STEP" value="1"> + Executes doppler trackin in idle step. </constant> <constant name="DOPPLER_TRACKING_FIXED_STEP" value="2"> + Executes doppler tracking in fixed step. </constant> </constants> </class> diff --git a/doc/classes/AudioStreamRandomPitch.xml b/doc/classes/AudioStreamRandomPitch.xml index 91856682e6..1573a78d1f 100644 --- a/doc/classes/AudioStreamRandomPitch.xml +++ b/doc/classes/AudioStreamRandomPitch.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamRandomPitch" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Plays audio with random pitch tweaking. </brief_description> <description> + Randomly varies pitch on each start. </description> <tutorials> </tutorials> @@ -40,8 +42,10 @@ </methods> <members> <member name="audio_stream" type="AudioStream" setter="set_audio_stream" getter="get_audio_stream"> + The current [AudioStream]. </member> <member name="random_pitch" type="float" setter="set_random_pitch" getter="get_random_pitch"> + The intensity of random pitch variation. </member> </members> <constants> diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml index e14a17a05c..7f7414e4d3 100644 --- a/doc/classes/AudioStreamSample.xml +++ b/doc/classes/AudioStreamSample.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="AudioStreamSample" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Plays audio. </brief_description> <description> + Plays audio, can loop. </description> <tutorials> </tutorials> @@ -110,20 +112,45 @@ </methods> <members> <member name="data" type="PoolByteArray" setter="set_data" getter="get_data"> + Raw audio data. </member> <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format"> + Audio format. See FORMAT_* constants for values. </member> <member name="loop_begin" type="int" setter="set_loop_begin" getter="get_loop_begin"> + Loop start in bytes. </member> <member name="loop_end" type="int" setter="set_loop_end" getter="get_loop_end"> + Loop end in bytes. </member> <member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamSample.LoopMode"> + Loop mode. See LOOP_* constants for values. </member> <member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate"> + The sample rate for mixing this audio. </member> <member name="stereo" type="bool" setter="set_stereo" getter="is_stereo"> + If [code]true[/code], audio is stereo. Default value: [code]false[/code]. </member> </members> <constants> + <constant name="FORMAT_8_BITS" value="0"> + Audio codec 8 bit. + </constant> + <constant name="FORMAT_16_BITS" value="1"> + Audio codec 16 bit. + </constant> + <constant name="FORMAT_IMA_ADPCM" value="2"> + Audio codec IMA ADPCM. + </constant> + <constant name="LOOP_DISABLED" value="0"> + Audio does not loop. + </constant> + <constant name="LOOP_FORWARD" value="1"> + Audio loops the data between loop_begin and loop_end playing forward only. + </constant> + <constant name="LOOP_PING_PONG" value="2"> + Audio loops the data between loop_begin and loop_end playing back and forth. + </constant> </constants> </class> diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml index f7e50f02d8..0c70d919f3 100644 --- a/doc/classes/BoxContainer.xml +++ b/doc/classes/BoxContainer.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="BoxContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Base class for Box containers. + Base class for box containers. </brief_description> <description> - Base class for Box containers. It arranges children controls vertically or horizontally, and rearranges them automatically when their minimum size changes. + Arranges child controls vertically or horizontally, and rearranges the controls automatically when their minimum size changes. </description> <tutorials> </tutorials> @@ -17,8 +17,7 @@ <argument index="0" name="begin" type="bool"> </argument> <description> - Add a control to the box as a spacer. - If [i]begin[/i] is true the spacer control will be inserted in front of other children. + Adds a control to the box as a spacer. If [code]true[/code], [i]begin[/i] will insert the spacer control in front of other children. </description> </method> <method name="get_alignment" qualifiers="const"> @@ -40,17 +39,18 @@ </methods> <members> <member name="alignment" type="int" setter="set_alignment" getter="get_alignment" enum="BoxContainer.AlignMode"> + The alignment of the container's children (must be one of ALIGN_BEGIN, ALIGN_CENTER, or ALIGN_END). </member> </members> <constants> <constant name="ALIGN_BEGIN" value="0"> - Align children with beginning of the container. + Aligns children with the beginning of the container. </constant> <constant name="ALIGN_CENTER" value="1"> - Align children with center of the container. + Aligns children with the center of the container. </constant> <constant name="ALIGN_END" value="2"> - Align children with end of the container. + Aligns children with the end of the container. </constant> </constants> </class> diff --git a/doc/classes/BoxShape.xml b/doc/classes/BoxShape.xml index 8c98c93b57..4e8eb0ba6f 100644 --- a/doc/classes/BoxShape.xml +++ b/doc/classes/BoxShape.xml @@ -4,7 +4,7 @@ Box shape resource. </brief_description> <description> - Box shape resource, which can be set into a [PhysicsBody] or area. + 3D box shape that can be a child of a [PhysicsBody] or [Area]. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="extents" type="Vector3" setter="set_extents" getter="get_extents"> + The shape's half extents. </member> </members> <constants> diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml index f19e7ef041..3ee1f10536 100644 --- a/doc/classes/CanvasLayer.xml +++ b/doc/classes/CanvasLayer.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CanvasLayer" inherits="Node" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Canvas Item layer. + Canvas drawing layer. </brief_description> <description> - Canvas Item layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below). + Canvas drawing layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below). </description> <tutorials> </tutorials> @@ -131,12 +131,16 @@ </methods> <members> <member name="layer" type="int" setter="set_layer" getter="get_layer"> + Layer index for draw order. Lower values are drawn first. Default value: [code]1[/code]. </member> <member name="offset" type="Vector2" setter="set_offset" getter="get_offset"> + The layer's base offset. </member> <member name="rotation" type="float" setter="set_rotationd" getter="get_rotationd"> + The layer's rotation in degrees. </member> <member name="scale" type="Vector2" setter="set_scale" getter="get_scale"> + The layer's scale. </member> </members> <constants> diff --git a/doc/classes/CapsuleShape.xml b/doc/classes/CapsuleShape.xml index 29072203ea..db075a504c 100644 --- a/doc/classes/CapsuleShape.xml +++ b/doc/classes/CapsuleShape.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CapsuleShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Capsule shape resource. + Capsule shape for collisions. </brief_description> <description> - Capsule shape resource, which can be set into a [PhysicsBody] or area. + Capsule shape for collisions. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="height" type="float" setter="set_height" getter="get_height"> + The capsule's height. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius"> + The capsule's radius. </member> </members> <constants> diff --git a/doc/classes/CapsuleShape2D.xml b/doc/classes/CapsuleShape2D.xml index 9c2b1c4a3d..df833e0582 100644 --- a/doc/classes/CapsuleShape2D.xml +++ b/doc/classes/CapsuleShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Capsule 2D shape resource for physics. + Capsule shape for 2D collisions. </brief_description> <description> - Capsule 2D shape resource for physics. A capsule (or sometimes called "pill") is like a line grown in all directions. It has a radius and a height, and is often useful for modeling biped characters. + Capsule shape for 2D collisions. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="height" type="float" setter="set_height" getter="get_height"> + The capsule's height. </member> <member name="radius" type="float" setter="set_radius" getter="get_radius"> + The capsules's radius. </member> </members> <constants> diff --git a/doc/classes/CircleShape2D.xml b/doc/classes/CircleShape2D.xml index c3d4bdae03..1ed54f0705 100644 --- a/doc/classes/CircleShape2D.xml +++ b/doc/classes/CircleShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Circular Shape for 2D Physics. + Circular shape for 2D collisions. </brief_description> <description> - Circular Shape for 2D Physics. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. + Circular shape for 2D collisions. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="radius" type="float" setter="set_radius" getter="get_radius"> + The circle's radius. </member> </members> <constants> diff --git a/doc/classes/CollisionPolygon.xml b/doc/classes/CollisionPolygon.xml index cf425e3d60..c2496424d6 100644 --- a/doc/classes/CollisionPolygon.xml +++ b/doc/classes/CollisionPolygon.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CollisionPolygon" inherits="Spatial" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Editor-only class for defining a collision polygon in 3D space. </brief_description> <description> + Allows editing a collision polygon's vertices on a selected plane. Can also set a depth perpendicular to that plane. This class is only available in the editor. It will not appear in the scene tree at runtime. Creates a [Shape] for gameplay. Properties modified during gameplay will have no effect. </description> <tutorials> </tutorials> @@ -54,10 +56,13 @@ </methods> <members> <member name="depth" type="float" setter="set_depth" getter="get_depth"> + Length that the resulting collision extends in either direction perpendicular to its polygon. </member> <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled"> + If true, no collision will be produced. </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> + Array of vertices which define the polygon. </member> </members> <constants> diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml index ef0f1ce451..d3dee1e9bb 100644 --- a/doc/classes/CollisionPolygon2D.xml +++ b/doc/classes/CollisionPolygon2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CollisionPolygon2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Editor-only class for easy editing of collision polygons. + Editor-only class for defining a collision polygon in 2D space. </brief_description> <description> - Editor-only class. This is not present when running the game. It's used in the editor to properly edit and position collision shapes in [CollisionObject2D]. This is not accessible from regular code. This class is for editing custom shape polygons. + Allows editing a collision polygon's vertices. This class is only available in the editor. It will not appear in the scene tree at runtime. Creates a [Shape2D] for gameplay. Properties modified during gameplay will have no effect. </description> <tutorials> </tutorials> @@ -75,14 +75,22 @@ </methods> <members> <member name="build_mode" type="int" setter="set_build_mode" getter="get_build_mode" enum="CollisionPolygon2D.BuildMode"> + If BUILD_SOLIDS, the polygon and the area within it will have collision. If BUILD_SEGMENTS, only the edges of the polygon will have collision. </member> <member name="disabled" type="bool" setter="set_disabled" getter="is_disabled"> + If true, no collision will be produced. </member> <member name="one_way_collision" type="bool" setter="set_one_way_collision" getter="is_one_way_collision_enabled"> + If true, only edges that face up, relative to CollisionPolygon2D's rotation, will collide with other objects. </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> + Array of vertices which define the polygon. </member> </members> <constants> + <constant name="BUILD_SOLIDS" value="0"> + </constant> + <constant name="BUILD_SEGMENTS" value="1"> + </constant> </constants> </class> diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml index bf9f7598e0..d676f635c9 100644 --- a/doc/classes/Curve.xml +++ b/doc/classes/Curve.xml @@ -227,5 +227,11 @@ </signal> </signals> <constants> + <constant name="TANGENT_FREE" value="0"> + </constant> + <constant name="TANGENT_LINEAR" value="1"> + </constant> + <constant name="TANGENT_MODE_COUNT" value="2"> + </constant> </constants> </class> diff --git a/doc/classes/EditorExportPlugin.xml b/doc/classes/EditorExportPlugin.xml new file mode 100644 index 0000000000..b0ed24b767 --- /dev/null +++ b/doc/classes/EditorExportPlugin.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="EditorExportPlugin" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="_export_begin" qualifiers="virtual"> + <return type="void"> + </return> + <argument index="0" name="features" type="PoolStringArray"> + </argument> + <description> + </description> + </method> + <method name="_export_file" qualifiers="virtual"> + <return type="void"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="type" type="String"> + </argument> + <argument index="2" name="features" type="PoolStringArray"> + </argument> + <description> + </description> + </method> + <method name="add_file"> + <return type="void"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <argument index="1" name="file" type="PoolByteArray"> + </argument> + <argument index="2" name="remap" type="bool"> + </argument> + <description> + </description> + </method> + <method name="add_shared_object"> + <return type="void"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + </description> + </method> + <method name="skip"> + <return type="void"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml index 1e0f27ef7f..6ae893f189 100644 --- a/doc/classes/EditorFileDialog.xml +++ b/doc/classes/EditorFileDialog.xml @@ -185,5 +185,9 @@ </constant> <constant name="ACCESS_FILESYSTEM" value="2"> </constant> + <constant name="DISPLAY_THUMBNAILS" value="0"> + </constant> + <constant name="DISPLAY_LIST" value="1"> + </constant> </constants> </class> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index f620c33f7a..2831555d41 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -66,6 +66,14 @@ During run-time, this will be a simple object with a script so this function does not need to be called then. </description> </method> + <method name="add_export_plugin"> + <return type="void"> + </return> + <argument index="0" name="exporter" type="EditorExportPlugin"> + </argument> + <description> + </description> + </method> <method name="add_import_plugin"> <return type="void"> </return> @@ -266,6 +274,14 @@ Remove a custom type added by [method EditorPlugin.add_custom_type] </description> </method> + <method name="remove_export_plugin"> + <return type="void"> + </return> + <argument index="0" name="exporter" type="EditorExportPlugin"> + </argument> + <description> + </description> + </method> <method name="remove_import_plugin"> <return type="void"> </return> diff --git a/doc/classes/GeometryInstance.xml b/doc/classes/GeometryInstance.xml index 550a1e97d7..57aec8be41 100644 --- a/doc/classes/GeometryInstance.xml +++ b/doc/classes/GeometryInstance.xml @@ -149,15 +149,17 @@ </member> </members> <constants> - <constant name="FLAG_MAX" value="1" enum=""> + <constant name="SHADOW_CASTING_SETTING_OFF" value="0"> </constant> - <constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum=""> + <constant name="SHADOW_CASTING_SETTING_ON" value="1"> </constant> - <constant name="SHADOW_CASTING_SETTING_ON" value="1" enum=""> + <constant name="SHADOW_CASTING_SETTING_DOUBLE_SIDED" value="2"> </constant> - <constant name="SHADOW_CASTING_SETTING_DOUBLE_SIDED" value="2" enum=""> + <constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3"> </constant> - <constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3" enum=""> + <constant name="FLAG_USE_BAKED_LIGHT" value="0"> + </constant> + <constant name="FLAG_MAX" value="1"> </constant> </constants> </class> diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml new file mode 100644 index 0000000000..a38b2f61cf --- /dev/null +++ b/doc/classes/JSON.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="JSON" inherits="Object" category="Core" version="3.0.alpha.custom_build"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="parse"> + <return type="JSONParseResult"> + </return> + <argument index="0" name="json" type="String"> + </argument> + <description> + </description> + </method> + <method name="print"> + <return type="String"> + </return> + <argument index="0" name="value" type="Variant"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml new file mode 100644 index 0000000000..6aeb614508 --- /dev/null +++ b/doc/classes/JSONParseResult.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="JSONParseResult" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="get_error" qualifiers="const"> + <return type="int" enum="Error"> + </return> + <description> + </description> + </method> + <method name="get_error_line" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_error_string" qualifiers="const"> + <return type="String"> + </return> + <description> + </description> + </method> + <method name="get_result" qualifiers="const"> + <return type="Variant"> + </return> + <description> + </description> + </method> + <method name="set_error"> + <return type="void"> + </return> + <argument index="0" name="error" type="int" enum="Error"> + </argument> + <description> + </description> + </method> + <method name="set_error_line"> + <return type="void"> + </return> + <argument index="0" name="error_line" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_error_string"> + <return type="void"> + </return> + <argument index="0" name="error_string" type="String"> + </argument> + <description> + </description> + </method> + <method name="set_result"> + <return type="void"> + </return> + <argument index="0" name="result" type="Variant"> + </argument> + <description> + </description> + </method> + </methods> + <members> + <member name="error" type="int" setter="set_error" getter="get_error" enum="Error"> + </member> + <member name="error_line" type="int" setter="set_error_line" getter="get_error_line"> + </member> + <member name="error_string" type="String" setter="set_error_string" getter="get_error_string"> + </member> + <member name="result" type="Variant" setter="set_result" getter="get_result"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index 26c7c6125d..dddae2c0fc 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -63,6 +63,7 @@ <argument index="0" name="rel_vec" type="Vector2"> </argument> <description> + Moves the body along the given vector. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the colliding body. </description> </method> <method name="move_and_slide"> @@ -97,7 +98,7 @@ <argument index="1" name="rel_vec" type="Vector2"> </argument> <description> - Return true if there would be a collision if the body moved from the given point in the given direction. + Returns true if there would be a collision if the body moved from the given point in the given direction. </description> </method> </methods> diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml index 5e5b125654..b7269a646e 100644 --- a/doc/classes/KinematicCollision.xml +++ b/doc/classes/KinematicCollision.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="KinematicCollision" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Collision data for KinematicBody2D collisions. </brief_description> <description> + Contains collision data for KinematicBody collisions. When a [KinematicBody] is moved using [method KinematicBody.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision object is returned. + This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response. </description> <tutorials> </tutorials> @@ -78,26 +81,37 @@ </methods> <members> <member name="collider" type="Object" setter="" getter="get_collider"> + The colliding body. </member> <member name="collider_id" type="int" setter="" getter="get_collider_id"> + The colliding body's unique [RID]. </member> <member name="collider_metadata" type="Variant" setter="" getter="get_collider_metadata"> + The colliding body's metadata. See [Object]. </member> <member name="collider_shape" type="Object" setter="" getter="get_collider_shape"> + The colliding body's shape. </member> <member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index"> + The colliding shape's index. See [CollisionObject]. </member> <member name="collider_velocity" type="Vector3" setter="" getter="get_collider_velocity"> + The colliding object's velocity. </member> <member name="local_shape" type="Object" setter="" getter="get_local_shape"> + The moving object's colliding shape. </member> <member name="normal" type="Vector3" setter="" getter="get_normal"> + The colliding body's shape's normal at the point of collision. </member> <member name="position" type="Vector3" setter="" getter="get_position"> + The point of collision. </member> <member name="remainder" type="Vector3" setter="" getter="get_remainder"> + The moving object's remaining movement vector. </member> <member name="travel" type="Vector3" setter="" getter="get_travel"> + The distance the moving object traveled before collision. </member> </members> <constants> diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml index 4ef35066d0..7a40a39292 100644 --- a/doc/classes/KinematicCollision2D.xml +++ b/doc/classes/KinematicCollision2D.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="KinematicCollision2D" inherits="Reference" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Collision data for KinematicBody2D collisions. </brief_description> <description> + Contains collision data for KinematicBody2D collisions. When a [KinematicBody2D] is moved using [method KinematicBody2D.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision2D object is returned. + This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response. </description> <tutorials> </tutorials> @@ -78,26 +81,37 @@ </methods> <members> <member name="collider" type="Object" setter="" getter="get_collider"> + The colliding body. </member> <member name="collider_id" type="int" setter="" getter="get_collider_id"> + The colliding body's unique [RID]. </member> <member name="collider_metadata" type="Variant" setter="" getter="get_collider_metadata"> + The colliding body's metadata. See [Object]. </member> <member name="collider_shape" type="Object" setter="" getter="get_collider_shape"> + The colliding body's shape. </member> <member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index"> + The colliding shape's index. See [CollisionObject2D]. </member> <member name="collider_velocity" type="Vector2" setter="" getter="get_collider_velocity"> + The colliding object's velocity. </member> <member name="local_shape" type="Object" setter="" getter="get_local_shape"> + The moving object's colliding shape. </member> <member name="normal" type="Vector2" setter="" getter="get_normal"> + The colliding body's shape's normal at the point of collision. </member> <member name="position" type="Vector2" setter="" getter="get_position"> + The point of collision. </member> <member name="remainder" type="Vector2" setter="" getter="get_remainder"> + The moving object's remaining movement vector. </member> <member name="travel" type="Vector2" setter="" getter="get_travel"> + The distance the moving object traveled before collision. </member> </members> <constants> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 2e860aac0c..8c5e69b407 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Label" inherits="Control" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Control that displays formatted text. + Displays plain text in a line or wrapped inside a rectangle. For formatted text, use [RichTextLabel]. </brief_description> <description> - Label is a control that displays formatted text, optionally autowrapping it to the [Control] area. It inherits from range to be able to scroll wrapped text vertically. + Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment, and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics or other formatting. For that, use [RichTextLabel] instead. </description> <tutorials> </tutorials> @@ -22,14 +22,14 @@ <return type="int"> </return> <description> - Return the amount of lines. + Returns the amount of lines of text the Label has. </description> </method> <method name="get_line_height" qualifiers="const"> <return type="int"> </return> <description> - Return the height of a line. + Returns the font size in pixels. </description> </method> <method name="get_lines_skipped" qualifiers="const"> @@ -98,14 +98,14 @@ <return type="bool"> </return> <description> - Return true if text would be cut off if it is too wide. + Return [code]true[/code] if text would be cut off if it is too wide. </description> </method> <method name="is_uppercase" qualifiers="const"> <return type="bool"> </return> <description> - Return true if text is displayed in all capitals. + Return [code]true[/code] if text is displayed in all capitals. </description> </method> <method name="set_align"> @@ -201,22 +201,31 @@ </methods> <members> <member name="align" type="int" setter="set_align" getter="get_align" enum="Label.Align"> + Controls the text's horizontal align. Supports left, center, right, and fill, or justify. Set it to one of the [code]ALIGN_*[/code] constants. </member> <member name="autowrap" type="bool" setter="set_autowrap" getter="has_autowrap"> + If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. Default: false. </member> <member name="clip_text" type="bool" setter="set_clip_text" getter="is_clipping_text"> + If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle. It also lets you scale the node down freely. </member> <member name="lines_skipped" type="int" setter="set_lines_skipped" getter="get_lines_skipped"> + The node ignores the first [code]lines_skipped[/code] lines before it starts to display text. </member> <member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible"> + Limits the lines of text the node shows on screen. </member> <member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible"> + Limits the count of visible characters. If you set [code]percent_visible[/code] to 50, only up to half of the text's characters will display on screen. Useful to animate the text in a dialog box. </member> <member name="text" type="String" setter="set_text" getter="get_text"> + The text to display on screen. </member> <member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase"> + If [code]true[/code], all the text displays as UPPERCASE. </member> <member name="valign" type="int" setter="set_valign" getter="get_valign" enum="Label.VAlign"> + Controls the text's vertical align. Supports top, center, bottom, and fill. Set it to one of the [code]VALIGN_*[/code] constants. </member> </members> <constants> diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml index 593799b57d..7ce7cef7c1 100644 --- a/doc/classes/Light2D.xml +++ b/doc/classes/Light2D.xml @@ -340,46 +340,67 @@ </methods> <members> <member name="color" type="Color" setter="set_color" getter="get_color"> + The Light2D's [Color]. </member> <member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only"> + If [code]true[/code] Light2D will only appear when editing the scene. Default value: [code]false[/code]. </member> <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled"> + If [code]true[/code] Light2D will emit light. Default value: [code]true[/code]. </member> <member name="energy" type="float" setter="set_energy" getter="get_energy"> + The Light2D's energy value. The larger the value, the stronger the light. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="Light2D.Mode"> + The Light2D's mode. See MODE_* constants for values. </member> <member name="offset" type="Vector2" setter="set_texture_offset" getter="get_texture_offset"> + The offset of the Light2D's [code]texture[/code]. </member> <member name="range_height" type="float" setter="set_height" getter="get_height"> + The height of the Light2D. Used with 2D normal mapping. </member> <member name="range_item_cull_mask" type="int" setter="set_item_cull_mask" getter="get_item_cull_mask"> + The layer mask. Only objects with a matching mask will be affected by the Light2D. </member> <member name="range_layer_max" type="int" setter="set_layer_range_max" getter="get_layer_range_max"> + Maximum layer value of objects that are affected by the Light2D. Default value: [code]0[/code]. </member> <member name="range_layer_min" type="int" setter="set_layer_range_min" getter="get_layer_range_min"> + Minimum layer value of objects that are affected by the Light2D. Default value: [code]0[/code]. </member> <member name="range_z_max" type="int" setter="set_z_range_max" getter="get_z_range_max"> + Maximum [code]Z[/code] value of objects that are affected by the Light2D. Default value: [code]1024[/code]. </member> <member name="range_z_min" type="int" setter="set_z_range_min" getter="get_z_range_min"> + Minimum [code]z[/code] value of objects that are affected by the Light2D. Default value: [code]-1024[/code]. </member> <member name="shadow_buffer_size" type="int" setter="set_shadow_buffer_size" getter="get_shadow_buffer_size"> + Shadow buffer size. Default value: [code]2048[/code]. </member> <member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color"> + [Color] of shadows cast by the Light2D. </member> <member name="shadow_enabled" type="bool" setter="set_shadow_enabled" getter="is_shadow_enabled"> + If [code]true[/code] the Light2D will cast shadows. Default value: [code]false[/code]. </member> <member name="shadow_filter" type="int" setter="set_shadow_filter" getter="get_shadow_filter" enum="Light2D.ShadowFilter"> + Shadow filter type. May be one of [code][None, PCF5, PCF9, PCF13][/code]. Default value: [code]None[/code]. </member> <member name="shadow_filter_smooth" type="float" setter="set_shadow_smooth" getter="get_shadow_smooth"> + Smoothing value for shadows. </member> <member name="shadow_gradient_length" type="float" setter="set_shadow_gradient_length" getter="get_shadow_gradient_length"> + Smooth shadow gradient length. </member> <member name="shadow_item_cull_mask" type="int" setter="set_item_shadow_cull_mask" getter="get_item_shadow_cull_mask"> + The shadow mask. Used with [LightOccluder2D] to cast shadows. Only occluders with a matching shadow mask will cast shadows. </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> + [Texture] used for the Light2D's appearance. </member> <member name="texture_scale" type="float" setter="set_texture_scale" getter="get_texture_scale"> + The [code]texture[/code]'s scale factor. </member> </members> <constants> @@ -395,5 +416,17 @@ <constant name="MODE_MASK" value="3"> The light texture of the Light2D is used as a mask, hiding or revealing parts of the screen underneath depending on the value of each pixel of the light (mask) texture. </constant> + <constant name="SHADOW_FILTER_NONE" value="0"> + </constant> + <constant name="SHADOW_FILTER_PCF3" value="1"> + </constant> + <constant name="SHADOW_FILTER_PCF5" value="2"> + </constant> + <constant name="SHADOW_FILTER_PCF7" value="3"> + </constant> + <constant name="SHADOW_FILTER_PCF9" value="4"> + </constant> + <constant name="SHADOW_FILTER_PCF13" value="5"> + </constant> </constants> </class> diff --git a/doc/classes/Line2D.xml b/doc/classes/Line2D.xml index e954173047..81fd255781 100644 --- a/doc/classes/Line2D.xml +++ b/doc/classes/Line2D.xml @@ -21,7 +21,7 @@ </description> </method> <method name="get_begin_cap_mode" qualifiers="const"> - <return type="int" enum="LineCapMode"> + <return type="int" enum="Line2D.LineCapMode"> </return> <description> </description> @@ -33,7 +33,7 @@ </description> </method> <method name="get_end_cap_mode" qualifiers="const"> - <return type="int" enum="LineCapMode"> + <return type="int" enum="Line2D.LineCapMode"> </return> <description> </description> @@ -45,7 +45,7 @@ </description> </method> <method name="get_joint_mode" qualifiers="const"> - <return type="int" enum="LineJointMode"> + <return type="int" enum="Line2D.LineJointMode"> </return> <description> </description> @@ -89,7 +89,7 @@ </description> </method> <method name="get_texture_mode" qualifiers="const"> - <return type="int" enum="LineTextureMode"> + <return type="int" enum="Line2D.LineTextureMode"> </return> <description> </description> @@ -112,7 +112,7 @@ <method name="set_begin_cap_mode"> <return type="void"> </return> - <argument index="0" name="mode" type="int" enum="LineCapMode"> + <argument index="0" name="mode" type="int" enum="Line2D.LineCapMode"> </argument> <description> </description> @@ -128,7 +128,7 @@ <method name="set_end_cap_mode"> <return type="void"> </return> - <argument index="0" name="mode" type="int" enum="LineCapMode"> + <argument index="0" name="mode" type="int" enum="Line2D.LineCapMode"> </argument> <description> </description> @@ -144,7 +144,7 @@ <method name="set_joint_mode"> <return type="void"> </return> - <argument index="0" name="mode" type="int" enum="LineJointMode"> + <argument index="0" name="mode" type="int" enum="Line2D.LineJointMode"> </argument> <description> </description> @@ -194,7 +194,7 @@ <method name="set_texture_mode"> <return type="void"> </return> - <argument index="0" name="mode" type="int" enum="LineTextureMode"> + <argument index="0" name="mode" type="int" enum="Line2D.LineTextureMode"> </argument> <description> </description> @@ -209,15 +209,15 @@ </method> </methods> <members> - <member name="begin_cap_mode" type="int" setter="set_begin_cap_mode" getter="get_begin_cap_mode" enum="LineCapMode"> + <member name="begin_cap_mode" type="int" setter="set_begin_cap_mode" getter="get_begin_cap_mode" enum="Line2D.LineCapMode"> </member> <member name="default_color" type="Color" setter="set_default_color" getter="get_default_color"> </member> - <member name="end_cap_mode" type="int" setter="set_end_cap_mode" getter="get_end_cap_mode" enum="LineCapMode"> + <member name="end_cap_mode" type="int" setter="set_end_cap_mode" getter="get_end_cap_mode" enum="Line2D.LineCapMode"> </member> <member name="gradient" type="Gradient" setter="set_gradient" getter="get_gradient"> </member> - <member name="joint_mode" type="int" setter="set_joint_mode" getter="get_joint_mode" enum="LineJointMode"> + <member name="joint_mode" type="int" setter="set_joint_mode" getter="get_joint_mode" enum="Line2D.LineJointMode"> </member> <member name="points" type="PoolVector2Array" setter="set_points" getter="get_points"> </member> @@ -227,7 +227,7 @@ </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> </member> - <member name="texture_mode" type="int" setter="set_texture_mode" getter="get_texture_mode" enum="LineTextureMode"> + <member name="texture_mode" type="int" setter="set_texture_mode" getter="get_texture_mode" enum="Line2D.LineTextureMode"> </member> <member name="width" type="float" setter="set_width" getter="get_width"> </member> diff --git a/doc/classes/LineShape2D.xml b/doc/classes/LineShape2D.xml index 3346c46a19..5596c48162 100644 --- a/doc/classes/LineShape2D.xml +++ b/doc/classes/LineShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="LineShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Line shape for 2D collision objects. + Line shape for 2D collisions. </brief_description> <description> - Line shape for 2D collision objects. It works like a 2D plane and will not allow any body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame. + Line shape for 2D collisions. It works like a 2D plane and will not allow any body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="d" type="float" setter="set_d" getter="get_d"> + The line's distance from the origin. </member> <member name="normal" type="Vector2" setter="set_normal" getter="get_normal"> + The line's normal. </member> </members> <constants> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index 66b52e7f48..658265d242 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -71,5 +71,73 @@ <constant name="PRIMITIVE_TRIANGLE_FAN" value="6"> Render array as triangle fans. </constant> + <constant name="BLEND_SHAPE_MODE_NORMALIZED" value="0"> + </constant> + <constant name="BLEND_SHAPE_MODE_RELATIVE" value="1"> + </constant> + <constant name="ARRAY_FORMAT_VERTEX" value="1"> + </constant> + <constant name="ARRAY_FORMAT_NORMAL" value="2"> + </constant> + <constant name="ARRAY_FORMAT_TANGENT" value="4"> + </constant> + <constant name="ARRAY_FORMAT_COLOR" value="8"> + </constant> + <constant name="ARRAY_FORMAT_TEX_UV" value="16"> + </constant> + <constant name="ARRAY_FORMAT_TEX_UV2" value="32"> + </constant> + <constant name="ARRAY_FORMAT_BONES" value="64"> + </constant> + <constant name="ARRAY_FORMAT_WEIGHTS" value="128"> + </constant> + <constant name="ARRAY_FORMAT_INDEX" value="256"> + </constant> + <constant name="ARRAY_COMPRESS_BASE" value="9"> + </constant> + <constant name="ARRAY_COMPRESS_VERTEX" value="512"> + </constant> + <constant name="ARRAY_COMPRESS_NORMAL" value="1024"> + </constant> + <constant name="ARRAY_COMPRESS_TANGENT" value="2048"> + </constant> + <constant name="ARRAY_COMPRESS_COLOR" value="4096"> + </constant> + <constant name="ARRAY_COMPRESS_TEX_UV" value="8192"> + </constant> + <constant name="ARRAY_COMPRESS_TEX_UV2" value="16384"> + </constant> + <constant name="ARRAY_COMPRESS_BONES" value="32768"> + </constant> + <constant name="ARRAY_COMPRESS_WEIGHTS" value="65536"> + </constant> + <constant name="ARRAY_COMPRESS_INDEX" value="131072"> + </constant> + <constant name="ARRAY_FLAG_USE_2D_VERTICES" value="262144"> + </constant> + <constant name="ARRAY_FLAG_USE_16_BIT_BONES" value="524288"> + </constant> + <constant name="ARRAY_COMPRESS_DEFAULT" value="97792"> + </constant> + <constant name="ARRAY_VERTEX" value="0"> + </constant> + <constant name="ARRAY_NORMAL" value="1"> + </constant> + <constant name="ARRAY_TANGENT" value="2"> + </constant> + <constant name="ARRAY_COLOR" value="3"> + </constant> + <constant name="ARRAY_TEX_UV" value="4"> + </constant> + <constant name="ARRAY_TEX_UV2" value="5"> + </constant> + <constant name="ARRAY_BONES" value="6"> + </constant> + <constant name="ARRAY_WEIGHTS" value="7"> + </constant> + <constant name="ARRAY_INDEX" value="8"> + </constant> + <constant name="ARRAY_MAX" value="9"> + </constant> </constants> </class> diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml index 092e928ef9..6829b36e14 100644 --- a/doc/classes/NinePatchRect.xml +++ b/doc/classes/NinePatchRect.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="NinePatchRect" inherits="Control" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Scalable texture-based frame that tiles the texture's centers and sides, but keeps the corners' original size. Perfect for panels and dialog boxes. </brief_description> <description> + Better known as 9-slice panels, NinePatchRect produces clean panels of any size, based on a small texture. To do so, it splits the texture in a 3 by 3 grid. When you scale the node, it tiles the texture's sides horizontally or vertically, the center on both axes but it doesn't scale or tile the corners. </description> <tutorials> </tutorials> @@ -100,36 +102,49 @@ </methods> <members> <member name="axis_stretch_horizontal" type="int" setter="set_h_axis_stretch_mode" getter="get_h_axis_stretch_mode" enum="NinePatchRect.AxisStretchMode"> + Doesn't do anything at the time of writing. </member> <member name="axis_stretch_vertical" type="int" setter="set_v_axis_stretch_mode" getter="get_v_axis_stretch_mode" enum="NinePatchRect.AxisStretchMode"> + Doesn't do anything at the time of writing. </member> <member name="draw_center" type="bool" setter="set_draw_center" getter="is_draw_center_enabled"> + If [code]true[/code], draw the panel's center. Else, only draw the 9-slice's borders. Default value: [code]true[/code] </member> <member name="patch_margin_bottom" type="int" setter="set_patch_margin" getter="get_patch_margin"> + The height of the 9-slice's bottom row. A margin of 16 means the 9-slice's bottom corners and side will have a height of 16 pixels. You can set all 4 margin values indivually to create panels with non-uniform borders. </member> <member name="patch_margin_left" type="int" setter="set_patch_margin" getter="get_patch_margin"> + The height of the 9-slice's left column. </member> <member name="patch_margin_right" type="int" setter="set_patch_margin" getter="get_patch_margin"> + The height of the 9-slice's right column. </member> <member name="patch_margin_top" type="int" setter="set_patch_margin" getter="get_patch_margin"> + The height of the 9-slice's top row. </member> <member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect"> + Rectangular region of the texture to sample from. If you're working with an atlas, use this property to define the area the 9-slice should use. All other properties are relative to this one. </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> + The node's texture resource. </member> </members> <signals> <signal name="texture_changed"> <description> + Fired when the node's texture changes. </description> </signal> </signals> <constants> <constant name="AXIS_STRETCH_MODE_STRETCH" value="0"> + Doesn't do anything at the time of writing. Default value for [code]axis_stretch_horizontal[/code] and [code]axis_stretch_vertical[/code]. </constant> <constant name="AXIS_STRETCH_MODE_TILE" value="1"> + Doesn't do anything at the time of writing. </constant> <constant name="AXIS_STRETCH_MODE_TILE_FIT" value="2"> + Doesn't do anything at the time of writing. </constant> </constants> </class> diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 38f1eb8ce1..65200c4769 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -233,7 +233,7 @@ </description> </method> <method name="get_power_state"> - <return type="int" enum="PowerState"> + <return type="int" enum="OS.PowerState"> </return> <description> </description> @@ -286,7 +286,7 @@ </description> </method> <method name="get_screen_orientation" qualifiers="const"> - <return type="int" enum="_OS.ScreenOrientation"> + <return type="int" enum="OS.ScreenOrientation"> </return> <description> Returns the current screen orientation, the return value will be one of the SCREEN_ORIENTATION constants in this class. @@ -331,7 +331,7 @@ <method name="get_system_dir" qualifiers="const"> <return type="String"> </return> - <argument index="0" name="dir" type="int" enum="_OS.SystemDir"> + <argument index="0" name="dir" type="int" enum="OS.SystemDir"> </argument> <description> </description> @@ -660,7 +660,7 @@ <method name="set_screen_orientation"> <return type="void"> </return> - <argument index="0" name="orientation" type="int" enum="_OS.ScreenOrientation"> + <argument index="0" name="orientation" type="int" enum="OS.ScreenOrientation"> </argument> <description> Sets the current screen orientation, the argument value must be one of the SCREEN_ORIENTATION constants in this class. diff --git a/doc/classes/OmniLight.xml b/doc/classes/OmniLight.xml index 8750fd7e99..cb8e756a4c 100644 --- a/doc/classes/OmniLight.xml +++ b/doc/classes/OmniLight.xml @@ -51,5 +51,13 @@ </member> </members> <constants> + <constant name="SHADOW_DUAL_PARABOLOID" value="0"> + </constant> + <constant name="SHADOW_CUBE" value="1"> + </constant> + <constant name="SHADOW_DETAIL_VERTICAL" value="0"> + </constant> + <constant name="SHADOW_DETAIL_HORIZONTAL" value="1"> + </constant> </constants> </class> diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml index e8ae986346..e75fbb8e2d 100644 --- a/doc/classes/PhysicsBody.xml +++ b/doc/classes/PhysicsBody.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Base class for different types of Physics bodies. + Base class for all objects affected by physics in 3D space. </brief_description> <description> - PhysicsBody is an abstract base class for implementing a physics body. All PhysicsBody types inherit from it. + PhysicsBody is an abstract base class for implementing a physics body. All *Body types inherit from it. </description> <tutorials> </tutorials> @@ -17,7 +17,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> - Adds a body to the collision exception list. This list contains bodies that this body will not collide with. + Adds a body to the list of bodies that this body can't collide with. </description> </method> <method name="get_collision_layer" qualifiers="const"> @@ -54,7 +54,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> - Removes a body from the collision exception list. + Removes a body from the list of bodies that this body can't collide with. </description> </method> <method name="set_collision_layer"> @@ -96,8 +96,12 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer"> + The physics layers this area is in. + Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. + A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> + The physics layers this area can scan for collisions. </member> </members> <constants> diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index e160311090..748506baa9 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Base class for all objects affected by physics. + Base class for all objects affected by physics in 2D space. </brief_description> <description> PhysicsBody2D is an abstract base class for implementing a physics body. All *Body2D types inherit from it. @@ -17,6 +17,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> + Adds a body to the list of bodies that this body can't collide with. </description> </method> <method name="get_collision_layer" qualifiers="const"> @@ -57,6 +58,7 @@ <argument index="0" name="body" type="Node"> </argument> <description> + Removes a body from the list of bodies that this body can't collide with. </description> </method> <method name="set_collision_layer"> @@ -104,10 +106,15 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer"> + The physics layers this area is in. + Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property. + A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask"> + The physics layers this area can scan for collisions. </member> <member name="layers" type="int" setter="_set_layers" getter="_get_layers"> + Both collision_layer and collision_mask. Returns collision_layer when accessed. Updates collision_layers and collision_mask when modified. </member> </members> <constants> diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml index 93a50eb1bf..0076625ebd 100644 --- a/doc/classes/PhysicsServer.xml +++ b/doc/classes/PhysicsServer.xml @@ -1248,5 +1248,29 @@ </constant> <constant name="INFO_ISLAND_COUNT" value="2"> </constant> + <constant name="SPACE_PARAM_CONTACT_RECYCLE_RADIUS" value="0"> + </constant> + <constant name="SPACE_PARAM_CONTACT_MAX_SEPARATION" value="1"> + </constant> + <constant name="SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION" value="2"> + </constant> + <constant name="SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD" value="3"> + </constant> + <constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD" value="4"> + </constant> + <constant name="SPACE_PARAM_BODY_TIME_TO_SLEEP" value="5"> + </constant> + <constant name="SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO" value="6"> + </constant> + <constant name="SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS" value="7"> + </constant> + <constant name="BODY_AXIS_LOCK_DISABLED" value="0"> + </constant> + <constant name="BODY_AXIS_LOCK_X" value="1"> + </constant> + <constant name="BODY_AXIS_LOCK_Y" value="2"> + </constant> + <constant name="BODY_AXIS_LOCK_Z" value="3"> + </constant> </constants> </class> diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml index 8414ee2348..4f6313a1d2 100644 --- a/doc/classes/RayShape2D.xml +++ b/doc/classes/RayShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RayShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Ray 2D shape resource for physics. + Ray shape for 2D collisions. </brief_description> <description> - Ray 2D shape resource for physics. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. + Ray shape for 2D collisions. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="length" type="float" setter="set_length" getter="get_length"> + The ray's length. </member> </members> <constants> diff --git a/doc/classes/RectangleShape2D.xml b/doc/classes/RectangleShape2D.xml index 9c18df970b..7a1aec2021 100644 --- a/doc/classes/RectangleShape2D.xml +++ b/doc/classes/RectangleShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Rectangle Shape for 2D Physics. + Rectangle shape for 2D collisions. </brief_description> <description> - Rectangle Shape for 2D Physics. This shape is useful for modeling box-like 2D objects. + Rectangle shape for 2D collisions. This shape is useful for modeling box-like 2D objects. </description> <tutorials> </tutorials> @@ -30,6 +30,7 @@ </methods> <members> <member name="extents" type="Vector2" setter="set_extents" getter="get_extents"> + The rectangle's half extents. The width and height of this shape is twice the half extents. </member> </members> <constants> diff --git a/doc/classes/Reference.xml b/doc/classes/Reference.xml index a8ca4cde0c..2531ea88ad 100644 --- a/doc/classes/Reference.xml +++ b/doc/classes/Reference.xml @@ -18,7 +18,7 @@ </description> </method> <method name="reference"> - <return type="void"> + <return type="bool"> </return> <description> Increase the internal reference counter. Use this only if you really know what you are doing. diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml index 446c6d14cb..8347597daf 100644 --- a/doc/classes/RigidBody.xml +++ b/doc/classes/RigidBody.xml @@ -1,10 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Rigid body node. + Physics Body whose position is determined through physics simulation in 3D space. </brief_description> <description> - Rigid body node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift mode between regular Rigid body, Kinematic, Character or Static. + This is the node that implements full 3D physics. This means that you do not control a RigidBody directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. + This node can use custom force integration, for writing complex physics motion behavior per node. + This node can shift state between regular Rigid body, Kinematic, Character or Static. + Character mode forbids this node from being rotated. + As a warning, don't change RigidBody's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. </description> <tutorials> </tutorials> @@ -324,55 +328,56 @@ </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp"> - Dampens rotational forces of the Rigid body by the 'angular_damp' rate. + Damps RigidBody's rotational forces. </member> <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity"> - The current rotational velocity of the Rigid body + RigidBody's rotational velocity. </member> <member name="axis_lock" type="int" setter="set_axis_lock" getter="get_axis_lock" enum="RigidBody.AxisLock"> Locks the rotational forces to a particular axis, preventing rotations on other axes. </member> <member name="bounce" type="float" setter="set_bounce" getter="get_bounce"> - Bounciness of the Rigid body. + RigidBody's bounciness. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep"> - If true, the Rigid body will no longer calculate forces when there is no movement and will act as a static body. It will wake up when other forces are applied through other collisions or when the 'apply_impulse' method is used. + If [code]true[/code] the RigidBody will not calculate forces and will act as a static body while there is no movement. It will wake up when forces are applied through other collisions or when the [code]apply_impulse[/code] method is used. </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled"> - If true, the Rigid body will emit signals when it collides with another Rigid body. + If true, the RigidBody will emit signals when it collides with another RigidBody. </member> <member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported"> The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. </member> <member name="continuous_cd" type="bool" setter="set_use_continuous_collision_detection" getter="is_using_continuous_collision_detection"> - Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. The first is more precise, and misses less impacts by small, fast-moving objects. The second is faster to compute, but can miss small, fast-moving objects. + If [code]true[/code] continuous collision detection is used. + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects. </member> <member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator"> - If true, internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined. + If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined. </member> <member name="friction" type="float" setter="set_friction" getter="get_friction"> The body friction, from 0 (frictionless) to 1 (max friction). </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale"> - The 'gravity_scale' for this Rigid body will be multiplied by the global 3d gravity setting found in "Project > Project Settings > Physics > 3d". A value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + This is multiplied by the global 3D gravity setting found in "Project > Project Settings > Physics > 3d" to produce RigidBody's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp"> - The linear damp for this body. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden. + RigidBody's linear damp. Default value: -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden. </member> <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity"> - The body linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. + RigidBody's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. </member> <member name="mass" type="float" setter="set_mass" getter="get_mass"> - The body mass. + RigidBody's mass. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody.Mode"> The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER. </member> <member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping"> - The current 'sleeping' state of the Rigid body. + If [code]true[/code] RigidBody is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method. </member> <member name="weight" type="float" setter="set_weight" getter="get_weight"> - The body weight given standard earth-weight (gravity 9.8). + RigidBody's weight based on its mass and the global 3D gravity. Global values are set in "Project > Project Settings > Physics > 3d". </member> </members> <signals> @@ -437,5 +442,13 @@ <constant name="MODE_CHARACTER" value="2"> Character body. This behaves like a rigid body, but can not rotate. </constant> + <constant name="AXIS_LOCK_DISABLED" value="0"> + </constant> + <constant name="AXIS_LOCK_X" value="1"> + </constant> + <constant name="AXIS_LOCK_Y" value="2"> + </constant> + <constant name="AXIS_LOCK_Z" value="3"> + </constant> </constants> </class> diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index e92c417323..a4faa697de 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Rigid body 2D node. + Physics Body whose position is determined through physics simulation in 2D space. </brief_description> <description> - Rigid body 2D node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift state between regular Rigid body, Kinematic, Character or Static. - Character mode forbids the node from being rotated. This node can have a custom force integrator function, for writing complex physics motion behavior per node. - As a warning, don't change this node position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. + This is the node that implements full 2D physics. This means that you do not control a RigidBody2D directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. + This node can use custom force integration, for writing complex physics motion behavior per node. + This node can shift state between regular Rigid body, Kinematic, Character or Static. + Character mode forbids this node from being rotated. + As a warning, don't change RigidBody2D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior. </description> <tutorials> </tutorials> @@ -382,36 +384,53 @@ </methods> <members> <member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp"> + Damps RigidBody2D's rotational forces. </member> <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity"> + RigidBody2D's rotational velocity. </member> <member name="bounce" type="float" setter="set_bounce" getter="get_bounce"> + RigidBody2D's bounciness. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep"> + If [code]true[/code] RigidBody2D will not calculate forces and will act as a static body while there is no movement. It will wake up when other forces are applied through other collisions or when the [code]apply_impulse[/code] method is used. Default value: [code]true[/code] </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled"> + If [code]true[/code] RigidBody2D will emit signals when it collides with another RigidBody2D. </member> <member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported"> + The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0. </member> <member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidBody2D.CCDMode"> + If [code]true[/code] continuous collision detection is used. Default value: [code]false[/code] + Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects. </member> <member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator"> + If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined. </member> <member name="friction" type="float" setter="set_friction" getter="get_friction"> + The body friction, from 0 (frictionless) to 1 (max friction). </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale"> + This is multiplied by the global 2D gravity setting found in "Project > Project Settings > Physics > 2d" to produce RigidBody2D's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. </member> <member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp"> + RigidBody2D's linear damp. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden. </member> <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity"> + RigidBody2D's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state. </member> <member name="mass" type="float" setter="set_mass" getter="get_mass"> + RigidBody2D's mass. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody2D.Mode"> + The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER. </member> <member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping"> + If [code]true[/code] RigidBody2D is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method. </member> <member name="weight" type="float" setter="set_weight" getter="get_weight"> + RigidBody2D's weight based on its mass and the global 2D gravity. Global values are set in "Project > Project Settings > Physics > 2d". </member> </members> <signals> diff --git a/doc/classes/SegmentShape2D.xml b/doc/classes/SegmentShape2D.xml index 0e2c5c86f3..3b7a747bcb 100644 --- a/doc/classes/SegmentShape2D.xml +++ b/doc/classes/SegmentShape2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Segment Shape for 2D Collision Detection. + Segment shape for 2D collisions. </brief_description> <description> - Segment Shape for 2D Collision Detection, consists of two points, 'a' and 'b'. + Segment shape for 2D collisions. Consists of two points, [code]a[/code] and [code]b[/code]. </description> <tutorials> </tutorials> @@ -46,8 +46,10 @@ </methods> <members> <member name="a" type="Vector2" setter="set_a" getter="get_a"> + The segment's first point position. </member> <member name="b" type="Vector2" setter="set_b" getter="get_b"> + The segment's second point position. </member> </members> <constants> diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml index 076d0b9bc3..e43e4dcc1b 100644 --- a/doc/classes/Spatial.xml +++ b/doc/classes/Spatial.xml @@ -4,7 +4,7 @@ Most basic 3D game object, parent of all 3D related nodes. </brief_description> <description> - Most basic 3D game object, with a 3D [Transform] and visibility settings. All 3D physics nodes and sprites inherit from Spatial. Use Spatial as a parent node to move, scale, rotate and show/hide children in a 3D project. + Most basic 3D game object, with a 3D [Transform] and visibility settings. All other 3D game objects inherit from Spatial. Use Spatial as a parent node to move, scale, rotate and show/hide children in a 3D project. </description> <tutorials> </tutorials> @@ -15,35 +15,35 @@ <return type="SpatialGizmo"> </return> <description> - Return the SpatialGizmo for this node. Used for example in [EditorSpatialGizmo] as custom visualization and editing handles in Editor. + Returns the SpatialGizmo for this node. Used for example in [EditorSpatialGizmo] as custom visualization and editing handles in Editor. </description> </method> <method name="get_global_transform" qualifiers="const"> <return type="Transform"> </return> <description> - Return the global transform, relative to worldspace. + Returns the global transform, relative to worldspace. </description> </method> <method name="get_parent_spatial" qualifiers="const"> <return type="Spatial"> </return> <description> - Return the parent [Spatial], or an empty [Object] if no parent exists or parent is not of type [Spatial]. + Returns the parent [Spatial], or an empty [Object] if no parent exists or parent is not of type [Spatial]. </description> </method> <method name="get_rotation" qualifiers="const"> <return type="Vector3"> </return> <description> - Return the rotation (in radians). + Returns the rotation (in radians). </description> </method> <method name="get_rotation_deg" qualifiers="const"> <return type="Vector3"> </return> <description> - Return the rotation (in degrees). + Returns the rotation (in degrees). </description> </method> <method name="get_scale" qualifiers="const"> @@ -56,7 +56,7 @@ <return type="Transform"> </return> <description> - Return the local transform, relative to the bone parent. + Returns the local transform, relative to the bone parent. </description> </method> <method name="get_translation" qualifiers="const"> @@ -69,7 +69,7 @@ <return type="World"> </return> <description> - Return current [World] resource this Spatial node is registered to. + Returns the current [World] resource this Spatial node is registered to. </description> </method> <method name="global_rotate"> @@ -80,7 +80,7 @@ <argument index="1" name="radians" type="float"> </argument> <description> - Rotate current node along normal [Vector3] by angle in radians in Global space. + Rotates the current node along normal [Vector3] by angle in radians in Global space. </description> </method> <method name="global_translate"> @@ -89,49 +89,49 @@ <argument index="0" name="offset" type="Vector3"> </argument> <description> - Move current node by [Vector3] offset in Global space. + Moves the node by [Vector3] offset in Global space. </description> </method> <method name="hide"> <return type="void"> </return> <description> - Disable rendering of this node. Change Spatial Visible property to false. + Disables rendering of this node. Change Spatial Visible property to false. </description> </method> <method name="is_local_transform_notification_enabled" qualifiers="const"> <return type="bool"> </return> <description> - Returns whether node sends notification that its local transformation changed. Spatial will not propagate this by default. + Returns whether node notifies about its local transformation changes. Spatial will not propagate this by default. </description> </method> <method name="is_set_as_toplevel" qualifiers="const"> <return type="bool"> </return> <description> - Returns whether this node is set as Toplevel, ignoring its parent node transformations. + Returns whether this node is set as Toplevel, that is whether it ignores its parent nodes transformations. </description> </method> <method name="is_transform_notification_enabled" qualifiers="const"> <return type="bool"> </return> <description> - Returns whether node sends notification that its transformation changed. Spatial will not propagate this by default. + Returns whether the node notifies about its global and local transformation changes. Spatial will not propagate this by default. </description> </method> <method name="is_visible" qualifiers="const"> <return type="bool"> </return> <description> - Returns whether this node is set to be visible. + Returns whether the node is set to be visible. </description> </method> <method name="is_visible_in_tree" qualifiers="const"> <return type="bool"> </return> <description> - Returns whether this node is visible, taking into consideration that its parents visibility. + Returns whether the node is visible, taking into consideration that its parents visibility. </description> </method> <method name="look_at"> @@ -155,14 +155,14 @@ <argument index="2" name="up" type="Vector3"> </argument> <description> - Moves itself to specified position and then rotates itself to point into direction of target position. Operations take place in global space. + Moves the node to specified position and then rotates itself to point into direction of target position. Operations take place in global space. </description> </method> <method name="orthonormalize"> <return type="void"> </return> <description> - Reset this node transformations (like scale, skew and taper) preserving its rotation and translation. Performs orthonormalization on this node [Transform3D]. + Resets this node's transformations (like scale, skew and taper) preserving its rotation and translation. Performs orthonormalization on this node [Transform3D]. </description> </method> <method name="rotate"> @@ -173,7 +173,7 @@ <argument index="1" name="radians" type="float"> </argument> <description> - Rotates node in local space on given normal [Vector3] by angle in radians. + Rotates the node in local space on given normal [Vector3] by angle in radians. </description> </method> <method name="rotate_x"> @@ -182,7 +182,7 @@ <argument index="0" name="radians" type="float"> </argument> <description> - Rotates node in local space on X axis by angle in radians. + Rotates the node in local space on X axis by angle in radians. </description> </method> <method name="rotate_y"> @@ -191,7 +191,7 @@ <argument index="0" name="radians" type="float"> </argument> <description> - Rotates node in local space on Y axis by angle in radians. + Rotates the node in local space on Y axis by angle in radians. </description> </method> <method name="rotate_z"> @@ -200,7 +200,7 @@ <argument index="0" name="radians" type="float"> </argument> <description> - Rotates node in local space on Z axis by angle in radians. + Rotates the node in local space on Z axis by angle in radians. </description> </method> <method name="set_as_toplevel"> @@ -209,7 +209,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> - Makes this node ignore its parents tranformations. Node tranformations are only in global space. + Makes the node ignore its parents tranformations. Node tranformations are only in global space. </description> </method> <method name="set_gizmo"> @@ -243,7 +243,7 @@ <argument index="0" name="enabled" type="bool"> </argument> <description> - Set whether this node ignores notification that its transformation changed. + Set whether the node ignores notification that its transformation (global or local) changed. </description> </method> <method name="set_notify_local_transform"> @@ -252,7 +252,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> - Set whether this node sends notification that its local transformation changed. Spatial will not propagate this by default. + Set whether the node notifies about its local transformation changes. Spatial will not propagate this by default. </description> </method> <method name="set_notify_transform"> @@ -261,7 +261,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> - Set whether this node sends notification that its transformation changed. Spatial will not propagate this by default. + Set whether the node notifies about its global and local transformation changes. Spatial will not propagate this by default. </description> </method> <method name="set_rotation"> @@ -320,7 +320,7 @@ <return type="void"> </return> <description> - Enable rendering of this node. Change Spatial Visible property to false. + Enables rendering of this node. Change Spatial Visible property to "True". </description> </method> <method name="to_global" qualifiers="const"> @@ -329,7 +329,7 @@ <argument index="0" name="local_point" type="Vector3"> </argument> <description> - Tranform [Vector3] from this node local space to world space. + Tranforms [Vector3] "local_point" from this node's local space to world space. </description> </method> <method name="to_local" qualifiers="const"> @@ -338,7 +338,7 @@ <argument index="0" name="global_point" type="Vector3"> </argument> <description> - Tranform [Vector3] from world space to this node local space. + Tranforms [Vector3] "global_point" from world space to this node's local space. </description> </method> <method name="translate"> @@ -347,14 +347,14 @@ <argument index="0" name="offset" type="Vector3"> </argument> <description> - Change node position by given offset [Vector3]. + Changes the node's position by given offset [Vector3]. </description> </method> <method name="update_gizmo"> <return type="void"> </return> <description> - Update [SpatialGizmo] of this node. + Updates the [SpatialGizmo] of this node. </description> </method> </methods> @@ -384,23 +384,23 @@ <signals> <signal name="visibility_changed"> <description> - Emitted when node visibility changed. + Emitted when node visibility changes. </description> </signal> </signals> <constants> <constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29" enum=""> - Spatial nodes receive this notification when their global transform changes. This means that either the current or a parent node changed its transform. + Spatial nodes receives this notification when their global transform changes. This means that either the current or a parent node changed its transform. In order for NOTIFICATION_TRANSFORM_CHANGED to work user first needs to ask for it, with set_notify_transform(true). </constant> <constant name="NOTIFICATION_ENTER_WORLD" value="41" enum=""> - Spatial nodes receive this notification when they are registered to new [World] resource. + Spatial nodes receives this notification when they are registered to new [World] resource. </constant> <constant name="NOTIFICATION_EXIT_WORLD" value="42" enum=""> - Spatial nodes receive this notification when they are unregistered from current [World] resource. + Spatial nodes receives this notification when they are unregistered from current [World] resource. </constant> <constant name="NOTIFICATION_VISIBILITY_CHANGED" value="43" enum=""> - Spatial nodes receive this notification when their visibility changes. + Spatial nodes receives this notification when their visibility changes. </constant> </constants> </class> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index f96b31262c..ffe99eb82b 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -190,6 +190,12 @@ </signal> </signals> <constants> + <constant name="ALIGN_LEFT" value="0"> + </constant> + <constant name="ALIGN_CENTER" value="1"> + </constant> + <constant name="ALIGN_RIGHT" value="2"> + </constant> </constants> <theme_items> <theme_item name="decrement" type="Texture"> diff --git a/doc/classes/TextureProgress.xml b/doc/classes/TextureProgress.xml index 1ac031c411..0a6ffcdeb8 100644 --- a/doc/classes/TextureProgress.xml +++ b/doc/classes/TextureProgress.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="TextureProgress" inherits="Range" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Textured progress bar implementation. + Textured progress bar. </brief_description> <description> - [ProgressBar] implementation that is easier to theme (by just passing a few textures). + A [ProgressBar] that uses textures to display fill percentage. Can be set to linear or radial mode. </description> <tutorials> </tutorials> @@ -148,28 +148,40 @@ </methods> <members> <member name="fill_mode" type="int" setter="set_fill_mode" getter="get_fill_mode"> + The fill direction. Uses FILL_* constants. </member> <member name="nine_patch_stretch" type="bool" setter="set_nine_patch_stretch" getter="get_nine_patch_stretch"> + If [code]true[/code] textures will be stretched as [NinePatchRect]. Uses [code]stretch_margin[/code] properties (see below). Default value: [code]false[/code] </member> <member name="radial_center_offset" type="Vector2" setter="set_radial_center_offset" getter="get_radial_center_offset"> + The offset amount for radial mode. </member> <member name="radial_fill_degrees" type="float" setter="set_fill_degrees" getter="get_fill_degrees"> + The amount of the texture to use for radial mode. </member> <member name="radial_initial_angle" type="float" setter="set_radial_initial_angle" getter="get_radial_initial_angle"> + Start angle for radial mode. </member> <member name="stretch_margin_bottom" type="int" setter="set_stretch_margin" getter="get_stretch_margin"> + Nine-patch texture offset for bottom margin. </member> <member name="stretch_margin_left" type="int" setter="set_stretch_margin" getter="get_stretch_margin"> + Nine-patch texture offset for left margin. </member> <member name="stretch_margin_right" type="int" setter="set_stretch_margin" getter="get_stretch_margin"> + Nine-patch texture offset for right margin. </member> <member name="stretch_margin_top" type="int" setter="set_stretch_margin" getter="get_stretch_margin"> + Nine-patch texture offset for top margin. </member> <member name="texture_over" type="Texture" setter="set_over_texture" getter="get_over_texture"> + The [Texture] that will be drawn over the progress bar. </member> <member name="texture_progress" type="Texture" setter="set_progress_texture" getter="get_progress_texture"> + The [Texture] used to display [code]value[/code]. </member> <member name="texture_under" type="Texture" setter="set_under_texture" getter="get_under_texture"> + The [Texture] that will be drawn under the progress bar. </member> </members> <constants> diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml index 6d137cb14c..af5626ae84 100644 --- a/doc/classes/TextureRect.xml +++ b/doc/classes/TextureRect.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="TextureRect" inherits="Control" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Control that draws a texture. + Draws a sprite or a texture inside a User Interface. The texture can tile or not. </brief_description> <description> - Control that draws a texture. + Use TextureRect to draw icons and sprites in your User Interfaces. To create panels and menu boxes, take a look at [NinePatchFrame]. Its Stretch Mode property controls the texture's scale and placement. It can scale, tile and stay centered inside its bounding rectangle. TextureRect is one of the 5 most common nodes to create game UI. </description> <tutorials> </tutorials> @@ -56,31 +56,39 @@ </methods> <members> <member name="expand" type="bool" setter="set_expand" getter="has_expand"> - If [code]true[/code] texture will expand to fit. Default value: [code]false[/code]. + If [code]true[/code], the texture scales to fit its bounding rectangle. Default value: [code]false[/code]. </member> <member name="stretch_mode" type="int" setter="set_stretch_mode" getter="get_stretch_mode" enum="TextureRect.StretchMode"> - Stretch mode of the texture. Use STRETCH_* constants as value. + Controls the texture's behavior when you resize the node's bounding rectangle. Set it to one of the [code]STRETCH_*[/code] constants. See the constants to learn more. </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> - The [Texture] resource for the node. + The node's [Texture] resource. </member> </members> <constants> <constant name="STRETCH_SCALE_ON_EXPAND" value="0"> + Scale to fit the node's bounding rectangle, only if [code]expand[/code] is [code]true[/code]. Default [code]stretch_mode[/code], for backwards compatibility. Until you set [code]expand[/code] to [code]true[/code], the texture will behave like [code]STRETCH_KEEP[/code]. </constant> <constant name="STRETCH_SCALE" value="1"> + Scale to fit the node's bounding rectangle. </constant> <constant name="STRETCH_TILE" value="2"> + Tile inside the node's bounding rectangle. </constant> <constant name="STRETCH_KEEP" value="3"> + The texture keeps its original size and stays in the bounding rectangle's top-left corner. </constant> <constant name="STRETCH_KEEP_CENTERED" value="4"> + The texture keeps its original size and stays centered in the node's bounding rectangle. </constant> <constant name="STRETCH_KEEP_ASPECT" value="5"> + Scale the texture to fit the node's bounding rectangle, but maintain the texture's aspect ratio. </constant> <constant name="STRETCH_KEEP_ASPECT_CENTERED" value="6"> + Scale the texture to fit the node's bounding rectangle, center it and maintain its aspect ratio. </constant> <constant name="STRETCH_KEEP_ASPECT_COVERED" value="7"> + Scale the texture so that the shorter side fits the bounding rectangle. The other side clips to the node's limits. </constant> </constants> </class> diff --git a/doc/classes/TouchScreenButton.xml b/doc/classes/TouchScreenButton.xml index bf8af20da9..8a96fa1454 100644 --- a/doc/classes/TouchScreenButton.xml +++ b/doc/classes/TouchScreenButton.xml @@ -173,5 +173,9 @@ </signal> </signals> <constants> + <constant name="VISIBILITY_ALWAYS" value="0"> + </constant> + <constant name="VISIBILITY_TOUCHSCREEN_ONLY" value="1"> + </constant> </constants> </class> diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index d632eee70a..6780de1943 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -23,7 +23,7 @@ <argument index="3" name="origin" type="Vector3"> </argument> <description> - Construct the Transform from four [Vector3]. Each axis corresponds to local basis vectors (some of which may be scaled). + Constructs the Transform from four [Vector3]. Each axis corresponds to local basis vectors (some of which may be scaled). </description> </method> <method name="Transform"> @@ -34,7 +34,7 @@ <argument index="1" name="origin" type="Vector3"> </argument> <description> - Construct the Transform from a [Basis] and [Vector3]. + Constructs the Transform from a [Basis] and [Vector3]. </description> </method> <method name="Transform"> @@ -43,7 +43,7 @@ <argument index="0" name="from" type="Transform2D"> </argument> <description> - Construct the Transform from a [Transform2D]. + Constructs the Transform from a [Transform2D]. </description> </method> <method name="Transform"> @@ -52,7 +52,7 @@ <argument index="0" name="from" type="Quat"> </argument> <description> - Construct the Transform from a [Quat]. The origin will be Vector3(0, 0, 0). + Constructs the Transform from a [Quat]. The origin will be Vector3(0, 0, 0). </description> </method> <method name="Transform"> @@ -61,7 +61,7 @@ <argument index="0" name="from" type="Basis"> </argument> <description> - Construct the Transform from a [Basis]. The origin will be Vector3(0, 0, 0). + Constructs the Transform from a [Basis]. The origin will be Vector3(0, 0, 0). </description> </method> <method name="affine_inverse"> @@ -79,7 +79,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Interpolate to other Transform by weight amount (0-1). + Interpolates the transform to other Transform by weight amount (0-1). </description> </method> <method name="inverse"> @@ -104,7 +104,7 @@ <return type="Transform"> </return> <description> - Returns a transfrom with the basis orthogonal (90 degrees), and normalized axis vectors. + Returns the transfrom with the basis orthogonal (90 degrees), and normalized axis vectors. </description> </method> <method name="rotated"> @@ -115,7 +115,7 @@ <argument index="1" name="phi" type="float"> </argument> <description> - Rotate the transform around given axis by phi. The axis must be a normalized vector. + Rotates the transform around given axis by phi. The axis must be a normalized vector. </description> </method> <method name="scaled"> @@ -124,7 +124,7 @@ <argument index="0" name="scale" type="Vector3"> </argument> <description> - Scale the transform by the specified 3D scaling factors. + Scales the transform by the specified 3D scaling factors. </description> </method> <method name="translated"> @@ -133,7 +133,7 @@ <argument index="0" name="ofs" type="Vector3"> </argument> <description> - Translate the transform by the specified offset. + Translates the transform by the specified offset. </description> </method> <method name="xform"> @@ -151,7 +151,7 @@ <argument index="0" name="v" type="var"> </argument> <description> - Inverse-transforms vector "v" by this transform. + Inverse-transforms the given vector "v" by this transform. </description> </method> </methods> diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml index b3b752c1da..4cbe9123f1 100644 --- a/doc/classes/Transform2D.xml +++ b/doc/classes/Transform2D.xml @@ -66,28 +66,28 @@ <argument index="0" name="v" type="var"> </argument> <description> - Inverse-transforms vector "v" by this transform basis (no translation). + Inverse-transforms the given vector "v" by this transform basis (no translation). </description> </method> <method name="get_origin"> <return type="Vector2"> </return> <description> - Return the origin [Vector2] (translation). + Returns the origin [Vector2] (translation). </description> </method> <method name="get_rotation"> <return type="float"> </return> <description> - Return the rotation (in radians). + Returns the rotation (in radians). </description> </method> <method name="get_scale"> <return type="Vector2"> </return> <description> - Return the scale. + Returns the scale. </description> </method> <method name="interpolate_with"> @@ -98,7 +98,7 @@ <argument index="1" name="weight" type="float"> </argument> <description> - Interpolate to other Transform2D by weight amount (0-1). + Interpolates the transform to other Transform2D by weight amount (0-1). </description> </method> <method name="inverse"> @@ -112,7 +112,7 @@ <return type="Transform2D"> </return> <description> - Returns a transfrom with the basis orthogonal (90 degrees), and normalized axis vectors. + Returns the transfrom with the basis orthogonal (90 degrees), and normalized axis vectors. </description> </method> <method name="rotated"> @@ -121,7 +121,7 @@ <argument index="0" name="phi" type="float"> </argument> <description> - Rotate the transform by phi. + Rotates the transform by phi. </description> </method> <method name="scaled"> @@ -130,7 +130,7 @@ <argument index="0" name="scale" type="Vector2"> </argument> <description> - Scale the transform by the specified 2D scaling factors. + Scales the transform by the specified 2D scaling factors. </description> </method> <method name="translated"> @@ -139,7 +139,7 @@ <argument index="0" name="offset" type="Vector2"> </argument> <description> - Translate the transform by the specified offset. + Translates the transform by the specified offset. </description> </method> <method name="xform"> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index 02c264cbff..d1e45bd10f 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -545,5 +545,11 @@ </constant> <constant name="CELL_MODE_CUSTOM" value="5"> </constant> + <constant name="ALIGN_LEFT" value="0"> + </constant> + <constant name="ALIGN_CENTER" value="1"> + </constant> + <constant name="ALIGN_RIGHT" value="2"> + </constant> </constants> </class> diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index 43e0ad7873..d450a8812e 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -108,6 +108,12 @@ Get the name of the current action. </description> </method> + <method name="get_max_steps" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> <method name="get_version" qualifiers="const"> <return type="int"> </return> @@ -116,6 +122,26 @@ This is useful mostly to check if something changed from a saved version. </description> </method> + <method name="redo"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="set_max_steps"> + <return type="void"> + </return> + <argument index="0" name="max_steps" type="int"> + </argument> + <description> + </description> + </method> + <method name="undo"> + <return type="void"> + </return> + <description> + </description> + </method> </methods> <constants> <constant name="MERGE_DISABLE" value="0"> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index c12ec86cbb..a5170b8d03 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -650,5 +650,19 @@ </constant> <constant name="MSAA_16X" value="4"> </constant> + <constant name="USAGE_2D" value="0"> + </constant> + <constant name="USAGE_2D_NO_SAMPLING" value="1"> + </constant> + <constant name="USAGE_3D" value="2"> + </constant> + <constant name="USAGE_3D_NO_EFFECTS" value="3"> + </constant> + <constant name="CLEAR_MODE_ALWAYS" value="0"> + </constant> + <constant name="CLEAR_MODE_NEVER" value="1"> + </constant> + <constant name="CLEAR_MODE_ONLY_NEXT_FRAME" value="2"> + </constant> </constants> </class> diff --git a/doc/classes/VisibilityNotifier.xml b/doc/classes/VisibilityNotifier.xml index 4d76c7c927..816523fc27 100644 --- a/doc/classes/VisibilityNotifier.xml +++ b/doc/classes/VisibilityNotifier.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisibilityNotifier" inherits="Spatial" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Detect when the node is visible on screen. + Detects when the node is visible on screen. </brief_description> <description> - The VisibilityNotifier is used to notify when its bounding box enters the screen, is visible on the screen, or when it exits the screen. + The VisibilityNotifier detects when it is visible on the screen. It also notifies when its bounding rectangle enters or exits the screen or a [Camera]'s view. </description> <tutorials> </tutorials> @@ -15,14 +15,14 @@ <return type="Rect3"> </return> <description> - Return the visibility bounding box of the VisibilityNotifier. + Returns the bounding box of the VisibilityNotifier. </description> </method> <method name="is_on_screen" qualifiers="const"> <return type="bool"> </return> <description> - Return true if any part of the bounding box is on the screen. + If [code]true[/code] the bounding box is on the screen. </description> </method> <method name="set_aabb"> @@ -37,6 +37,7 @@ </methods> <members> <member name="aabb" type="Rect3" setter="set_aabb" getter="get_aabb"> + The VisibilityNotifier's bounding box. </member> </members> <signals> diff --git a/doc/classes/VisibilityNotifier2D.xml b/doc/classes/VisibilityNotifier2D.xml index 1058e3d6d4..86227a0277 100644 --- a/doc/classes/VisibilityNotifier2D.xml +++ b/doc/classes/VisibilityNotifier2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisibilityNotifier2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build"> <brief_description> - Detect when the node is visible on screen. + Detects when the node is visible on screen. </brief_description> <description> - The VisibilityNotifier2D is used to notify when its bounding rectangle enters the screen, is visible on the screen, or when it exits the screen. + The VisibilityNotifier2D detects when it is visible on the screen. It also notifies when its bounding rectangle enters or exits the screen or a viewport. </description> <tutorials> </tutorials> @@ -15,14 +15,14 @@ <return type="Rect2"> </return> <description> - Return the visibility bounding rectangle of the VisibilityNotifier2D. + Returns the bounding rectangle of the VisibilityNotifier2D. </description> </method> <method name="is_on_screen" qualifiers="const"> <return type="bool"> </return> <description> - Return true if any part of the bounding rectangle is on the screen. + If [code]true[/code] the bounding rectangle is on the screen. </description> </method> <method name="set_rect"> @@ -37,6 +37,7 @@ </methods> <members> <member name="rect" type="Rect2" setter="set_rect" getter="get_rect"> + The VisibilityNotifier2D's bounding rectangle. </member> </members> <signals> diff --git a/doc/classes/VisualScriptBuiltinFunc.xml b/doc/classes/VisualScriptBuiltinFunc.xml index eb9af69ea9..a88633749e 100644 --- a/doc/classes/VisualScriptBuiltinFunc.xml +++ b/doc/classes/VisualScriptBuiltinFunc.xml @@ -29,5 +29,121 @@ </member> </members> <constants> + <constant name="MATH_SIN" value="0"> + </constant> + <constant name="MATH_COS" value="1"> + </constant> + <constant name="MATH_TAN" value="2"> + </constant> + <constant name="MATH_SINH" value="3"> + </constant> + <constant name="MATH_COSH" value="4"> + </constant> + <constant name="MATH_TANH" value="5"> + </constant> + <constant name="MATH_ASIN" value="6"> + </constant> + <constant name="MATH_ACOS" value="7"> + </constant> + <constant name="MATH_ATAN" value="8"> + </constant> + <constant name="MATH_ATAN2" value="9"> + </constant> + <constant name="MATH_SQRT" value="10"> + </constant> + <constant name="MATH_FMOD" value="11"> + </constant> + <constant name="MATH_FPOSMOD" value="12"> + </constant> + <constant name="MATH_FLOOR" value="13"> + </constant> + <constant name="MATH_CEIL" value="14"> + </constant> + <constant name="MATH_ROUND" value="15"> + </constant> + <constant name="MATH_ABS" value="16"> + </constant> + <constant name="MATH_SIGN" value="17"> + </constant> + <constant name="MATH_POW" value="18"> + </constant> + <constant name="MATH_LOG" value="19"> + </constant> + <constant name="MATH_EXP" value="20"> + </constant> + <constant name="MATH_ISNAN" value="21"> + </constant> + <constant name="MATH_ISINF" value="22"> + </constant> + <constant name="MATH_EASE" value="23"> + </constant> + <constant name="MATH_DECIMALS" value="24"> + </constant> + <constant name="MATH_STEPIFY" value="25"> + </constant> + <constant name="MATH_LERP" value="26"> + </constant> + <constant name="MATH_DECTIME" value="27"> + </constant> + <constant name="MATH_RANDOMIZE" value="28"> + </constant> + <constant name="MATH_RAND" value="29"> + </constant> + <constant name="MATH_RANDF" value="30"> + </constant> + <constant name="MATH_RANDOM" value="31"> + </constant> + <constant name="MATH_SEED" value="32"> + </constant> + <constant name="MATH_RANDSEED" value="33"> + </constant> + <constant name="MATH_DEG2RAD" value="34"> + </constant> + <constant name="MATH_RAD2DEG" value="35"> + </constant> + <constant name="MATH_LINEAR2DB" value="36"> + </constant> + <constant name="MATH_DB2LINEAR" value="37"> + </constant> + <constant name="LOGIC_MAX" value="38"> + </constant> + <constant name="LOGIC_MIN" value="39"> + </constant> + <constant name="LOGIC_CLAMP" value="40"> + </constant> + <constant name="LOGIC_NEAREST_PO2" value="41"> + </constant> + <constant name="OBJ_WEAKREF" value="42"> + </constant> + <constant name="FUNC_FUNCREF" value="43"> + </constant> + <constant name="TYPE_CONVERT" value="44"> + </constant> + <constant name="TYPE_OF" value="45"> + </constant> + <constant name="TYPE_EXISTS" value="46"> + </constant> + <constant name="TEXT_CHAR" value="47"> + </constant> + <constant name="TEXT_STR" value="48"> + </constant> + <constant name="TEXT_PRINT" value="49"> + </constant> + <constant name="TEXT_PRINTERR" value="50"> + </constant> + <constant name="TEXT_PRINTRAW" value="51"> + </constant> + <constant name="VAR_TO_STR" value="52"> + </constant> + <constant name="STR_TO_VAR" value="53"> + </constant> + <constant name="VAR_TO_BYTES" value="54"> + </constant> + <constant name="BYTES_TO_VAR" value="55"> + </constant> + <constant name="COLORN" value="56"> + </constant> + <constant name="FUNC_MAX" value="57"> + </constant> </constants> </class> diff --git a/doc/classes/VisualScriptFunctionCall.xml b/doc/classes/VisualScriptFunctionCall.xml index 9a56831253..36c808afce 100644 --- a/doc/classes/VisualScriptFunctionCall.xml +++ b/doc/classes/VisualScriptFunctionCall.xml @@ -183,5 +183,17 @@ </constant> <constant name="CALL_MODE_BASIC_TYPE" value="3"> </constant> + <constant name="CALL_MODE_SINGLETON" value="4"> + </constant> + <constant name="RPC_DISABLED" value="0"> + </constant> + <constant name="RPC_RELIABLE" value="1"> + </constant> + <constant name="RPC_UNRELIABLE" value="2"> + </constant> + <constant name="RPC_RELIABLE_TO_ID" value="3"> + </constant> + <constant name="RPC_UNRELIABLE_TO_ID" value="4"> + </constant> </constants> </class> diff --git a/doc/classes/VisualScriptInputAction.xml b/doc/classes/VisualScriptInputAction.xml index b0f7827024..b555a0228b 100644 --- a/doc/classes/VisualScriptInputAction.xml +++ b/doc/classes/VisualScriptInputAction.xml @@ -45,5 +45,13 @@ </member> </members> <constants> + <constant name="MODE_PRESSED" value="0"> + </constant> + <constant name="MODE_RELEASED" value="1"> + </constant> + <constant name="MODE_JUST_PRESSED" value="2"> + </constant> + <constant name="MODE_JUST_RELEASED" value="3"> + </constant> </constants> </class> diff --git a/doc/classes/VisualScriptMathConstant.xml b/doc/classes/VisualScriptMathConstant.xml index 8e0436edfa..1ef7d71e10 100644 --- a/doc/classes/VisualScriptMathConstant.xml +++ b/doc/classes/VisualScriptMathConstant.xml @@ -29,5 +29,23 @@ </member> </members> <constants> + <constant name="MATH_CONSTANT_ONE" value="0"> + </constant> + <constant name="MATH_CONSTANT_PI" value="1"> + </constant> + <constant name="MATH_CONSTANT_2PI" value="2"> + </constant> + <constant name="MATH_CONSTANT_HALF_PI" value="3"> + </constant> + <constant name="MATH_CONSTANT_E" value="4"> + </constant> + <constant name="MATH_CONSTANT_SQRT2" value="5"> + </constant> + <constant name="MATH_CONSTANT_INF" value="6"> + </constant> + <constant name="MATH_CONSTANT_NAN" value="7"> + </constant> + <constant name="MATH_CONSTANT_MAX" value="8"> + </constant> </constants> </class> diff --git a/doc/classes/VisualScriptPropertySet.xml b/doc/classes/VisualScriptPropertySet.xml index a129cc36f8..88d47a7463 100644 --- a/doc/classes/VisualScriptPropertySet.xml +++ b/doc/classes/VisualScriptPropertySet.xml @@ -149,5 +149,29 @@ </constant> <constant name="CALL_MODE_INSTANCE" value="2"> </constant> + <constant name="CALL_MODE_BASIC_TYPE" value="3"> + </constant> + <constant name="ASSIGN_OP_NONE" value="0"> + </constant> + <constant name="ASSIGN_OP_ADD" value="1"> + </constant> + <constant name="ASSIGN_OP_SUB" value="2"> + </constant> + <constant name="ASSIGN_OP_MUL" value="3"> + </constant> + <constant name="ASSIGN_OP_DIV" value="4"> + </constant> + <constant name="ASSIGN_OP_MOD" value="5"> + </constant> + <constant name="ASSIGN_OP_SHIFT_LEFT" value="6"> + </constant> + <constant name="ASSIGN_OP_SHIFT_RIGHT" value="7"> + </constant> + <constant name="ASSIGN_OP_BIT_AND" value="8"> + </constant> + <constant name="ASSIGN_OP_BIT_OR" value="9"> + </constant> + <constant name="ASSIGN_OP_BIT_XOR" value="10"> + </constant> </constants> </class> diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py index 1386e91ce1..6b6b794f11 100644 --- a/doc/tools/doc_status.py +++ b/doc/tools/doc_status.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +import os import sys import re import math @@ -220,6 +221,21 @@ class ClassStatus: def generate_for_class(c): status = ClassStatus() status.name = c.attrib['name'] + + # setgets do not count + methods = [] + for tag in list(c): + if tag.tag in ['methods']: + for sub_tag in list(tag): + methods.append(sub_tag.find('name')) + if tag.tag in ['members']: + for sub_tag in list(tag): + try: + methods.remove(sub_tag.find('setter')) + methods.remove(sub_tag.find('getter')) + except: + pass + for tag in list(c): if tag.tag == 'brief_description': @@ -230,13 +246,16 @@ class ClassStatus: elif tag.tag in ['methods', 'signals']: for sub_tag in list(tag): - descr = sub_tag.find('description') - status.progresses[tag.tag].increment(len(descr.text.strip()) > 0) - + if sub_tag.find('name') in methods or tag.tag == 'signals': + descr = sub_tag.find('description') + status.progresses[tag.tag].increment(len(descr.text.strip()) > 0) elif tag.tag in ['constants', 'members']: for sub_tag in list(tag): status.progresses[tag.tag].increment(len(sub_tag.text.strip()) > 0) + elif tag.tag in ['tutorials', 'demos']: + pass # Ignore those tags for now + elif tag.tag in ['theme_items']: pass # Ignore those tags, since they seem to lack description at all @@ -252,6 +271,7 @@ class ClassStatus: input_file_list = [] input_class_list = [] +merged_file = "" for arg in sys.argv[1:]: if arg.startswith('--'): @@ -259,8 +279,10 @@ for arg in sys.argv[1:]: elif arg.startswith('-'): for f in arg[1:]: flags[f] = not flags[f] - elif arg.endswith('.xml'): - input_file_list.append(arg) + elif os.path.isdir(arg): + for f in os.listdir(arg): + if f.endswith('.xml'): + input_file_list.append(os.path.join(arg, f)); else: input_class_list.append(arg) @@ -287,10 +309,9 @@ if flags['u']: if len(input_file_list) < 1 or flags['h']: if not flags['h']: - print(color('section', 'Invalid usage') + ': At least one classes.xml file is required') - print(color('section', 'Usage') + ': doc_status.py [flags] <classes.xml> [class names]') + print(color('section', 'Invalid usage') + ': Please specify a classes directory') + print(color('section', 'Usage') + ': doc_status.py [flags] <classes_dir> [class names]') print('\t< and > signify required parameters, while [ and ] signify optional parameters.') - print('\tNote that you can give more than one classes file, in which case they will be merged on-the-fly.') print(color('section', 'Available flags') + ':') possible_synonym_list = list(long_flags) possible_synonym_list.sort() @@ -327,11 +348,10 @@ for file in input_file_list: version = doc.attrib['version'] - for c in list(doc): - if c.attrib['name'] in class_names: - continue - class_names.append(c.attrib['name']) - classes[c.attrib['name']] = c + if doc.attrib['name'] in class_names: + continue + class_names.append(doc.attrib['name']) + classes[doc.attrib['name']] = doc class_names.sort() @@ -344,7 +364,7 @@ if len(input_class_list) < 1: ################################################################################ table = [table_column_names] -table_row_chars = '+- ' +table_row_chars = '| - ' table_column_chars = '|' total_status = ClassStatus('Total') @@ -406,7 +426,7 @@ for row in table: divider_string = table_row_chars[0] for cell_i in range(len(table[0])): - divider_string += table_row_chars[1] * (table_column_sizes[cell_i] + 2) + table_row_chars[0] + divider_string += table_row_chars[1] + table_row_chars[2] * (table_column_sizes[cell_i]) + table_row_chars[1] + table_row_chars[0] print(divider_string) for row_i, row in enumerate(table): @@ -414,9 +434,9 @@ for row_i, row in enumerate(table): for cell_i, cell in enumerate(row): padding_needed = table_column_sizes[cell_i] - nonescape_len(cell) + 2 if cell_i == 0: - row_string += table_row_chars[2] + cell + table_row_chars[2] * (padding_needed - 1) + row_string += table_row_chars[3] + cell + table_row_chars[3] * (padding_needed - 1) else: - row_string += table_row_chars[2] * math.floor(padding_needed / 2) + cell + table_row_chars[2] * math.ceil((padding_needed / 2)) + row_string += table_row_chars[3] * math.floor(padding_needed / 2) + cell + table_row_chars[3] * math.ceil((padding_needed / 2)) row_string += table_column_chars print(row_string) diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b3fd6fa2a0..8669c42a7a 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -806,7 +806,7 @@ public: void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows); - _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_passs); + _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass); _FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass); diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp index ae5fdd28b6..a184c9e9cf 100644 --- a/drivers/rtaudio/audio_driver_rtaudio.cpp +++ b/drivers/rtaudio/audio_driver_rtaudio.cpp @@ -143,7 +143,7 @@ Error AudioDriverRtAudio::init() { } } - return OK; + return active ? OK : ERR_UNAVAILABLE; } int AudioDriverRtAudio::get_mix_rate() const { diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 45ea654bad..e7054e11a3 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -183,17 +183,18 @@ void DirAccessUnix::list_dir_end() { _cisdir = false; } -#ifdef HAVE_MNTENT +#if defined(HAVE_MNTENT) && defined(X11_ENABLED) static bool _filter_drive(struct mntent *mnt) { // Ignore devices that don't point to /dev if (strncmp(mnt->mnt_fsname, "/dev", 4) != 0) { return false; } - // Accept devices mounted at /media, /mnt or /home + // Accept devices mounted at common locations if (strncmp(mnt->mnt_dir, "/media", 6) == 0 || strncmp(mnt->mnt_dir, "/mnt", 4) == 0 || - strncmp(mnt->mnt_dir, "/home", 5) == 0) { + strncmp(mnt->mnt_dir, "/home", 5) == 0 || + strncmp(mnt->mnt_dir, "/run/media", 10) == 0) { return true; } @@ -204,7 +205,7 @@ static bool _filter_drive(struct mntent *mnt) { static void _get_drives(List<String> *list) { -#ifdef HAVE_MNTENT +#if defined(HAVE_MNTENT) && defined(X11_ENABLED) // Check /etc/mtab for the list of mounted partitions FILE *mtab = setmntent("/etc/mtab", "r"); if (mtab) { diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 80565c5b02..e19bc738cb 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -274,6 +274,15 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) { }; } +Error FileAccessUnix::_chmod(const String &p_path, int p_mod) { + int err = chmod(p_path.utf8().get_data(), p_mod); + if (!err) { + return OK; + } + + return FAILED; +} + FileAccess *FileAccessUnix::create_libc() { return memnew(FileAccessUnix); diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h index 6e5110431f..c5ab8821be 100644 --- a/drivers/unix/file_access_unix.h +++ b/drivers/unix/file_access_unix.h @@ -78,6 +78,8 @@ public: virtual uint64_t _get_modified_time(const String &p_file); + virtual Error _chmod(const String &p_path, int p_mod); + FileAccessUnix(); virtual ~FileAccessUnix(); }; diff --git a/editor/SCsub b/editor/SCsub index 839d8e74c1..315865ad32 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -41,7 +41,7 @@ def make_doc_header(target, source, env): src = s.srcnode().abspath f = open_utf8(src, "r") content = f.read() - buf+=content + buf+=content buf = encode_utf8(docbegin + buf + docend) decomp_size = len(buf) @@ -385,13 +385,13 @@ def make_license_header(target, source, env): def _make_doc_data_class_path(to_path): - g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "wb") + g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "w") g.write("static const int _doc_data_class_path_count="+str(len(env.doc_class_path))+";\n") g.write("struct _DocDataClassPath { const char* name; const char* path; };\n") g.write("static const _DocDataClassPath _doc_data_class_paths["+str(len(env.doc_class_path)+1)+"]={\n"); for c in env.doc_class_path: - g.write("{\""+c+"\",\""+env.doc_class_path[c]+"\"},\n") + g.write("{\""+c+"\",\""+env.doc_class_path[c]+"\"},\n") g.write("{NULL,NULL}\n") g.write("};\n") @@ -414,7 +414,7 @@ if (env["tools"] == "yes"): docs=[] print("cdir is: "+env.Dir('#').abspath) for f in os.listdir(os.path.join(env.Dir('#').abspath,"doc/classes")): - docs.append("#doc/classes/"+f) + docs.append("#doc/classes/"+f) _make_doc_data_class_path(os.path.join(env.Dir('#').abspath,"editor/doc")) diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index 47360ff7fb..96e5627bef 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -2898,10 +2898,6 @@ void AnimationKeyEditor::_notification(int p_what) { zoomicon->set_custom_minimum_size(Size2(24 * EDSCALE, 0)); zoomicon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); - menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), "Add Normal Track", ADD_TRACK_MENU_ADD_VALUE_TRACK); - menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), "Add Transform Track", ADD_TRACK_MENU_ADD_TRANSFORM_TRACK); - menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), "Add Call Func Track", ADD_TRACK_MENU_ADD_CALL_TRACK); - menu_track->set_icon(get_icon("Tools", "EditorIcons")); menu_track->get_popup()->add_item(TTR("Scale Selection"), TRACK_MENU_SCALE); menu_track->get_popup()->add_item(TTR("Scale From Cursor"), TRACK_MENU_SCALE_PIVOT); @@ -3817,6 +3813,9 @@ AnimationKeyEditor::AnimationKeyEditor() { hb->add_child(menu_add_track); menu_add_track->get_popup()->connect("id_pressed", this, "_menu_add_track"); menu_add_track->set_tooltip(TTR("Add new tracks.")); + menu_add_track->get_popup()->add_icon_item(get_icon("KeyValue", "EditorIcons"), "Add Normal Track", ADD_TRACK_MENU_ADD_VALUE_TRACK); + menu_add_track->get_popup()->add_icon_item(get_icon("KeyXform", "EditorIcons"), "Add Transform Track", ADD_TRACK_MENU_ADD_TRANSFORM_TRACK); + menu_add_track->get_popup()->add_icon_item(get_icon("KeyCall", "EditorIcons"), "Add Call Func Track", ADD_TRACK_MENU_ADD_CALL_TRACK); move_up_button = memnew(ToolButton); hb->add_child(move_up_button); @@ -3934,7 +3933,7 @@ AnimationKeyEditor::AnimationKeyEditor() { key_editor_tab = memnew(TabContainer); key_editor_tab->set_tab_align(TabContainer::ALIGN_LEFT); hb->add_child(key_editor_tab); - key_editor_tab->set_custom_minimum_size(Size2(200, 0)); + key_editor_tab->set_custom_minimum_size(Size2(200, 0) * EDSCALE); key_editor = memnew(PropertyEditor); key_editor->set_area_as_parent_rect(); @@ -4052,8 +4051,6 @@ AnimationKeyEditor::AnimationKeyEditor() { cleanup_dialog->connect("confirmed", this, "_menu_track", varray(TRACK_MENU_CLEAN_UP_CONFIRM)); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); - track_editor->set_clip_contents(true); } diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 8c153d2745..5dd8b8a800 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1023,8 +1023,10 @@ void CodeTextEditor::_line_col_changed() { void CodeTextEditor::_text_changed() { - code_complete_timer->start(); - idle->start(); + if (text_editor->is_insert_text_operation()) { + code_complete_timer->start(); + idle->start(); + } } void CodeTextEditor::_code_complete_timer_timeout() { diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 7b6cfe6c83..33734957e2 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -54,12 +54,7 @@ void CreateDialog::popup_create(bool p_dontclear) { TreeItem *ti = recent->create_item(root); ti->set_text(0, l); - if (has_icon(l, "EditorIcons")) { - - ti->set_icon(0, get_icon(l, "EditorIcons")); - } else { - ti->set_icon(0, get_icon("Object", "EditorIcons")); - } + ti->set_icon(0, _get_editor_icon(l)); } } @@ -122,6 +117,29 @@ void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) { } } +Ref<Texture> CreateDialog::_get_editor_icon(const String &p_type) const { + + if (has_icon(p_type, "EditorIcons")) { + return get_icon(p_type, "EditorIcons"); + } + + const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types(); + for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) { + const Vector<EditorData::CustomType> &ct = E->value(); + for (int i = 0; i < ct.size(); ++i) { + if (ct[i].name == p_type) { + if (ct[i].icon.is_valid()) { + return ct[i].icon; + } else { + return get_icon("Object", "EditorIcons"); + } + } + } + } + + return get_icon("Object", "EditorIcons"); +} + void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root, TreeItem **to_select) { if (p_types.has(p_type)) @@ -457,13 +475,7 @@ void CreateDialog::_update_favorite_list() { TreeItem *ti = favorites->create_item(root); String l = favorite_list[i]; ti->set_text(0, l); - - if (has_icon(l, "EditorIcons")) { - - ti->set_icon(0, get_icon(l, "EditorIcons")); - } else { - ti->set_icon(0, get_icon("Object", "EditorIcons")); - } + ti->set_icon(0, _get_editor_icon(l)); } } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index 31f106ea22..a523539ba0 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -74,6 +74,8 @@ class CreateDialog : public ConfirmationDialog { void _confirmed(); void _text_changed(const String &p_newtext); + Ref<Texture> _get_editor_icon(const String &p_type) const; + void add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root, TreeItem **to_select); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp index 272a5af59b..d35dc53ae1 100644 --- a/editor/doc/doc_data.cpp +++ b/editor/doc/doc_data.cpp @@ -170,6 +170,8 @@ static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const Property if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { p_method.return_enum = p_retinfo.class_name; + if (p_method.return_enum.begins_with("_")) //proxy class + p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length()); p_method.return_type = "int"; } else if (p_retinfo.class_name != StringName()) { p_method.return_type = p_retinfo.class_name; @@ -190,6 +192,8 @@ static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const Pr if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { p_argument.enumeration = p_arginfo.class_name; + if (p_argument.enumeration.begins_with("_")) //proxy class + p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length()); p_argument.type = "int"; } else if (p_arginfo.class_name != StringName()) { p_argument.type = p_arginfo.class_name; diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp index cfb3abfd1d..658c12d4d0 100644 --- a/editor/editor_dir_dialog.cpp +++ b/editor/editor_dir_dialog.cpp @@ -64,7 +64,7 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p } } -void EditorDirDialog::reload(const String &p_with_path) { +void EditorDirDialog::reload(const String &p_path) { if (!is_visible_in_tree()) { must_reload = true; @@ -73,7 +73,7 @@ void EditorDirDialog::reload(const String &p_with_path) { tree->clear(); TreeItem *root = tree->create_item(); - _update_dir(root, EditorFileSystem::get_singleton()->get_filesystem(), p_with_path); + _update_dir(root, EditorFileSystem::get_singleton()->get_filesystem(), p_path); _item_collapsed(root); must_reload = false; } diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 8623b9acdb..ad9bc4a662 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -476,19 +476,77 @@ void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String & memdelete(da); } -Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata) { +void EditorExportPlugin::add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap) { + + ExtraFile ef; + ef.data = p_file; + ef.path = p_path; + ef.remap = p_remap; + extra_files.push_back(ef); +} + +void EditorExportPlugin::add_shared_object(const String &p_path) { + + shared_objects.push_back(p_path); +} + +void EditorExportPlugin::_export_file_script(const String &p_path, const String &p_type, const PoolVector<String> &p_features) { + + if (get_script_instance()) { + get_script_instance()->call("_export_file", p_path, p_type, p_features); + } +} + +void EditorExportPlugin::_export_begin_script(const PoolVector<String> &p_features) { + + if (get_script_instance()) { + get_script_instance()->call("_export_begin", p_features); + } +} + +void EditorExportPlugin::_export_file(const String &p_path, const String &p_type, const Set<String> &p_features) { +} + +void EditorExportPlugin::_export_begin(const Set<String> &p_features) { +} + +void EditorExportPlugin::skip() { + + skipped = true; +} + +void EditorExportPlugin::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_shared_object", "path"), &EditorExportPlugin::add_shared_object); + ClassDB::bind_method(D_METHOD("add_file", "path", "file", "remap"), &EditorExportPlugin::add_file); + ClassDB::bind_method(D_METHOD("skip"), &EditorExportPlugin::skip); + + BIND_VMETHOD(MethodInfo("_export_file", PropertyInfo(Variant::STRING, "path"), PropertyInfo(Variant::STRING, "type"), PropertyInfo(Variant::POOL_STRING_ARRAY, "features"))); + BIND_VMETHOD(MethodInfo("_export_begin", PropertyInfo(Variant::POOL_STRING_ARRAY, "features"))); +} + +EditorExportPlugin::EditorExportPlugin() { + skipped = false; +} + +Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func) { Ref<EditorExportPlatform> platform = p_preset->get_platform(); List<String> feature_list; platform->get_preset_features(p_preset, &feature_list); //figure out features Set<String> features; + PoolVector<String> features_pv; for (List<String>::Element *E = feature_list.front(); E; E = E->next()) { features.insert(E->get()); + features_pv.push_back(E->get()); } + Vector<Ref<EditorExportPlugin> > export_plugins = EditorExport::get_singleton()->get_export_plugins(); + //figure out paths of files that will be exported Set<String> paths; + Vector<String> path_remaps; if (p_preset->get_export_filter() == EditorExportPreset::EXPORT_ALL_RESOURCES) { //find stuff @@ -508,6 +566,25 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & _edit_filter_list(paths, p_preset->get_include_filter(), false); _edit_filter_list(paths, p_preset->get_exclude_filter(), true); + //initial export plugin callback + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->get_script_instance()) { //script based + export_plugins[i]->_export_begin_script(features_pv); + } else { + export_plugins[i]->_export_begin(features); + } + if (p_so_func) { + for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { + p_so_func(p_udata, export_plugins[i]->shared_objects[j]); + } + } + for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { + p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size()); + } + + export_plugins[i]->_clear(); + } + //store everything in the export medium int idx = 0; int total = paths.size(); @@ -515,6 +592,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & for (Set<String>::Element *E = paths.front(); E; E = E->next()) { String path = E->get(); + String type = ResourceLoader::get_resource_type(path); if (FileAccess::exists(path + ".import")) { //file is imported, replace by what it imports @@ -551,9 +629,42 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & p_func(p_udata, path + ".import", array, idx, total); } else { + + bool do_export = true; + for (int i = 0; i < export_plugins.size(); i++) { + if (export_plugins[i]->get_script_instance()) { //script based + export_plugins[i]->_export_file_script(path, type, features_pv); + } else { + export_plugins[i]->_export_file(path, type, features); + } + if (p_so_func) { + for (int j = 0; j < export_plugins[i]->shared_objects.size(); j++) { + p_so_func(p_udata, export_plugins[i]->shared_objects[j]); + } + } + + for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { + p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total); + if (export_plugins[i]->extra_files[j].remap) { + do_export = false; //if remap, do not + path_remaps.push_back(path); + path_remaps.push_back(export_plugins[i]->extra_files[j].path); + } + } + + if (export_plugins[i]->skipped) { + do_export = false; + } + export_plugins[i]->_clear(); + + if (!do_export) + break; //apologies, not exporting + } //just store it as it comes - Vector<uint8_t> array = FileAccess::get_file_as_array(path); - p_func(p_udata, path, array, idx, total); + if (do_export) { + Vector<uint8_t> array = FileAccess::get_file_as_array(path); + p_func(p_udata, path, array, idx, total); + } } idx++; @@ -575,9 +686,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } + ProjectSettings::CustomMap custom_map; + if (path_remaps.size()) { + custom_map["path_remap/remapped_paths"] = path_remaps; + } + String config_file = "project.binary"; String engine_cfb = EditorSettings::get_singleton()->get_settings_path() + "/tmp/tmp" + config_file; - ProjectSettings::get_singleton()->save_custom(engine_cfb, ProjectSettings::CustomMap(), custom_list); + ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list); Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb); p_func(p_udata, "res://" + config_file, data, idx, total); @@ -867,6 +983,23 @@ void EditorExport::remove_export_preset(int p_idx) { export_presets.remove(p_idx); } +void EditorExport::add_export_plugin(const Ref<EditorExportPlugin> &p_plugin) { + + if (export_plugins.find(p_plugin) == 1) { + export_plugins.push_back(p_plugin); + } +} + +void EditorExport::remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin) { + + export_plugins.erase(p_plugin); +} + +Vector<Ref<EditorExportPlugin> > EditorExport::get_export_plugins() { + + return export_plugins; +} + void EditorExport::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -1113,9 +1246,13 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr } DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - da->copy(template_path, p_path); + Error err = da->copy(template_path, p_path, get_chmod_flags()); memdelete(da); + if (err != OK) { + return err; + } + String pck_path = p_path.get_basename() + ".pck"; return save_pack(p_preset, pck_path); @@ -1169,5 +1306,17 @@ void EditorExportPlatformPC::get_platform_features(List<String> *r_features) { } } +int EditorExportPlatformPC::get_chmod_flags() const { + + return chmod_flags; +} + +void EditorExportPlatformPC::set_chmod_flags(int p_flags) { + + chmod_flags = p_flags; +} + EditorExportPlatformPC::EditorExportPlatformPC() { + + chmod_flags = -1; } diff --git a/editor/editor_export.h b/editor/editor_export.h index 3b99c68c85..50379b9683 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -124,6 +124,7 @@ class EditorExportPlatform : public Reference { public: typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total); + typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const String &p_path); private: struct SavedData { @@ -189,7 +190,7 @@ public: virtual String get_name() const = 0; virtual Ref<Texture> get_logo() const = 0; - Error export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata); + Error export_project_files(const Ref<EditorExportPreset> &p_preset, EditorExportSaveFunction p_func, void *p_udata, EditorExportSaveSharedObject p_so_func = NULL); Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path); @@ -219,11 +220,49 @@ public: EditorExportPlatform(); }; +class EditorExportPlugin : public Reference { + GDCLASS(EditorExportPlugin, Reference) + + friend class EditorExportPlatform; + + Vector<String> shared_objects; + struct ExtraFile { + String path; + Vector<uint8_t> data; + bool remap; + }; + Vector<ExtraFile> extra_files; + bool skipped; + + _FORCE_INLINE_ void _clear() { + shared_objects.clear(); + extra_files.clear(); + skipped = false; + } + + void _export_file_script(const String &p_path, const String &p_type, const PoolVector<String> &p_features); + void _export_begin_script(const PoolVector<String> &p_features); + +protected: + void add_file(const String &p_path, const Vector<uint8_t> &p_file, bool p_remap); + void add_shared_object(const String &p_path); + void skip(); + + virtual void _export_file(const String &p_path, const String &p_type, const Set<String> &p_features); + virtual void _export_begin(const Set<String> &p_features); + + static void _bind_methods(); + +public: + EditorExportPlugin(); +}; + class EditorExport : public Node { GDCLASS(EditorExport, Node); Vector<Ref<EditorExportPlatform> > export_platforms; Vector<Ref<EditorExportPreset> > export_presets; + Vector<Ref<EditorExportPlugin> > export_plugins; Timer *save_timer; bool block_save; @@ -251,6 +290,10 @@ public: Ref<EditorExportPreset> get_export_preset(int p_idx); void remove_export_preset(int p_idx); + void add_export_plugin(const Ref<EditorExportPlugin> &p_plugin); + void remove_export_plugin(const Ref<EditorExportPlugin> &p_plugin); + Vector<Ref<EditorExportPlugin> > get_export_plugins(); + void load_config(); bool poll_export_platforms(); @@ -276,6 +319,7 @@ class EditorExportPlatformPC : public EditorExportPlatform { Set<String> extra_features; bool use64; + int chmod_flags; public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features); @@ -304,6 +348,9 @@ public: void add_platform_feature(const String &p_feature); virtual void get_platform_features(List<String> *r_features); + int get_chmod_flags() const; + void set_chmod_flags(int p_flags); + EditorExportPlatformPC(); }; diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index be8dc0f494..8d13153128 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -107,8 +107,6 @@ void EditorFileDialog::_notification(int p_what) { fav_down->set_icon(get_icon("MoveDown", "EditorIcons")); fav_rm->set_icon(get_icon("RemoveSmall", "EditorIcons")); - Theme::get_default()->clear_icon("ResizedFile", "EditorIcons"); - Theme::get_default()->clear_icon("ResizedFolder", "EditorIcons"); update_file_list(); } } @@ -1198,6 +1196,9 @@ void EditorFileDialog::_bind_methods() { BIND_ENUM_CONSTANT(ACCESS_RESOURCES); BIND_ENUM_CONSTANT(ACCESS_USERDATA); BIND_ENUM_CONSTANT(ACCESS_FILESYSTEM); + + BIND_ENUM_CONSTANT(DISPLAY_THUMBNAILS); + BIND_ENUM_CONSTANT(DISPLAY_LIST); } void EditorFileDialog::set_show_hidden_files(bool p_show) { diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index d806b825ba..345c7b1f65 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -137,6 +137,9 @@ void editor_register_fonts(Ref<Theme> p_theme) { p_theme->set_font("doc", "EditorFonts", df_doc); p_theme->set_font("doc_title", "EditorFonts", df_title); + MAKE_DEFAULT_FONT(df_rulers, int(EDITOR_DEF("canvas_item_editor/rulers", 8)) * EDSCALE); + p_theme->set_font("rulers", "EditorFonts", df_rulers); + Ref<DynamicFont> df_code; df_code.instance(); df_code->set_size(int(EditorSettings::get_singleton()->get("interface/source_font_size")) * EDSCALE); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 035819f503..481f2aaecf 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -85,7 +85,11 @@ void EditorLog::clear() { void EditorLog::add_message(const String &p_msg, bool p_error) { + Ref<Font> doc_code_font = get_font("doc_source", "EditorFonts"); + log->push_font(doc_code_font); + log->add_newline(); + if (p_error) { log->push_color(get_color("error_color", "Editor")); Ref<Texture> icon = get_icon("Error", "EditorIcons"); @@ -100,6 +104,8 @@ void EditorLog::add_message(const String &p_msg, bool p_error) { if (p_error) log->pop(); + + log->pop(); // pop font; } /* diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4bcf5a49e6..1a89d6ef6e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -254,7 +254,7 @@ void EditorNode::_notification(int p_what) { get_tree()->get_root()->set_as_audio_listener_2d(false); get_tree()->set_auto_accept_quit(false); get_tree()->connect("files_dropped", this, "_dropped_files"); - property_editable_warning->set_icon(gui_base->get_icon("NodeWarning","EditorIcons")); + property_editable_warning->set_icon(gui_base->get_icon("NodeWarning", "EditorIcons")); } if (p_what == NOTIFICATION_EXIT_TREE) { @@ -1436,18 +1436,18 @@ void EditorNode::_edit_current() { EditorNode::get_singleton()->get_import_dock()->set_edit_path(current_res->get_path()); int subr_idx = current_res->get_path().find("::"); - if (subr_idx!=-1) { - String base_path=current_res->get_path().substr(0,subr_idx); - if (FileAccess::exists(base_path+".import")) { - editable_warning=TTR("This resource belongs to a scene that was imported, so it's not editable.\nPlease read the documentation relevant to importing scenes to better understand this workflow."); + if (subr_idx != -1) { + String base_path = current_res->get_path().substr(0, subr_idx); + if (FileAccess::exists(base_path + ".import")) { + editable_warning = TTR("This resource belongs to a scene that was imported, so it's not editable.\nPlease read the documentation relevant to importing scenes to better understand this workflow."); } else { - if (!get_edited_scene() || get_edited_scene()->get_filename()!=base_path) { - editable_warning=TTR("This resource belongs to a scene that was instanced or inherited.\nChanges to it will not be kept when saving the current scene."); + if (!get_edited_scene() || get_edited_scene()->get_filename() != base_path) { + editable_warning = TTR("This resource belongs to a scene that was instanced or inherited.\nChanges to it will not be kept when saving the current scene."); } } - } else if (current_res->get_path().is_resource_file()){ - if (FileAccess::exists(current_res->get_path()+".import")) { - editable_warning=TTR("This resource was imported, so it's not editable. Change it's settings in the import panel and re-import."); + } else if (current_res->get_path().is_resource_file()) { + if (FileAccess::exists(current_res->get_path() + ".import")) { + editable_warning = TTR("This resource was imported, so it's not editable. Change it's settings in the import panel and re-import."); } } } else if (is_node) { @@ -1465,10 +1465,10 @@ void EditorNode::_edit_current() { } object_menu->get_popup()->clear(); - if (get_edited_scene() && get_edited_scene()->get_filename()!=String()) { + if (get_edited_scene() && get_edited_scene()->get_filename() != String()) { String source_scene = get_edited_scene()->get_filename(); - if (FileAccess::exists(source_scene+".import")) { - editable_warning=TTR("This scene was imported, so changes to it will not be kept.\nInstancing it or inheriting will allow making changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow."); + if (FileAccess::exists(source_scene + ".import")) { + editable_warning = TTR("This scene was imported, so changes to it will not be kept.\nInstancing it or inheriting will allow making changes to it.\nPlease read the documentation relevant to importing scenes to better understand this workflow."); } } @@ -1478,10 +1478,9 @@ void EditorNode::_edit_current() { node_dock->set_node(NULL); } - if (editable_warning!=String()) { + if (editable_warning != String()) { property_editable_warning->show(); //hide by default property_editable_warning_dialog->set_text(editable_warning); - } /* Take care of PLUGIN EDITOR */ @@ -2781,14 +2780,6 @@ Dictionary EditorNode::_get_main_scene_state() { state["property_edit_offset"] = get_property_editor()->get_scene_tree()->get_vscroll_bar()->get_value(); state["saved_version"] = saved_version; state["node_filter"] = scene_tree_dock->get_filter(); - int current = -1; - for (int i = 0; i < editor_table.size(); i++) { - if (editor_plugin_screen == editor_table[i]) { - current = i; - break; - } - } - state["editor_index"] = current; return state; } @@ -2799,29 +2790,32 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { changing_scene = false; - if (p_state.has("editor_index")) { - - int index = p_state["editor_index"]; - int current = -1; - for (int i = 0; i < editor_table.size(); i++) { - if (editor_plugin_screen == editor_table[i]) { - current = i; - break; - } + int current = -1; + for (int i = 0; i < editor_table.size(); i++) { + if (editor_plugin_screen == editor_table[i]) { + current = i; + break; } + } + if (p_state.has("editor_index")) { + int index = p_state["editor_index"]; if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if curently in script, stay there if (index < 2 || !get_edited_scene()) { _editor_select(index); - } else { - //use heuristic instead - int n2d = 0, n3d = 0; - _find_node_types(get_edited_scene(), n2d, n3d); - if (n2d > n3d) { - _editor_select(EDITOR_2D); - } else if (n3d > n2d) { - _editor_select(EDITOR_3D); - } + } + } + } + + if (get_edited_scene()) { + if (current < 2) { + //use heuristic instead + int n2d = 0, n3d = 0; + _find_node_types(get_edited_scene(), n2d, n3d); + if (n2d > n3d) { + _editor_select(EDITOR_2D); + } else if (n3d > n2d) { + _editor_select(EDITOR_3D); } } } @@ -3252,9 +3246,9 @@ void EditorNode::register_editor_types() { ClassDB::register_class<EditorFileSystemDirectory>(); ClassDB::register_virtual_class<ScriptEditor>(); ClassDB::register_virtual_class<EditorInterface>(); + ClassDB::register_class<EditorExportPlugin>(); // FIXME: Is this stuff obsolete, or should it be ported to new APIs? - //ClassDB::register_class<EditorExportPlugin>(); //ClassDB::register_class<EditorScenePostImport>(); //ClassDB::register_type<EditorImportExport>(); } @@ -3344,9 +3338,9 @@ void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog) { Vector<EditorNodeInitCallback> EditorNode::_init_callbacks; -Error EditorNode::export_preset(const String &preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after) { +Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after) { - export_defer.preset = preset; + export_defer.preset = p_preset; export_defer.path = p_path; export_defer.debug = p_debug; export_defer.password = p_password; @@ -4067,6 +4061,13 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { ERR_FAIL_INDEX(p_idx, bottom_panel_items.size()); if (p_enable) { + // this is the debug panel wich uses tabs, so the top section should be smaller + if (ScriptEditor::get_singleton()->get_debugger() == bottom_panel_items[p_idx].control) { + Ref<StyleBoxFlat> style_panel_invisible_top = gui_base->get_stylebox("debugger_panel", "EditorStyles"); + bottom_panel->add_style_override("panel", style_panel_invisible_top); + } else { + bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + } for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->set_pressed(i == p_idx); @@ -4075,11 +4076,14 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) { center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE); center_split->set_collapsed(false); } else { + bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer")); + for (int i = 0; i < bottom_panel_items.size(); i++) { bottom_panel_items[i].button->set_pressed(false); bottom_panel_items[i].control->set_visible(false); } + center_split->set_dragger_visibility(SplitContainer::DRAGGER_HIDDEN); center_split->set_collapsed(true); } @@ -4511,8 +4515,6 @@ void EditorNode::_bind_methods() { ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode); ClassDB::bind_method("_property_editable_warning_pressed", &EditorNode::_property_editable_warning_pressed); - - ClassDB::bind_method(D_METHOD("get_gui_base"), &EditorNode::get_gui_base); ClassDB::bind_method(D_METHOD("_bottom_panel_switch"), &EditorNode::_bottom_panel_switch); @@ -4857,7 +4859,7 @@ EditorNode::EditorNode() { scene_root_parent = memnew(PanelContainer); scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE); scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles")); - + scene_root_parent->set_draw_behind_parent(true); srt->add_child(scene_root_parent); scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL); @@ -5273,14 +5275,13 @@ EditorNode::EditorNode() { search_bar->add_child(clear_button); clear_button->connect("pressed", this, "_clear_search_box"); - property_editable_warning = memnew (Button); + property_editable_warning = memnew(Button); property_editable_warning->set_text(TTR("Changes may be lost!")); prop_editor_base->add_child(property_editable_warning); - property_editable_warning_dialog = memnew( AcceptDialog ); + property_editable_warning_dialog = memnew(AcceptDialog); gui_base->add_child(property_editable_warning_dialog); property_editable_warning->hide(); - property_editable_warning->connect("pressed",this,"_property_editable_warning_pressed"); - + property_editable_warning->connect("pressed", this, "_property_editable_warning_pressed"); property_editor = memnew(PropertyEditor); property_editor->set_autoclear(true); @@ -5302,7 +5303,6 @@ EditorNode::EditorNode() { dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(import_dock); import_dock->set_name(TTR("Import")); - bool use_single_dock_column = (OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x < 1200); node_dock = memnew(NodeDock); diff --git a/editor/editor_node.h b/editor/editor_node.h index 5c6c5be4c8..33031e5634 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -609,7 +609,6 @@ private: void _license_tree_selected(); - protected: void _notification(int p_what); static void _bind_methods(); @@ -716,7 +715,7 @@ public: void show_warning(const String &p_text, const String &p_title = "Warning!"); - Error export_preset(const String &p_platform, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after = false); + Error export_preset(const String &p_preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after = false); static void register_editor_types(); static void unregister_editor_types(); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 86acfcc50e..246599be11 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -530,6 +530,14 @@ void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importe EditorFileSystem::get_singleton()->scan(); } +void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) { + EditorExport::get_singleton()->add_export_plugin(p_exporter); +} + +void EditorPlugin::remove_export_plugin(const Ref<EditorExportPlugin> &p_exporter) { + EditorExport::get_singleton()->remove_export_plugin(p_exporter); +} + void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) { if (get_script_instance() && get_script_instance()->has_method("set_window_layout")) { @@ -585,6 +593,8 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("queue_save_layout"), &EditorPlugin::queue_save_layout); ClassDB::bind_method(D_METHOD("add_import_plugin", "importer"), &EditorPlugin::add_import_plugin); ClassDB::bind_method(D_METHOD("remove_import_plugin", "importer"), &EditorPlugin::remove_import_plugin); + ClassDB::bind_method(D_METHOD("add_export_plugin", "exporter"), &EditorPlugin::add_export_plugin); + ClassDB::bind_method(D_METHOD("remove_export_plugin", "exporter"), &EditorPlugin::remove_export_plugin); ClassDB::bind_method(D_METHOD("set_input_event_forwarding_always_enabled"), &EditorPlugin::set_input_event_forwarding_always_enabled); ClassDB::bind_method(D_METHOD("get_editor_interface"), &EditorPlugin::get_editor_interface); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 99328f8149..18530e9ce4 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -191,6 +191,9 @@ public: void add_import_plugin(const Ref<EditorImportPlugin> &p_importer); void remove_import_plugin(const Ref<EditorImportPlugin> &p_importer); + void add_export_plugin(const Ref<EditorExportPlugin> &p_exporter); + void remove_export_plugin(const Ref<EditorExportPlugin> &p_exporter); + EditorPlugin(); virtual ~EditorPlugin(); }; diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp index 6b972262b9..247775fa1d 100644 --- a/editor/editor_profiler.cpp +++ b/editor/editor_profiler.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "editor_profiler.h" +#include "editor_scale.h" #include "editor_settings.h" #include "os/os.h" @@ -656,14 +657,14 @@ EditorProfiler::EditorProfiler() { hb->add_child(cursor_metric_edit); cursor_metric_edit->connect("value_changed", this, "_cursor_metric_changed"); - hb->add_constant_override("separation", 8); + hb->add_constant_override("separation", 8 * EDSCALE); h_split = memnew(HSplitContainer); add_child(h_split); h_split->set_v_size_flags(SIZE_EXPAND_FILL); variables = memnew(Tree); - variables->set_custom_minimum_size(Size2(300, 0)); + variables->set_custom_minimum_size(Size2(300, 0) * EDSCALE); variables->set_hide_folding(true); h_split->add_child(variables); variables->set_hide_root(true); @@ -674,10 +675,10 @@ EditorProfiler::EditorProfiler() { variables->set_column_min_width(0, 60); variables->set_column_title(1, "Time"); variables->set_column_expand(1, false); - variables->set_column_min_width(1, 60); + variables->set_column_min_width(1, 60 * EDSCALE); variables->set_column_title(2, "Calls"); variables->set_column_expand(2, false); - variables->set_column_min_width(2, 60); + variables->set_column_min_width(2, 60 * EDSCALE); variables->connect("item_edited", this, "_item_edited"); graph = memnew(TextureRect); @@ -691,8 +692,6 @@ EditorProfiler::EditorProfiler() { h_split->add_child(graph); graph->set_h_size_flags(SIZE_EXPAND_FILL); - add_constant_override("separation", 3); - int metric_size = CLAMP(int(EDITOR_DEF("debugger/profiler_frame_history_size", 600)), 60, 1024); frame_metrics.resize(metric_size); last_metric = -1; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 8ce7129a13..eb72fdf64b 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -460,7 +460,7 @@ void EditorSettings::setup_network() { List<IP_Address> local_ip; IP::get_singleton()->get_local_addresses(&local_ip); - String lip; + String lip = "127.0.0.1"; String hint; String current = has("network/debug/remote_host") ? get("network/debug/remote_host") : ""; int port = has("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007; @@ -469,8 +469,9 @@ void EditorSettings::setup_network() { String ip = E->get(); - if (lip == "") - lip = ip; + // link-local IPv6 addresses don't work, skipping them + if (ip.begins_with("fe80:0:0:0:")) // fe80::/64 + continue; if (ip == current) lip = current; //so it saves if (hint != "") @@ -600,8 +601,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { hints["global/default_project_export_path"] = PropertyInfo(Variant::STRING, "global/default_project_export_path", PROPERTY_HINT_GLOBAL_DIR); set("interface/show_script_in_scene_tabs", false); - set("text_editor/theme/color_theme", "Default"); - hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Default"); + set("text_editor/theme/color_theme", "Adaptive"); + hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Adaptive,Default"); set("text_editor/theme/line_spacing", 4); @@ -925,13 +926,13 @@ void EditorSettings::load_favorites() { } void EditorSettings::list_text_editor_themes() { - String themes = "Default"; + String themes = "Adaptive,Default"; DirAccess *d = DirAccess::open(settings_path + "/text_editor_themes"); if (d) { d->list_dir_begin(); String file = d->get_next(); while (file != String()) { - if (file.get_extension() == "tet" && file.get_basename().to_lower() != "default") { + if (file.get_extension() == "tet" && file.get_basename().to_lower() != "default" && file.get_basename().to_lower() != "adaptive") { themes += "," + file.get_basename(); } file = d->get_next(); @@ -943,7 +944,7 @@ void EditorSettings::list_text_editor_themes() { } void EditorSettings::load_text_editor_theme() { - if (get("text_editor/theme/color_theme") == "Default") { + if (get("text_editor/theme/color_theme") == "Default" || get("text_editor/theme/color_theme") == "Adaptive") { _load_default_text_editor_theme(); // sorry for "Settings changed" console spam return; } @@ -1000,7 +1001,7 @@ bool EditorSettings::save_text_editor_theme() { String p_file = get("text_editor/theme/color_theme"); - if (p_file.get_file().to_lower() == "default") { + if (p_file.get_file().to_lower() == "default" || p_file.get_file().to_lower() == "adaptive") { return false; } String theme_path = get_settings_path() + "/text_editor_themes/" + p_file + ".tet"; @@ -1012,7 +1013,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) { p_file += ".tet"; } - if (p_file.get_file().to_lower() == "default.tet") { + if (p_file.get_file().to_lower() == "default.tet" || p_file.get_file().to_lower() == "adaptive.tet") { return false; } if (_save_text_editor_theme(p_file)) { diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 9616af1dd6..4aa1ccaa81 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -335,6 +335,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const int border_width = CLAMP(border_size, 0, 3) * EDSCALE; const int default_margin_size = 4; + const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 3); // styleboxes // this is the most commonly used stylebox, variations should be made as duplicate of this @@ -346,11 +347,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // Button and widgets Ref<StyleBoxFlat> style_widget = style_default->duplicate(); - // style_widget->set_bg_color(dark_color_1.linear_interpolate(base_color, 0.4)); style_widget->set_bg_color(dark_color_1); style_widget->set_default_margin(MARGIN_LEFT, 6 * EDSCALE); style_widget->set_default_margin(MARGIN_RIGHT, 6 * EDSCALE); - // style_widget->set_border_color_all(contrast_color_1); style_widget->set_border_color_all(dark_color_2); Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate(); @@ -381,14 +380,19 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size); // Tabs + const int tab_default_margin_side = 10 * EDSCALE; Ref<StyleBoxFlat> style_tab_selected = style_default->duplicate(); - style_tab_selected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE); - style_tab_selected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE); + style_tab_selected->set_border_width_all(border_width); + style_tab_selected->set_border_width(MARGIN_BOTTOM, 0); + style_tab_selected->set_border_color_all(dark_color_3); + style_tab_selected->set_expand_margin_size(MARGIN_BOTTOM, border_width); + style_tab_selected->set_default_margin(MARGIN_LEFT, tab_default_margin_side); + style_tab_selected->set_default_margin(MARGIN_RIGHT, tab_default_margin_side); style_tab_selected->set_bg_color(tab_color); - Ref<StyleBoxEmpty> style_tab_unselected = style_empty->duplicate(); - style_tab_unselected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE); - style_tab_unselected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE); + Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate(); + style_tab_unselected->set_bg_color(Color(0.0, 0.0, 0.0, 0.0)); + style_tab_unselected->set_border_color_all(Color(0.0, 0.0, 0.0, 0.0)); // Editor background theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); @@ -448,19 +452,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border); - // Content of each tab - Ref<StyleBoxFlat> style_content_panel = style_default->duplicate(); - style_content_panel->set_border_color_all(base_color); - - // this is the stylebox used in 3d and 2d viewports (no borders) - Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate(); - style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width); - style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size); - style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width); - style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width); - theme->set_stylebox("panel", "TabContainer", style_content_panel); - theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp); - // Buttons theme->set_stylebox("normal", "Button", style_widget); theme->set_stylebox("hover", "Button", style_widget_hover); @@ -621,19 +612,52 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("button_pressed", "Tabs", style_menu); theme->set_stylebox("button", "Tabs", style_menu); + // Content of each tab + Ref<StyleBoxFlat> style_content_panel = style_default->duplicate(); + style_content_panel->set_border_color_all(dark_color_3); + style_content_panel->set_border_width_all(border_width); + // compensate the border + style_content_panel->set_default_margin(MARGIN_TOP, margin_size_extra * EDSCALE); + style_content_panel->set_default_margin(MARGIN_RIGHT, margin_size_extra * EDSCALE); + style_content_panel->set_default_margin(MARGIN_BOTTOM, margin_size_extra * EDSCALE); + style_content_panel->set_default_margin(MARGIN_LEFT, margin_size_extra * EDSCALE); + + // this is the stylebox used in 3d and 2d viewports (no borders) + Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate(); + style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width * 2); + style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE); + style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width * 2); + style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width * 2); + theme->set_stylebox("panel", "TabContainer", style_content_panel); + theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp); + // Separators (no separators) theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, border_width)); theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, border_width, 0, true)); - // Debugger - Ref<StyleBoxFlat> style_panel_debugger = style_default->duplicate(); - theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger); + // HACK Debuger panel + Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate(); + const int v_offset = theme->get_font("font", "Tabs")->get_height() + style_tab_selected->get_minimum_size().height + default_margin_size * EDSCALE; + style_panel_debugger->set_expand_margin_size(MARGIN_TOP, -v_offset); + theme->set_stylebox("debugger_panel", "EditorStyles", style_panel_debugger); + // Debugger + Ref<StyleBoxFlat> style_debugger_contents = style_content_panel->duplicate(); + style_debugger_contents->set_default_margin(MARGIN_LEFT, 0); + style_debugger_contents->set_default_margin(MARGIN_BOTTOM, 0); + style_debugger_contents->set_default_margin(MARGIN_RIGHT, 0); + style_debugger_contents->set_border_width_all(0); + style_debugger_contents->set_expand_margin_size(MARGIN_TOP, -v_offset); + theme->set_constant("extra_margin", "DebuggerPanel", default_margin_size * EDSCALE + border_width); + theme->set_stylebox("DebuggerPanel", "EditorStyles", style_debugger_contents); Ref<StyleBoxFlat> style_tab_fg_debugger = style_tab_selected->duplicate(); - style_tab_fg_debugger->set_border_width_all(0); - + style_tab_fg_debugger->set_expand_margin_size(MARGIN_LEFT, default_margin_size * EDSCALE + border_width); + style_tab_fg_debugger->set_default_margin(MARGIN_LEFT, tab_default_margin_side - default_margin_size * EDSCALE); theme->set_stylebox("DebuggerTabFG", "EditorStyles", style_tab_fg_debugger); - theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_unselected); + Ref<StyleBoxFlat> style_tab_bg_debugger = style_tab_unselected->duplicate(); + style_tab_bg_debugger->set_expand_margin_size(MARGIN_LEFT, default_margin_size * EDSCALE + border_width); + style_tab_bg_debugger->set_default_margin(MARGIN_LEFT, tab_default_margin_side - default_margin_size * EDSCALE); + theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_bg_debugger); // LineEdit theme->set_stylebox("normal", "LineEdit", style_widget); @@ -647,6 +671,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("normal", "TextEdit", style_widget); theme->set_stylebox("focus", "TextEdit", style_widget_hover); theme->set_constant("side_margin", "TabContainer", 0); + theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons")); // H/VSplitContainer theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1)); @@ -658,6 +683,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); + // Containers + theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); + theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); + theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE); + theme->set_constant("margin_left", "MarginContainer", 0); + theme->set_constant("margin_top", "MarginContainer", 0); + theme->set_constant("margin_right", "MarginContainer", 0); + theme->set_constant("margin_bottom", "MarginContainer", 0); + theme->set_constant("hseparation", "GridContainer", default_margin_size * EDSCALE); + theme->set_constant("vseparation", "GridContainer", default_margin_size * EDSCALE); + // WindowDialog Ref<StyleBoxFlat> style_window = style_popup->duplicate(); style_window->set_border_color_all(tab_color); @@ -807,6 +843,80 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // FileDialog theme->set_color("files_disabled", "FileDialog", font_color_disabled); + // adaptive script theme constants + // for comments and elements with lower relevance + const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5); + + const float mono_value = mono_color.r; + const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.1); + const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.3); + const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.5); + const Color alpha4 = Color(mono_value, mono_value, mono_value, 0.7); + + // editor main color + const Color main_color = Color::html(dark_theme ? "#57b3ff" : "#0480ff"); + + const Color symbol_color = Color::html("#5792ff").linear_interpolate(mono_color, dark_theme ? 0.5 : 0.3); + const Color keyword_color = main_color.linear_interpolate(mono_color, 0.4); + const Color basetype_color = Color::html(dark_theme ? "#42ffc2" : "#00c161"); + const Color type_color = basetype_color.linear_interpolate(mono_color, dark_theme ? 0.7 : 0.5); + const Color comment_color = dim_color; + const Color string_color = Color::html(dark_theme ? "#ffd942" : "#ffd118").linear_interpolate(mono_color, dark_theme ? 0.5 : 0.3); + + const Color te_background_color = Color(0, 0, 0, 0); + const Color completion_background_color = base_color; + const Color completion_selected_color = alpha1; + const Color completion_existing_color = alpha2; + const Color completion_scroll_color = alpha1; + const Color completion_font_color = font_color; + const Color text_color = font_color; + const Color line_number_color = dim_color; + const Color caret_color = mono_color; + const Color caret_background_color = mono_color.inverted(); + const Color text_selected_color = dark_color_3; + const Color selection_color = alpha3; + const Color brace_mismatch_color = error_color; + const Color current_line_color = alpha1; + const Color line_length_guideline_color = warning_color; + const Color word_highlighted_color = alpha1; + const Color number_color = basetype_color.linear_interpolate(mono_color, dark_theme ? 0.5 : 0.3); + const Color function_color = main_color; + const Color member_variable_color = mono_color; + const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); + const Color breakpoint_color = error_color; + const Color search_result_color = alpha1; + const Color search_result_border_color = alpha4; + + theme->set_color("text_editor/theme/symbol_color", "Editor", symbol_color); + theme->set_color("text_editor/theme/keyword_color", "Editor", keyword_color); + theme->set_color("text_editor/theme/basetype_color", "Editor", basetype_color); + theme->set_color("text_editor/theme/type_color", "Editor", type_color); + theme->set_color("text_editor/theme/comment_color", "Editor", comment_color); + theme->set_color("text_editor/theme/string_color", "Editor", string_color); + theme->set_color("text_editor/theme/background_color", "Editor", te_background_color); + theme->set_color("text_editor/theme/completion_background_color", "Editor", completion_background_color); + theme->set_color("text_editor/theme/completion_selected_color", "Editor", completion_selected_color); + theme->set_color("text_editor/theme/completion_existing_color", "Editor", completion_existing_color); + theme->set_color("text_editor/theme/completion_scroll_color", "Editor", completion_scroll_color); + theme->set_color("text_editor/theme/completion_font_color", "Editor", completion_font_color); + theme->set_color("text_editor/theme/text_color", "Editor", text_color); + theme->set_color("text_editor/theme/line_number_color", "Editor", line_number_color); + theme->set_color("text_editor/theme/caret_color", "Editor", caret_color); + theme->set_color("text_editor/theme/caret_background_color", "Editor", caret_background_color); + theme->set_color("text_editor/theme/text_selected_color", "Editor", text_selected_color); + theme->set_color("text_editor/theme/selection_color", "Editor", selection_color); + theme->set_color("text_editor/theme/brace_mismatch_color", "Editor", brace_mismatch_color); + theme->set_color("text_editor/theme/current_line_color", "Editor", current_line_color); + theme->set_color("text_editor/theme/line_length_guideline_color", "Editor", line_length_guideline_color); + theme->set_color("text_editor/theme/word_highlighted_color", "Editor", word_highlighted_color); + theme->set_color("text_editor/theme/number_color", "Editor", number_color); + theme->set_color("text_editor/theme/function_color", "Editor", function_color); + theme->set_color("text_editor/theme/member_variable_color", "Editor", member_variable_color); + theme->set_color("text_editor/theme/mark_color", "Editor", mark_color); + theme->set_color("text_editor/theme/breakpoint_color", "Editor", breakpoint_color); + theme->set_color("text_editor/theme/search_result_color", "Editor", search_result_color); + theme->set_color("text_editor/theme/search_result_border_color", "Editor", search_result_border_color); + return theme; } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index f0ace864e4..526a8fe810 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1812,8 +1812,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { display_mode = DISPLAY_THUMBNAILS; path = "res://"; - - add_constant_override("separation", 4); } FileSystemDock::~FileSystemDock() { diff --git a/editor/icons/icon_GUI_tab.svg b/editor/icons/icon_GUI_tab.svg new file mode 100644 index 0000000000..3eed0680c0 --- /dev/null +++ b/editor/icons/icon_GUI_tab.svg @@ -0,0 +1,5 @@ +<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(0 -1044.4)"> +<path transform="translate(0 1044.4)" d="m6 0v8h2v-8h-2zm-5.0137 0.0019531a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l2.293 2.293-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l3-3a1.0001 1.0001 0 0 0 0 -1.4141l-3-3a1 1 0 0 0 -0.7207 -0.29102z" fill="#fff" fill-opacity=".19608"/> +</g> +</svg> diff --git a/editor/icons/icon_snap.svg b/editor/icons/icon_snap.svg index b1f36cfe43..0195f7cfc6 100644 --- a/editor/icons/icon_snap.svg +++ b/editor/icons/icon_snap.svg @@ -1,10 +1,93 @@ -<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(0 -1036.4)"> -<path d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z" fill="#f3f3f3"/> -<path d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z" fill="#ff8484"/> -<rect x="7" y="1047.4" width="2" height="2" fill="#ff8484"/> -<rect x="13" y="1047.4" width="2" height="2" fill="#ff8484"/> -<rect x="7" y="1049.4" width="2" height="2" fill="#fff"/> -<rect x="13" y="1049.4" width="2" height="2" fill="#fff"/> -</g> +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg848" + sodipodi:docname="icon_snap.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata854"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs852" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2558" + inkscape:window-height="1422" + id="namedview850" + showgrid="true" + inkscape:pagecheckerboard="true" + inkscape:zoom="26.317631" + inkscape:cx="-14.078109" + inkscape:cy="-1.3201296" + inkscape:window-x="1366" + inkscape:window-y="16" + inkscape:window-maximized="1" + inkscape:current-layer="svg848"> + <inkscape:grid + type="xygrid" + id="grid862" /> + </sodipodi:namedview> + <path + style="fill:#ff8484;stroke-width:1.48039925" + inkscape:connector-curvature="0" + id="path836" + d="m 3.9501321,14.20668 a 5.9215969,5.9215969 0 0 0 8.0890509,-2.167455 l -2.5641252,-1.4804 A 2.9607985,2.9607985 0 0 1 5.4305313,11.642553 2.9607985,2.9607985 0 0 1 4.3468039,7.5980268 L 1.7826772,6.1176278 A 5.9215969,5.9215969 0 0 0 3.9501321,14.20668 Z" /> + <rect + style="fill:#ff8484;stroke-width:1.48039925" + id="rect838" + height="2.9607985" + width="2.9607985" + y="-4.4066463" + x="-16.44585" + transform="rotate(-150)" /> + <rect + style="fill:#ff8484;stroke-width:1.48039925" + id="rect840" + height="2.9607985" + width="2.9607985" + y="-4.4066463" + x="-7.5634551" + transform="rotate(-150)" /> + <rect + style="fill:#ffffff;stroke-width:1.48039925" + id="rect842" + height="2.9607985" + width="2.9607985" + y="-1.4458472" + x="-16.44585" + transform="rotate(-150)" /> + <rect + style="fill:#ffffff;stroke-width:1.48039925" + id="rect844" + height="2.9607985" + width="2.9607985" + y="-1.4458472" + x="-7.5634551" + transform="rotate(-150)" /> </svg> diff --git a/editor/icons/icon_snap_grid.svg b/editor/icons/icon_snap_grid.svg new file mode 100644 index 0000000000..b479496327 --- /dev/null +++ b/editor/icons/icon_snap_grid.svg @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg913" + sodipodi:docname="icon_snap_grid.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata919"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs917" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2558" + inkscape:window-height="1422" + id="namedview915" + showgrid="false" + inkscape:pagecheckerboard="true" + inkscape:zoom="52.635261" + inkscape:cx="6.4374987" + inkscape:cy="5.7074131" + inkscape:window-x="1366" + inkscape:window-y="16" + inkscape:window-maximized="1" + inkscape:current-layer="svg913" /> + <g + transform="translate(0 -1036.4)" + id="g911"> + <path + d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z" + fill="#f3f3f3" + id="path899" /> + <path + d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z" + fill="#ff8484" + id="path901" /> + <rect + x="7" + y="1047.4" + width="2" + height="2" + fill="#ff8484" + id="rect903" /> + <rect + x="13" + y="1047.4" + width="2" + height="2" + fill="#ff8484" + id="rect905" /> + <rect + x="7" + y="1049.4" + width="2" + height="2" + fill="#fff" + id="rect907" /> + <rect + x="13" + y="1049.4" + width="2" + height="2" + fill="#fff" + id="rect909" /> + </g> +</svg> diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index cc519c1c4b..b448ab8920 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -120,13 +120,13 @@ String ResourceImporterScene::get_preset_name(int p_idx) const { switch (p_idx) { case PRESET_SINGLE_SCENE: return TTR("Import as Single Scene"); - case PRESET_SEPERATE_ANIMATIONS: return TTR("Import with Seperate Animations"); + case PRESET_SEPARATE_ANIMATIONS: return TTR("Import with Separate Animations"); case PRESET_SEPARATE_MATERIALS: return TTR("Import with Separate Materials"); case PRESET_SEPARATE_MESHES: return TTR("Import with Separate Objects"); case PRESET_SEPARATE_MESHES_AND_MATERIALS: return TTR("Import with Separate Objects+Materials"); - case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Animations"); - case PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Materials+Animations"); - case PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Materials+Animations"); + case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Separate Objects+Animations"); + case PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Materials+Animations"); + case PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Objects+Materials+Animations"); case PRESET_MULTIPLE_SCENES: return TTR("Import as Multiple Scenes"); case PRESET_MULTIPLE_SCENES_AND_MATERIALS: return TTR("Import as Multiple Scenes+Materials"); } @@ -954,10 +954,10 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in script_ext_hint += "*." + E->get(); } - bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS; - bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS; + bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; + bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; bool scenes_out = p_preset == PRESET_MULTIPLE_SCENES || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS; - bool animations_out = p_preset == PRESET_SEPERATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS; + bool animations_out = p_preset == PRESET_SEPARATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS; r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "nodes/custom_script", PROPERTY_HINT_FILE, script_ext_hint), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0)); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index a483c3776f..c3a66aa8b8 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -85,14 +85,14 @@ class ResourceImporterScene : public ResourceImporter { enum Presets { PRESET_SEPARATE_MATERIALS, PRESET_SEPARATE_MESHES, - PRESET_SEPERATE_ANIMATIONS, + PRESET_SEPARATE_ANIMATIONS, PRESET_SINGLE_SCENE, PRESET_SEPARATE_MESHES_AND_MATERIALS, PRESET_SEPARATE_MESHES_AND_ANIMATIONS, - PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS, - PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS, + PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS, + PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS, PRESET_MULTIPLE_SCENES, PRESET_MULTIPLE_SCENES_AND_MATERIALS, @@ -119,7 +119,7 @@ public: virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const; virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const; - void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animation, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes); + void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes); Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index d7762a66df..c8db1763ab 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -103,13 +103,11 @@ void AnimationPlayerEditor::_notification(int p_what) { get_tree()->connect("node_removed", this, "_node_removed"); add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel")); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel")); - add_constant_override("separation", get_constant("separation", "VBoxContainer")); } break; case NOTIFICATION_THEME_CHANGED: { diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index 054124da8f..414b091475 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -476,7 +476,7 @@ void AnimationTreeEditor::_draw_node(const StringName &p_node) { Color font_color = get_color("font_color", "PopupMenu"); Color font_color_title = get_color("font_color_hover", "PopupMenu"); font_color_title.a *= 0.8; - Ref<Texture> slot_icon = get_icon("NodeRealSlot", "EditorIcons"); + Ref<Texture> slot_icon = get_icon("VisualShaderPort", "EditorIcons"); Size2 size = get_node_size(p_node); Point2 pos = anim_tree->node_get_pos(p_node); @@ -599,7 +599,7 @@ void AnimationTreeEditor::_draw_node(const StringName &p_node) { if (editable) { - Ref<Texture> arrow = get_icon("arrow", "Tree"); + Ref<Texture> arrow = get_icon("GuiDropdown", "EditorIcons"); Point2 arrow_ofs(w - arrow->get_width(), Math::floor((h - arrow->get_height()) / 2)); arrow->draw(ci, ofs + arrow_ofs); } @@ -671,7 +671,7 @@ Point2 AnimationTreeEditor::_get_slot_pos(const StringName &p_node_id, bool p_in Ref<StyleBox> style = get_stylebox("panel", "PopupMenu"); Ref<Font> font = get_font("font", "PopupMenu"); - Ref<Texture> slot_icon = get_icon("NodeRealSlot", "EditorIcons"); + Ref<Texture> slot_icon = get_icon("VisualShaderPort", "EditorIcons"); Size2 size = get_node_size(p_node_id); Point2 pos = anim_tree->node_get_pos(p_node_id); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index ad01d0a31e..27dad7756e 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -53,6 +53,8 @@ #define MIN_ZOOM 0.01 #define MAX_ZOOM 100 +#define RULER_WIDTH 15 * EDSCALE + class SnapDialog : public ConfirmationDialog { GDCLASS(SnapDialog, ConfirmationDialog); @@ -109,13 +111,13 @@ public: label->set_h_size_flags(SIZE_EXPAND_FILL); grid_step_x = memnew(SpinBox); - grid_step_x->set_min(-SPIN_BOX_GRID_RANGE); + grid_step_x->set_min(0.01); grid_step_x->set_max(SPIN_BOX_GRID_RANGE); grid_step_x->set_suffix("px"); child_container->add_child(grid_step_x); grid_step_y = memnew(SpinBox); - grid_step_y->set_min(-SPIN_BOX_GRID_RANGE); + grid_step_y->set_min(0.01); grid_step_y->set_max(SPIN_BOX_GRID_RANGE); grid_step_y->set_suffix("px"); child_container->add_child(grid_step_y); @@ -149,7 +151,7 @@ public: child_container->add_child(rotation_step); } - void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) { + void set_fields(const Point2 p_grid_offset, const Point2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) { grid_offset_x->set_value(p_grid_offset.x); grid_offset_y->set_value(p_grid_offset.y); grid_step_x->set_value(p_grid_step.x); @@ -158,11 +160,9 @@ public: rotation_step->set_value(p_rotation_step * (180 / Math_PI)); } - void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) { - p_grid_offset.x = grid_offset_x->get_value(); - p_grid_offset.y = grid_offset_y->get_value(); - p_grid_step.x = grid_step_x->get_value(); - p_grid_step.y = grid_step_y->get_value(); + void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) { + p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value()); + p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value()); p_rotation_offset = rotation_offset->get_value() / (180 / Math_PI); p_rotation_step = rotation_step->get_value() / (180 / Math_PI); } @@ -222,6 +222,135 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) { undo_redo->commit_action(); } +void CanvasItemEditor::_snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) { + float radius = p_radius / zoom; + float dist; + + Transform2D rot_trans = Transform2D(rotation, Point2()); + p_value = rot_trans.inverse().xform(p_value); + p_target_snap = rot_trans.inverse().xform(p_target_snap); + r_current_snap = rot_trans.inverse().xform(r_current_snap); + + dist = Math::abs(p_value.x - p_target_snap.x); + if (p_radius < 0 || dist < radius && (!r_snapped[0] || dist < Math::abs(r_current_snap.x - p_value.x))) { + r_current_snap.x = p_target_snap.x; + r_snapped[0] = true; + } + + dist = Math::abs(p_value.y - p_target_snap.y); + if (p_radius < 0 || dist < radius && (!r_snapped[1] || dist < Math::abs(r_current_snap.y - p_value.y))) { + r_current_snap.y = p_target_snap.y; + r_snapped[1] = true; + } + + r_current_snap = rot_trans.xform(r_current_snap); +} + +void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap) { + const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current); + if (canvas_item && p_current != p_to_snap) { + Transform2D ci_transform = canvas_item->get_global_transform_with_canvas(); + Transform2D to_snap_transform = p_to_snap->get_global_transform_with_canvas(); + if (ci_transform.get_rotation() == to_snap_transform.get_rotation()) { + Point2 begin = ci_transform.xform(canvas_item->get_item_rect().get_position()); + Point2 end = ci_transform.xform(canvas_item->get_item_rect().get_position() + canvas_item->get_item_rect().get_size()); + + _snap_if_closer(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); + _snap_if_closer(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); + } + } + for (int i = 0; i < p_current->get_child_count(); i++) { + _snap_other_nodes(p_value, r_current_snap, r_snapped, p_current->get_child(i), p_to_snap); + } +} + +Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const CanvasItem *p_canvas_item, unsigned int p_forced_modes) { + Point2 dist[2]; + bool snapped[2] = { false, false }; + + // Smart snap using the canvas position + Vector2 output = p_target; + real_t rotation = 0.0; + + if (p_canvas_item) { + Point2 begin; + Point2 end; + rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation(); + + if ((snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) { + // Parent sides and center + bool can_snap = false; + if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { + begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); + end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1))); + can_snap = true; + } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) { + begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position()); + end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position() + parent_ci->get_item_rect().get_size()); + can_snap = true; + } + + if (can_snap) { + _snap_if_closer(p_target, begin, output, snapped, rotation); + _snap_if_closer(p_target, (begin + end) / 2.0, output, snapped, rotation); + _snap_if_closer(p_target, end, output, snapped, rotation); + } + } + + // Self anchors (for sides) + if ((snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) { + if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { + begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP)))); + end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM)))); + _snap_if_closer(p_target, begin, output, snapped, rotation); + _snap_if_closer(p_target, end, output, snapped, rotation); + } + } + + // Self sides (for anchors) + if ((snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) { + begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position()); + end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position() + p_canvas_item->get_item_rect().get_size()); + _snap_if_closer(p_target, begin, output, snapped, rotation); + _snap_if_closer(p_target, end, output, snapped, rotation); + } + + // Other nodes sides + if ((snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) { + _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item); + } + } + + if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && rotation == 0.0) { + // Grid + Point2 offset = grid_offset; + if (snap_relative) { + List<Node *> &selection = editor_selection->get_selected_node_list(); + if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) { + offset = Object::cast_to<Node2D>(selection[0])->get_global_position(); + } else { + offset = _find_topleftmost_point(); + } + } + Point2 grid_output; + grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x; + grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y; + _snap_if_closer(p_target, grid_output, output, snapped, 0.0, -1.0); + } + + if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) { + // Pixel + output = output.snapped(Size2(1, 1)); + } + + return output; +} + +float CanvasItemEditor::snap_angle(float p_target, float p_start) const { + float offset = snap_relative ? p_start : p_target; + return (snap_rotation && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target; +} + void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { Ref<InputEventKey> k = p_ev; @@ -232,22 +361,34 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { if (k->get_control()) return; - if (k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V && drag == DRAG_NONE && can_move_pivot) { - - if (k->get_shift()) { + if (k->is_pressed() && !k->is_echo()) { + if (drag_pivot_shortcut.is_valid() && drag_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) { //move drag pivot drag = DRAG_PIVOT; - } else if (!Input::get_singleton()->is_mouse_button_pressed(0)) { - - List<Node *> &selection = editor_selection->get_selected_node_list(); - Vector2 mouse_pos = viewport->get_local_mouse_pos(); - if (selection.size() && viewport->get_rect().has_point(mouse_pos)) { - //just in case, make it work if over viewport - mouse_pos = transform.affine_inverse().xform(mouse_pos); - mouse_pos = snap_point(mouse_pos); - - _edit_set_pivot(mouse_pos); + } else if (set_pivot_shortcut.is_valid() && set_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) { + if (!Input::get_singleton()->is_mouse_button_pressed(0)) { + List<Node *> &selection = editor_selection->get_selected_node_list(); + Vector2 mouse_pos = viewport->get_local_mouse_pos(); + if (selection.size() && viewport->get_rect().has_point(mouse_pos)) { + //just in case, make it work if over viewport + mouse_pos = transform.affine_inverse().xform(mouse_pos); + mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); + + _edit_set_pivot(mouse_pos); + } } + } else if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) { + // Multiply the grid size + grid_step_multiplier = MIN(grid_step_multiplier + 1, 12); + viewport_base->update(); + viewport->update(); + } else if ((snap_grid || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) { + // Divide the grid size + Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1); + if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0) + grid_step_multiplier--; + viewport_base->update(); + viewport->update(); } } } @@ -272,38 +413,25 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) { return memnew(CanvasItemEditorSelectedItem); } -inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) { - float offset = p_snap_relative ? p_start : p_offset; - return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target; -} - -Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const { - if (snap_grid) { - p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x); - p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y); - } - if (snap_pixel) - p_target = p_target.snapped(Size2(1, 1)); - - return p_target; -} - -float CanvasItemEditor::snap_angle(float p_target, float p_start) const { - return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target; -} - Dictionary CanvasItemEditor::get_state() const { Dictionary state; state["zoom"] = zoom; state["ofs"] = Point2(h_scroll->get_value(), v_scroll->get_value()); //state["ofs"]=-transform.get_origin(); - state["snap_offset"] = snap_offset; - state["snap_step"] = snap_step; + state["grid_offset"] = grid_offset; + state["grid_step"] = grid_step; state["snap_rotation_offset"] = snap_rotation_offset; state["snap_rotation_step"] = snap_rotation_step; + state["snap_active"] = snap_active; + state["snap_node_parent"] = snap_node_parent; + state["snap_node_anchors"] = snap_node_anchors; + state["snap_node_sides"] = snap_node_sides; + state["snap_other_nodes"] = snap_other_nodes; state["snap_grid"] = snap_grid; - state["snap_show_grid"] = snap_show_grid; + state["show_grid"] = show_grid; + state["show_rulers"] = show_rulers; + state["show_helpers"] = show_helpers; state["snap_rotation"] = snap_rotation; state["snap_relative"] = snap_relative; state["snap_pixel"] = snap_pixel; @@ -324,12 +452,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { v_scroll->set_value(ofs.y); } - if (state.has("snap_step")) { - snap_step = state["snap_step"]; + if (state.has("grid_offset")) { + grid_offset = state["grid_offset"]; } - if (state.has("snap_offset")) { - snap_offset = state["snap_offset"]; + if (state.has("grid_step")) { + grid_step = state["grid_step"]; } if (state.has("snap_rotation_step")) { @@ -340,40 +468,81 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { snap_rotation_offset = state["snap_rotation_offset"]; } + if (state.has("snap_active")) { + snap_active = state["snap_active"]; + snap_button->set_pressed(snap_active); + } + + if (state.has("snap_node_parent")) { + snap_node_parent = state["snap_node_parent"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); + smartsnap_config_popup->set_item_checked(idx, snap_node_parent); + } + + if (state.has("snap_node_anchors")) { + snap_node_anchors = state["snap_node_anchors"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->set_item_checked(idx, snap_node_anchors); + } + + if (state.has("snap_node_sides")) { + snap_node_sides = state["snap_node_sides"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); + smartsnap_config_popup->set_item_checked(idx, snap_node_sides); + } + + if (state.has("snap_other_nodes")) { + snap_other_nodes = state["snap_other_nodes"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); + smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); + } + if (state.has("snap_grid")) { snap_grid = state["snap_grid"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE); - edit_menu->get_popup()->set_item_checked(idx, snap_grid); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); + snap_config_menu->get_popup()->set_item_checked(idx, snap_grid); + } + + if (state.has("show_grid")) { + show_grid = state["show_grid"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); + view_menu->get_popup()->set_item_checked(idx, show_grid); } - if (state.has("snap_show_grid")) { - snap_show_grid = state["snap_show_grid"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID); - edit_menu->get_popup()->set_item_checked(idx, snap_show_grid); + if (state.has("show_rulers")) { + show_rulers = state["show_rulers"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); + view_menu->get_popup()->set_item_checked(idx, show_rulers); + } + + if (state.has("show_helpers")) { + show_helpers = state["show_helpers"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); + view_menu->get_popup()->set_item_checked(idx, show_helpers); } if (state.has("snap_rotation")) { snap_rotation = state["snap_rotation"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); - edit_menu->get_popup()->set_item_checked(idx, snap_rotation); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation); } if (state.has("snap_relative")) { snap_relative = state["snap_relative"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE); - edit_menu->get_popup()->set_item_checked(idx, snap_relative); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); + snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); } if (state.has("snap_pixel")) { snap_pixel = state["snap_pixel"]; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - edit_menu->get_popup()->set_item_checked(idx, snap_pixel); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); + snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel); } if (state.has("skeleton_show_bones")) { skeleton_show_bones = state["skeleton_show_bones"]; - int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES); - skeleton_menu->set_item_checked(idx, skeleton_show_bones); + int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones); } viewport->update(); @@ -495,6 +664,7 @@ void CanvasItemEditor::_select_click_on_empty_area(Point2 p_click_pos, bool p_ap if (!p_append) { editor_selection->clear(); viewport->update(); + viewport_base->update(); }; if (p_box_selection) { @@ -534,6 +704,7 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po } viewport->update(); + viewport_base->update(); return still_selected; } @@ -566,7 +737,7 @@ void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE Vector2 drag = p_dir; if (p_snap) - drag *= snap_step; + drag *= grid_step * Math::pow(2.0, grid_step_multiplier); undo_redo->add_undo_method(canvas_item, "edit_set_state", canvas_item->edit_get_state()); @@ -649,7 +820,7 @@ int CanvasItemEditor::get_item_count() { return ic; } -CanvasItem *CanvasItemEditor::get_single_item() { +CanvasItem *CanvasItemEditor::_get_single_item() { Map<Node *, Object *> &selection = editor_selection->get_selection(); @@ -674,7 +845,7 @@ CanvasItem *CanvasItemEditor::get_single_item() { CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point) { // Returns a drag type if a resize handle is clicked - CanvasItem *canvas_item = get_single_item(); + CanvasItem *canvas_item = _get_single_item(); ERR_FAIL_COND_V(!canvas_item, DRAG_NONE); @@ -738,35 +909,7 @@ CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const return DRAG_NONE; } -float CanvasItemEditor::_anchor_snap(float p_anchor, bool *p_snapped, float p_opposite_anchor) { - bool snapped = false; - float dist, dist_min = 0.0; - float radius = 0.05 / zoom; - float basic_anchors[3] = { 0.0, 0.5, 1.0 }; - for (int i = 0; i < 3; i++) { - dist = fabs(p_anchor - basic_anchors[i]); - if (dist < radius) { - if (!snapped || dist <= dist_min) { - p_anchor = basic_anchors[i]; - dist_min = dist; - snapped = true; - } - } - } - dist = fabs(p_anchor - p_opposite_anchor); - if (p_opposite_anchor >= 0 && dist < radius) { - if (!snapped || dist <= dist_min) { - p_anchor = p_opposite_anchor; - dist_min = dist; - snapped = true; - } - } - if (p_snapped) - *p_snapped = snapped; - return p_anchor; -} - -Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor) { +Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) { ERR_FAIL_COND_V(!p_control, Vector2()); Transform2D parent_transform = p_control->get_transform().affine_inverse(); @@ -775,7 +918,7 @@ Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor return parent_transform.xform(Vector2(parent_size.x * anchor.x, parent_size.y * anchor.y)); } -Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 position) { +Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) { ERR_FAIL_COND_V(!p_control, Vector2()); Size2 parent_size = p_control->get_parent_area_size(); @@ -784,7 +927,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 positi CanvasItemEditor::DragType CanvasItemEditor::_get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point) { // Returns a drag type if an anchor handle is clicked - CanvasItem *canvas_item = get_single_item(); + CanvasItem *canvas_item = _get_single_item(); ERR_FAIL_COND_V(!canvas_item, DRAG_NONE); Control *control = Object::cast_to<Control>(canvas_item); @@ -845,6 +988,8 @@ void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) { se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot(); if (Object::cast_to<Control>(canvas_item)) se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); + + se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); } if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) { @@ -918,28 +1063,12 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *p_item) { } void CanvasItemEditor::_snap_changed() { - ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); + ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step); + grid_step_multiplier = 0; + viewport_base->update(); viewport->update(); } -void CanvasItemEditor::_dialog_value_changed(double) { - - if (updating_value_dialog) - return; - - switch (last_option) { - - case ZOOM_SET: { - - zoom = dialog_val->get_value() / 100.0; - _update_scroll(0); - viewport->update(); - - } break; - default: {} - } -} - void CanvasItemEditor::_selection_result_pressed(int p_result) { if (selection_results.size() <= p_result) @@ -960,7 +1089,7 @@ void CanvasItemEditor::_selection_menu_hide() { void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) { - Point2 click = b->get_position(); + Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); Node *scene = editor->get_edited_scene(); if (!scene) @@ -1068,7 +1197,7 @@ void CanvasItemEditor::_update_cursor() { viewport->set_default_cursor_shape(c); } -void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { +void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) { { EditorNode *en = editor; @@ -1101,7 +1230,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { float prev_zoom = zoom; zoom = zoom * (1 - (0.05 * b->get_factor())); { - Point2 ofs = b->get_position(); + Point2 ofs = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); ofs = ofs / prev_zoom - ofs / zoom; h_scroll->set_value(h_scroll->get_value() + ofs.x); v_scroll->set_value(v_scroll->get_value() + ofs.y); @@ -1125,7 +1254,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { float prev_zoom = zoom; zoom = zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95); { - Point2 ofs = b->get_position(); + Point2 ofs = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); ofs = ofs / prev_zoom - ofs / zoom; h_scroll->set_value(h_scroll->get_value() + ofs.x); v_scroll->set_value(v_scroll->get_value() + ofs.y); @@ -1214,9 +1343,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) { if (b->is_pressed()) { // Set the pivot point - Point2 mouse_pos = b->get_position(); + Point2 mouse_pos = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); mouse_pos = transform.affine_inverse().xform(mouse_pos); - mouse_pos = snap_point(mouse_pos); + mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item()); _edit_set_pivot(mouse_pos); } return; @@ -1337,8 +1466,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { E->get().to }; - Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s); - float d = p.distance_to(b->get_position()); + Vector2 p = Geometry::get_closest_point_to_segment_2d(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()), s); + float d = p.distance_to(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position())); if (d < bone_width && d < closest_dist) { Cbone = E; closest_dist = d; @@ -1395,12 +1524,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } // Single selected item - CanvasItem *canvas_item = get_single_item(); + CanvasItem *canvas_item = _get_single_item(); if (canvas_item) { CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); ERR_FAIL_COND(!se); - Point2 click = b->get_position(); + Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); // Rotation if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) { @@ -1411,6 +1540,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot(); if (Object::cast_to<Control>(canvas_item)) se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); + se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); return; } @@ -1432,15 +1562,18 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot(); if (Object::cast_to<Control>(canvas_item)) se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset(); + se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); return; } // Drag anchor handles - if (Object::cast_to<Control>(canvas_item)) { + Control *control = Object::cast_to<Control>(canvas_item); + if (control && show_helpers && !Object::cast_to<Container>(control->get_parent())) { drag = _get_anchor_handle_drag_type(click, drag_point_from); if (drag != DRAG_NONE) { drag_from = transform.affine_inverse().xform(click); se->undo_state = canvas_item->edit_get_state(); + se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); return; } } @@ -1448,7 +1581,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } // Multiple selected items - Point2 click = b->get_position(); + Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()); if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) { // Drag the nodes @@ -1508,12 +1641,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { // Mouse motion event _update_cursor(); - if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) - viewport->call_deferred("grab_focus"); + if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) + viewport_base->call_deferred("grab_focus"); if (box_selecting) { // Update box selection - box_selecting_to = transform.affine_inverse().xform(m->get_position()); + box_selecting_to = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position())); viewport->update(); return; } @@ -1559,7 +1692,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } Vector2 dfrom = drag_from; - Vector2 dto = transform.affine_inverse().xform(m->get_position()); + Vector2 dto = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position())); if (canvas_item->has_meta("_edit_lock_")) continue; @@ -1593,60 +1726,74 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { continue; } + bool uniform = m->get_shift(); + bool symmetric = m->get_alt(); + + Vector2 drag_vector = + canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - + canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom); + + switch (drag) { + case DRAG_ALL: + case DRAG_NODE_2D: + dto -= drag_from - drag_point_from; + if (uniform) { + if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) { + dto.y = drag_point_from.y; + } else { + dto.x = drag_point_from.x; + } + } + break; + } + Control *control = Object::cast_to<Control>(canvas_item); if (control) { // Drag and snap the anchor - Vector2 anchor = _position_to_anchor(control, canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto - drag_from + drag_point_from)); + Transform2D c_trans_rev = canvas_item->get_global_transform_with_canvas().affine_inverse(); + + Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from); + anchor = _position_to_anchor(control, anchor); + + Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES)); + anchor_snapped = _position_to_anchor(control, anchor_snapped).snapped(Vector2(0.00001, 0.00001)); + + bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x); switch (drag) { case DRAG_ANCHOR_TOP_LEFT: - control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false); - control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y); continue; break; case DRAG_ANCHOR_TOP_RIGHT: - control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false); - control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y); continue; break; case DRAG_ANCHOR_BOTTOM_RIGHT: - control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false); - control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false); - continue; + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y); break; case DRAG_ANCHOR_BOTTOM_LEFT: - control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false); - control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y); continue; break; case DRAG_ANCHOR_ALL: - control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x)); - control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x)); - control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y)); - control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y)); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x); + if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y); + if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y); continue; break; } } - bool uniform = m->get_shift(); - bool symmetric = m->get_alt(); - - if (drag == DRAG_ALL || drag == DRAG_NODE_2D) - dto -= drag_from - drag_point_from; - - if (uniform && (drag == DRAG_ALL || drag == DRAG_NODE_2D)) { - if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) { - dto.y = drag_point_from.y; - } else { - dto.x = drag_point_from.x; - } - } - dfrom = drag_point_from; - dto = snap_point(dto, drag_point_from); + dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, _get_single_item()); - Vector2 drag_vector = + drag_vector = canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom); @@ -1896,56 +2043,148 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { } } +void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) { + Color color = Color(0.8, 0.8, 0.8, 0.5); + Ref<Font> font = get_font("font", "Label"); + Size2 text_size = font->get_string_size(p_string); + switch (p_side) { + case MARGIN_LEFT: + p_position += Vector2(-text_size.x - 5, text_size.y / 2); + break; + case MARGIN_TOP: + p_position += Vector2(-text_size.x / 2, -5); + break; + case MARGIN_RIGHT: + p_position += Vector2(5, text_size.y / 2); + break; + case MARGIN_BOTTOM: + p_position += Vector2(-text_size.x / 2, text_size.y + 5); + break; + } + viewport->draw_string(font, p_position, p_string, color); +} + +void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) { + String str = vformat("%d px", p_value); + if (p_value != 0) { + _draw_text_at_position(p_position, str, p_side); + } +} + void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) { + String str = vformat("%.1f %%", p_value * 100.0); if (p_value != 0) { - Color color = Color(0.8, 0.8, 0.8, 0.5); - Ref<Font> font = get_font("font", "Label"); - String str = vformat("%.1f %%", p_value * 100.0); - Size2 text_size = font->get_string_size(str); - switch (p_side) { - case MARGIN_LEFT: - p_position += Vector2(-text_size.x - 5, text_size.y / 2); - break; - case MARGIN_TOP: - p_position += Vector2(-text_size.x / 2, -5); - break; - case MARGIN_RIGHT: - p_position += Vector2(5, text_size.y / 2); - break; - case MARGIN_BOTTOM: - p_position += Vector2(-text_size.x / 2, text_size.y + 5); - break; - } - viewport->draw_string(font, p_position, str, color); + _draw_text_at_position(p_position, str, p_side); } } -void CanvasItemEditor::_viewport_draw() { +void CanvasItemEditor::_draw_rulers() { + Color graduation_color = Color(0.5, 0.5, 0.5, 1); + Color bg_color = get_color("dark_color_2", "Editor"); + Color font_color = Color(0.8, 0.8, 0.8, 1); + Ref<Font> font = get_font("rulers", "EditorFonts"); + + // The rule transform + Transform2D ruler_transform; + if (show_grid || snap_grid) { + ruler_transform = Transform2D(); + if (snap_relative && get_item_count() > 0) { + ruler_transform.translate(_find_topleftmost_point()); + ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); + } else { + ruler_transform.translate(grid_offset); + ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier)); + } + while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) { - // TODO fetch the viewport? + ruler_transform.scale_basis(Point2(2, 2)); + } + } else { + float basic_rule = 100; + for (int i = 0; basic_rule * zoom > 100; i++) { + basic_rule /= (i % 2) ? 5.0 : 2.0; + } + for (int i = 0; basic_rule * zoom < 100; i++) { + basic_rule *= (i % 2) ? 2.0 : 5.0; + } + ruler_transform = Transform2D(); + ruler_transform.scale(Size2(basic_rule, basic_rule)); + } - Ref<Texture> pivot = get_icon("EditorPivot", "EditorIcons"); - _update_scrollbars(); - RID ci = viewport->get_canvas_item(); + // Subdivisions + int major_subdivision = 2; + Transform2D major_subdivide = Transform2D(); + major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision)); + + int minor_subdivision = 5; + Transform2D minor_subdivide = Transform2D(); + minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision)); + + // First and last graduations to draw (in the ruler space) + Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2()); + Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size()); + + // Draw top ruler + viewport_base->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color); + for (int i = Math::ceil(first.x); i < last.x; i++) { + Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)); + if (i % (major_subdivision * minor_subdivision) == 0) { + viewport_base->draw_line(Point2(position.x + RULER_WIDTH, 0), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x; + viewport_base->draw_string(font, Point2(position.x + RULER_WIDTH + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + } else { + if (i % minor_subdivision == 0) { + viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.33), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + } else { + viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color); + } + } + } - if (snap_show_grid) { + // Draw left ruler + viewport_base->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color); + for (int i = Math::ceil(first.y); i < last.y; i++) { + Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)); + if (i % (major_subdivision * minor_subdivision) == 0) { + viewport_base->draw_line(Point2(0, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y; + viewport_base->draw_string(font, Point2(2, position.y + RULER_WIDTH + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color); + } else { + if (i % minor_subdivision == 0) { + viewport_base->draw_line(Point2(RULER_WIDTH * 0.33, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + } else { + viewport_base->draw_line(Point2(RULER_WIDTH * 0.66, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color); + } + } + } + viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color); +} + +void CanvasItemEditor::_draw_focus() { + if (viewport_base->has_focus()) { + get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size())); + } +} + +void CanvasItemEditor::_draw_grid() { + if (show_grid) { //Draw the grid Size2 s = viewport->get_size(); int last_cell = 0; Transform2D xform = transform.affine_inverse(); - Vector2 grid_offset; - if (snap_relative && snap_grid && get_item_count() > 0) { + Vector2 real_grid_offset; + if (snap_relative && get_item_count() > 0) { Vector2 topleft = _find_topleftmost_point(); - grid_offset.x = fmod(topleft.x, snap_step.x); - grid_offset.y = fmod(topleft.y, snap_step.y); + real_grid_offset.x = fmod(topleft.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)); + real_grid_offset.y = fmod(topleft.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)); } else { - grid_offset = snap_offset; + real_grid_offset = grid_offset; } - if (snap_step.x != 0) { + if (grid_step.x != 0) { for (int i = 0; i < s.width; i++) { - int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - grid_offset.x) / snap_step.x)); + int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier)))); if (i == 0) last_cell = cell; if (last_cell != cell) @@ -1954,9 +2193,9 @@ void CanvasItemEditor::_viewport_draw() { } } - if (snap_step.y != 0) { + if (grid_step.y != 0) { for (int i = 0; i < s.height; i++) { - int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - grid_offset.y) / snap_step.y)); + int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier)))); if (i == 0) last_cell = cell; if (last_cell != cell) @@ -1965,21 +2204,15 @@ void CanvasItemEditor::_viewport_draw() { } } } +} - if (viewport->has_focus()) { - Size2 size = viewport->get_size(); - get_stylebox("Focus", "EditorStyles")->draw(ci, Rect2(Point2(), size)); - } - - Ref<Texture> lock = get_icon("Lock", "EditorIcons"); - Ref<Texture> group = get_icon("Group", "EditorIcons"); - - bool single = get_single_item() != NULL; - - Map<Node *, Object *> &selection = editor_selection->get_selection(); - +void CanvasItemEditor::_draw_selection() { bool pivot_found = false; + Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons"); + bool single = _get_single_item() != NULL; + RID ci = viewport->get_canvas_item(); + Map<Node *, Object *> &selection = editor_selection->get_selection(); for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key()); @@ -1993,6 +2226,23 @@ void CanvasItemEditor::_viewport_draw() { Rect2 rect = canvas_item->get_item_rect(); + if (drag != DRAG_NONE && drag != DRAG_PIVOT) { + const Transform2D pre_drag_xform = transform * se->pre_drag_xform; + const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7); + + Vector2 pre_drag_endpoints[4] = { + + pre_drag_xform.xform(rect.position), + pre_drag_xform.xform(rect.position + Vector2(rect.size.x, 0)), + pre_drag_xform.xform(rect.position + rect.size), + pre_drag_xform.xform(rect.position + Vector2(0, rect.size.y)) + }; + + for (int i = 0; i < 4; i++) { + viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2); + } + } + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform); @@ -2014,10 +2264,10 @@ void CanvasItemEditor::_viewport_draw() { if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks - if (Object::cast_to<Node2D>(canvas_item)) { - - if (Object::cast_to<Node2D>(canvas_item)->edit_has_pivot()) { - viewport->draw_texture(pivot, xform.get_origin() + (-pivot->get_size() / 2).floor()); + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d) { + if (node2d->edit_has_pivot()) { + viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor()); can_move_pivot = true; pivot_found = true; } @@ -2027,12 +2277,15 @@ void CanvasItemEditor::_viewport_draw() { if (control) { Vector2 pivot_ofs = control->get_pivot_offset(); if (pivot_ofs != Vector2()) { - viewport->draw_texture(pivot, xform.xform(pivot_ofs) + (-pivot->get_size() / 2).floor()); + viewport->draw_texture(pivot_icon, xform.xform(pivot_ofs) + (-pivot_icon->get_size() / 2).floor()); } can_move_pivot = true; pivot_found = true; - if (tool == TOOL_SELECT) { + if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) { + // Draw the helpers + Color color_base = Color(0.8, 0.8, 0.8, 0.5); + float anchors_values[4]; anchors_values[0] = control->get_anchor(MARGIN_LEFT); anchors_values[1] = control->get_anchor(MARGIN_TOP); @@ -2047,6 +2300,7 @@ void CanvasItemEditor::_viewport_draw() { anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i])); } + Map<Node *, Object *> &selection = editor_selection->get_selection(); // Get which anchor is dragged int dragged_anchor = -1; switch (drag) { @@ -2069,7 +2323,6 @@ void CanvasItemEditor::_viewport_draw() { // Draw the 4 lines when dragged bool snapped; Color color_snapped = Color(0.64, 0.93, 0.67, 0.5); - Color color_base = Color(0.8, 0.8, 0.8, 0.5); Vector2 corners_pos[4]; for (int i = 0; i < 4; i++) { @@ -2082,7 +2335,7 @@ void CanvasItemEditor::_viewport_draw() { float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i]; line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val); line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val); - _anchor_snap(anchors_values[i], &snapped); + snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0; viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1); } @@ -2114,6 +2367,83 @@ void CanvasItemEditor::_viewport_draw() { for (int i = 0; i < 4; i++) { anchor_handle->draw_rect(ci, anchor_rects[i]); } + + // Draw the margin values and the node width/height when dragging control side + float ratio = 0.33; + Transform2D parent_transform = xform * control->get_transform().affine_inverse(); + float node_pos_in_parent[4]; + + node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * control->get_parent_area_size().width + control->get_margin(MARGIN_LEFT); + node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * control->get_parent_area_size().height + control->get_margin(MARGIN_TOP); + node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * control->get_parent_area_size().width + control->get_margin(MARGIN_RIGHT); + node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * control->get_parent_area_size().height + control->get_margin(MARGIN_BOTTOM); + + switch (drag) { + case DRAG_LEFT: + case DRAG_TOP_LEFT: + case DRAG_BOTTOM_LEFT: + _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); + case DRAG_ALL: + Point2 start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio)); + Point2 end = start - Vector2(control->get_margin(MARGIN_LEFT), 0); + _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + switch (drag) { + case DRAG_RIGHT: + case DRAG_TOP_RIGHT: + case DRAG_BOTTOM_RIGHT: + _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM); + case DRAG_ALL: + Point2 start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio)); + Point2 end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0); + _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + switch (drag) { + case DRAG_TOP: + case DRAG_TOP_LEFT: + case DRAG_TOP_RIGHT: + _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT); + case DRAG_ALL: + Point2 start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]); + Point2 end = start - Vector2(0, control->get_margin(MARGIN_TOP)); + _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + switch (drag) { + case DRAG_BOTTOM: + case DRAG_BOTTOM_LEFT: + case DRAG_BOTTOM_RIGHT: + _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT); + case DRAG_ALL: + Point2 start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]); + Point2 end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM)); + _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT); + viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1); + break; + } + + switch (drag) { + //Draw the ghost rect if the node if rotated/scaled + case DRAG_LEFT: + case DRAG_TOP_LEFT: + case DRAG_TOP: + case DRAG_TOP_RIGHT: + case DRAG_RIGHT: + case DRAG_BOTTOM_RIGHT: + case DRAG_BOTTOM: + case DRAG_BOTTOM_LEFT: + case DRAG_ALL: + if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) { + Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size()); + viewport->draw_rect(parent_transform.xform(rect), color_base, false); + } + break; + } } } @@ -2136,33 +2466,32 @@ void CanvasItemEditor::_viewport_draw() { } } } - - //DRAW_EMPTY_RECT( Rect2( current_window->get_scroll()-Point2(1,1), get_size()+Size2(2,2)), Color(0.8,0.8,1.0,0.8) ); - //E->get().last_rect = rect; } - pivot_button->set_disabled(!pivot_found); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); - - Color x_axis_color(1.0, 0.4, 0.4, 0.6); - Color y_axis_color(0.4, 1.0, 0.4, 0.6); - Color area_axis_color(0.4, 0.4, 1.0, 0.4); - Color rotate_color(0.4, 0.7, 1.0, 0.8); - - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(h_scroll->get_min(), 0) + transform.get_origin(), Point2(h_scroll->get_max(), 0) + transform.get_origin(), x_axis_color); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, v_scroll->get_min()) + transform.get_origin(), Point2(0, v_scroll->get_max()) + transform.get_origin(), y_axis_color); if (box_selecting) { - Point2 bsfrom = transform.xform(drag_from); Point2 bsto = transform.xform(box_selecting_to); VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(bsfrom, bsto - bsfrom), Color(0.7, 0.7, 1.0, 0.3)); } + Color rotate_color(0.4, 0.7, 1.0, 0.8); if (drag == DRAG_ROTATE) { VisualServer::get_singleton()->canvas_item_add_line(ci, transform.xform(display_rotate_from), transform.xform(display_rotate_to), rotate_color); } +} + +void CanvasItemEditor::_draw_axis() { + RID ci = viewport->get_canvas_item(); + + Color x_axis_color(1.0, 0.4, 0.4, 0.6); + Color y_axis_color(0.4, 1.0, 0.4, 0.6); + Color area_axis_color(0.4, 0.4, 1.0, 0.4); + + Point2 origin = transform.get_origin(); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, origin.y), Point2(viewport->get_size().x, origin.y), x_axis_color); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(origin.x, 0), Point2(origin.x, viewport->get_size().y), y_axis_color); Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); @@ -2174,34 +2503,12 @@ void CanvasItemEditor::_viewport_draw() { }; for (int i = 0; i < 4; i++) { - VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color); } +} - for (List<LockList>::Element *E = lock_list.front(); E; E = E->next()) { - - Vector2 ofs = transform.xform(E->get().pos); - if (E->get().lock) { - - lock->draw(ci, ofs); - ofs.x += lock->get_width(); - } - if (E->get().group) { - - group->draw(ci, ofs); - } - } - - { - - EditorNode *en = editor; - EditorPluginList *over_plugin_list = en->get_editor_plugins_over(); - - if (!over_plugin_list->empty()) { - - over_plugin_list->forward_draw_over_canvas(transform, viewport); - } - } +void CanvasItemEditor::_draw_bones() { + RID ci = viewport->get_canvas_item(); if (skeleton_show_bones) { int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width"); @@ -2269,6 +2576,125 @@ void CanvasItemEditor::_viewport_draw() { } } +void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) { + RID viewport_ci = viewport->get_canvas_item(); + + Transform2D transform_ci = p_xform; + CanvasItem *ci = Object::cast_to<CanvasItem>(p_node); + if (ci) + transform_ci = transform_ci * ci->get_transform(); + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + _draw_locks_and_groups(p_node->get_child(i), transform_ci); + } + + if (ci) { + Ref<Texture> lock = get_icon("Lock", "EditorIcons"); + if (p_node->has_meta("_edit_lock_")) { + lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0))); + } + + Ref<Texture> group = get_icon("Group", "EditorIcons"); + if (ci->has_meta("_edit_group_")) { + Vector2 ofs = transform_ci.xform(Point2(0, 0)); + if (ci->has_meta("_edit_lock_")) + ofs = Point2(ofs.x + lock->get_size().x, ofs.y); + group->draw(viewport_ci, ofs); + } + } +} + +void CanvasItemEditor::_build_bones_list(Node *p_node) { + for (int i = 0; i < p_node->get_child_count(); i++) { + _build_bones_list(p_node->get_child(i)); + } + + CanvasItem *c = Object::cast_to<CanvasItem>(p_node); + if (c && c->is_visible_in_tree()) { + if (c->has_meta("_edit_bone_")) { + + ObjectID id = c->get_instance_id(); + if (!bone_list.has(id)) { + BoneList bone; + bone.bone = id; + bone_list[id] = bone; + } + + bone_list[id].last_pass = bone_last_frame; + } + } +} + +void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) { + for (int i = 0; i < p_node->get_child_count(); i++) { + _get_encompassing_rect(p_node->get_child(i), r_rect, p_xform); + } + + CanvasItem *c = Object::cast_to<CanvasItem>(p_node); + if (c && c->is_visible_in_tree()) { + Rect2 rect = c->get_item_rect(); + Transform2D xform = p_xform * c->get_transform(); + r_rect.expand_to(xform.xform(rect.position)); + r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); + r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); + r_rect.expand_to(xform.xform(rect.position + rect.size)); + } +} + +void CanvasItemEditor::_draw_viewport_base() { + if (show_rulers) + _draw_rulers(); + _draw_focus(); +} + +void CanvasItemEditor::_draw_viewport() { + + // hide/show buttons depending on the selection + bool all_locked = true; + bool all_group = true; + List<Node *> &selection = editor_selection->get_selected_node_list(); + if (selection.empty()) { + all_locked = false; + all_group = false; + } else { + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + if (Object::cast_to<Control>(E->get()) && !Object::cast_to<Control>(E->get())->has_meta("_edit_lock_")) { + all_locked = false; + break; + } + } + for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { + if (Object::cast_to<Control>(E->get()) && !Object::cast_to<Control>(E->get())->has_meta("_edit_group_")) { + all_group = false; + break; + } + } + } + + lock_button->set_visible(!all_locked); + lock_button->set_disabled(selection.empty()); + unlock_button->set_visible(all_locked); + group_button->set_visible(!all_group); + group_button->set_disabled(selection.empty()); + ungroup_button->set_visible(all_group); + + _update_scrollbars(); + + _draw_grid(); + _draw_selection(); + _draw_axis(); + _draw_locks_and_groups(editor->get_edited_scene(), transform); + + RID ci = viewport->get_canvas_item(); + VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); + + EditorPluginList *over_plugin_list = editor->get_editor_plugins_over(); + if (!over_plugin_list->empty()) { + over_plugin_list->forward_draw_over_canvas(transform, viewport); + } + _draw_focus(); +} + void CanvasItemEditor::_notification(int p_what) { if (p_what == NOTIFICATION_FIXED_PROCESS) { @@ -2319,6 +2745,7 @@ void CanvasItemEditor::_notification(int p_what) { if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) { viewport->update(); + viewport_base->update(); se->prev_pivot = pivot; se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT]; se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT]; @@ -2367,6 +2794,9 @@ void CanvasItemEditor::_notification(int p_what) { list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); move_button->set_icon(get_icon("ToolMove", "EditorIcons")); rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons")); + snap_button->set_icon(get_icon("Snap", "EditorIcons")); + snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); + skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); select_handle = get_icon("EditorHandle", "EditorIcons"); @@ -2377,6 +2807,10 @@ void CanvasItemEditor::_notification(int p_what) { ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons")); key_insert_button->set_icon(get_icon("Key", "EditorIcons")); + zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons")); + zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); + zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons")); + anchor_menu->set_icon(get_icon("Anchor", "EditorIcons")); PopupMenu *p = anchor_menu->get_popup(); @@ -2411,6 +2845,9 @@ void CanvasItemEditor::_notification(int p_what) { list_select_button->set_icon(get_icon("ListSelect", "EditorIcons")); move_button->set_icon(get_icon("ToolMove", "EditorIcons")); rotate_button->set_icon(get_icon("ToolRotate", "EditorIcons")); + snap_button->set_icon(get_icon("Snap", "EditorIcons")); + snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); + skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); select_handle = get_icon("EditorHandle", "EditorIcons"); @@ -2452,66 +2889,23 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) { drag = DRAG_NONE; + // Clear the selection editor_selection->clear(); //_clear_canvas_items(); editor_selection->add_node(p_canvas_item); //_add_canvas_item(p_canvas_item); viewport->update(); -} - -void CanvasItemEditor::_find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) { - - if (!p_node) - return; - - CanvasItem *c = Object::cast_to<CanvasItem>(p_node); - - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - - //CanvasItem *r=NULL; - - if (c && !c->is_set_as_toplevel()) - _find_canvas_items_span(p_node->get_child(i), r_rect, p_xform * c->get_transform()); - else - _find_canvas_items_span(p_node->get_child(i), r_rect, Transform2D()); - } - - if (c && c->is_visible_in_tree()) { - - Rect2 rect = c->get_item_rect(); - Transform2D xform = p_xform * c->get_transform(); - - LockList lock; - lock.lock = c->has_meta("_edit_lock_"); - lock.group = c->has_meta("_edit_group_"); - - if (lock.group || lock.lock) { - lock.pos = xform.xform(rect.position); - lock_list.push_back(lock); - } - - if (c->has_meta("_edit_bone_")) { - - ObjectID id = c->get_instance_id(); - if (!bone_list.has(id)) { - BoneList bone; - bone.bone = id; - bone_list[id] = bone; - } - - bone_list[id].last_pass = bone_last_frame; - } - - r_rect.expand_to(xform.xform(rect.position)); - r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); - r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); - r_rect.expand_to(xform.xform(rect.position + rect.size)); - } + viewport_base->update(); } void CanvasItemEditor::_update_scrollbars() { updating_scroll = true; + if (show_rulers) + viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH)); + else + viewport_scrollable->set_begin(Point2()); + Size2 size = viewport->get_size(); Size2 hmin = h_scroll->get_minimum_size(); Size2 vmin = v_scroll->get_minimum_size(); @@ -2528,11 +2922,12 @@ void CanvasItemEditor::_update_scrollbars() { Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); - lock_list.clear(); bone_last_frame++; - if (editor->get_edited_scene()) - _find_canvas_items_span(editor->get_edited_scene(), canvas_item_rect, Transform2D()); + if (editor->get_edited_scene()) { + _build_bones_list(editor->get_edited_scene()); + _get_encompassing_rect(editor->get_edited_scene(), canvas_item_rect, Transform2D()); + } List<Map<ObjectID, BoneList>::Element *> bone_to_erase; @@ -2555,7 +2950,6 @@ void CanvasItemEditor::_update_scrollbars() { Point2 ofs; if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) { - v_scroll->hide(); ofs.y = canvas_item_rect.position.y; } else { @@ -2616,6 +3010,7 @@ void CanvasItemEditor::_update_scroll(float) { editor->get_scene_root()->set_global_canvas_transform(transform); viewport->update(); + viewport_base->update(); } void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) { @@ -2662,88 +3057,117 @@ void CanvasItemEditor::_set_full_rect() { undo_redo->commit_action(); } +void CanvasItemEditor::_zoom_minus() { + if (zoom < MIN_ZOOM) + return; + zoom /= 2.0; + + _update_scroll(0); + viewport->update(); + viewport_base->update(); +} + +void CanvasItemEditor::_zoom_reset() { + zoom = 1; + _update_scroll(0); + viewport->update(); + viewport_base->update(); +} + +void CanvasItemEditor::_zoom_plus() { + if (zoom > MAX_ZOOM) + return; + + zoom *= 2.0; + _update_scroll(0); + viewport->update(); + viewport_base->update(); +} + +void CanvasItemEditor::_toggle_snap(bool p_status) { + snap_active = p_status; + viewport->update(); + viewport_base->update(); +} + void CanvasItemEditor::_popup_callback(int p_op) { last_option = MenuOption(p_op); switch (p_op) { - case SNAP_USE: { - snap_grid = !snap_grid; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE); - edit_menu->get_popup()->set_item_checked(idx, snap_grid); + case SHOW_GRID: { + show_grid = !show_grid; + int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); + view_menu->get_popup()->set_item_checked(idx, show_grid); viewport->update(); + viewport_base->update(); } break; - case SNAP_SHOW_GRID: { - snap_show_grid = !snap_show_grid; - int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID); - edit_menu->get_popup()->set_item_checked(idx, snap_show_grid); - viewport->update(); + case SNAP_USE_NODE_PARENT: { + snap_node_parent = !snap_node_parent; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); + smartsnap_config_popup->set_item_checked(idx, snap_node_parent); + } break; + case SNAP_USE_NODE_ANCHORS: { + snap_node_anchors = !snap_node_anchors; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->set_item_checked(idx, snap_node_anchors); + } break; + case SNAP_USE_NODE_SIDES: { + snap_node_sides = !snap_node_sides; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES); + smartsnap_config_popup->set_item_checked(idx, snap_node_sides); + } break; + case SNAP_USE_OTHER_NODES: { + snap_other_nodes = !snap_other_nodes; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES); + smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); + } break; + case SNAP_USE_GRID: { + snap_grid = !snap_grid; + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); + snap_config_menu->get_popup()->set_item_checked(idx, snap_grid); } break; case SNAP_USE_ROTATION: { snap_rotation = !snap_rotation; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); - edit_menu->get_popup()->set_item_checked(idx, snap_rotation); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION); + snap_config_menu->get_popup()->set_item_checked(idx, snap_rotation); } break; case SNAP_RELATIVE: { snap_relative = !snap_relative; - int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE); - edit_menu->get_popup()->set_item_checked(idx, snap_relative); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE); + snap_config_menu->get_popup()->set_item_checked(idx, snap_relative); viewport->update(); + viewport_base->update(); } break; case SNAP_USE_PIXEL: { snap_pixel = !snap_pixel; - int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); - edit_menu->get_popup()->set_item_checked(idx, snap_pixel); + int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); + snap_config_menu->get_popup()->set_item_checked(idx, snap_pixel); } break; case SNAP_CONFIGURE: { - ((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step); + ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step); snap_dialog->popup_centered(Size2(220, 160)); } break; case SKELETON_SHOW_BONES: { skeleton_show_bones = !skeleton_show_bones; - int idx = skeleton_menu->get_item_index(SKELETON_SHOW_BONES); - skeleton_menu->set_item_checked(idx, skeleton_show_bones); - viewport->update(); - } break; - case ZOOM_IN: { - if (zoom > MAX_ZOOM) - return; - zoom = zoom * (1.0 / 0.5); - _update_scroll(0); + int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES); + skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones); viewport->update(); - return; } break; - case ZOOM_OUT: { - if (zoom < MIN_ZOOM) - return; - - zoom = zoom * 0.5; - _update_scroll(0); + case SHOW_HELPERS: { + show_helpers = !show_helpers; + int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); + view_menu->get_popup()->set_item_checked(idx, show_helpers); viewport->update(); - return; - } break; - case ZOOM_RESET: { - - zoom = 1; - _update_scroll(0); + case SHOW_RULERS: { + show_rulers = !show_rulers; + int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS); + view_menu->get_popup()->set_item_checked(idx, show_rulers); viewport->update(); - return; - + viewport_base->update(); } break; - case ZOOM_SET: { - - updating_value_dialog = true; - - dialog_label->set_text(TTR("Zoom (%):")); - dialog_val->set_min(0.1); - dialog_val->set_step(0.1); - dialog_val->set_max(800); - dialog_val->set_value(zoom * 100); - value_dialog->popup_centered(Size2(200, 85)); - updating_value_dialog = false; - } break; case LOCK_SELECTED: { List<Node *> &selection = editor_selection->get_selected_node_list(); @@ -3090,7 +3514,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { n2d->set_meta("_edit_bone_", true); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3109,7 +3533,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { n2d->set_meta("_edit_bone_", Variant()); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3129,7 +3553,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { canvas_item->set_meta("_edit_ik_", true); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3149,7 +3573,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { n2d->set_meta("_edit_ik_", Variant()); if (!skeleton_show_bones) - skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES)); + skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES)); } viewport->update(); @@ -3212,15 +3636,19 @@ void CanvasItemEditor::_focus_selection(int p_op) { void CanvasItemEditor::_bind_methods() { + ClassDB::bind_method("_zoom_minus", &CanvasItemEditor::_zoom_minus); + ClassDB::bind_method("_zoom_reset", &CanvasItemEditor::_zoom_reset); + ClassDB::bind_method("_zoom_plus", &CanvasItemEditor::_zoom_plus); + ClassDB::bind_method("_toggle_snap", &CanvasItemEditor::_toggle_snap); ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll); ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback); - ClassDB::bind_method("_dialog_value_changed", &CanvasItemEditor::_dialog_value_changed); ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data); ClassDB::bind_method("_tool_select", &CanvasItemEditor::_tool_select); ClassDB::bind_method("_keying_changed", &CanvasItemEditor::_keying_changed); ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input); - ClassDB::bind_method("_viewport_draw", &CanvasItemEditor::_viewport_draw); - ClassDB::bind_method("_viewport_gui_input", &CanvasItemEditor::_viewport_gui_input); + ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport); + ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base); + ClassDB::bind_method("_viewport_base_gui_input", &CanvasItemEditor::_viewport_base_gui_input); ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); @@ -3262,64 +3690,92 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->set_area_as_parent_rect(); bottom_split = memnew(VSplitContainer); - bottom_split->set_v_size_flags(SIZE_EXPAND_FILL); add_child(bottom_split); + bottom_split->set_v_size_flags(SIZE_EXPAND_FILL); palette_split = memnew(HSplitContainer); - palette_split->set_v_size_flags(SIZE_EXPAND_FILL); bottom_split->add_child(palette_split); + palette_split->set_v_size_flags(SIZE_EXPAND_FILL); - Control *vp_base = memnew(Control); - vp_base->set_v_size_flags(SIZE_EXPAND_FILL); - palette_split->add_child(vp_base); - - ViewportContainer *vp = memnew(ViewportContainer); - vp->set_stretch(true); - vp_base->add_child(vp); - vp->set_area_as_parent_rect(); - vp->add_child(p_editor->get_scene_root()); + viewport_base = memnew(Control); + palette_split->add_child(viewport_base); + viewport_base->connect("draw", this, "_draw_viewport_base"); + viewport_base->connect("gui_input", this, "_viewport_base_gui_input"); + viewport_base->set_focus_mode(FOCUS_ALL); + viewport_base->set_v_size_flags(SIZE_EXPAND_FILL); + viewport_base->set_h_size_flags(SIZE_EXPAND_FILL); + + viewport_scrollable = memnew(Control); + viewport_base->add_child(viewport_scrollable); + viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS); + viewport_scrollable->set_draw_behind_parent(true); + viewport_scrollable->set_area_as_parent_rect(); + viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH)); + + ViewportContainer *scene_tree = memnew(ViewportContainer); + viewport_scrollable->add_child(scene_tree); + scene_tree->set_stretch(true); + scene_tree->set_area_as_parent_rect(); + scene_tree->add_child(p_editor->get_scene_root()); viewport = memnew(CanvasItemEditorViewport(p_editor, this)); - vp_base->add_child(viewport); + viewport_scrollable->add_child(viewport); + viewport->set_mouse_filter(MOUSE_FILTER_PASS); viewport->set_area_as_parent_rect(); viewport->set_clip_contents(true); + viewport->connect("draw", this, "_draw_viewport"); h_scroll = memnew(HScrollBar); - v_scroll = memnew(VScrollBar); - viewport->add_child(h_scroll); - viewport->add_child(v_scroll); - viewport->connect("draw", this, "_viewport_draw"); - viewport->connect("gui_input", this, "_viewport_gui_input"); - h_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); - v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); - h_scroll->hide(); + + v_scroll = memnew(VScrollBar); + viewport->add_child(v_scroll); + v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED); v_scroll->hide(); + + HBoxContainer *zoom_hb = memnew(HBoxContainer); + viewport->add_child(zoom_hb); + zoom_hb->set_begin(Point2(5, 5)); + + zoom_minus = memnew(ToolButton); + zoom_hb->add_child(zoom_minus); + zoom_minus->connect("pressed", this, "_zoom_minus"); + zoom_minus->set_focus_mode(FOCUS_NONE); + + zoom_reset = memnew(ToolButton); + zoom_hb->add_child(zoom_reset); + zoom_reset->connect("pressed", this, "_zoom_reset"); + zoom_reset->set_focus_mode(FOCUS_NONE); + + zoom_plus = memnew(ToolButton); + zoom_hb->add_child(zoom_plus); + zoom_plus->connect("pressed", this, "_zoom_plus"); + zoom_plus->set_focus_mode(FOCUS_NONE); + updating_scroll = false; - viewport->set_focus_mode(FOCUS_ALL); handle_len = 10; first_update = true; select_button = memnew(ToolButton); - select_button->set_toggle_mode(true); hb->add_child(select_button); + select_button->set_toggle_mode(true); select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_SELECT)); select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q)); select_button->set_tooltip(TTR("Select Mode") + " $sc\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Depth list selection")); move_button = memnew(ToolButton); - move_button->set_toggle_mode(true); hb->add_child(move_button); + move_button->set_toggle_mode(true); move_button->connect("pressed", this, "_tool_select", make_binds(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W)); move_button->set_tooltip(TTR("Move Mode")); rotate_button = memnew(ToolButton); - rotate_button->set_toggle_mode(true); hb->add_child(rotate_button); + rotate_button->set_toggle_mode(true); rotate_button->connect("pressed", this, "_tool_select", make_binds(TOOL_ROTATE)); rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E)); rotate_button->set_tooltip(TTR("Rotate Mode")); @@ -3327,25 +3783,60 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); list_select_button = memnew(ToolButton); - list_select_button->set_toggle_mode(true); hb->add_child(list_select_button); + list_select_button->set_toggle_mode(true); list_select_button->connect("pressed", this, "_tool_select", make_binds(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); pivot_button = memnew(ToolButton); - pivot_button->set_toggle_mode(true); hb->add_child(pivot_button); + pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", this, "_tool_select", make_binds(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); pan_button = memnew(ToolButton); - pan_button->set_toggle_mode(true); hb->add_child(pan_button); + pan_button->set_toggle_mode(true); pan_button->connect("pressed", this, "_tool_select", make_binds(TOOL_PAN)); pan_button->set_tooltip(TTR("Pan Mode")); hb->add_child(memnew(VSeparator)); + snap_button = memnew(ToolButton); + hb->add_child(snap_button); + snap_button->set_toggle_mode(true); + snap_button->connect("toggled", this, "_toggle_snap"); + snap_button->set_tooltip(TTR("Toggles snapping")); + snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap"), KEY_S)); + + snap_config_menu = memnew(MenuButton); + hb->add_child(snap_config_menu); + snap_config_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); + snap_config_menu->set_h_size_flags(SIZE_SHRINK_END); + snap_config_menu->set_tooltip(TTR("Snapping options")); + + PopupMenu *p = snap_config_menu->get_popup(); + p->connect("id_pressed", this, "_popup_callback"); + p->set_hide_on_checkable_item_selection(false); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_grid", TTR("Snap to grid")), SNAP_USE_GRID); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap...")), SNAP_CONFIGURE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL); + p->add_submenu_item(TTR("Smart snapping"), "SmartSnapping"); + + smartsnap_config_popup = memnew(PopupMenu); + p->add_child(smartsnap_config_popup); + smartsnap_config_popup->set_name("SmartSnapping"); + smartsnap_config_popup->connect("id_pressed", this, "_popup_callback"); + smartsnap_config_popup->set_hide_on_checkable_item_selection(false); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to parent")), SNAP_USE_NODE_PARENT); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to node anchor")), SNAP_USE_NODE_ANCHORS); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to node sides")), SNAP_USE_NODE_SIDES); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES); + + hb->add_child(memnew(VSeparator)); + lock_button = memnew(ToolButton); hb->add_child(lock_button); @@ -3369,35 +3860,23 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - edit_menu = memnew(MenuButton); - edit_menu->set_text(TTR("Edit")); - hb->add_child(edit_menu); - edit_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); + skeleton_menu = memnew(MenuButton); + hb->add_child(skeleton_menu); - PopupMenu *p; - p = edit_menu->get_popup(); + p = skeleton_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap")), SNAP_USE); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid")), SNAP_SHOW_GRID); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap..")), SNAP_CONFIGURE); + p->connect("id_pressed", this, "_popup_callback"); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES); p->add_separator(); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); p->add_separator(); - p->add_submenu_item(TTR("Skeleton.."), "skeleton"); - skeleton_menu = memnew(PopupMenu); - p->add_child(skeleton_menu); - skeleton_menu->set_name("skeleton"); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES); - skeleton_menu->add_separator(); - skeleton_menu->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES); - skeleton_menu->add_separator(); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); - skeleton_menu->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); - skeleton_menu->set_hide_on_checkable_item_selection(false); - skeleton_menu->connect("id_pressed", this, "_popup_callback"); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN); + p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN); + p->set_hide_on_checkable_item_selection(false); + p->connect("id_pressed", this, "_popup_callback"); + + hb->add_child(memnew(VSeparator)); view_menu = memnew(MenuButton); view_menu->set_text(TTR("View")); @@ -3405,11 +3884,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { view_menu->get_popup()->connect("id_pressed", this, "_popup_callback"); p = view_menu->get_popup(); - - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_in", TTR("Zoom In")), ZOOM_IN); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_out", TTR("Zoom Out")), ZOOM_OUT); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset")), ZOOM_RESET); - p->add_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_set", TTR("Zoom Set..")), ZOOM_SET); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), SHOW_GRID); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show helpers"), KEY_H), SHOW_HELPERS); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show rulers"), KEY_R), SHOW_RULERS); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); @@ -3480,23 +3957,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_dialog->connect("confirmed", this, "_snap_changed"); add_child(snap_dialog); - value_dialog = memnew(AcceptDialog); - value_dialog->set_title(TTR("Set a Value")); - value_dialog->get_ok()->set_text(TTR("Close")); - add_child(value_dialog); - - Label *l = memnew(Label); - l->set_text(TTR("Snap (Pixels):")); - l->set_position(Point2(5, 5)); - value_dialog->add_child(l); - dialog_label = l; - - dialog_val = memnew(SpinBox); - dialog_val->set_anchor(MARGIN_RIGHT, ANCHOR_END); - dialog_val->set_begin(Point2(15, 25)); - dialog_val->set_end(Point2(-10, 25)); - value_dialog->add_child(dialog_val); - dialog_val->connect("value_changed", this, "_dialog_value_changed"); select_sb = Ref<StyleBoxTexture>(memnew(StyleBoxTexture)); selection_menu = memnew(PopupMenu); @@ -3505,22 +3965,35 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { selection_menu->connect("id_pressed", this, "_selection_result_pressed"); selection_menu->connect("popup_hide", this, "_selection_menu_hide"); + drag_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/drag_pivot", TTR("Drag pivot from mouse position"), KEY_MASK_SHIFT | KEY_V); + set_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/set_pivot", TTR("Set pivot at mouse position"), KEY_V); + + multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY); + divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE); + key_pos = true; key_rot = true; key_scale = false; + show_grid = false; + show_helpers = false; + show_rulers = false; zoom = 1; - snap_offset = Vector2(0, 0); - snap_step = Vector2(10, 10); + grid_offset = Point2(); + grid_step = Point2(10, 10); + grid_step_multiplier = 0; snap_rotation_offset = 0; snap_rotation_step = 15 / (180 / Math_PI); - snap_grid = false; - snap_show_grid = false; + snap_active = false; + snap_node_parent = true; + snap_node_anchors = true; + snap_node_sides = true; + snap_other_nodes = true; + snap_grid = true; snap_rotation = false; snap_pixel = false; skeleton_show_bones = true; - skeleton_menu->set_item_checked(skeleton_menu->get_item_index(SKELETON_SHOW_BONES), true); - updating_value_dialog = false; + skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); box_selecting = false; //zoom=0.5; singleton = this; @@ -3551,7 +4024,7 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) { canvas_item_editor->show(); canvas_item_editor->set_fixed_process(true); VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false); - canvas_item_editor->viewport->grab_focus(); + canvas_item_editor->viewport_base->grab_focus(); } else { @@ -3720,7 +4193,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & target_pos -= texture_size / 2; } // there's nothing to be used as source position so snapping will work as absolute if enabled - target_pos = canvas->snap_point(target_pos, Vector2()); + target_pos = canvas->snap_point(target_pos); editor_data->get_undo_redo().add_do_method(child, "set_position", target_pos); } @@ -3754,22 +4227,13 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons editor_data->get_undo_redo().add_do_method(sed, "live_debug_instance_node", editor->get_edited_scene()->get_path_to(parent), path, new_name); editor_data->get_undo_redo().add_undo_method(sed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); - Point2 pos; - Node2D *parent_node2d = Object::cast_to<Node2D>(parent); - if (parent_node2d) { - pos = parent_node2d->get_global_position(); - } else { - Control *parent_control = Object::cast_to<Control>(parent); - if (parent_control) { - pos = parent_control->get_global_position(); - } + CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent); + if (parent_ci) { + Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point); + target_pos = canvas->snap_point(target_pos); + target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); + editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } - Transform2D trans = canvas->get_canvas_transform(); - Vector2 target_pos = (p_point - trans.get_origin()) / trans.get_scale().x - pos; - // in relative snapping it may be useful for the user to take the original node position into account - Vector2 start_pos = Object::cast_to<Node2D>(instanced_scene) ? Object::cast_to<Node2D>(instanced_scene)->get_position() : target_pos; - target_pos = canvas->snap_point(target_pos, start_pos); - editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); return true; } @@ -3848,6 +4312,20 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian continue; } memdelete(instanced_scene); + } else if (type == "Texture" || + type == "ImageTexture" || + type == "ViewportTexture" || + type == "CurveTexture" || + type == "GradientTexture" || + type == "StreamTexture" || + type == "AtlasTexture" || + type == "LargeTexture") { + Ref<Texture> texture = ResourceLoader::load(files[i]); + if (texture.is_valid() == false) { + continue; + } + } else { + continue; } can_instance = true; break; @@ -3956,41 +4434,39 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte editor_data = editor->get_scene_tree_dock()->get_editor_data(); canvas = p_canvas; preview_node = memnew(Node2D); + accept = memnew(AcceptDialog); editor->get_gui_base()->add_child(accept); selector = memnew(AcceptDialog); + editor->get_gui_base()->add_child(selector); selector->set_title(TTR("Change default type")); + selector->connect("confirmed", this, "_on_change_type"); VBoxContainer *vbc = memnew(VBoxContainer); + selector->add_child(vbc); vbc->set_h_size_flags(SIZE_EXPAND_FILL); vbc->set_v_size_flags(SIZE_EXPAND_FILL); vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE); selector_label = memnew(Label); + vbc->add_child(selector_label); selector_label->set_align(Label::ALIGN_CENTER); selector_label->set_valign(Label::VALIGN_BOTTOM); selector_label->set_custom_minimum_size(Size2(0, 30) * EDSCALE); - vbc->add_child(selector_label); - - button_group.instance(); btn_group = memnew(VBoxContainer); + vbc->add_child(btn_group); btn_group->set_h_size_flags(0); + button_group.instance(); for (int i = 0; i < types.size(); i++) { CheckBox *check = memnew(CheckBox); + btn_group->add_child(check); check->set_text(types[i]); check->connect("button_down", this, "_on_select_type", varray(check)); - btn_group->add_child(check); check->set_button_group(button_group); } - vbc->add_child(btn_group); - - selector->connect("confirmed", this, "_on_change_type"); - - selector->add_child(vbc); - editor->get_gui_base()->add_child(selector); label = memnew(Label); label->add_color_override("font_color_shadow", Color(0, 0, 0, 1)); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 2e1a2eac5f..af834507e0 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -58,6 +58,8 @@ public: Vector2 prev_pivot; float prev_anchors[4]; + Transform2D pre_drag_xform; + CanvasItemEditorSelectedItem() { prev_rot = 0; } }; @@ -68,7 +70,6 @@ class CanvasItemEditor : public VBoxContainer { EditorNode *editor; enum Tool { - TOOL_SELECT, TOOL_LIST_SELECT, TOOL_MOVE, @@ -80,15 +81,18 @@ class CanvasItemEditor : public VBoxContainer { enum MenuOption { SNAP_USE, - SNAP_SHOW_GRID, + SNAP_USE_NODE_PARENT, + SNAP_USE_NODE_ANCHORS, + SNAP_USE_NODE_SIDES, + SNAP_USE_OTHER_NODES, + SNAP_USE_GRID, SNAP_USE_ROTATION, SNAP_RELATIVE, SNAP_CONFIGURE, SNAP_USE_PIXEL, - ZOOM_IN, - ZOOM_OUT, - ZOOM_RESET, - ZOOM_SET, + SHOW_GRID, + SHOW_HELPERS, + SHOW_RULERS, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -161,6 +165,8 @@ class CanvasItemEditor : public VBoxContainer { Tool tool; bool first_update; Control *viewport; + Control *viewport_base; + Control *viewport_scrollable; bool can_move_pivot; @@ -168,14 +174,28 @@ class CanvasItemEditor : public VBoxContainer { VScrollBar *v_scroll; HBoxContainer *hb; + ToolButton *zoom_minus; + ToolButton *zoom_reset; + ToolButton *zoom_plus; + Transform2D transform; + bool show_grid; + bool show_rulers; + bool show_helpers; float zoom; - Vector2 snap_offset; - Vector2 snap_step; + + Point2 grid_offset; + Point2 grid_step; + int grid_step_multiplier; + float snap_rotation_step; float snap_rotation_offset; + bool snap_active; + bool snap_node_parent; + bool snap_node_anchors; + bool snap_node_sides; + bool snap_other_nodes; bool snap_grid; - bool snap_show_grid; bool snap_rotation; bool snap_relative; bool snap_pixel; @@ -202,18 +222,6 @@ class CanvasItemEditor : public VBoxContainer { Vector<_SelectResult> selection_results; - struct LockList { - Point2 pos; - bool lock; - bool group; - LockList() { - lock = false; - group = false; - } - }; - - List<LockList> lock_list; - struct BoneList { Transform2D xform; @@ -253,6 +261,10 @@ class CanvasItemEditor : public VBoxContainer { ToolButton *move_button; ToolButton *rotate_button; + ToolButton *snap_button; + MenuButton *snap_config_menu; + PopupMenu *smartsnap_config_popup; + ToolButton *pivot_button; ToolButton *pan_button; @@ -262,8 +274,7 @@ class CanvasItemEditor : public VBoxContainer { ToolButton *group_button; ToolButton *ungroup_button; - MenuButton *edit_menu; - PopupMenu *skeleton_menu; + MenuButton *skeleton_menu; MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; @@ -276,6 +287,9 @@ class CanvasItemEditor : public VBoxContainer { PopupMenu *selection_menu; + Control *top_ruler; + Control *left_ruler; + //PopupMenu *popup; DragType drag; Point2 drag_from; @@ -288,6 +302,11 @@ class CanvasItemEditor : public VBoxContainer { Ref<Texture> select_handle; Ref<Texture> anchor_handle; + Ref<ShortCut> drag_pivot_shortcut; + Ref<ShortCut> set_pivot_shortcut; + Ref<ShortCut> multiply_grid_step_shortcut; + Ref<ShortCut> divide_grid_step_shortcut; + int handle_len; bool _is_part_of_subscene(CanvasItem *p_item); void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform, Vector<_SelectResult> &r_items, int limit = 0); @@ -298,10 +317,6 @@ class CanvasItemEditor : public VBoxContainer { ConfirmationDialog *snap_dialog; - AcceptDialog *value_dialog; - Label *dialog_label; - SpinBox *dialog_val; - CanvasItem *ref_item; void _edit_set_pivot(const Vector2 &mouse_pos); @@ -315,9 +330,8 @@ class CanvasItemEditor : public VBoxContainer { void _prepare_drag(const Point2 &p_click_pos); DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point); - float _anchor_snap(float anchor, bool *snapped = NULL, float p_opposite_anchor = -1); - Vector2 _anchor_to_position(Control *p_control, Vector2 anchor); - Vector2 _position_to_anchor(Control *p_control, Vector2 position); + Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor); + Vector2 _position_to_anchor(const Control *p_control, Vector2 position); void _popup_callback(int p_op); bool updating_scroll; @@ -328,7 +342,6 @@ class CanvasItemEditor : public VBoxContainer { void incend(float &beg, float &end, float inc, float minsize, bool p_symmetric); void _append_canvas_item(CanvasItem *p_item); - void _dialog_value_changed(double); void _snap_changed(); void _selection_result_pressed(int); void _selection_menu_hide(); @@ -337,26 +350,49 @@ class CanvasItemEditor : public VBoxContainer { Point2 _find_topleftmost_point(); - void _find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform); + void _build_bones_list(Node *p_node); + + void _get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform); Object *_get_editor_data(Object *p_what); - CanvasItem *get_single_item(); + CanvasItem *_get_single_item(); int get_item_count(); void _keying_changed(); void _unhandled_key_input(const Ref<InputEvent> &p_ev); + void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side); + void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side); void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side); - void _viewport_gui_input(const Ref<InputEvent> &p_event); - void _viewport_draw(); + void _draw_rulers(); + void _draw_focus(); + void _draw_grid(); + void _draw_selection(); + void _draw_axis(); + void _draw_bones(); + void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform); + + void _draw_viewport(); + + void _viewport_base_gui_input(const Ref<InputEvent> &p_event); + void _draw_viewport_base(); void _focus_selection(int p_op); + void _snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0); + void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap); + void _set_anchors_preset(Control::LayoutPreset p_preset); void _set_full_rect(); + void _zoom_minus(); + void _zoom_reset(); + void _zoom_plus(); + + void _toggle_snap(bool p_status); + HSplitContainer *palette_split; VSplitContainer *bottom_split; @@ -400,7 +436,18 @@ protected: static CanvasItemEditor *singleton; public: - Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const; + enum SnapMode { + SNAP_GRID = 1 << 0, + SNAP_PIXEL = 1 << 1, + SNAP_NODE_PARENT = 1 << 2, + SNAP_NODE_ANCHORS = 1 << 3, + SNAP_NODE_SIDES = 1 << 4, + SNAP_OTHER_NODES = 1 << 5, + + SNAP_DEFAULT = 0x03, + }; + + Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0); float snap_angle(float p_target, float p_start = 0) const; Transform2D get_canvas_transform() const { return transform; } diff --git a/editor/plugins/navigation_mesh_editor_plugin.h b/editor/plugins/navigation_mesh_editor_plugin.h index 3009e2addc..bac7f608ab 100644 --- a/editor/plugins/navigation_mesh_editor_plugin.h +++ b/editor/plugins/navigation_mesh_editor_plugin.h @@ -56,7 +56,7 @@ class NavigationMeshEditor : public Control { protected: void _node_removed(Node *p_node); static void _bind_methods(); - void _notification(int p_what); + void _notification(int p_option); public: void edit(NavigationMeshInstance *p_nav_mesh_instance); @@ -74,8 +74,8 @@ class NavigationMeshEditorPlugin : public EditorPlugin { public: virtual String get_name() const { return "NavigationMesh"; } bool has_main_screen() const { return false; } - virtual void edit(Object *p_node); - virtual bool handles(Object *p_node) const; + virtual void edit(Object *p_object); + virtual bool handles(Object *p_object) const; virtual void make_visible(bool p_visible); NavigationMeshEditorPlugin(EditorNode *p_node); diff --git a/editor/plugins/navigation_mesh_generator.h b/editor/plugins/navigation_mesh_generator.h index 48e7dfe53f..0a1c497f8f 100644 --- a/editor/plugins/navigation_mesh_generator.h +++ b/editor/plugins/navigation_mesh_generator.h @@ -56,7 +56,7 @@ protected: rcPolyMeshDetail *detail_mesh, Vector<float> &verticies, Vector<int> &indices); public: - static void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_base); + static void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node); static void clear(Ref<NavigationMesh> p_nav_mesh); }; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 3917c700f0..8c4e1b8f27 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -52,7 +52,7 @@ void Polygon2DEditor::_notification(int p_what) { uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); b_snap_grid->set_icon(get_icon("Grid", "EditorIcons")); - b_snap_enable->set_icon(get_icon("Snap", "EditorIcons")); + b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); get_tree()->connect("node_removed", this, "_node_removed"); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 44a9bc6d2e..9af5885a17 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1682,9 +1682,10 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool break; } ERR_FAIL_COND_V(!se, false); - tab_container->add_child(se); + // load script before adding as child else editor will crash at theme loading se->set_edited_script(p_script); + tab_container->add_child(se); se->set_tooltip_request_func("_get_debug_tooltip", this); if (se->get_edit_menu()) { se->get_edit_menu()->hide(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index d2cb96bf3b..c875ee7011 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -75,35 +75,98 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->clear_colors(); - /* keyword color */ - - text_edit->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0))); - text_edit->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0))); - text_edit->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244"))); - text_edit->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"))); - text_edit->add_color_override("completion_scroll_color", EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"))); - text_edit->add_color_override("completion_font_color", EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"))); - text_edit->add_color_override("font_color", EDITOR_DEF("text_editor/highlighting/text_color", Color(0, 0, 0))); - text_edit->add_color_override("line_number_color", EDITOR_DEF("text_editor/highlighting/line_number_color", Color(0, 0, 0))); - text_edit->add_color_override("caret_color", EDITOR_DEF("text_editor/highlighting/caret_color", Color(0, 0, 0))); - text_edit->add_color_override("caret_background_color", EDITOR_DEF("text_editor/highlighting/caret_background_color", Color(0, 0, 0))); - text_edit->add_color_override("font_selected_color", EDITOR_DEF("text_editor/highlighting/text_selected_color", Color(1, 1, 1))); - text_edit->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1))); - text_edit->add_color_override("brace_mismatch_color", EDITOR_DEF("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2))); - text_edit->add_color_override("current_line_color", EDITOR_DEF("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15))); - text_edit->add_color_override("line_length_guideline_color", EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0, 0, 0))); - text_edit->add_color_override("word_highlighted_color", EDITOR_DEF("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15))); - text_edit->add_color_override("number_color", EDITOR_DEF("text_editor/highlighting/number_color", Color(0.9, 0.6, 0.0, 2))); - text_edit->add_color_override("function_color", EDITOR_DEF("text_editor/highlighting/function_color", Color(0.4, 0.6, 0.8))); - text_edit->add_color_override("member_variable_color", EDITOR_DEF("text_editor/highlighting/member_variable_color", Color(0.9, 0.3, 0.3))); - text_edit->add_color_override("mark_color", EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4))); - text_edit->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2))); - text_edit->add_color_override("search_result_color", EDITOR_DEF("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1))); - text_edit->add_color_override("search_result_border_color", EDITOR_DEF("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1))); - text_edit->add_color_override("symbol_color", EDITOR_DEF("text_editor/highlighting/symbol_color", Color::hex(0x005291ff))); - text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 4)); + Color background_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0)); + Color completion_background_color = EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0)); + Color completion_selected_color = EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")); + Color completion_existing_color = EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")); + Color completion_scroll_color = EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff")); + Color completion_font_color = EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa")); + Color text_color = EDITOR_DEF("text_editor/highlighting/text_color", Color(0, 0, 0)); + Color line_number_color = EDITOR_DEF("text_editor/highlighting/line_number_color", Color(0, 0, 0)); + Color caret_color = EDITOR_DEF("text_editor/highlighting/caret_color", Color(0, 0, 0)); + Color caret_background_color = EDITOR_DEF("text_editor/highlighting/caret_background_color", Color(0, 0, 0)); + Color text_selected_color = EDITOR_DEF("text_editor/highlighting/text_selected_color", Color(1, 1, 1)); + Color selection_color = EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)); + Color brace_mismatch_color = EDITOR_DEF("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2)); + Color current_line_color = EDITOR_DEF("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15)); + Color line_length_guideline_color = EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0, 0, 0)); + Color word_highlighted_color = EDITOR_DEF("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15)); + Color number_color = EDITOR_DEF("text_editor/highlighting/number_color", Color(0.9, 0.6, 0.0, 2)); + Color function_color = EDITOR_DEF("text_editor/highlighting/function_color", Color(0.4, 0.6, 0.8)); + Color member_variable_color = EDITOR_DEF("text_editor/highlighting/member_variable_color", Color(0.9, 0.3, 0.3)); + Color mark_color = EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4)); + Color breakpoint_color = EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2)); + Color search_result_color = EDITOR_DEF("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1)); + Color search_result_border_color = EDITOR_DEF("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1)); + Color symbol_color = EDITOR_DEF("text_editor/highlighting/symbol_color", Color::hex(0x005291ff)); Color keyword_color = EDITOR_DEF("text_editor/highlighting/keyword_color", Color(0.5, 0.0, 0.2)); + Color basetype_color = EDITOR_DEF("text_editor/highlighting/base_type_color", Color(0.3, 0.3, 0.0)); + Color type_color = EDITOR_DEF("text_editor/highlighting/engine_type_color", Color(0.0, 0.2, 0.4)); + Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color", Color::hex(0x797e7eff)); + Color string_color = EDITOR_DEF("text_editor/highlighting/string_color", Color::hex(0x6b6f00ff)); + + // Adapt + if (EditorSettings::get_singleton()->get("text_editor/theme/color_theme") == "Adaptive") { + Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); + + symbol_color = tm->get_color("text_editor/theme/symbol_color", "Editor"); + keyword_color = tm->get_color("text_editor/theme/keyword_color", "Editor"); + basetype_color = tm->get_color("text_editor/theme/basetype_color", "Editor"); + type_color = tm->get_color("text_editor/theme/type_color", "Editor"); + comment_color = tm->get_color("text_editor/theme/comment_color", "Editor"); + string_color = tm->get_color("text_editor/theme/string_color", "Editor"); + background_color = tm->get_color("text_editor/theme/background_color", "Editor"); + completion_background_color = tm->get_color("text_editor/theme/completion_background_color", "Editor"); + completion_selected_color = tm->get_color("text_editor/theme/completion_selected_color", "Editor"); + completion_existing_color = tm->get_color("text_editor/theme/completion_existing_color", "Editor"); + completion_scroll_color = tm->get_color("text_editor/theme/completion_scroll_color", "Editor"); + completion_font_color = tm->get_color("text_editor/theme/completion_font_color", "Editor"); + text_color = tm->get_color("text_editor/theme/text_color", "Editor"); + line_number_color = tm->get_color("text_editor/theme/line_number_color", "Editor"); + caret_color = tm->get_color("text_editor/theme/caret_color", "Editor"); + caret_background_color = tm->get_color("text_editor/theme/caret_background_color", "Editor"); + text_selected_color = tm->get_color("text_editor/theme/text_selected_color", "Editor"); + selection_color = tm->get_color("text_editor/theme/selection_color", "Editor"); + brace_mismatch_color = tm->get_color("text_editor/theme/brace_mismatch_color", "Editor"); + current_line_color = tm->get_color("text_editor/theme/current_line_color", "Editor"); + line_length_guideline_color = tm->get_color("text_editor/theme/line_length_guideline_color", "Editor"); + word_highlighted_color = tm->get_color("text_editor/theme/word_highlighted_color", "Editor"); + number_color = tm->get_color("text_editor/theme/number_color", "Editor"); + function_color = tm->get_color("text_editor/theme/function_color", "Editor"); + member_variable_color = tm->get_color("text_editor/theme/member_variable_color", "Editor"); + mark_color = tm->get_color("text_editor/theme/mark_color", "Editor"); + breakpoint_color = tm->get_color("text_editor/theme/breakpoint_color", "Editor"); + search_result_color = tm->get_color("text_editor/theme/search_result_color", "Editor"); + search_result_border_color = tm->get_color("text_editor/theme/search_result_border_color", "Editor"); + } + + text_edit->add_color_override("background_color", background_color); + text_edit->add_color_override("completion_background_color", completion_background_color); + text_edit->add_color_override("completion_selected_color", completion_selected_color); + text_edit->add_color_override("completion_existing_color", completion_existing_color); + text_edit->add_color_override("completion_scroll_color", completion_scroll_color); + text_edit->add_color_override("completion_font_color", completion_font_color); + text_edit->add_color_override("font_color", text_color); + text_edit->add_color_override("line_number_color", line_number_color); + text_edit->add_color_override("caret_color", caret_color); + text_edit->add_color_override("caret_background_color", caret_background_color); + text_edit->add_color_override("font_selected_color", text_selected_color); + text_edit->add_color_override("selection_color", selection_color); + text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color); + text_edit->add_color_override("current_line_color", current_line_color); + text_edit->add_color_override("line_length_guideline_color", line_length_guideline_color); + text_edit->add_color_override("word_highlighted_color", word_highlighted_color); + text_edit->add_color_override("number_color", number_color); + text_edit->add_color_override("function_color", function_color); + text_edit->add_color_override("member_variable_color", member_variable_color); + text_edit->add_color_override("mark_color", mark_color); + text_edit->add_color_override("breakpoint_color", breakpoint_color); + text_edit->add_color_override("search_result_color", search_result_color); + text_edit->add_color_override("search_result_border_color", search_result_border_color); + text_edit->add_color_override("symbol_color", symbol_color); + + text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 4)); List<String> keywords; script->get_language()->get_reserved_words(&keywords); @@ -113,8 +176,6 @@ void ScriptTextEditor::_load_theme_settings() { } //colorize core types - Color basetype_color = EDITOR_DEF("text_editor/highlighting/base_type_color", Color(0.3, 0.3, 0.0)); - text_edit->add_keyword_color("String", basetype_color); text_edit->add_keyword_color("Vector2", basetype_color); text_edit->add_keyword_color("Rect2", basetype_color); @@ -140,8 +201,6 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->add_keyword_color("PoolColorArray", basetype_color); //colorize engine types - Color type_color = EDITOR_DEF("text_editor/highlighting/engine_type_color", Color(0.0, 0.2, 0.4)); - List<StringName> types; ClassDB::get_class_list(&types); @@ -155,7 +214,6 @@ void ScriptTextEditor::_load_theme_settings() { } //colorize comments - Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color", Color::hex(0x797e7eff)); List<String> comments; script->get_language()->get_comment_delimiters(&comments); @@ -169,7 +227,6 @@ void ScriptTextEditor::_load_theme_settings() { } //colorize strings - Color string_color = EDITOR_DEF("text_editor/highlighting/string_color", Color::hex(0x6b6f00ff)); List<String> strings; script->get_language()->get_string_delimiters(&strings); @@ -209,6 +266,7 @@ void ScriptTextEditor::_notification(int p_what) { if (p_what == NOTIFICATION_READY) { //emit_signal("name_changed"); + _load_theme_settings(); } } @@ -492,8 +550,6 @@ void ScriptTextEditor::set_edited_script(const Ref<Script> &p_script) { script = p_script; - _load_theme_settings(); - code_editor->get_text_edit()->set_text(script->get_source_code()); code_editor->get_text_edit()->clear_undo_history(); code_editor->get_text_edit()->tag_saved_version(); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 1b02f18d85..b0ee1a32ca 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -60,33 +60,96 @@ void ShaderTextEditor::_load_theme_settings() { get_text_edit()->clear_colors(); - /* keyword color */ - - get_text_edit()->add_color_override("background_color", EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0))); - get_text_edit()->add_color_override("completion_background_color", EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0))); - get_text_edit()->add_color_override("completion_selected_color", EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244"))); - get_text_edit()->add_color_override("completion_existing_color", EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"))); - get_text_edit()->add_color_override("completion_scroll_color", EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"))); - get_text_edit()->add_color_override("completion_font_color", EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"))); - get_text_edit()->add_color_override("font_color", EDITOR_DEF("text_editor/highlighting/text_color", Color(0, 0, 0))); - get_text_edit()->add_color_override("line_number_color", EDITOR_DEF("text_editor/highlighting/line_number_color", Color(0, 0, 0))); - get_text_edit()->add_color_override("caret_color", EDITOR_DEF("text_editor/highlighting/caret_color", Color(0, 0, 0))); - get_text_edit()->add_color_override("caret_background_color", EDITOR_DEF("text_editor/highlighting/caret_background_color", Color(0, 0, 0))); - get_text_edit()->add_color_override("font_selected_color", EDITOR_DEF("text_editor/highlighting/text_selected_color", Color(1, 1, 1))); - get_text_edit()->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1))); - get_text_edit()->add_color_override("brace_mismatch_color", EDITOR_DEF("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2))); - get_text_edit()->add_color_override("current_line_color", EDITOR_DEF("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15))); - get_text_edit()->add_color_override("word_highlighted_color", EDITOR_DEF("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15))); - get_text_edit()->add_color_override("number_color", EDITOR_DEF("text_editor/highlighting/number_color", Color(0.9, 0.6, 0.0, 2))); - get_text_edit()->add_color_override("function_color", EDITOR_DEF("text_editor/highlighting/function_color", Color(0.4, 0.6, 0.8))); - get_text_edit()->add_color_override("member_variable_color", EDITOR_DEF("text_editor/highlighting/member_variable_color", Color(0.9, 0.3, 0.3))); - get_text_edit()->add_color_override("mark_color", EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4))); - get_text_edit()->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2))); - get_text_edit()->add_color_override("search_result_color", EDITOR_DEF("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1))); - get_text_edit()->add_color_override("search_result_border_color", EDITOR_DEF("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1))); - get_text_edit()->add_color_override("symbol_color", EDITOR_DEF("text_editor/highlighting/symbol_color", Color::hex(0x005291ff))); + Color background_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0)); + Color completion_background_color = EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0)); + Color completion_selected_color = EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244")); + Color completion_existing_color = EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf")); + Color completion_scroll_color = EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff")); + Color completion_font_color = EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa")); + Color text_color = EDITOR_DEF("text_editor/highlighting/text_color", Color(0, 0, 0)); + Color line_number_color = EDITOR_DEF("text_editor/highlighting/line_number_color", Color(0, 0, 0)); + Color caret_color = EDITOR_DEF("text_editor/highlighting/caret_color", Color(0, 0, 0)); + Color caret_background_color = EDITOR_DEF("text_editor/highlighting/caret_background_color", Color(0, 0, 0)); + Color text_selected_color = EDITOR_DEF("text_editor/highlighting/text_selected_color", Color(1, 1, 1)); + Color selection_color = EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)); + Color brace_mismatch_color = EDITOR_DEF("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2)); + Color current_line_color = EDITOR_DEF("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15)); + Color line_length_guideline_color = EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0, 0, 0)); + Color word_highlighted_color = EDITOR_DEF("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15)); + Color number_color = EDITOR_DEF("text_editor/highlighting/number_color", Color(0.9, 0.6, 0.0, 2)); + Color function_color = EDITOR_DEF("text_editor/highlighting/function_color", Color(0.4, 0.6, 0.8)); + Color member_variable_color = EDITOR_DEF("text_editor/highlighting/member_variable_color", Color(0.9, 0.3, 0.3)); + Color mark_color = EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4)); + Color breakpoint_color = EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2)); + Color search_result_color = EDITOR_DEF("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1)); + Color search_result_border_color = EDITOR_DEF("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1)); + Color symbol_color = EDITOR_DEF("text_editor/highlighting/symbol_color", Color::hex(0x005291ff)); Color keyword_color = EDITOR_DEF("text_editor/highlighting/keyword_color", Color(0.5, 0.0, 0.2)); + Color basetype_color = EDITOR_DEF("text_editor/highlighting/base_type_color", Color(0.3, 0.3, 0.0)); + Color type_color = EDITOR_DEF("text_editor/highlighting/engine_type_color", Color(0.0, 0.2, 0.4)); + Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color", Color::hex(0x797e7eff)); + Color string_color = EDITOR_DEF("text_editor/highlighting/string_color", Color::hex(0x6b6f00ff)); + + // Adapt + if (EditorSettings::get_singleton()->get("text_editor/theme/color_theme") == "Adaptive") { + Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme(); + + symbol_color = tm->get_color("text_editor/theme/symbol_color", "Editor"); + keyword_color = tm->get_color("text_editor/theme/keyword_color", "Editor"); + basetype_color = tm->get_color("text_editor/theme/basetype_color", "Editor"); + type_color = tm->get_color("text_editor/theme/type_color", "Editor"); + comment_color = tm->get_color("text_editor/theme/comment_color", "Editor"); + string_color = tm->get_color("text_editor/theme/string_color", "Editor"); + background_color = tm->get_color("text_editor/theme/background_color", "Editor"); + completion_background_color = tm->get_color("text_editor/theme/completion_background_color", "Editor"); + completion_selected_color = tm->get_color("text_editor/theme/completion_selected_color", "Editor"); + completion_existing_color = tm->get_color("text_editor/theme/completion_existing_color", "Editor"); + completion_scroll_color = tm->get_color("text_editor/theme/completion_scroll_color", "Editor"); + completion_font_color = tm->get_color("text_editor/theme/completion_font_color", "Editor"); + text_color = tm->get_color("text_editor/theme/text_color", "Editor"); + line_number_color = tm->get_color("text_editor/theme/line_number_color", "Editor"); + caret_color = tm->get_color("text_editor/theme/caret_color", "Editor"); + caret_background_color = tm->get_color("text_editor/theme/caret_background_color", "Editor"); + text_selected_color = tm->get_color("text_editor/theme/text_selected_color", "Editor"); + selection_color = tm->get_color("text_editor/theme/selection_color", "Editor"); + brace_mismatch_color = tm->get_color("text_editor/theme/brace_mismatch_color", "Editor"); + current_line_color = tm->get_color("text_editor/theme/current_line_color", "Editor"); + line_length_guideline_color = tm->get_color("text_editor/theme/line_length_guideline_color", "Editor"); + word_highlighted_color = tm->get_color("text_editor/theme/word_highlighted_color", "Editor"); + number_color = tm->get_color("text_editor/theme/number_color", "Editor"); + function_color = tm->get_color("text_editor/theme/function_color", "Editor"); + member_variable_color = tm->get_color("text_editor/theme/member_variable_color", "Editor"); + mark_color = tm->get_color("text_editor/theme/mark_color", "Editor"); + breakpoint_color = tm->get_color("text_editor/theme/breakpoint_color", "Editor"); + search_result_color = tm->get_color("text_editor/theme/search_result_color", "Editor"); + search_result_border_color = tm->get_color("text_editor/theme/search_result_border_color", "Editor"); + } + + get_text_edit()->add_color_override("background_color", background_color); + get_text_edit()->add_color_override("completion_background_color", completion_background_color); + get_text_edit()->add_color_override("completion_selected_color", completion_selected_color); + get_text_edit()->add_color_override("completion_existing_color", completion_existing_color); + get_text_edit()->add_color_override("completion_scroll_color", completion_scroll_color); + get_text_edit()->add_color_override("completion_font_color", completion_font_color); + get_text_edit()->add_color_override("font_color", text_color); + get_text_edit()->add_color_override("line_number_color", line_number_color); + get_text_edit()->add_color_override("caret_color", caret_color); + get_text_edit()->add_color_override("caret_background_color", caret_background_color); + get_text_edit()->add_color_override("font_selected_color", text_selected_color); + get_text_edit()->add_color_override("selection_color", selection_color); + get_text_edit()->add_color_override("brace_mismatch_color", brace_mismatch_color); + get_text_edit()->add_color_override("current_line_color", current_line_color); + get_text_edit()->add_color_override("line_length_guideline_color", line_length_guideline_color); + get_text_edit()->add_color_override("word_highlighted_color", word_highlighted_color); + get_text_edit()->add_color_override("number_color", number_color); + get_text_edit()->add_color_override("function_color", function_color); + get_text_edit()->add_color_override("member_variable_color", member_variable_color); + get_text_edit()->add_color_override("mark_color", mark_color); + get_text_edit()->add_color_override("breakpoint_color", breakpoint_color); + get_text_edit()->add_color_override("search_result_color", search_result_color); + get_text_edit()->add_color_override("search_result_border_color", search_result_border_color); + get_text_edit()->add_color_override("symbol_color", symbol_color); List<String> keywords; ShaderLanguage::get_keyword_list(&keywords); @@ -115,8 +178,6 @@ void ShaderTextEditor::_load_theme_settings() { //Color basetype_color= EDITOR_DEF("text_editor/base_type_color",Color(0.3,0.3,0.0)); //colorize comments - Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color", Color::hex(0x797e7eff)); - get_text_edit()->add_color_region("/*", "*/", comment_color, false); get_text_edit()->add_color_region("//", "", comment_color, false); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 704d474746..c1b0fdb5d6 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -76,18 +76,29 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) { } else camera->set_perspective(get_fov(), get_znear(), get_zfar()); - float inertia = EDITOR_DEF("editors/3d/orbit_inertia", 0.5); - inertia = MAX(0, inertia); + //when not being manipulated, move softly + float free_orbit_inertia = EDITOR_DEF("editors/3d/free_orbit_inertia", 0.15); + float free_translation_inertia = EDITOR_DEF("editors/3d/free_translation_inertia", 0.15); + //when being manipulated, move more quickly + float manip_orbit_inertia = EDITOR_DEF("editors/3d/manipulation_orbit_inertia", 0.075); + float manip_translation_inertia = EDITOR_DEF("editors/3d/manipulation_translation_inertia", 0.075); + + //determine if being manipulated + bool manipulated = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL); + + float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia); + float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia); Cursor old_camera_cursor = camera_cursor; camera_cursor = cursor; - camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, p_interp_delta * (1 / inertia)); - camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, p_interp_delta * (1 / inertia)); + camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); + camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia))); - bool disable_interp = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL); + camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia))); + camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / translation_inertia))); - if (p_interp_delta == 0 || disable_interp || is_freelook_active()) { + if (p_interp_delta == 0 || is_freelook_active()) { camera_cursor = cursor; } @@ -2555,11 +2566,18 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const { String path = files[i]; RES res = ResourceLoader::load(path); Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res)); - if (scene != NULL) { - if (scene.is_valid()) { - Node *instance = scene->instance(); - if (instance) { - preview_node->add_child(instance); + Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res)); + if (mesh != NULL || scene != NULL) { + if (mesh != NULL) { + MeshInstance *mesh_instance = memnew(MeshInstance); + mesh_instance->set_mesh(mesh); + preview_node->add_child(mesh_instance); + } else { + if (scene.is_valid()) { + Node *instance = scene->instance(); + if (instance) { + preview_node->add_child(instance); + } } } editor->get_scene_root()->add_child(preview_node); @@ -2595,13 +2613,29 @@ bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_s } bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { - Ref<PackedScene> sdata = ResourceLoader::load(path); - if (!sdata.is_valid()) { // invalid scene - return false; + RES res = ResourceLoader::load(path); + + Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res)); + Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res)); + + Node *instanced_scene = NULL; + + if (mesh != NULL || scene != NULL) { + if (mesh != NULL) { + MeshInstance *mesh_instance = memnew(MeshInstance); + mesh_instance->set_mesh(mesh); + mesh_instance->set_name(mesh->get_name()); + instanced_scene = mesh_instance; + } else { + if (!scene.is_valid()) { // invalid scene + return false; + } else { + instanced_scene = scene->instance(); + } + } } - Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE); - if (!instanced_scene) { // error on instancing + if (instanced_scene == NULL) { return false; } @@ -2650,7 +2684,8 @@ void SpatialEditorViewport::_perform_drop_data() { continue; } Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res)); - if (scene != NULL) { + Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res)); + if (mesh != NULL || scene != NULL) { bool success = _create_instance(target_node, path, drop_pos); if (!success) { error_files.push_back(path); @@ -2683,9 +2718,11 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian List<String> scene_extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); + List<String> mesh_extensions; + ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions); for (int i = 0; i < files.size(); i++) { - if (scene_extensions.find(files[i].get_extension())) { + if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) { RES res = ResourceLoader::load(files[i]); if (res.is_null()) { continue; @@ -2699,6 +2736,13 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian continue; } memdelete(instanced_scene); + } else if (type == "Mesh" || "ArrayMesh" || "PrimitiveMesh") { + Ref<Mesh> mesh = ResourceLoader::load(files[i]); + if (!mesh.is_valid()) { + continue; + } + } else { + continue; } can_instance = true; break; @@ -2843,8 +2887,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D); ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W); ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S); - ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q); - ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E); + ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_E); + ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_Q); ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT); preview_camera = memnew(Button); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 43856116a6..b85ffd6c67 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -72,6 +72,14 @@ void TileMapEditor::_menu_option(int p_option) { switch (p_option) { + case OPTION_PAINTING: { + // NOTE: We do not set tool = TOOL_PAINTING as this begins painting + // immediately without pressing the left mouse button first + tool = TOOL_NONE; + + canvas_item_editor->update(); + + } break; case OPTION_BUCKET: { tool = TOOL_BUCKET; @@ -703,7 +711,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } else { - + // Mousebutton was released if (tool != TOOL_NONE) { if (tool == TOOL_PAINTING) { @@ -801,6 +809,9 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->add_undo_method(this, "_fill_points", points, pop); undo_redo->commit_action(); + + // We want to keep the bucket-tool active + return true; } tool = TOOL_NONE; @@ -1046,9 +1057,25 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } - if (tool != TOOL_NONE || !mouse_over) + if (!mouse_over) { + // Editor shortcuts should not fire if mouse not in viewport return false; + } + if (ED_IS_SHORTCUT("tile_map_editor/paint_tile", p_event)) { + // NOTE: We do not set tool = TOOL_PAINTING as this begins painting + // immediately without pressing the left mouse button first + tool = TOOL_NONE; + canvas_item_editor->update(); + + return true; + } + if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) { + tool = TOOL_BUCKET; + canvas_item_editor->update(); + + return true; + } if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) { _menu_option(OPTION_ERASE_SELECTION); @@ -1458,7 +1485,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { ED_SHORTCUT("tile_map_editor/erase_selection", TTR("Erase selection"), KEY_DELETE); ED_SHORTCUT("tile_map_editor/find_tile", TTR("Find tile"), KEY_MASK_CMD + KEY_F); - ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose")); + ED_SHORTCUT("tile_map_editor/transpose", TTR("Transpose"), KEY_T); ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A); ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S); @@ -1512,7 +1539,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { PopupMenu *p = options->get_popup(); - p->add_item(TTR("Bucket"), OPTION_BUCKET); + p->add_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P), OPTION_PAINTING); + p->add_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_G), OPTION_BUCKET); p->add_separator(); p->add_item(TTR("Pick Tile"), OPTION_PICK_TILE, KEY_CONTROL); p->add_separator(); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index e863c4bf3d..de9b9e8e0d 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -68,7 +68,8 @@ class TileMapEditor : public VBoxContainer { OPTION_PICK_TILE, OPTION_SELECT, OPTION_DUPLICATE, - OPTION_ERASE_SELECTION + OPTION_ERASE_SELECTION, + OPTION_PAINTING, }; TileMap *node; diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index c7a4e1fc3b..b7300b9610 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -861,13 +861,13 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: menu->add_separator(); } - menu->add_icon_item(get_icon("Load", "EditorIcons"), "Load", OBJ_MENU_LOAD); + menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD); if (!RES(v).is_null()) { - menu->add_icon_item(get_icon("Edit", "EditorIcons"), "Edit", OBJ_MENU_EDIT); - menu->add_icon_item(get_icon("Clear", "EditorIcons"), "Clear", OBJ_MENU_CLEAR); - menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), "Make Unique", OBJ_MENU_MAKE_UNIQUE); + menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT); + menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR); + menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE); RES r = v; if (r.is_valid() && r->get_path().is_resource_file()) { menu->add_separator(); diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index b92ebed167..4bcbe073ee 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -189,7 +189,7 @@ Vector<Pair<String, Ref<Texture> > > EditorQuickOpen::_sort_fs(Vector<Pair<Strin Vector<Pair<String, Ref<Texture> > > sorted_list; if (search_text == String() || list.size() == 0) - return sorted_list; + return list; Vector<float> scores; scores.resize(list.size()); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 5b783493cb..2fcba7e3c0 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2016,6 +2016,5 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel clear_inherit_confirm->get_ok()->set_text(TTR("Clear!")); add_child(clear_inherit_confirm); - vbc->add_constant_override("separation", 4); set_process_input(true); } diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 284b25801c..76e75cff0a 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1622,7 +1622,6 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles")); tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles")); tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles")); - tabs->set_v_size_flags(SIZE_EXPAND_FILL); tabs->set_area_as_parent_rect(); add_child(tabs); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index 6cb5f0a70c..64ac2535a9 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -150,7 +150,7 @@ class ScriptEditorDebugger : public Control { void _scene_tree_selected(); void _scene_tree_request(); void _parse_message(const String &p_msg, const Array &p_data); - void _set_reason_text(const String &p_msg, MessageType p_type); + void _set_reason_text(const String &p_reason, MessageType p_type); void _scene_tree_property_select_object(ObjectID p_object); void _scene_tree_property_value_edited(const String &p_prop, const Variant &p_value); diff --git a/main/input_default.cpp b/main/input_default.cpp index b4c9a6207f..902d3168d8 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -80,7 +80,7 @@ bool InputDefault::is_key_pressed(int p_scancode) const { bool InputDefault::is_mouse_button_pressed(int p_button) const { _THREAD_SAFE_METHOD_ - return (mouse_button_mask & (1 << p_button)) != 0; + return (mouse_button_mask & (1 << (p_button - 1))) != 0; } static int _combine_device(int p_value, int p_device) { @@ -265,10 +265,11 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) { if (mb.is_valid() && !mb->is_doubleclick()) { - if (mb->is_pressed()) - mouse_button_mask |= (1 << mb->get_button_index()); - else - mouse_button_mask &= ~(1 << mb->get_button_index()); + if (mb->is_pressed()) { + mouse_button_mask |= (1 << (mb->get_button_index() - 1)); + } else { + mouse_button_mask &= ~(1 << (mb->get_button_index() - 1)); + } if (main_loop && emulate_touch && mb->get_button_index() == 1) { Ref<InputEventScreenTouch> touch_event; diff --git a/main/main.cpp b/main/main.cpp index bb601198db..04375666a9 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -248,7 +248,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph performance = memnew(Performance); globals->add_singleton(ProjectSettings::Singleton("Performance", performance)); - GLOBAL_DEF("debug/settings/backtrace/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); + GLOBAL_DEF("debug/settings/crash_handler/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues")); MAIN_PRINT("Main: Parse CMDLine"); diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp index 645db2826e..d9b20254a8 100644 --- a/main/tests/test_main.cpp +++ b/main/tests/test_main.cpp @@ -37,6 +37,7 @@ #include "test_image.h" #include "test_io.h" #include "test_math.h" +#include "test_oa_hash_map.h" #include "test_ordered_hash_map.h" #include "test_physics.h" #include "test_physics_2d.h" @@ -56,6 +57,7 @@ const char **tests_get_names() { "io", "shaderlang", "physics", + "oa_hash_map", NULL }; @@ -89,6 +91,11 @@ MainLoop *test_main(String p_test, const List<String> &p_args) { return TestRender::test(); } + if (p_test == "oa_hash_map") { + + return TestOAHashMap::test(); + } + #ifndef _3D_DISABLED if (p_test == "gui") { diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp new file mode 100644 index 0000000000..302c259262 --- /dev/null +++ b/main/tests/test_oa_hash_map.cpp @@ -0,0 +1,97 @@ +/*************************************************************************/ +/* test_oa_hash_map.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "test_oa_hash_map.h" + +#include "core/os/os.h" + +#include "core/oa_hash_map.h" + +namespace TestOAHashMap { + +MainLoop *test() { + + OS::get_singleton()->print("\n\n\nHello from test\n"); + + // test element tracking. + { + OAHashMap<int, int> map; + + map.set(42, 1337); + map.set(1337, 21); + map.set(42, 11880); + + int value; + map.lookup(42, &value); + + OS::get_singleton()->print("capacity %d\n", map.get_capacity()); + OS::get_singleton()->print("elements %d\n", map.get_num_elements()); + + OS::get_singleton()->print("map[42] = %d\n", value); + } + + // rehashing and deletion + { + OAHashMap<int, int> map; + + for (int i = 0; i < 500; i++) { + map.set(i, i * 2); + } + + for (int i = 0; i < 500; i += 2) { + map.remove(i); + } + + uint32_t num_elems = 0; + for (int i = 0; i < 500; i++) { + int tmp; + if (map.lookup(i, &tmp)) + num_elems++; + } + + OS::get_singleton()->print("elements %d == %d.\n", map.get_num_elements(), num_elems); + } + + // iteration + { + OAHashMap<String, int> map; + + map.set("Hello", 1); + map.set("World", 2); + map.set("Godot rocks", 42); + + for (OAHashMap<String, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) { + OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.data); + } + } + + return NULL; +} +} // namespace TestOAHashMap diff --git a/core/os/power.h b/main/tests/test_oa_hash_map.h index 59a091012e..92b4bc5e5a 100644 --- a/core/os/power.h +++ b/main/tests/test_oa_hash_map.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* power.h */ +/* test_oa_hash_map.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -27,16 +27,13 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef TEST_OA_HASH_MAP_H +#define TEST_OA_HASH_MAP_H -#ifndef CORE_OS_POWER_H_ -#define CORE_OS_POWER_H_ +#include "os/main_loop.h" -typedef enum { - POWERSTATE_UNKNOWN, /**< cannot determine power status */ - POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */ - POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */ - POWERSTATE_CHARGING, /**< Plugged in, charging battery */ - POWERSTATE_CHARGED /**< Plugged in, battery charged */ -} PowerState; +namespace TestOAHashMap { -#endif /* CORE_OS_POWER_H_ */ +MainLoop *test(); +} +#endif // TEST_OA_HASH_MAP_H diff --git a/modules/gdnative/gd_native_library_editor.cpp b/modules/gdnative/gd_native_library_editor.cpp new file mode 100644 index 0000000000..cc2c2b69a6 --- /dev/null +++ b/modules/gdnative/gd_native_library_editor.cpp @@ -0,0 +1,148 @@ +/*************************************************************************/ +/* gd_native_library_editor.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef TOOLS_ENABLED +#include "gd_native_library_editor.h" + +#include "gdnative.h" + +void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list) { + + // check children + + for (int i = 0; i < p_dir->get_file_count(); i++) { + String file_type = p_dir->get_file_type(i); + + if (file_type != "GDNativeLibrary") { + continue; + } + + Ref<GDNativeLibrary> lib = ResourceLoader::load(p_dir->get_file_path(i)); + if (lib.is_valid() && lib->is_singleton_gdnative()) { + String path = p_dir->get_file_path(i); + TreeItem *ti = libraries->create_item(libraries->get_root()); + ti->set_text(0, path.get_file()); + ti->set_tooltip(0, path); + ti->set_metadata(0, path); + ti->set_cell_mode(1, TreeItem::CELL_MODE_RANGE); + ti->set_text(1, "Disabled,Enabled"); + bool enabled = enabled_list.has(path) ? true : false; + + ti->set_range(1, enabled ? 1 : 0); + ti->set_custom_color(1, enabled ? Color(0, 1, 0) : Color(1, 0, 0)); + } + } + + // check subdirectories + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + _find_gdnative_singletons(p_dir->get_subdir(i), enabled_list); + } +} + +void GDNativeLibraryEditor::_update_libraries() { + + updating = true; + libraries->clear(); + libraries->create_item(); //rppt + + Vector<String> enabled_paths; + if (ProjectSettings::get_singleton()->has("gdnative/singletons")) { + enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); + } + Set<String> enabled_list; + for (int i = 0; i < enabled_paths.size(); i++) { + enabled_list.insert(enabled_paths[i]); + } + + EditorFileSystemDirectory *fs = EditorFileSystem::get_singleton()->get_filesystem(); + if (fs) { + _find_gdnative_singletons(fs, enabled_list); + } + + updating = false; +} + +void GDNativeLibraryEditor::_item_edited() { + if (updating) + return; + + TreeItem *item = libraries->get_edited(); + if (!item) + return; + + bool enabled = item->get_range(1); + String path = item->get_metadata(0); + + Vector<String> enabled_paths; + if (ProjectSettings::get_singleton()->has("gdnative/singletons")) { + enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons"); + } + + if (enabled) { + if (enabled_paths.find(path) == -1) { + enabled_paths.push_back(path); + } + } else { + enabled_paths.erase(path); + } + + if (enabled_paths.size()) { + ProjectSettings::get_singleton()->set("gdnative/singletons", enabled_paths); + } else { + ProjectSettings::get_singleton()->set("gdnative/singletons", Variant()); + } +} + +void GDNativeLibraryEditor::_notification(int p_what) { + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (is_visible_in_tree()) { + _update_libraries(); + } + } +} + +void GDNativeLibraryEditor::_bind_methods() { + + ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibraryEditor::_item_edited); +} + +GDNativeLibraryEditor::GDNativeLibraryEditor() { + libraries = memnew(Tree); + libraries->set_columns(2); + libraries->set_column_titles_visible(true); + libraries->set_column_title(0, TTR("Library")); + libraries->set_column_title(1, TTR("Status")); + libraries->set_hide_root(true); + add_margin_child(TTR("Libraries: "), libraries, true); + updating = false; + libraries->connect("item_edited", this, "_item_edited"); +} + +#endif // TOOLS_ENABLED diff --git a/modules/gdnative/gd_native_library_editor.h b/modules/gdnative/gd_native_library_editor.h new file mode 100644 index 0000000000..a11c4620dd --- /dev/null +++ b/modules/gdnative/gd_native_library_editor.h @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* gd_native_library_editor.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef GD_NATIVE_LIBRARY_EDITOR_H +#define GD_NATIVE_LIBRARY_EDITOR_H + +#ifdef TOOLS_ENABLED +#include "editor/editor_file_system.h" +#include "editor/project_settings_editor.h" + +class GDNativeLibraryEditor : public VBoxContainer { + Tree *libraries; + + bool updating; + void _update_libraries(); + + void _find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list); + void _item_edited(); + +protected: + void _notification(int p_what); + static void _bind_methods(); + +public: + GDNativeLibraryEditor(); +}; + +#endif +#endif // GD_NATIVE_LIBRARY_EDITOR_H diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 6da538844a..93a9bac11c 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -40,6 +40,16 @@ const String init_symbol = "godot_gdnative_init"; const String terminate_symbol = "godot_gdnative_terminate"; +#define GDAPI_FUNC(name, ret_type, ...) name, +#define GDAPI_FUNC_VOID(name, ...) name, + +const godot_gdnative_api_struct api_struct = { + GODOT_GDNATIVE_API_FUNCTIONS +}; + +#undef GDAPI_FUNC +#undef GDAPI_FUNC_VOID + String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = { "X11_32bit", "X11_64bit", @@ -91,7 +101,7 @@ GDNativeLibrary::Platform GDNativeLibrary::current_platform = #endif GDNativeLibrary::GDNativeLibrary() - : library_paths() { + : library_paths(), singleton_gdnative(false) { } GDNativeLibrary::~GDNativeLibrary() { @@ -249,6 +259,7 @@ bool GDNative::initialize() { godot_gdnative_init_options options; + options.api_struct = &api_struct; options.in_editor = Engine::get_singleton()->is_editor_hint(); options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE); options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR); diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 4753c7efe5..29c6201641 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -36,6 +36,7 @@ #include "resource.h" #include "gdnative/gdnative.h" +#include "gdnative_api_struct.h" class GDNativeLibrary : public Resource { GDCLASS(GDNativeLibrary, Resource) @@ -77,7 +78,7 @@ class GDNativeLibrary : public Resource { String library_paths[NUM_PLATFORMS]; - bool singleton_gdnative = false; + bool singleton_gdnative; protected: bool _set(const StringName &p_name, const Variant &p_value); diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp index b61f80b1f9..9ba4166c1d 100644 --- a/modules/gdnative/gdnative/variant.cpp +++ b/modules/gdnative/gdnative/variant.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "gdnative/variant.h" +#include "core/reference.h" #include "core/variant.h" #ifdef __cplusplus @@ -158,7 +159,21 @@ void GDAPI godot_variant_new_rid(godot_variant *r_dest, const godot_rid *p_rid) void GDAPI godot_variant_new_object(godot_variant *r_dest, const godot_object *p_obj) { Variant *dest = (Variant *)r_dest; Object *obj = (Object *)p_obj; - memnew_placement_custom(dest, Variant, Variant(obj)); + Reference *reference = Object::cast_to<Reference>(obj); + REF ref; + if (reference) { + ref = REF(reference); + } + if (!ref.is_null()) { + memnew_placement_custom(dest, Variant, Variant(ref.get_ref_ptr())); + } else { +#if defined(DEBUG_METHODS_ENABLED) + if (reference) { + ERR_PRINT("Reference object has 0 refcount in godot_variant_new_object - you lost it somewhere."); + } +#endif + memnew_placement_custom(dest, Variant, Variant(obj)); + } } void GDAPI godot_variant_new_dictionary(godot_variant *r_dest, const godot_dictionary *p_dict) { @@ -465,10 +480,9 @@ godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const g return self->hash_compare(*other); } -godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid) { +godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self) { const Variant *self = (const Variant *)p_self; - bool &valid = *r_valid; - return self->booleanize(valid); + return self->booleanize(); } void GDAPI godot_variant_destroy(godot_variant *p_self) { diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h index c574c56d5a..1c5e91d733 100644 --- a/modules/gdnative/include/gdnative/gdnative.h +++ b/modules/gdnative/include/gdnative/gdnative.h @@ -234,12 +234,15 @@ void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_obj godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error); ////// Script API +struct godot_gdnative_api_struct; // Forward declaration + typedef struct { godot_bool in_editor; uint64_t core_api_hash; uint64_t editor_api_hash; uint64_t no_api_hash; godot_object *gd_native_library; // pointer to GDNativeLibrary that is being initialized + const struct godot_gdnative_api_struct *api_struct; } godot_gdnative_init_options; typedef struct { diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index 969506585d..7b804c1eaf 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/modules/gdnative/include/gdnative/variant.h @@ -190,7 +190,7 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other); -godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid); +godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self); void GDAPI godot_variant_destroy(godot_variant *p_self); diff --git a/modules/gdnative/include/gdnative_api_struct.h b/modules/gdnative/include/gdnative_api_struct.h new file mode 100644 index 0000000000..c345e27227 --- /dev/null +++ b/modules/gdnative/include/gdnative_api_struct.h @@ -0,0 +1,723 @@ +/*************************************************************************/ +/* gdnative_api_struct.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef GODOT_GDNATIVE_API_STRUCT_H +#define GODOT_GDNATIVE_API_STRUCT_H + +#include <gdnative/gdnative.h> +#include <nativescript/godot_nativescript.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Using X_MACRO to keep api function signatures in a single list +#define GODOT_GDNATIVE_API_FUNCTIONS \ + GDAPI_FUNC_VOID(godot_color_new_rgba, godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) \ + GDAPI_FUNC_VOID(godot_color_new_rgb, godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b) \ + GDAPI_FUNC(godot_color_get_r, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_r, godot_color *p_self, const godot_real r) \ + GDAPI_FUNC(godot_color_get_g, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_g, godot_color *p_self, const godot_real g) \ + GDAPI_FUNC(godot_color_get_b, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_b, godot_color *p_self, const godot_real b) \ + GDAPI_FUNC(godot_color_get_a, godot_real, const godot_color *p_self) \ + GDAPI_FUNC_VOID(godot_color_set_a, godot_color *p_self, const godot_real a) \ + GDAPI_FUNC(godot_color_get_h, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_get_s, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_get_v, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_as_string, godot_string, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_to_rgba32, godot_int, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_to_argb32, godot_int, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_gray, godot_real, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_inverted, godot_color, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_contrasted, godot_color, const godot_color *p_self) \ + GDAPI_FUNC(godot_color_linear_interpolate, godot_color, const godot_color *p_self, const godot_color *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_color_blend, godot_color, const godot_color *p_self, const godot_color *p_over) \ + GDAPI_FUNC(godot_color_to_html, godot_string, const godot_color *p_self, const godot_bool p_with_alpha) \ + GDAPI_FUNC(godot_color_operator_equal, godot_bool, const godot_color *p_self, const godot_color *p_b) \ + GDAPI_FUNC(godot_color_operator_less, godot_bool, const godot_color *p_self, const godot_color *p_b) \ + GDAPI_FUNC_VOID(godot_vector2_new, godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) \ + GDAPI_FUNC(godot_vector2_as_string, godot_string, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_normalized, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_length, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_angle, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_length_squared, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_is_normalized, godot_bool, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_distance_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_distance_squared_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_angle_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_angle_to_point, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_vector2_linear_interpolate, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector2_cubic_interpolate, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_vector2 *p_pre_a, const godot_vector2 *p_post_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector2_rotated, godot_vector2, const godot_vector2 *p_self, const godot_real p_phi) \ + GDAPI_FUNC(godot_vector2_tangent, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_floor, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_snapped, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_by) \ + GDAPI_FUNC(godot_vector2_aspect, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_dot, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_with) \ + GDAPI_FUNC(godot_vector2_slide, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \ + GDAPI_FUNC(godot_vector2_bounce, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \ + GDAPI_FUNC(godot_vector2_reflect, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \ + GDAPI_FUNC(godot_vector2_abs, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_clamped, godot_vector2, const godot_vector2 *p_self, const godot_real p_length) \ + GDAPI_FUNC(godot_vector2_operator_add, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_substract, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_multiply_vector, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_multiply_scalar, godot_vector2, const godot_vector2 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector2_operator_divide_vector, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_divide_scalar, godot_vector2, const godot_vector2 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector2_operator_equal, godot_bool, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_less, godot_bool, const godot_vector2 *p_self, const godot_vector2 *p_b) \ + GDAPI_FUNC(godot_vector2_operator_neg, godot_vector2, const godot_vector2 *p_self) \ + GDAPI_FUNC_VOID(godot_vector2_set_x, godot_vector2 *p_self, const godot_real p_x) \ + GDAPI_FUNC_VOID(godot_vector2_set_y, godot_vector2 *p_self, const godot_real p_y) \ + GDAPI_FUNC(godot_vector2_get_x, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC(godot_vector2_get_y, godot_real, const godot_vector2 *p_self) \ + GDAPI_FUNC_VOID(godot_quat_new, godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) \ + GDAPI_FUNC_VOID(godot_quat_new_with_axis_angle, godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle) \ + GDAPI_FUNC(godot_quat_get_x, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_x, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_get_y, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_y, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_get_z, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_z, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_get_w, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_quat_set_w, godot_quat *p_self, const godot_real val) \ + GDAPI_FUNC(godot_quat_as_string, godot_string, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_length, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_length_squared, godot_real, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_normalized, godot_quat, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_is_normalized, godot_bool, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_inverse, godot_quat, const godot_quat *p_self) \ + GDAPI_FUNC(godot_quat_dot, godot_real, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_xform, godot_vector3, const godot_quat *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_quat_slerp, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_quat_slerpni, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_quat_cubic_slerp, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_quat *p_pre_a, const godot_quat *p_post_b, const godot_real p_t) \ + GDAPI_FUNC(godot_quat_operator_multiply, godot_quat, const godot_quat *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_quat_operator_add, godot_quat, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_operator_substract, godot_quat, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_operator_divide, godot_quat, const godot_quat *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_quat_operator_equal, godot_bool, const godot_quat *p_self, const godot_quat *p_b) \ + GDAPI_FUNC(godot_quat_operator_neg, godot_quat, const godot_quat *p_self) \ + GDAPI_FUNC_VOID(godot_basis_new_with_rows, godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) \ + GDAPI_FUNC_VOID(godot_basis_new_with_axis_and_angle, godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC_VOID(godot_basis_new_with_euler, godot_basis *r_dest, const godot_vector3 *p_euler) \ + GDAPI_FUNC(godot_basis_as_string, godot_string, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_inverse, godot_basis, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_transposed, godot_basis, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_orthonormalized, godot_basis, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_determinant, godot_real, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_rotated, godot_basis, const godot_basis *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC(godot_basis_scaled, godot_basis, const godot_basis *p_self, const godot_vector3 *p_scale) \ + GDAPI_FUNC(godot_basis_get_scale, godot_vector3, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_get_euler, godot_vector3, const godot_basis *p_self) \ + GDAPI_FUNC(godot_basis_tdotx, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \ + GDAPI_FUNC(godot_basis_tdoty, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \ + GDAPI_FUNC(godot_basis_tdotz, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \ + GDAPI_FUNC(godot_basis_xform, godot_vector3, const godot_basis *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_basis_xform_inv, godot_vector3, const godot_basis *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_basis_get_orthogonal_index, godot_int, const godot_basis *p_self) \ + GDAPI_FUNC_VOID(godot_basis_new, godot_basis *r_dest) \ + GDAPI_FUNC_VOID(godot_basis_new_with_euler_quat, godot_basis *r_dest, const godot_quat *p_euler) \ + GDAPI_FUNC_VOID(godot_basis_get_elements, godot_basis *p_self, godot_vector3 *p_elements) \ + GDAPI_FUNC(godot_basis_get_axis, godot_vector3, const godot_basis *p_self, const godot_int p_axis) \ + GDAPI_FUNC_VOID(godot_basis_set_axis, godot_basis *p_self, const godot_int p_axis, const godot_vector3 *p_value) \ + GDAPI_FUNC(godot_basis_get_row, godot_vector3, const godot_basis *p_self, const godot_int p_row) \ + GDAPI_FUNC_VOID(godot_basis_set_row, godot_basis *p_self, const godot_int p_row, const godot_vector3 *p_value) \ + GDAPI_FUNC(godot_basis_operator_equal, godot_bool, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_add, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_substract, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_multiply_vector, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \ + GDAPI_FUNC(godot_basis_operator_multiply_scalar, godot_basis, const godot_basis *p_self, const godot_real p_b) \ + GDAPI_FUNC_VOID(godot_vector3_new, godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) \ + GDAPI_FUNC(godot_vector3_as_string, godot_string, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_min_axis, godot_int, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_max_axis, godot_int, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_length, godot_real, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_length_squared, godot_real, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_is_normalized, godot_bool, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_normalized, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_inverse, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_snapped, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_by) \ + GDAPI_FUNC(godot_vector3_rotated, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC(godot_vector3_linear_interpolate, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector3_cubic_interpolate, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_vector3 *p_pre_a, const godot_vector3 *p_post_b, const godot_real p_t) \ + GDAPI_FUNC(godot_vector3_dot, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_cross, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_outer, godot_basis, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_to_diagonal_matrix, godot_basis, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_abs, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_floor, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_ceil, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC(godot_vector3_distance_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_distance_squared_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_angle_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_to) \ + GDAPI_FUNC(godot_vector3_slide, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \ + GDAPI_FUNC(godot_vector3_bounce, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \ + GDAPI_FUNC(godot_vector3_reflect, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \ + GDAPI_FUNC(godot_vector3_operator_add, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_substract, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_multiply_vector, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_multiply_scalar, godot_vector3, const godot_vector3 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector3_operator_divide_vector, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_divide_scalar, godot_vector3, const godot_vector3 *p_self, const godot_real p_b) \ + GDAPI_FUNC(godot_vector3_operator_equal, godot_bool, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_less, godot_bool, const godot_vector3 *p_self, const godot_vector3 *p_b) \ + GDAPI_FUNC(godot_vector3_operator_neg, godot_vector3, const godot_vector3 *p_self) \ + GDAPI_FUNC_VOID(godot_vector3_set_axis, godot_vector3 *p_self, const godot_vector3_axis p_axis, const godot_real p_val) \ + GDAPI_FUNC(godot_vector3_get_axis, godot_real, const godot_vector3 *p_self, const godot_vector3_axis p_axis) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_new, godot_pool_byte_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_new_copy, godot_pool_byte_array *r_dest, const godot_pool_byte_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_new_with_array, godot_pool_byte_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_append, godot_pool_byte_array *p_self, const uint8_t p_data) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_append_array, godot_pool_byte_array *p_self, const godot_pool_byte_array *p_array) \ + GDAPI_FUNC(godot_pool_byte_array_insert, godot_error, godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_invert, godot_pool_byte_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_push_back, godot_pool_byte_array *p_self, const uint8_t p_data) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_remove, godot_pool_byte_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_resize, godot_pool_byte_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_set, godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) \ + GDAPI_FUNC(godot_pool_byte_array_get, uint8_t, const godot_pool_byte_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_byte_array_size, godot_int, const godot_pool_byte_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_byte_array_destroy, godot_pool_byte_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_int_array_new, godot_pool_int_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_int_array_new_copy, godot_pool_int_array *r_dest, const godot_pool_int_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_int_array_new_with_array, godot_pool_int_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_int_array_append, godot_pool_int_array *p_self, const godot_int p_data) \ + GDAPI_FUNC_VOID(godot_pool_int_array_append_array, godot_pool_int_array *p_self, const godot_pool_int_array *p_array) \ + GDAPI_FUNC(godot_pool_int_array_insert, godot_error, godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) \ + GDAPI_FUNC_VOID(godot_pool_int_array_invert, godot_pool_int_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_int_array_push_back, godot_pool_int_array *p_self, const godot_int p_data) \ + GDAPI_FUNC_VOID(godot_pool_int_array_remove, godot_pool_int_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_int_array_resize, godot_pool_int_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_int_array_set, godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) \ + GDAPI_FUNC(godot_pool_int_array_get, godot_int, const godot_pool_int_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_int_array_size, godot_int, const godot_pool_int_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_int_array_destroy, godot_pool_int_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_real_array_new, godot_pool_real_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_real_array_new_copy, godot_pool_real_array *r_dest, const godot_pool_real_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_real_array_new_with_array, godot_pool_real_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_real_array_append, godot_pool_real_array *p_self, const godot_real p_data) \ + GDAPI_FUNC_VOID(godot_pool_real_array_append_array, godot_pool_real_array *p_self, const godot_pool_real_array *p_array) \ + GDAPI_FUNC(godot_pool_real_array_insert, godot_error, godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) \ + GDAPI_FUNC_VOID(godot_pool_real_array_invert, godot_pool_real_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_real_array_push_back, godot_pool_real_array *p_self, const godot_real p_data) \ + GDAPI_FUNC_VOID(godot_pool_real_array_remove, godot_pool_real_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_real_array_resize, godot_pool_real_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_real_array_set, godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) \ + GDAPI_FUNC(godot_pool_real_array_get, godot_real, const godot_pool_real_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_real_array_size, godot_int, const godot_pool_real_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_real_array_destroy, godot_pool_real_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_string_array_new, godot_pool_string_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_string_array_new_copy, godot_pool_string_array *r_dest, const godot_pool_string_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_string_array_new_with_array, godot_pool_string_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_string_array_append, godot_pool_string_array *p_self, const godot_string *p_data) \ + GDAPI_FUNC_VOID(godot_pool_string_array_append_array, godot_pool_string_array *p_self, const godot_pool_string_array *p_array) \ + GDAPI_FUNC(godot_pool_string_array_insert, godot_error, godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) \ + GDAPI_FUNC_VOID(godot_pool_string_array_invert, godot_pool_string_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_string_array_push_back, godot_pool_string_array *p_self, const godot_string *p_data) \ + GDAPI_FUNC_VOID(godot_pool_string_array_remove, godot_pool_string_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_string_array_resize, godot_pool_string_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_string_array_set, godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) \ + GDAPI_FUNC(godot_pool_string_array_get, godot_string, const godot_pool_string_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_string_array_size, godot_int, const godot_pool_string_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_string_array_destroy, godot_pool_string_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_new, godot_pool_vector2_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_new_copy, godot_pool_vector2_array *r_dest, const godot_pool_vector2_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_new_with_array, godot_pool_vector2_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_append, godot_pool_vector2_array *p_self, const godot_vector2 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_append_array, godot_pool_vector2_array *p_self, const godot_pool_vector2_array *p_array) \ + GDAPI_FUNC(godot_pool_vector2_array_insert, godot_error, godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_invert, godot_pool_vector2_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_push_back, godot_pool_vector2_array *p_self, const godot_vector2 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_remove, godot_pool_vector2_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_resize, godot_pool_vector2_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_set, godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) \ + GDAPI_FUNC(godot_pool_vector2_array_get, godot_vector2, const godot_pool_vector2_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_vector2_array_size, godot_int, const godot_pool_vector2_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector2_array_destroy, godot_pool_vector2_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_new, godot_pool_vector3_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_new_copy, godot_pool_vector3_array *r_dest, const godot_pool_vector3_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_new_with_array, godot_pool_vector3_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_append, godot_pool_vector3_array *p_self, const godot_vector3 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_append_array, godot_pool_vector3_array *p_self, const godot_pool_vector3_array *p_array) \ + GDAPI_FUNC(godot_pool_vector3_array_insert, godot_error, godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_invert, godot_pool_vector3_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_push_back, godot_pool_vector3_array *p_self, const godot_vector3 *p_data) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_remove, godot_pool_vector3_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_resize, godot_pool_vector3_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_set, godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) \ + GDAPI_FUNC(godot_pool_vector3_array_get, godot_vector3, const godot_pool_vector3_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_vector3_array_size, godot_int, const godot_pool_vector3_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_vector3_array_destroy, godot_pool_vector3_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_color_array_new, godot_pool_color_array *r_dest) \ + GDAPI_FUNC_VOID(godot_pool_color_array_new_copy, godot_pool_color_array *r_dest, const godot_pool_color_array *p_src) \ + GDAPI_FUNC_VOID(godot_pool_color_array_new_with_array, godot_pool_color_array *r_dest, const godot_array *p_a) \ + GDAPI_FUNC_VOID(godot_pool_color_array_append, godot_pool_color_array *p_self, const godot_color *p_data) \ + GDAPI_FUNC_VOID(godot_pool_color_array_append_array, godot_pool_color_array *p_self, const godot_pool_color_array *p_array) \ + GDAPI_FUNC(godot_pool_color_array_insert, godot_error, godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) \ + GDAPI_FUNC_VOID(godot_pool_color_array_invert, godot_pool_color_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_color_array_push_back, godot_pool_color_array *p_self, const godot_color *p_data) \ + GDAPI_FUNC_VOID(godot_pool_color_array_remove, godot_pool_color_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_pool_color_array_resize, godot_pool_color_array *p_self, const godot_int p_size) \ + GDAPI_FUNC_VOID(godot_pool_color_array_set, godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) \ + GDAPI_FUNC(godot_pool_color_array_get, godot_color, const godot_pool_color_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_pool_color_array_size, godot_int, const godot_pool_color_array *p_self) \ + GDAPI_FUNC_VOID(godot_pool_color_array_destroy, godot_pool_color_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_new, godot_array *r_dest) \ + GDAPI_FUNC_VOID(godot_array_new_copy, godot_array *r_dest, const godot_array *p_src) \ + GDAPI_FUNC_VOID(godot_array_new_pool_color_array, godot_array *r_dest, const godot_pool_color_array *p_pca) \ + GDAPI_FUNC_VOID(godot_array_new_pool_vector3_array, godot_array *r_dest, const godot_pool_vector3_array *p_pv3a) \ + GDAPI_FUNC_VOID(godot_array_new_pool_vector2_array, godot_array *r_dest, const godot_pool_vector2_array *p_pv2a) \ + GDAPI_FUNC_VOID(godot_array_new_pool_string_array, godot_array *r_dest, const godot_pool_string_array *p_psa) \ + GDAPI_FUNC_VOID(godot_array_new_pool_real_array, godot_array *r_dest, const godot_pool_real_array *p_pra) \ + GDAPI_FUNC_VOID(godot_array_new_pool_int_array, godot_array *r_dest, const godot_pool_int_array *p_pia) \ + GDAPI_FUNC_VOID(godot_array_new_pool_byte_array, godot_array *r_dest, const godot_pool_byte_array *p_pba) \ + GDAPI_FUNC_VOID(godot_array_set, godot_array *p_self, const godot_int p_idx, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_get, godot_variant, const godot_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_array_operator_index, godot_variant *, godot_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_array_append, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_clear, godot_array *p_self) \ + GDAPI_FUNC(godot_array_count, godot_int, const godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_empty, godot_bool, const godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_erase, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_front, godot_variant, const godot_array *p_self) \ + GDAPI_FUNC(godot_array_back, godot_variant, const godot_array *p_self) \ + GDAPI_FUNC(godot_array_find, godot_int, const godot_array *p_self, const godot_variant *p_what, const godot_int p_from) \ + GDAPI_FUNC(godot_array_find_last, godot_int, const godot_array *p_self, const godot_variant *p_what) \ + GDAPI_FUNC(godot_array_has, godot_bool, const godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC(godot_array_hash, godot_int, const godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_insert, godot_array *p_self, const godot_int p_pos, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_invert, godot_array *p_self) \ + GDAPI_FUNC(godot_array_pop_back, godot_variant, godot_array *p_self) \ + GDAPI_FUNC(godot_array_pop_front, godot_variant, godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_push_back, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_push_front, godot_array *p_self, const godot_variant *p_value) \ + GDAPI_FUNC_VOID(godot_array_remove, godot_array *p_self, const godot_int p_idx) \ + GDAPI_FUNC_VOID(godot_array_resize, godot_array *p_self, const godot_int p_size) \ + GDAPI_FUNC(godot_array_rfind, godot_int, const godot_array *p_self, const godot_variant *p_what, const godot_int p_from) \ + GDAPI_FUNC(godot_array_size, godot_int, const godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_sort, godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_array_sort_custom, godot_array *p_self, godot_object *p_obj, const godot_string *p_func) \ + GDAPI_FUNC_VOID(godot_array_destroy, godot_array *p_self) \ + GDAPI_FUNC_VOID(godot_dictionary_new, godot_dictionary *r_dest) \ + GDAPI_FUNC_VOID(godot_dictionary_new_copy, godot_dictionary *r_dest, const godot_dictionary *p_src) \ + GDAPI_FUNC_VOID(godot_dictionary_destroy, godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_size, godot_int, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_empty, godot_bool, const godot_dictionary *p_self) \ + GDAPI_FUNC_VOID(godot_dictionary_clear, godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_has, godot_bool, const godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_has_all, godot_bool, const godot_dictionary *p_self, const godot_array *p_keys) \ + GDAPI_FUNC_VOID(godot_dictionary_erase, godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_hash, godot_int, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_keys, godot_array, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_values, godot_array, const godot_dictionary *p_self) \ + GDAPI_FUNC(godot_dictionary_get, godot_variant, const godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC_VOID(godot_dictionary_set, godot_dictionary *p_self, const godot_variant *p_key, const godot_variant *p_value) \ + GDAPI_FUNC(godot_dictionary_operator_index, godot_variant *, godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_next, godot_variant *, const godot_dictionary *p_self, const godot_variant *p_key) \ + GDAPI_FUNC(godot_dictionary_operator_equal, godot_bool, const godot_dictionary *p_self, const godot_dictionary *p_b) \ + GDAPI_FUNC(godot_dictionary_to_json, godot_string, const godot_dictionary *p_self) \ + GDAPI_FUNC_VOID(godot_node_path_new, godot_node_path *r_dest, const godot_string *p_from) \ + GDAPI_FUNC_VOID(godot_node_path_new_copy, godot_node_path *r_dest, const godot_node_path *p_src) \ + GDAPI_FUNC_VOID(godot_node_path_destroy, godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_as_string, godot_string, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_is_absolute, godot_bool, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_get_name_count, godot_int, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_get_name, godot_string, const godot_node_path *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_node_path_get_subname_count, godot_int, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_get_subname, godot_string, const godot_node_path *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_node_path_get_property, godot_string, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_is_empty, godot_bool, const godot_node_path *p_self) \ + GDAPI_FUNC(godot_node_path_operator_equal, godot_bool, const godot_node_path *p_self, const godot_node_path *p_b) \ + GDAPI_FUNC_VOID(godot_plane_new_with_reals, godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) \ + GDAPI_FUNC_VOID(godot_plane_new_with_vectors, godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3) \ + GDAPI_FUNC_VOID(godot_plane_new_with_normal, godot_plane *r_dest, const godot_vector3 *p_normal, const godot_real p_d) \ + GDAPI_FUNC(godot_plane_as_string, godot_string, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_normalized, godot_plane, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_center, godot_vector3, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_get_any_point, godot_vector3, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_is_point_over, godot_bool, const godot_plane *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_plane_distance_to, godot_real, const godot_plane *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_plane_has_point, godot_bool, const godot_plane *p_self, const godot_vector3 *p_point, const godot_real p_epsilon) \ + GDAPI_FUNC(godot_plane_project, godot_vector3, const godot_plane *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_plane_intersect_3, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_plane *p_b, const godot_plane *p_c) \ + GDAPI_FUNC(godot_plane_intersects_ray, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_vector3 *p_from, const godot_vector3 *p_dir) \ + GDAPI_FUNC(godot_plane_intersects_segment, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_vector3 *p_begin, const godot_vector3 *p_end) \ + GDAPI_FUNC(godot_plane_operator_neg, godot_plane, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_operator_equal, godot_bool, const godot_plane *p_self, const godot_plane *p_b) \ + GDAPI_FUNC_VOID(godot_plane_set_normal, godot_plane *p_self, const godot_vector3 *p_normal) \ + GDAPI_FUNC(godot_plane_get_normal, godot_vector3, const godot_plane *p_self) \ + GDAPI_FUNC(godot_plane_get_d, godot_real, const godot_plane *p_self) \ + GDAPI_FUNC_VOID(godot_plane_set_d, godot_plane *p_self, const godot_real p_d) \ + GDAPI_FUNC_VOID(godot_rect2_new_with_position_and_size, godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) \ + GDAPI_FUNC_VOID(godot_rect2_new, godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height) \ + GDAPI_FUNC(godot_rect2_as_string, godot_string, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_get_area, godot_real, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_intersects, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_encloses, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_has_no_area, godot_bool, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_clip, godot_rect2, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_merge, godot_rect2, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_has_point, godot_bool, const godot_rect2 *p_self, const godot_vector2 *p_point) \ + GDAPI_FUNC(godot_rect2_grow, godot_rect2, const godot_rect2 *p_self, const godot_real p_by) \ + GDAPI_FUNC(godot_rect2_expand, godot_rect2, const godot_rect2 *p_self, const godot_vector2 *p_to) \ + GDAPI_FUNC(godot_rect2_operator_equal, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \ + GDAPI_FUNC(godot_rect2_get_position, godot_vector2, const godot_rect2 *p_self) \ + GDAPI_FUNC(godot_rect2_get_size, godot_vector2, const godot_rect2 *p_self) \ + GDAPI_FUNC_VOID(godot_rect2_set_position, godot_rect2 *p_self, const godot_vector2 *p_pos) \ + GDAPI_FUNC_VOID(godot_rect2_set_size, godot_rect2 *p_self, const godot_vector2 *p_size) \ + GDAPI_FUNC_VOID(godot_rect3_new, godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) \ + GDAPI_FUNC(godot_rect3_get_position, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC_VOID(godot_rect3_set_position, const godot_rect3 *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_rect3_get_size, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC_VOID(godot_rect3_set_size, const godot_rect3 *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_rect3_as_string, godot_string, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_area, godot_real, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_has_no_area, godot_bool, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_has_no_surface, godot_bool, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_intersects, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_encloses, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_merge, godot_rect3, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_intersection, godot_rect3, const godot_rect3 *p_self, const godot_rect3 *p_with) \ + GDAPI_FUNC(godot_rect3_intersects_plane, godot_bool, const godot_rect3 *p_self, const godot_plane *p_plane) \ + GDAPI_FUNC(godot_rect3_intersects_segment, godot_bool, const godot_rect3 *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to) \ + GDAPI_FUNC(godot_rect3_has_point, godot_bool, const godot_rect3 *p_self, const godot_vector3 *p_point) \ + GDAPI_FUNC(godot_rect3_get_support, godot_vector3, const godot_rect3 *p_self, const godot_vector3 *p_dir) \ + GDAPI_FUNC(godot_rect3_get_longest_axis, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_longest_axis_index, godot_int, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_longest_axis_size, godot_real, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_shortest_axis, godot_vector3, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_shortest_axis_index, godot_int, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_get_shortest_axis_size, godot_real, const godot_rect3 *p_self) \ + GDAPI_FUNC(godot_rect3_expand, godot_rect3, const godot_rect3 *p_self, const godot_vector3 *p_to_point) \ + GDAPI_FUNC(godot_rect3_grow, godot_rect3, const godot_rect3 *p_self, const godot_real p_by) \ + GDAPI_FUNC(godot_rect3_get_endpoint, godot_vector3, const godot_rect3 *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_rect3_operator_equal, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_b) \ + GDAPI_FUNC_VOID(godot_rid_new, godot_rid *r_dest) \ + GDAPI_FUNC(godot_rid_get_id, godot_int, const godot_rid *p_self) \ + GDAPI_FUNC_VOID(godot_rid_new_with_resource, godot_rid *r_dest, const godot_object *p_from) \ + GDAPI_FUNC(godot_rid_operator_equal, godot_bool, const godot_rid *p_self, const godot_rid *p_b) \ + GDAPI_FUNC(godot_rid_operator_less, godot_bool, const godot_rid *p_self, const godot_rid *p_b) \ + GDAPI_FUNC_VOID(godot_transform_new_with_axis_origin, godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) \ + GDAPI_FUNC_VOID(godot_transform_new, godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin) \ + GDAPI_FUNC(godot_transform_get_basis, godot_basis, const godot_transform *p_self) \ + GDAPI_FUNC_VOID(godot_transform_set_basis, godot_transform *p_self, godot_basis *p_v) \ + GDAPI_FUNC(godot_transform_get_origin, godot_vector3, const godot_transform *p_self) \ + GDAPI_FUNC_VOID(godot_transform_set_origin, godot_transform *p_self, godot_vector3 *p_v) \ + GDAPI_FUNC(godot_transform_as_string, godot_string, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_inverse, godot_transform, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_affine_inverse, godot_transform, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_orthonormalized, godot_transform, const godot_transform *p_self) \ + GDAPI_FUNC(godot_transform_rotated, godot_transform, const godot_transform *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \ + GDAPI_FUNC(godot_transform_scaled, godot_transform, const godot_transform *p_self, const godot_vector3 *p_scale) \ + GDAPI_FUNC(godot_transform_translated, godot_transform, const godot_transform *p_self, const godot_vector3 *p_ofs) \ + GDAPI_FUNC(godot_transform_looking_at, godot_transform, const godot_transform *p_self, const godot_vector3 *p_target, const godot_vector3 *p_up) \ + GDAPI_FUNC(godot_transform_xform_plane, godot_plane, const godot_transform *p_self, const godot_plane *p_v) \ + GDAPI_FUNC(godot_transform_xform_inv_plane, godot_plane, const godot_transform *p_self, const godot_plane *p_v) \ + GDAPI_FUNC_VOID(godot_transform_new_identity, godot_transform *r_dest) \ + GDAPI_FUNC(godot_transform_operator_equal, godot_bool, const godot_transform *p_self, const godot_transform *p_b) \ + GDAPI_FUNC(godot_transform_operator_multiply, godot_transform, const godot_transform *p_self, const godot_transform *p_b) \ + GDAPI_FUNC(godot_transform_xform_vector3, godot_vector3, const godot_transform *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_transform_xform_inv_vector3, godot_vector3, const godot_transform *p_self, const godot_vector3 *p_v) \ + GDAPI_FUNC(godot_transform_xform_rect3, godot_rect3, const godot_transform *p_self, const godot_rect3 *p_v) \ + GDAPI_FUNC(godot_transform_xform_inv_rect3, godot_rect3, const godot_transform *p_self, const godot_rect3 *p_v) \ + GDAPI_FUNC_VOID(godot_transform2d_new, godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) \ + GDAPI_FUNC_VOID(godot_transform2d_new_axis_origin, godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin) \ + GDAPI_FUNC(godot_transform2d_as_string, godot_string, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_inverse, godot_transform2d, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_affine_inverse, godot_transform2d, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_get_rotation, godot_real, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_get_origin, godot_vector2, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_get_scale, godot_vector2, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_orthonormalized, godot_transform2d, const godot_transform2d *p_self) \ + GDAPI_FUNC(godot_transform2d_rotated, godot_transform2d, const godot_transform2d *p_self, const godot_real p_phi) \ + GDAPI_FUNC(godot_transform2d_scaled, godot_transform2d, const godot_transform2d *p_self, const godot_vector2 *p_scale) \ + GDAPI_FUNC(godot_transform2d_translated, godot_transform2d, const godot_transform2d *p_self, const godot_vector2 *p_offset) \ + GDAPI_FUNC(godot_transform2d_xform_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_xform_inv_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_basis_xform_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_basis_xform_inv_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \ + GDAPI_FUNC(godot_transform2d_interpolate_with, godot_transform2d, const godot_transform2d *p_self, const godot_transform2d *p_m, const godot_real p_c) \ + GDAPI_FUNC(godot_transform2d_operator_equal, godot_bool, const godot_transform2d *p_self, const godot_transform2d *p_b) \ + GDAPI_FUNC(godot_transform2d_operator_multiply, godot_transform2d, const godot_transform2d *p_self, const godot_transform2d *p_b) \ + GDAPI_FUNC_VOID(godot_transform2d_new_identity, godot_transform2d *r_dest) \ + GDAPI_FUNC(godot_transform2d_xform_rect2, godot_rect2, const godot_transform2d *p_self, const godot_rect2 *p_v) \ + GDAPI_FUNC(godot_transform2d_xform_inv_rect2, godot_rect2, const godot_transform2d *p_self, const godot_rect2 *p_v) \ + GDAPI_FUNC(godot_variant_get_type, godot_variant_type, const godot_variant *p_v) \ + GDAPI_FUNC_VOID(godot_variant_new_copy, godot_variant *r_dest, const godot_variant *p_src) \ + GDAPI_FUNC_VOID(godot_variant_new_nil, godot_variant *r_dest) \ + GDAPI_FUNC_VOID(godot_variant_new_bool, godot_variant *p_v, const godot_bool p_b) \ + GDAPI_FUNC_VOID(godot_variant_new_uint, godot_variant *r_dest, const uint64_t p_i) \ + GDAPI_FUNC_VOID(godot_variant_new_int, godot_variant *r_dest, const int64_t p_i) \ + GDAPI_FUNC_VOID(godot_variant_new_real, godot_variant *r_dest, const double p_r) \ + GDAPI_FUNC_VOID(godot_variant_new_string, godot_variant *r_dest, const godot_string *p_s) \ + GDAPI_FUNC_VOID(godot_variant_new_vector2, godot_variant *r_dest, const godot_vector2 *p_v2) \ + GDAPI_FUNC_VOID(godot_variant_new_rect2, godot_variant *r_dest, const godot_rect2 *p_rect2) \ + GDAPI_FUNC_VOID(godot_variant_new_vector3, godot_variant *r_dest, const godot_vector3 *p_v3) \ + GDAPI_FUNC_VOID(godot_variant_new_transform2d, godot_variant *r_dest, const godot_transform2d *p_t2d) \ + GDAPI_FUNC_VOID(godot_variant_new_plane, godot_variant *r_dest, const godot_plane *p_plane) \ + GDAPI_FUNC_VOID(godot_variant_new_quat, godot_variant *r_dest, const godot_quat *p_quat) \ + GDAPI_FUNC_VOID(godot_variant_new_rect3, godot_variant *r_dest, const godot_rect3 *p_rect3) \ + GDAPI_FUNC_VOID(godot_variant_new_basis, godot_variant *r_dest, const godot_basis *p_basis) \ + GDAPI_FUNC_VOID(godot_variant_new_transform, godot_variant *r_dest, const godot_transform *p_trans) \ + GDAPI_FUNC_VOID(godot_variant_new_color, godot_variant *r_dest, const godot_color *p_color) \ + GDAPI_FUNC_VOID(godot_variant_new_node_path, godot_variant *r_dest, const godot_node_path *p_np) \ + GDAPI_FUNC_VOID(godot_variant_new_rid, godot_variant *r_dest, const godot_rid *p_rid) \ + GDAPI_FUNC_VOID(godot_variant_new_object, godot_variant *r_dest, const godot_object *p_obj) \ + GDAPI_FUNC_VOID(godot_variant_new_dictionary, godot_variant *r_dest, const godot_dictionary *p_dict) \ + GDAPI_FUNC_VOID(godot_variant_new_array, godot_variant *r_dest, const godot_array *p_arr) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_byte_array, godot_variant *r_dest, const godot_pool_byte_array *p_pba) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_int_array, godot_variant *r_dest, const godot_pool_int_array *p_pia) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_real_array, godot_variant *r_dest, const godot_pool_real_array *p_pra) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_string_array, godot_variant *r_dest, const godot_pool_string_array *p_psa) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_vector2_array, godot_variant *r_dest, const godot_pool_vector2_array *p_pv2a) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_vector3_array, godot_variant *r_dest, const godot_pool_vector3_array *p_pv3a) \ + GDAPI_FUNC_VOID(godot_variant_new_pool_color_array, godot_variant *r_dest, const godot_pool_color_array *p_pca) \ + GDAPI_FUNC(godot_variant_as_bool, godot_bool, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_uint, uint64_t, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_int, int64_t, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_real, double, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_string, godot_string, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_vector2, godot_vector2, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_rect2, godot_rect2, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_vector3, godot_vector3, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_transform2d, godot_transform2d, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_plane, godot_plane, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_quat, godot_quat, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_rect3, godot_rect3, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_basis, godot_basis, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_transform, godot_transform, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_color, godot_color, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_node_path, godot_node_path, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_rid, godot_rid, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_object, godot_object *, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_dictionary, godot_dictionary, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_array, godot_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_byte_array, godot_pool_byte_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_int_array, godot_pool_int_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_real_array, godot_pool_real_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_string_array, godot_pool_string_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_vector2_array, godot_pool_vector2_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_vector3_array, godot_pool_vector3_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_as_pool_color_array, godot_pool_color_array, const godot_variant *p_self) \ + GDAPI_FUNC(godot_variant_call, godot_variant, godot_variant *p_self, const godot_string *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant_call_error *r_error) \ + GDAPI_FUNC(godot_variant_has_method, godot_bool, const godot_variant *p_self, const godot_string *p_method) \ + GDAPI_FUNC(godot_variant_operator_equal, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \ + GDAPI_FUNC(godot_variant_operator_less, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \ + GDAPI_FUNC(godot_variant_hash_compare, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \ + GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self) \ + GDAPI_FUNC_VOID(godot_variant_destroy, godot_variant *p_self) \ + GDAPI_FUNC_VOID(godot_string_new, godot_string *r_dest) \ + GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src) \ + GDAPI_FUNC_VOID(godot_string_new_data, godot_string *r_dest, const char *p_contents, const int p_size) \ + GDAPI_FUNC_VOID(godot_string_new_unicode_data, godot_string *r_dest, const wchar_t *p_contents, const int p_size) \ + GDAPI_FUNC_VOID(godot_string_get_data, const godot_string *p_self, char *p_dest, int *p_size) \ + GDAPI_FUNC(godot_string_operator_index, wchar_t *, godot_string *p_self, const godot_int p_idx) \ + GDAPI_FUNC(godot_string_c_str, const char *, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_unicode_str, const wchar_t *, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_operator_equal, godot_bool, const godot_string *p_self, const godot_string *p_b) \ + GDAPI_FUNC(godot_string_operator_less, godot_bool, const godot_string *p_self, const godot_string *p_b) \ + GDAPI_FUNC(godot_string_operator_plus, godot_string, const godot_string *p_self, const godot_string *p_b) \ + GDAPI_FUNC(godot_string_length, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_begins_with, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_begins_with_char_array, godot_bool, const godot_string *p_self, const char *p_char_array) \ + GDAPI_FUNC(godot_string_bigrams, godot_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_chr, godot_string, wchar_t p_character) \ + GDAPI_FUNC(godot_string_ends_with, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_find, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_find_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_findmk, godot_int, const godot_string *p_self, const godot_array *p_keys) \ + GDAPI_FUNC(godot_string_findmk_from, godot_int, const godot_string *p_self, const godot_array *p_keys, godot_int p_from) \ + GDAPI_FUNC(godot_string_findmk_from_in_place, godot_int, const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key) \ + GDAPI_FUNC(godot_string_findn, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_findn_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_find_last, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_format, godot_string, const godot_string *p_self, const godot_variant *p_values) \ + GDAPI_FUNC(godot_string_format_with_custom_placeholder, godot_string, const godot_string *p_self, const godot_variant *p_values, const char *p_placeholder) \ + GDAPI_FUNC(godot_string_hex_encode_buffer, godot_string, const uint8_t *p_buffer, godot_int p_len) \ + GDAPI_FUNC(godot_string_hex_to_int, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hex_to_int_without_prefix, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_insert, godot_string, const godot_string *p_self, godot_int p_at_pos, godot_string p_string) \ + GDAPI_FUNC(godot_string_is_numeric, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_subsequence_of, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_is_subsequence_ofi, godot_bool, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_lpad, godot_string, const godot_string *p_self, godot_int p_min_length) \ + GDAPI_FUNC(godot_string_lpad_with_custom_character, godot_string, const godot_string *p_self, godot_int p_min_length, const godot_string *p_character) \ + GDAPI_FUNC(godot_string_match, godot_bool, const godot_string *p_self, const godot_string *p_wildcard) \ + GDAPI_FUNC(godot_string_matchn, godot_bool, const godot_string *p_self, const godot_string *p_wildcard) \ + GDAPI_FUNC(godot_string_md5, godot_string, const uint8_t *p_md5) \ + GDAPI_FUNC(godot_string_num, godot_string, double p_num) \ + GDAPI_FUNC(godot_string_num_int64, godot_string, int64_t p_num, godot_int p_base) \ + GDAPI_FUNC(godot_string_num_int64_capitalized, godot_string, int64_t p_num, godot_int p_base, godot_bool p_capitalize_hex) \ + GDAPI_FUNC(godot_string_num_real, godot_string, double p_num) \ + GDAPI_FUNC(godot_string_num_scientific, godot_string, double p_num) \ + GDAPI_FUNC(godot_string_num_with_decimals, godot_string, double p_num, godot_int p_decimals) \ + GDAPI_FUNC(godot_string_pad_decimals, godot_string, const godot_string *p_self, godot_int p_digits) \ + GDAPI_FUNC(godot_string_pad_zeros, godot_string, const godot_string *p_self, godot_int p_digits) \ + GDAPI_FUNC(godot_string_replace_first, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \ + GDAPI_FUNC(godot_string_replace, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \ + GDAPI_FUNC(godot_string_replacen, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \ + GDAPI_FUNC(godot_string_rfind, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_rfindn, godot_int, const godot_string *p_self, godot_string p_what) \ + GDAPI_FUNC(godot_string_rfind_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_rfindn_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \ + GDAPI_FUNC(godot_string_rpad, godot_string, const godot_string *p_self, godot_int p_min_length) \ + GDAPI_FUNC(godot_string_rpad_with_custom_character, godot_string, const godot_string *p_self, godot_int p_min_length, const godot_string *p_character) \ + GDAPI_FUNC(godot_string_similarity, godot_real, const godot_string *p_self, const godot_string *p_string) \ + GDAPI_FUNC(godot_string_sprintf, godot_string, const godot_string *p_self, const godot_array *p_values, godot_bool *p_error) \ + GDAPI_FUNC(godot_string_substr, godot_string, const godot_string *p_self, godot_int p_from, godot_int p_chars) \ + GDAPI_FUNC(godot_string_to_double, double, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_float, godot_real, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_int, godot_int, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_camelcase_to_underscore, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_camelcase_to_underscore_lowercased, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_capitalize, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_char_to_double, double, const char *p_what) \ + GDAPI_FUNC(godot_string_char_to_int, godot_int, const char *p_what) \ + GDAPI_FUNC(godot_string_wchar_to_int, int64_t, const wchar_t *p_str) \ + GDAPI_FUNC(godot_string_char_to_int_with_len, godot_int, const char *p_what, godot_int p_len) \ + GDAPI_FUNC(godot_string_char_to_int64_with_len, int64_t, const wchar_t *p_str, int p_len) \ + GDAPI_FUNC(godot_string_hex_to_int64, int64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hex_to_int64_with_prefix, int64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_int64, int64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_unicode_char_to_double, double, const wchar_t *p_str, const wchar_t **r_end) \ + GDAPI_FUNC(godot_string_get_slice_count, godot_int, const godot_string *p_self, godot_string p_splitter) \ + GDAPI_FUNC(godot_string_get_slice, godot_string, const godot_string *p_self, godot_string p_splitter, godot_int p_slice) \ + GDAPI_FUNC(godot_string_get_slicec, godot_string, const godot_string *p_self, wchar_t p_splitter, godot_int p_slice) \ + GDAPI_FUNC(godot_string_split, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_allow_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_floats, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_floats_allows_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_floats_mk, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_floats_mk_allows_empty, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_ints, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_ints_allows_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \ + GDAPI_FUNC(godot_string_split_ints_mk, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_ints_mk_allows_empty, godot_array, const godot_string *p_self, const godot_array *p_splitters) \ + GDAPI_FUNC(godot_string_split_spaces, godot_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_char_lowercase, wchar_t, wchar_t p_char) \ + GDAPI_FUNC(godot_string_char_uppercase, wchar_t, wchar_t p_char) \ + GDAPI_FUNC(godot_string_to_lower, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_to_upper, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_basename, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_extension, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_left, godot_string, const godot_string *p_self, godot_int p_pos) \ + GDAPI_FUNC(godot_string_ord_at, wchar_t, const godot_string *p_self, godot_int p_idx) \ + GDAPI_FUNC(godot_string_plus_file, godot_string, const godot_string *p_self, const godot_string *p_file) \ + GDAPI_FUNC(godot_string_right, godot_string, const godot_string *p_self, godot_int p_pos) \ + GDAPI_FUNC(godot_string_strip_edges, godot_string, const godot_string *p_self, godot_bool p_left, godot_bool p_right) \ + GDAPI_FUNC(godot_string_strip_escapes, godot_string, const godot_string *p_self) \ + GDAPI_FUNC_VOID(godot_string_erase, godot_string *p_self, godot_int p_pos, godot_int p_chars) \ + GDAPI_FUNC_VOID(godot_string_ascii, godot_string *p_self, char *result) \ + GDAPI_FUNC_VOID(godot_string_ascii_extended, godot_string *p_self, char *result) \ + GDAPI_FUNC_VOID(godot_string_utf8, godot_string *p_self, char *result) \ + GDAPI_FUNC(godot_string_parse_utf8, godot_bool, godot_string *p_self, const char *p_utf8) \ + GDAPI_FUNC(godot_string_parse_utf8_with_len, godot_bool, godot_string *p_self, const char *p_utf8, godot_int p_len) \ + GDAPI_FUNC(godot_string_chars_to_utf8, godot_string, const char *p_utf8) \ + GDAPI_FUNC(godot_string_chars_to_utf8_with_len, godot_string, const char *p_utf8, godot_int p_len) \ + GDAPI_FUNC(godot_string_hash, uint32_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hash64, uint64_t, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_hash_chars, uint32_t, const char *p_cstr) \ + GDAPI_FUNC(godot_string_hash_chars_with_len, uint32_t, const char *p_cstr, godot_int p_len) \ + GDAPI_FUNC(godot_string_hash_utf8_chars, uint32_t, const wchar_t *p_str) \ + GDAPI_FUNC(godot_string_hash_utf8_chars_with_len, uint32_t, const wchar_t *p_str, godot_int p_len) \ + GDAPI_FUNC(godot_string_md5_buffer, godot_pool_byte_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_md5_text, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_sha256_buffer, godot_pool_byte_array, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_sha256_text, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_empty, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_base_dir, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_get_file, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_humanize_size, godot_string, size_t p_size) \ + GDAPI_FUNC(godot_string_is_abs_path, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_rel_path, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_resource_file, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_path_to, godot_string, const godot_string *p_self, const godot_string *p_path) \ + GDAPI_FUNC(godot_string_path_to_file, godot_string, const godot_string *p_self, const godot_string *p_path) \ + GDAPI_FUNC(godot_string_simplify_path, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_c_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_c_escape_multiline, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_c_unescape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_http_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_http_unescape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_json_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_word_wrap, godot_string, const godot_string *p_self, godot_int p_chars_per_line) \ + GDAPI_FUNC(godot_string_xml_escape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_xml_escape_with_quotes, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_xml_unescape, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_percent_decode, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_percent_encode, godot_string, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_float, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_hex_number, godot_bool, const godot_string *p_self, godot_bool p_with_prefix) \ + GDAPI_FUNC(godot_string_is_valid_html_color, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_identifier, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_integer, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC(godot_string_is_valid_ip_address, godot_bool, const godot_string *p_self) \ + GDAPI_FUNC_VOID(godot_string_destroy, godot_string *p_self) \ + GDAPI_FUNC_VOID(godot_object_destroy, godot_object *p_o) \ + GDAPI_FUNC(godot_global_get_singleton, godot_object *, char *p_name) \ + GDAPI_FUNC(godot_get_stack_bottom, void *) \ + GDAPI_FUNC(godot_method_bind_get_method, godot_method_bind *, const char *p_classname, const char *p_methodname) \ + GDAPI_FUNC_VOID(godot_method_bind_ptrcall, godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret) \ + GDAPI_FUNC(godot_method_bind_call, godot_variant, godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error) \ + GDAPI_FUNC(godot_get_class_constructor, godot_class_constructor, const char *p_classname) \ + GDAPI_FUNC(godot_get_global_constants, godot_dictionary) \ + GDAPI_FUNC(godot_alloc, void *, int p_bytes) \ + GDAPI_FUNC(godot_realloc, void *, void *p_ptr, int p_bytes) \ + GDAPI_FUNC_VOID(godot_free, void *p_ptr) \ + GDAPI_FUNC_VOID(godot_print_error, const char *p_description, const char *p_function, const char *p_file, int p_line) \ + GDAPI_FUNC_VOID(godot_print_warning, const char *p_description, const char *p_function, const char *p_file, int p_line) \ + GDAPI_FUNC_VOID(godot_print, const godot_string *p_message) \ + GDAPI_FUNC_VOID(godot_nativescript_register_class, void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) \ + GDAPI_FUNC_VOID(godot_nativescript_register_tool_class, void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) \ + GDAPI_FUNC_VOID(godot_nativescript_register_method, void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) \ + GDAPI_FUNC_VOID(godot_nativescript_register_property, void *p_gdnative_handle, const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) \ + GDAPI_FUNC_VOID(godot_nativescript_register_signal, void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal) \ + GDAPI_FUNC(godot_nativescript_get_userdata, void *, godot_object *p_instance) + +#define GDAPI_FUNC(name, ret_type, ...) \ + ret_type (*name)(__VA_ARGS__); +#define GDAPI_FUNC_VOID(name, ...) \ + void (*name)(__VA_ARGS__); + +typedef struct godot_gdnative_api_struct { + GODOT_GDNATIVE_API_FUNCTIONS +} godot_gdnative_api_struct; + +#undef GDAPI_FUNC +#undef GDAPI_FUNC_VOID + +#ifdef __cplusplus +} +#endif + +#endif // GODOT_GDNATIVE_API_STRUCT_H diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 559e9fa455..997c342045 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -43,7 +43,7 @@ #ifdef TOOLS_ENABLED #include "editor/editor_node.h" - +#include "gd_native_library_editor.h" // Class used to discover singleton gdnative files void actual_discoverer_handler(); @@ -115,7 +115,12 @@ void actual_discoverer_handler() { GDNativeSingletonDiscover *discoverer = NULL; -void discoverer_callback() { +static void editor_init_callback() { + + GDNativeLibraryEditor *library_editor = memnew(GDNativeLibraryEditor); + library_editor->set_name(TTR("GDNative")); + ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor); + discoverer = memnew(GDNativeSingletonDiscover); EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class"); } @@ -184,7 +189,7 @@ void register_gdnative_types() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - EditorNode::add_init_callback(discoverer_callback); + EditorNode::add_init_callback(editor_init_callback); } #endif diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index 4803781c67..7036a708e5 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -131,7 +131,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDParser: switch (p_expression->op) { case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break; - case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBSTRACT; break; + case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break; case GDParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break; case GDParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break; case GDParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break; @@ -759,7 +759,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) return -1; } break; case GDParser::OperatorNode::OP_SUB: { - if (!_create_binary_operator(codegen, on, Variant::OP_SUBSTRACT, p_stack_level)) return -1; + if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) return -1; } break; case GDParser::OperatorNode::OP_MUL: { if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) return -1; diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index bc51b84047..aa39ad92c4 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -908,7 +908,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser: Variant::Operator vop = Variant::OP_MAX; switch (op->op) { case GDParser::OperatorNode::OP_ADD: vop = Variant::OP_ADD; break; - case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBSTRACT; break; + case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBTRACT; break; case GDParser::OperatorNode::OP_MUL: vop = Variant::OP_MULTIPLY; break; case GDParser::OperatorNode::OP_DIV: vop = Variant::OP_DIVIDE; break; case GDParser::OperatorNode::OP_MOD: vop = Variant::OP_MODULE; break; diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp index ddee7b2521..df7b16c96e 100644 --- a/modules/gdscript/gd_function.cpp +++ b/modules/gdscript/gd_function.cpp @@ -271,6 +271,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a if (ScriptDebugger::get_singleton()) GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line); +#define GD_ERR_BREAK(m_cond) ERR_BREAK(m_cond) + #define CHECK_SPACE(m_space) \ ERR_BREAK((ip + m_space) > _code_size) @@ -281,6 +283,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a break; #else +#define GD_ERR_BREAK(m_cond) #define CHECK_SPACE(m_space) #define GET_VARIANT_PTR(m_v, m_code_ofs) \ Variant *m_v; \ @@ -302,9 +305,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #endif bool exit_ok = false; +#ifdef DEBUG_ENABLED while (ip < _code_size) { - int last_opcode = _code_ptr[ip]; +#else + while (true) { +#endif + switch (_code_ptr[ip]) { case OPCODE_OPERATOR: { @@ -313,21 +320,21 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; Variant::Operator op = (Variant::Operator)_code_ptr[ip + 1]; - ERR_BREAK(op >= Variant::OP_MAX); + GD_ERR_BREAK(op >= Variant::OP_MAX); GET_VARIANT_PTR(a, 2); GET_VARIANT_PTR(b, 3); GET_VARIANT_PTR(dst, 4); #ifdef DEBUG_ENABLED + Variant ret; Variant::evaluate(op, *a, *b, ret, valid); #else Variant::evaluate(op, *a, *b, *dst, valid); #endif - - if (!valid) { #ifdef DEBUG_ENABLED + if (!valid) { if (ret.get_type() == Variant::STRING) { //return a string when invalid with the error @@ -336,13 +343,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } else { err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'."; } -#endif break; } -#ifdef DEBUG_ENABLED *dst = ret; #endif - ip += 5; continue; } @@ -355,7 +359,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(dst, 3); #ifdef DEBUG_ENABLED - if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) { err_text = "Left operand of 'is' is not an instance of anything."; @@ -367,7 +370,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a break; } #endif - Object *obj_A = *a; Object *obj_B = *b; @@ -399,12 +401,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GDNativeClass *nc = Object::cast_to<GDNativeClass>(obj_B); +#ifdef DEBUG_ENABLED if (!nc) { err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; break; } - +#endif extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); } @@ -423,6 +426,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; dst->set(*index, *value, &valid); +#ifdef DEBUG_ENABLED if (!valid) { String v = index->operator String(); if (v != "") { @@ -433,7 +437,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "')."; break; } - +#endif ip += 4; continue; } @@ -453,6 +457,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a *dst = src->get(*index, &valid); #endif +#ifdef DEBUG_ENABLED if (!valid) { String v = index->operator String(); if (v != "") { @@ -463,7 +468,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "')."; break; } -#ifdef DEBUG_ENABLED *dst = ret; #endif ip += 4; @@ -478,18 +482,19 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a int indexname = _code_ptr[ip + 2]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; bool valid; dst->set_named(*index, *value, &valid); +#ifdef DEBUG_ENABLED if (!valid) { String err_type; err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "')."; break; } - +#endif ip += 4; continue; } @@ -502,7 +507,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a int indexname = _code_ptr[ip + 2]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; bool valid; @@ -513,7 +518,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #else *dst = src->get_named(*index, &valid); #endif - +#ifdef DEBUG_ENABLED if (!valid) { if (src->has_method(*index)) { err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' ?"; @@ -522,7 +527,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } break; } -#ifdef DEBUG_ENABLED *dst = ret; #endif ip += 4; @@ -532,7 +536,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(src, 2); @@ -554,7 +558,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(3); int indexname = _code_ptr[ip + 1]; - ERR_BREAK(indexname < 0 || indexname >= _global_names_count); + GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; GET_VARIANT_PTR(dst, 2); bool ok = ClassDB::get_property(p_instance->owner, *index, *dst); @@ -615,11 +619,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a Variant::CallError err; *dst = Variant::construct(t, (const Variant **)argptrs, argc, err); +#ifdef DEBUG_ENABLED if (err.error != Variant::CallError::CALL_OK) { err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs); break; } +#endif ip += 4 + argc; //construct a basic type @@ -677,10 +683,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(base, 2); int nameg = _code_ptr[ip + 3]; - ERR_BREAK(nameg < 0 || nameg >= _global_names_count); + GD_ERR_BREAK(nameg < 0 || nameg >= _global_names_count); const StringName *methodname = &_global_names_ptr[nameg]; - ERR_BREAK(argc < 0); + GD_ERR_BREAK(argc < 0); ip += 4; CHECK_SPACE(argc + 1); Variant **argptrs = call_args; @@ -711,7 +717,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a if (GDScriptLanguage::get_singleton()->profiling) { function_call_time += OS::get_singleton()->get_ticks_usec() - call_time; } -#endif if (err.error != Variant::CallError::CALL_OK) { @@ -742,6 +747,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = _get_call_error(err, "function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs); break; } +#endif //_call_func(NULL,base,*methodname,ip,argc,p_instance,stack); ip += argc + 1; @@ -753,7 +759,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip + 1]); int argc = _code_ptr[ip + 2]; - ERR_BREAK(argc < 0); + GD_ERR_BREAK(argc < 0); ip += 3; CHECK_SPACE(argc + 1); @@ -770,6 +776,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GDFunctions::call(func, (const Variant **)argptrs, argc, *dst, err); +#ifdef DEBUG_ENABLED if (err.error != Variant::CallError::CALL_OK) { String methodstr = GDFunctions::get_func_name(func); @@ -781,6 +788,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } break; } +#endif ip += argc + 1; continue; } @@ -792,8 +800,8 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(2); int self_fun = _code_ptr[ip + 1]; -#ifdef DEBUG_ENABLED +#ifdef DEBUG_ENABLED if (self_fun < 0 || self_fun >= _global_names_count) { err_text = "compiler bug, function name not found"; @@ -898,10 +906,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a retvalue = gdfs; if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) { + //do the oneshot connect GET_VARIANT_PTR(argobj, 1); GET_VARIANT_PTR(argname, 2); - //do the oneshot connect +#ifdef DEBUG_ENABLED if (argobj->get_type() != Variant::OBJECT) { err_text = "First argument of yield() not of type object."; break; @@ -910,6 +919,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a err_text = "Second argument of yield() not a string (for signal name)."; break; } +#endif Object *obj = argobj->operator Object *(); String signal = argname->operator String(); #ifdef DEBUG_ENABLED @@ -932,10 +942,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a #endif Error err = obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT); +#ifdef DEBUG_ENABLED if (err != OK) { err_text = "Error connecting to signal: " + signal + " during yield()."; break; } +#endif } exit_ok = true; @@ -944,10 +956,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a case OPCODE_YIELD_RESUME: { CHECK_SPACE(2); +#ifdef DEBUG_ENABLED if (!p_state) { err_text = ("Invalid Resume (bug?)"); break; } +#endif GET_VARIANT_PTR(result, 1); *result = p_state->result; ip += 2; @@ -958,7 +972,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a CHECK_SPACE(2); int to = _code_ptr[ip + 1]; - ERR_BREAK(to < 0 || to > _code_size); + GD_ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } @@ -968,18 +982,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(test, 1); - bool valid; - bool result = test->booleanize(valid); -#ifdef DEBUG_ENABLED - if (!valid) { + bool result = test->booleanize(); - err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); - break; - } -#endif if (result) { int to = _code_ptr[ip + 2]; - ERR_BREAK(to < 0 || to > _code_size); + GD_ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } @@ -992,18 +999,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(test, 1); - bool valid; - bool result = test->booleanize(valid); -#ifdef DEBUG_ENABLED - if (!valid) { + bool result = test->booleanize(); - err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); - break; - } -#endif if (!result) { int to = _code_ptr[ip + 2]; - ERR_BREAK(to < 0 || to > _code_size); + GD_ERR_BREAK(to < 0 || to > _code_size); ip = to; continue; } @@ -1033,23 +1033,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; if (!container->iter_init(*counter, valid)) { +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "'."; break; } +#endif int jumpto = _code_ptr[ip + 3]; - ERR_BREAK(jumpto < 0 || jumpto > _code_size); + GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; continue; } GET_VARIANT_PTR(iterator, 4); *iterator = container->iter_get(*counter, valid); +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'."; break; } - +#endif ip += 5; //skip regular iterate which is always next continue; } @@ -1062,23 +1065,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a bool valid; if (!container->iter_next(*counter, valid)) { +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?)."; break; } +#endif int jumpto = _code_ptr[ip + 3]; - ERR_BREAK(jumpto < 0 || jumpto > _code_size); + GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; continue; } GET_VARIANT_PTR(iterator, 4); *iterator = container->iter_get(*counter, valid); +#ifdef DEBUG_ENABLED if (!valid) { err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?)."; break; } - +#endif ip += 5; //loop again continue; } @@ -1087,14 +1093,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a GET_VARIANT_PTR(test, 1); #ifdef DEBUG_ENABLED - bool valid; - bool result = test->booleanize(valid); - - if (!valid) { - - err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type()); - break; - } + bool result = test->booleanize(); if (!result) { @@ -1103,7 +1102,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } #endif - ip += 2; continue; } @@ -1157,6 +1155,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a } } +#ifdef DEBUG_ENABLED if (exit_ok) break; //error @@ -1182,6 +1181,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), ERR_HANDLER_SCRIPT); } +#endif break; } diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index 72c3f9612a..36aaa1f807 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -1699,7 +1699,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) { _REDUCE_BINARY(Variant::OP_ADD); } break; case OperatorNode::OP_SUB: { - _REDUCE_BINARY(Variant::OP_SUBSTRACT); + _REDUCE_BINARY(Variant::OP_SUBTRACT); } break; case OperatorNode::OP_MUL: { _REDUCE_BINARY(Variant::OP_MULTIPLY); diff --git a/modules/regex/regex.h b/modules/regex/regex.h index 0d97bcce54..bfa9c84042 100644 --- a/modules/regex/regex.h +++ b/modules/regex/regex.h @@ -87,8 +87,8 @@ public: Error compile(const String &p_pattern); void _init(const String &p_pattern = ""); - Ref<RegExMatch> search(const String &p_subject, int offset = 0, int end = -1) const; - String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_start = 0, int p_end = -1) const; + Ref<RegExMatch> search(const String &p_subject, int p_offset = 0, int p_end = -1) const; + String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_offset = 0, int p_end = -1) const; bool is_valid() const; String get_pattern() const; diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index c575edbba3..e27452354b 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -128,13 +128,13 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t return OK; } -Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *svg_str, float p_scale, bool upsample, bool convert_colors) { +Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p_svg_str, float p_scale, bool upsample, bool convert_colors) { - size_t str_len = strlen(svg_str); + size_t str_len = strlen(p_svg_str); PoolVector<uint8_t> src_data; src_data.resize(str_len + 1); PoolVector<uint8_t>::Write src_w = src_data.write(); - memcpy(src_w.ptr(), svg_str, str_len + 1); + memcpy(src_w.ptr(), p_svg_str, str_len + 1); return _create_image(p_image, &src_data, p_scale, upsample, convert_colors); } @@ -160,4 +160,4 @@ void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const ImageLoaderSVG::ImageLoaderSVG() { } -ImageLoaderSVG::ReplaceColors ImageLoaderSVG::replace_colors;
\ No newline at end of file +ImageLoaderSVG::ReplaceColors ImageLoaderSVG::replace_colors; diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h index 332ac214a5..cf44cd8c50 100644 --- a/modules/svg/image_loader_svg.h +++ b/modules/svg/image_loader_svg.h @@ -57,7 +57,7 @@ class ImageLoaderSVG : public ImageFormatLoader { List<uint32_t> new_colors; } replace_colors; static SVGRasterizer rasterizer; - static void _convert_colors(NSVGimage *p_svg_imge); + static void _convert_colors(NSVGimage *p_svg_image); static Error _create_image(Ref<Image> p_image, const PoolVector<uint8_t> *p_data, float p_scale, bool upsample, bool convert_colors = false); public: diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 2c8796820e..972be5f5a4 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -1175,6 +1175,65 @@ void VisualScriptBuiltinFunc::_bind_methods() { cc += func_name[i]; } ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, cc), "set_func", "get_func"); + + BIND_ENUM_CONSTANT(MATH_SIN); + BIND_ENUM_CONSTANT(MATH_COS); + BIND_ENUM_CONSTANT(MATH_TAN); + BIND_ENUM_CONSTANT(MATH_SINH); + BIND_ENUM_CONSTANT(MATH_COSH); + BIND_ENUM_CONSTANT(MATH_TANH); + BIND_ENUM_CONSTANT(MATH_ASIN); + BIND_ENUM_CONSTANT(MATH_ACOS); + BIND_ENUM_CONSTANT(MATH_ATAN); + BIND_ENUM_CONSTANT(MATH_ATAN2); + BIND_ENUM_CONSTANT(MATH_SQRT); + BIND_ENUM_CONSTANT(MATH_FMOD); + BIND_ENUM_CONSTANT(MATH_FPOSMOD); + BIND_ENUM_CONSTANT(MATH_FLOOR); + BIND_ENUM_CONSTANT(MATH_CEIL); + BIND_ENUM_CONSTANT(MATH_ROUND); + BIND_ENUM_CONSTANT(MATH_ABS); + BIND_ENUM_CONSTANT(MATH_SIGN); + BIND_ENUM_CONSTANT(MATH_POW); + BIND_ENUM_CONSTANT(MATH_LOG); + BIND_ENUM_CONSTANT(MATH_EXP); + BIND_ENUM_CONSTANT(MATH_ISNAN); + BIND_ENUM_CONSTANT(MATH_ISINF); + BIND_ENUM_CONSTANT(MATH_EASE); + BIND_ENUM_CONSTANT(MATH_DECIMALS); + BIND_ENUM_CONSTANT(MATH_STEPIFY); + BIND_ENUM_CONSTANT(MATH_LERP); + BIND_ENUM_CONSTANT(MATH_DECTIME); + BIND_ENUM_CONSTANT(MATH_RANDOMIZE); + BIND_ENUM_CONSTANT(MATH_RAND); + BIND_ENUM_CONSTANT(MATH_RANDF); + BIND_ENUM_CONSTANT(MATH_RANDOM); + BIND_ENUM_CONSTANT(MATH_SEED); + BIND_ENUM_CONSTANT(MATH_RANDSEED); + BIND_ENUM_CONSTANT(MATH_DEG2RAD); + BIND_ENUM_CONSTANT(MATH_RAD2DEG); + BIND_ENUM_CONSTANT(MATH_LINEAR2DB); + BIND_ENUM_CONSTANT(MATH_DB2LINEAR); + BIND_ENUM_CONSTANT(LOGIC_MAX); + BIND_ENUM_CONSTANT(LOGIC_MIN); + BIND_ENUM_CONSTANT(LOGIC_CLAMP); + BIND_ENUM_CONSTANT(LOGIC_NEAREST_PO2); + BIND_ENUM_CONSTANT(OBJ_WEAKREF); + BIND_ENUM_CONSTANT(FUNC_FUNCREF); + BIND_ENUM_CONSTANT(TYPE_CONVERT); + BIND_ENUM_CONSTANT(TYPE_OF); + BIND_ENUM_CONSTANT(TYPE_EXISTS); + BIND_ENUM_CONSTANT(TEXT_CHAR); + BIND_ENUM_CONSTANT(TEXT_STR); + BIND_ENUM_CONSTANT(TEXT_PRINT); + BIND_ENUM_CONSTANT(TEXT_PRINTERR); + BIND_ENUM_CONSTANT(TEXT_PRINTRAW); + BIND_ENUM_CONSTANT(VAR_TO_STR); + BIND_ENUM_CONSTANT(STR_TO_VAR); + BIND_ENUM_CONSTANT(VAR_TO_BYTES); + BIND_ENUM_CONSTANT(BYTES_TO_VAR); + BIND_ENUM_CONSTANT(COLORN); + BIND_ENUM_CONSTANT(FUNC_MAX); } VisualScriptBuiltinFunc::VisualScriptBuiltinFunc() { diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index eae866d167..897e910f20 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -1023,7 +1023,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { 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_SUBSTRACT; 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; @@ -1085,7 +1085,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() { case Variant::OP_MODULE: priority = 2; break; case Variant::OP_ADD: priority = 3; break; - case Variant::OP_SUBSTRACT: 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; diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 5fcc5b0ad9..f02e797fe6 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -748,6 +748,13 @@ void VisualScriptFunctionCall::_bind_methods() { BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH); BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE); BIND_ENUM_CONSTANT(CALL_MODE_BASIC_TYPE); + BIND_ENUM_CONSTANT(CALL_MODE_SINGLETON); + + BIND_ENUM_CONSTANT(RPC_DISABLED); + BIND_ENUM_CONSTANT(RPC_RELIABLE); + BIND_ENUM_CONSTANT(RPC_UNRELIABLE); + BIND_ENUM_CONSTANT(RPC_RELIABLE_TO_ID); + BIND_ENUM_CONSTANT(RPC_UNRELIABLE_TO_ID); } class VisualScriptNodeInstanceFunctionCall : public VisualScriptNodeInstance { @@ -1487,6 +1494,19 @@ void VisualScriptPropertySet::_bind_methods() { BIND_ENUM_CONSTANT(CALL_MODE_SELF); BIND_ENUM_CONSTANT(CALL_MODE_NODE_PATH); BIND_ENUM_CONSTANT(CALL_MODE_INSTANCE); + BIND_ENUM_CONSTANT(CALL_MODE_BASIC_TYPE); + + BIND_ENUM_CONSTANT(ASSIGN_OP_NONE); + BIND_ENUM_CONSTANT(ASSIGN_OP_ADD); + BIND_ENUM_CONSTANT(ASSIGN_OP_SUB); + BIND_ENUM_CONSTANT(ASSIGN_OP_MUL); + BIND_ENUM_CONSTANT(ASSIGN_OP_DIV); + BIND_ENUM_CONSTANT(ASSIGN_OP_MOD); + BIND_ENUM_CONSTANT(ASSIGN_OP_SHIFT_LEFT); + BIND_ENUM_CONSTANT(ASSIGN_OP_SHIFT_RIGHT); + BIND_ENUM_CONSTANT(ASSIGN_OP_BIT_AND); + BIND_ENUM_CONSTANT(ASSIGN_OP_BIT_OR); + BIND_ENUM_CONSTANT(ASSIGN_OP_BIT_XOR); } class VisualScriptNodeInstancePropertySet : public VisualScriptNodeInstance { @@ -1526,7 +1546,7 @@ public: value = Variant::evaluate(Variant::OP_ADD, value, p_argument); } break; case VisualScriptPropertySet::ASSIGN_OP_SUB: { - value = Variant::evaluate(Variant::OP_SUBSTRACT, value, p_argument); + value = Variant::evaluate(Variant::OP_SUBTRACT, value, p_argument); } break; case VisualScriptPropertySet::ASSIGN_OP_MUL: { value = Variant::evaluate(Variant::OP_MULTIPLY, value, p_argument); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 39f23fcf50..16aec76e57 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -1882,6 +1882,16 @@ void VisualScriptMathConstant::_bind_methods() { cc += const_name[i]; } ADD_PROPERTY(PropertyInfo(Variant::INT, "constant", PROPERTY_HINT_ENUM, cc), "set_math_constant", "get_math_constant"); + + BIND_ENUM_CONSTANT(MATH_CONSTANT_ONE); + BIND_ENUM_CONSTANT(MATH_CONSTANT_PI); + BIND_ENUM_CONSTANT(MATH_CONSTANT_2PI); + BIND_ENUM_CONSTANT(MATH_CONSTANT_HALF_PI); + BIND_ENUM_CONSTANT(MATH_CONSTANT_E); + BIND_ENUM_CONSTANT(MATH_CONSTANT_SQRT2); + BIND_ENUM_CONSTANT(MATH_CONSTANT_INF); + BIND_ENUM_CONSTANT(MATH_CONSTANT_NAN); + BIND_ENUM_CONSTANT(MATH_CONSTANT_MAX); } VisualScriptMathConstant::VisualScriptMathConstant() { @@ -3535,6 +3545,11 @@ void VisualScriptInputAction::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "action"), "set_action_name", "get_action_name"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Pressed,Released,JustPressed,JustReleased"), "set_action_mode", "get_action_mode"); + + BIND_ENUM_CONSTANT(MODE_PRESSED); + BIND_ENUM_CONSTANT(MODE_RELEASED); + BIND_ENUM_CONSTANT(MODE_JUST_PRESSED); + BIND_ENUM_CONSTANT(MODE_JUST_RELEASED); } VisualScriptInputAction::VisualScriptInputAction() { @@ -3747,7 +3762,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("operators/compare/greater_equal", create_op_node<Variant::OP_GREATER_EQUAL>); //mathematic VisualScriptLanguage::singleton->add_register_func("operators/math/add", create_op_node<Variant::OP_ADD>); - VisualScriptLanguage::singleton->add_register_func("operators/math/subtract", create_op_node<Variant::OP_SUBSTRACT>); + VisualScriptLanguage::singleton->add_register_func("operators/math/subtract", create_op_node<Variant::OP_SUBTRACT>); VisualScriptLanguage::singleton->add_register_func("operators/math/multiply", create_op_node<Variant::OP_MULTIPLY>); VisualScriptLanguage::singleton->add_register_func("operators/math/divide", create_op_node<Variant::OP_DIVIDE>); VisualScriptLanguage::singleton->add_register_func("operators/math/negate", create_op_node<Variant::OP_NEGATE>); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 1de2608b9e..dbea2d7531 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -137,12 +137,7 @@ void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int visual_server->init(); // visual_server->cursor_set_visible(false, 0); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); physics_server = memnew(PhysicsServerSW); physics_server->init(); diff --git a/platform/android/power_android.cpp b/platform/android/power_android.cpp index 98d4d810b9..48c9377a5a 100644 --- a/platform/android/power_android.cpp +++ b/platform/android/power_android.cpp @@ -198,19 +198,19 @@ bool power_android::GetPowerInfo_Android() { if (Android_JNI_GetPowerInfo(&plugged, &charged, &battery, &this->nsecs_left, &this->percent_left) != -1) { if (plugged) { if (charged) { - this->power_state = POWERSTATE_CHARGED; + this->power_state = OS::POWERSTATE_CHARGED; } else if (battery) { - this->power_state = POWERSTATE_CHARGING; + this->power_state = OS::POWERSTATE_CHARGING; } else { - this->power_state = POWERSTATE_NO_BATTERY; + this->power_state = OS::POWERSTATE_NO_BATTERY; this->nsecs_left = -1; this->percent_left = -1; } } else { - this->power_state = POWERSTATE_ON_BATTERY; + this->power_state = OS::POWERSTATE_ON_BATTERY; } } else { - this->power_state = POWERSTATE_UNKNOWN; + this->power_state = OS::POWERSTATE_UNKNOWN; this->nsecs_left = -1; this->percent_left = -1; } @@ -218,12 +218,12 @@ bool power_android::GetPowerInfo_Android() { return true; } -PowerState power_android::get_power_state() { +OS::PowerState power_android::get_power_state() { if (GetPowerInfo_Android()) { return power_state; } else { WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } @@ -246,7 +246,7 @@ int power_android::get_power_percent_left() { } power_android::power_android() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } power_android::~power_android() { diff --git a/platform/android/power_android.h b/platform/android/power_android.h index fc618c660d..4c7af1c771 100644 --- a/platform/android/power_android.h +++ b/platform/android/power_android.h @@ -31,7 +31,7 @@ #ifndef PLATFORM_ANDROID_POWER_ANDROID_H_ #define PLATFORM_ANDROID_POWER_ANDROID_H_ -#include "os/power.h" +#include "os/os.h" #include <android/native_window_jni.h> class power_android { @@ -57,7 +57,7 @@ private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; bool GetPowerInfo_Android(); bool UpdatePowerInfo(); @@ -71,7 +71,7 @@ public: static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func); static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index de2f79a0ac..9f2f88bb4e 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -137,11 +137,7 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_ //physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>(); physics_2d_server->init(); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); power_manager = memnew(PowerHaiku); } diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index cb68f9303f..d2fafb9129 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -117,7 +117,7 @@ public: virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; virtual String get_executable_path() const; - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/haiku/power_haiku.cpp b/platform/haiku/power_haiku.cpp index 449b43a621..8718b317a3 100644 --- a/platform/haiku/power_haiku.cpp +++ b/platform/haiku/power_haiku.cpp @@ -37,12 +37,12 @@ bool PowerHaiku::UpdatePowerInfo() { return false; } -PowerState PowerHaiku::get_power_state() { +OS::PowerState PowerHaiku::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } @@ -65,7 +65,7 @@ int PowerX11::get_power_percent_left() { } PowerHaiku::PowerHaiku() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } PowerHaiku::~PowerHaiku() { diff --git a/platform/haiku/power_haiku.h b/platform/haiku/power_haiku.h index 12513bdaef..59a93cd976 100644 --- a/platform/haiku/power_haiku.h +++ b/platform/haiku/power_haiku.h @@ -31,11 +31,13 @@ #ifndef PLATFORM_HAIKU_POWER_HAIKU_H_ #define PLATFORM_HAIKU_POWER_HAIKU_H_ +#include <os/os.h> + class PowerHaiku { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; bool UpdatePowerInfo(); @@ -43,7 +45,7 @@ public: PowerHaiku(); virtual ~PowerHaiku(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/iphone/power_iphone.cpp b/platform/iphone/power_iphone.cpp index 2811e62108..055d31ef0a 100644 --- a/platform/iphone/power_iphone.cpp +++ b/platform/iphone/power_iphone.cpp @@ -30,15 +30,15 @@ #include "power_iphone.h" -bool PowerState::UpdatePowerInfo() { +bool OS::PowerState::UpdatePowerInfo() { return false; } -PowerState PowerIphone::get_power_state() { +OS::PowerState PowerIphone::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } @@ -59,7 +59,7 @@ int PowerIphone::get_power_percent_left() { } PowerIphone::PowerIphone() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { // TODO Auto-generated constructor stub } diff --git a/platform/iphone/power_iphone.h b/platform/iphone/power_iphone.h index b4fb8d62dc..6270a8069c 100644 --- a/platform/iphone/power_iphone.h +++ b/platform/iphone/power_iphone.h @@ -31,11 +31,13 @@ #ifndef PLATFORM_IPHONE_POWER_IPHONE_H_ #define PLATFORM_IPHONE_POWER_IPHONE_H_ +#include <os/os.h> + class PowerIphone { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; bool UpdatePowerInfo(); @@ -43,7 +45,7 @@ public: PowerIphone(); virtual ~PowerIphone(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index ac8d367366..f103035b27 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -172,14 +172,14 @@ static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent if (!is_canvas_focused()) { focus_canvas(); } - mask |= 1 << ev->get_button_index(); - } else if (mask & (1 << ev->get_button_index())) { - mask &= ~(1 << ev->get_button_index()); + mask |= ev->get_button_index(); + } else if (mask & ev->get_button_index()) { + mask &= ~ev->get_button_index(); } else { // release event, but press was outside the canvas, so ignore return false; } - ev->set_button_mask(mask >> 1); + ev->set_button_mask(mask); _input->parse_input_event(ev); // prevent selection dragging @@ -200,7 +200,7 @@ static EM_BOOL _mousemove_callback(int event_type, const EmscriptenMouseEvent *m Ref<InputEventMouseMotion> ev; ev.instance(); dom2godot_mod(mouse_event, ev); - ev->set_button_mask(input_mask >> 1); + ev->set_button_mask(input_mask); ev->set_position(pos); ev->set_global_position(ev->get_position()); @@ -227,7 +227,7 @@ static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel Ref<InputEventMouseButton> ev; ev.instance(); - ev->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev->set_button_mask(_input->get_mouse_button_mask()); ev->set_position(_input->get_mouse_position()); ev->set_global_position(ev->get_position()); @@ -291,7 +291,7 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent * Ref<InputEventMouseButton> ev_mouse; ev_mouse.instance(); - ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev_mouse->set_button_mask(_input->get_mouse_button_mask()); dom2godot_mod(touch_event, ev_mouse); const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index]; @@ -334,7 +334,7 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t Ref<InputEventMouseMotion> ev_mouse; ev_mouse.instance(); dom2godot_mod(touch_event, ev_mouse); - ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1); + ev_mouse->set_button_mask(_input->get_mouse_button_mask()); const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index]; ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY)); @@ -464,11 +464,7 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i print_line("Init Audio"); AudioDriverManager::add_driver(&audio_driver_javascript); - audio_driver_javascript.set_singleton(); - if (audio_driver_javascript.init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); @@ -976,7 +972,7 @@ String OS_JavaScript::get_joy_guid(int p_device) const { return input->get_joy_guid_remapped(p_device); } -PowerState OS_JavaScript::get_power_state() { +OS::PowerState OS_JavaScript::get_power_state() { return power_manager->get_power_state(); } diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index f78a3f2768..4c6469cb58 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -165,7 +165,7 @@ public: virtual String get_joy_guid(int p_device) const; bool joy_connection_changed(int p_type, const EmscriptenGamepadEvent *p_event); - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/javascript/power_javascript.cpp b/platform/javascript/power_javascript.cpp index 3d54146595..10964502d4 100644 --- a/platform/javascript/power_javascript.cpp +++ b/platform/javascript/power_javascript.cpp @@ -36,12 +36,12 @@ bool PowerJavascript::UpdatePowerInfo() { return false; } -PowerState PowerJavascript::get_power_state() { +OS::PowerState PowerJavascript::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } @@ -64,7 +64,7 @@ int PowerJavascript::get_power_percent_left() { } PowerJavascript::PowerJavascript() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } PowerJavascript::~PowerJavascript() { diff --git a/platform/javascript/power_javascript.h b/platform/javascript/power_javascript.h index 834d765557..8454c5d728 100644 --- a/platform/javascript/power_javascript.h +++ b/platform/javascript/power_javascript.h @@ -31,13 +31,13 @@ #ifndef PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_ #define PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_ -#include "os/power.h" +#include "os/os.h" class PowerJavascript { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; bool UpdatePowerInfo(); @@ -45,7 +45,7 @@ public: PowerJavascript(); virtual ~PowerJavascript(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index 9239573734..2ed88db309 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -43,6 +43,7 @@ #include <dlfcn.h> #include <execinfo.h> #include <signal.h> +#include <stdlib.h> #include <mach-o/dyld.h> #include <mach-o/getsect.h> @@ -77,7 +78,7 @@ static void handle_crash(int sig) { void *bt_buffer[256]; size_t size = backtrace(bt_buffer, 256); String _execpath = OS::get_singleton()->get_executable_path(); - String msg = GLOBAL_GET("debug/settings/backtrace/message"); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); // Dump the backtrace to stderr with a message to the user fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index ca3e5745e9..059dd5afd0 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -216,7 +216,7 @@ public: virtual void set_ime_position(const Point2 &p_pos); virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp); - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index beda6f4c38..111cdb0cf1 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1088,12 +1088,7 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au visual_server->init(); // visual_server->cursor_set_visible(false, 0); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); // physics_server = memnew(PhysicsServerSW); @@ -1914,7 +1909,7 @@ String OS_OSX::get_joy_guid(int p_device) const { return input->get_joy_guid_remapped(p_device); } -PowerState OS_OSX::get_power_state() { +OS::PowerState OS_OSX::get_power_state() { return power_manager->get_power_state(); } diff --git a/platform/osx/power_osx.cpp b/platform/osx/power_osx.cpp index 5f3938cb91..eed03e63c1 100644 --- a/platform/osx/power_osx.cpp +++ b/platform/osx/power_osx.cpp @@ -174,7 +174,7 @@ bool power_osx::GetPowerInfo_MacOSX() { nsecs_left = -1; percent_left = -1; - power_state = POWERSTATE_UNKNOWN; + power_state = OS::POWERSTATE_UNKNOWN; if (blob != NULL) { CFArrayRef list = IOPSCopyPowerSourcesList(blob); @@ -194,13 +194,13 @@ bool power_osx::GetPowerInfo_MacOSX() { } if (!have_battery) { - power_state = POWERSTATE_NO_BATTERY; + power_state = OS::POWERSTATE_NO_BATTERY; } else if (charging) { - power_state = POWERSTATE_CHARGING; + power_state = OS::POWERSTATE_CHARGING; } else if (have_ac) { - power_state = POWERSTATE_CHARGED; + power_state = OS::POWERSTATE_CHARGED; } else { - power_state = POWERSTATE_ON_BATTERY; + power_state = OS::POWERSTATE_ON_BATTERY; } CFRelease(list); @@ -218,11 +218,11 @@ bool power_osx::UpdatePowerInfo() { return false; } -PowerState power_osx::get_power_state() { +OS::PowerState power_osx::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } @@ -243,7 +243,7 @@ int power_osx::get_power_percent_left() { } power_osx::power_osx() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } power_osx::~power_osx() { diff --git a/platform/osx/power_osx.h b/platform/osx/power_osx.h index 692c850d7c..20e47e9cd9 100644 --- a/platform/osx/power_osx.h +++ b/platform/osx/power_osx.h @@ -33,7 +33,7 @@ #include "dir_access_osx.h" #include "os/file_access.h" -#include "os/power.h" +#include "os/os.h" #include <CoreFoundation/CoreFoundation.h> class power_osx { @@ -41,7 +41,7 @@ class power_osx { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; void checkps(CFDictionaryRef dict, bool *have_ac, bool *have_battery, bool *charging); bool GetPowerInfo_MacOSX(/*PowerState * state, int *seconds, int *percent*/); bool UpdatePowerInfo(); @@ -50,7 +50,7 @@ public: power_osx(); virtual ~power_osx(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 44034e815d..300c5cffcc 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -62,12 +62,7 @@ void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p //visual_server = memnew( VisualServerRaster(rasterizer) ); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); sample_manager = memnew(SampleManagerMallocSW); audio_server = memnew(AudioServerSW(sample_manager)); @@ -200,7 +195,7 @@ void OS_Server::move_window_to_foreground() { void OS_Server::set_cursor_shape(CursorShape p_shape) { } -PowerState OS_Server::get_power_state() { +OS::PowerState OS_Server::get_power_state() { return power_manager->get_power_state(); } @@ -232,7 +227,6 @@ void OS_Server::run() { OS_Server::OS_Server() { - AudioDriverManager::add_driver(&driver_dummy); //adriver here grab = false; }; diff --git a/platform/server/os_server.h b/platform/server/os_server.h index f3db053be3..ba12f649be 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -34,7 +34,6 @@ #include "drivers/rtaudio/audio_driver_rtaudio.h" #include "drivers/unix/os_unix.h" #include "main/input_default.h" -#include "servers/audio/audio_driver_dummy.h" #include "servers/audio_server.h" #include "servers/physics_2d/physics_2d_server_sw.h" #include "servers/physics_server.h" @@ -55,7 +54,6 @@ class OS_Server : public OS_Unix { List<String> args; MainLoop *main_loop; - AudioDriverDummy driver_dummy; bool grab; PhysicsServer *physics_server; @@ -106,7 +104,7 @@ public: void run(); - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 3a8932aae2..b909ccccd6 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -268,12 +268,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud joypad = ref new JoypadUWP(input); joypad->register_events(); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); power_manager = memnew(PowerUWP); @@ -855,7 +850,7 @@ bool OSUWP::_check_internal_feature_support(const String &p_feature) { return p_feature == "pc" || p_feature == "s3tc"; } -PowerState OSUWP::get_power_state() { +OS::PowerState OSUWP::get_power_state() { return power_manager->get_power_state(); } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 5f36396017..a7a5d32cb9 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -259,7 +259,7 @@ public: void input_event(const Ref<InputEvent> &p_event); - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/uwp/power_uwp.cpp b/platform/uwp/power_uwp.cpp index 07a726647d..81e97b1391 100644 --- a/platform/uwp/power_uwp.cpp +++ b/platform/uwp/power_uwp.cpp @@ -31,7 +31,7 @@ #include "power_uwp.h" PowerUWP::PowerUWP() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } PowerUWP::~PowerUWP() { @@ -47,12 +47,12 @@ bool PowerUWP::UpdatePowerInfo() { return false; } -PowerState PowerUWP::get_power_state() { +OS::PowerState PowerUWP::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { WARN_PRINT("Power management is not implemented on this platform, defaulting to POWERSTATE_UNKNOWN"); - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } diff --git a/platform/uwp/power_uwp.h b/platform/uwp/power_uwp.h index 9a9811a4f5..0c57689c50 100644 --- a/platform/uwp/power_uwp.h +++ b/platform/uwp/power_uwp.h @@ -33,14 +33,14 @@ #include "os/dir_access.h" #include "os/file_access.h" -#include "os/power.h" +#include "os/os.h" class PowerUWP { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; bool UpdatePowerInfo(); @@ -48,7 +48,7 @@ public: PowerUWP(); virtual ~PowerUWP(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_win.cpp index c9385f36d6..2f5ee7956e 100644 --- a/platform/windows/crash_handler_win.cpp +++ b/platform/windows/crash_handler_win.cpp @@ -116,7 +116,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) { DWORD cbNeeded; std::vector<HMODULE> module_handles(1); - if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler()) { + if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler() || IsDebuggerPresent()) { return EXCEPTION_CONTINUE_SEARCH; } @@ -159,7 +159,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) { IMAGE_NT_HEADERS *h = ImageNtHeader(base); DWORD image_type = h->FileHeader.Machine; int n = 0; - String msg = GLOBAL_GET("debug/settings/backtrace/message"); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str()); diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_win.cpp index 4450cb3670..cff2cbad42 100644 --- a/platform/windows/godot_win.cpp +++ b/platform/windows/godot_win.cpp @@ -156,32 +156,36 @@ int widechar_main(int argc, wchar_t **argv) { return os.get_exit_code(); }; -int main(int _argc, char **_argv) { -// _argc and _argv are ignored -// we are going to use the WideChar version of them instead +int _main() { + LPWSTR *wc_argv; + int argc; + int result; -#ifdef CRASH_HANDLER_EXCEPTION - __try { -#endif - LPWSTR *wc_argv; - int argc; - int result; + wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc); + + if (NULL == wc_argv) { + wprintf(L"CommandLineToArgvW failed\n"); + return 0; + } - wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc); + result = widechar_main(argc, wc_argv); - if (NULL == wc_argv) { - wprintf(L"CommandLineToArgvW failed\n"); - return 0; - } + LocalFree(wc_argv); + return result; +} - result = widechar_main(argc, wc_argv); +int main(int _argc, char **_argv) { +// _argc and _argv are ignored +// we are going to use the WideChar version of them instead - LocalFree(wc_argv); - return result; #ifdef CRASH_HANDLER_EXCEPTION + __try { + return _main(); } __except (CrashHandlerException(GetExceptionInformation())) { return 1; } +#else + return _main(); #endif } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 530072db6e..461caf479c 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1081,12 +1081,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int power_manager = memnew(PowerWindows); - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - ERR_PRINT("Initializing audio failed."); - } + AudioDriverManager::initialize(p_audio_driver); TRACKMOUSEEVENT tme; tme.cbSize = sizeof(TRACKMOUSEEVENT); @@ -2353,7 +2348,7 @@ bool OS_Windows::is_vsync_enabled() const { return true; } -PowerState OS_Windows::get_power_state() { +OS::PowerState OS_Windows::get_power_state() { return power_manager->get_power_state(); } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 474b0fea5c..1a01ac950d 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -281,7 +281,7 @@ public: virtual void set_use_vsync(bool p_enable); virtual bool is_vsync_enabled() const; - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/windows/power_windows.cpp b/platform/windows/power_windows.cpp index b37e189a3a..8d86f160f1 100644 --- a/platform/windows/power_windows.cpp +++ b/platform/windows/power_windows.cpp @@ -64,19 +64,19 @@ bool PowerWindows::GetPowerInfo_Windows() { /* This API should exist back to Win95. */ if (!GetSystemPowerStatus(&status)) { /* !!! FIXME: push GetLastError() into GetError() */ - power_state = POWERSTATE_UNKNOWN; + power_state = OS::POWERSTATE_UNKNOWN; } else if (status.BatteryFlag == 0xFF) { /* unknown state */ - power_state = POWERSTATE_UNKNOWN; + power_state = OS::POWERSTATE_UNKNOWN; } else if (status.BatteryFlag & (1 << 7)) { /* no battery */ - power_state = POWERSTATE_NO_BATTERY; + power_state = OS::POWERSTATE_NO_BATTERY; } else if (status.BatteryFlag & (1 << 3)) { /* charging */ - power_state = POWERSTATE_CHARGING; + power_state = OS::POWERSTATE_CHARGING; need_details = TRUE; } else if (status.ACLineStatus == 1) { - power_state = POWERSTATE_CHARGED; /* on AC, not charging. */ + power_state = OS::POWERSTATE_CHARGED; /* on AC, not charging. */ need_details = TRUE; } else { - power_state = POWERSTATE_ON_BATTERY; /* not on AC. */ + power_state = OS::POWERSTATE_ON_BATTERY; /* not on AC. */ need_details = TRUE; } @@ -97,11 +97,11 @@ bool PowerWindows::GetPowerInfo_Windows() { return TRUE; /* always the definitive answer on Windows. */ } -PowerState PowerWindows::get_power_state() { +OS::PowerState PowerWindows::get_power_state() { if (GetPowerInfo_Windows()) { return power_state; } else { - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } @@ -122,7 +122,7 @@ int PowerWindows::get_power_percent_left() { } PowerWindows::PowerWindows() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } PowerWindows::~PowerWindows() { diff --git a/platform/windows/power_windows.h b/platform/windows/power_windows.h index 9da9841f48..0745615195 100644 --- a/platform/windows/power_windows.h +++ b/platform/windows/power_windows.h @@ -33,7 +33,7 @@ #include "os/dir_access.h" #include "os/file_access.h" -#include "os/power.h" +#include "os/os.h" #include <windows.h> @@ -42,7 +42,7 @@ class PowerWindows { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; bool GetPowerInfo_Windows(); @@ -50,7 +50,7 @@ public: PowerWindows(); virtual ~PowerWindows(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index c926b7799d..3c54d5cbc2 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -39,6 +39,7 @@ #include <dlfcn.h> #include <execinfo.h> #include <signal.h> +#include <stdlib.h> static void handle_crash(int sig) { if (OS::get_singleton() == NULL) @@ -47,7 +48,7 @@ static void handle_crash(int sig) { void *bt_buffer[256]; size_t size = backtrace(bt_buffer, 256); String _execpath = OS::get_singleton()->get_executable_path(); - String msg = GLOBAL_GET("debug/settings/backtrace/message"); + String msg = GLOBAL_GET("debug/settings/crash_handler/message"); // Dump the backtrace to stderr with a message to the user fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig); diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp index 59b1a44247..fdb43c9ae0 100644 --- a/platform/x11/export/export.cpp +++ b/platform/x11/export/export.cpp @@ -50,6 +50,7 @@ void register_x11_exporter() { platform->set_release_64("linux_x11_64_release"); platform->set_debug_64("linux_x11_64_debug"); platform->set_os_name("X11"); + platform->set_chmod_flags(0755); EditorExport::get_singleton()->add_export_platform(platform); } diff --git a/platform/x11/joypad_linux.cpp b/platform/x11/joypad_linux.cpp index 3453297716..428385f7cb 100644 --- a/platform/x11/joypad_linux.cpp +++ b/platform/x11/joypad_linux.cpp @@ -125,7 +125,6 @@ void JoypadLinux::enumerate_joypads(udev *p_udev) { enumerate = udev_enumerate_new(p_udev); udev_enumerate_add_match_subsystem(enumerate, "input"); - udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYPAD", "1"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index f61ccacb98..3e8709a11e 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -313,29 +313,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au XFree(xsh); } - AudioDriverManager::get_driver(p_audio_driver)->set_singleton(); - - audio_driver_index = p_audio_driver; - if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) { - - bool success = false; - audio_driver_index = -1; - for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { - if (i == p_audio_driver) - continue; - AudioDriverManager::get_driver(i)->set_singleton(); - if (AudioDriverManager::get_driver(i)->init() == OK) { - success = true; - print_line("Audio Driver Failed: " + String(AudioDriverManager::get_driver(p_audio_driver)->get_name())); - print_line("Using alternate audio driver: " + String(AudioDriverManager::get_driver(i)->get_name())); - audio_driver_index = i; - break; - } - } - if (!success) { - ERR_PRINT("Initializing audio failed."); - } - } + AudioDriverManager::initialize(p_audio_driver); ERR_FAIL_COND(!visual_server); ERR_FAIL_COND(x11_window == 0); @@ -2167,7 +2145,7 @@ void OS_X11::set_context(int p_context) { } } -PowerState OS_X11::get_power_state() { +OS::PowerState OS_X11::get_power_state() { return power_manager->get_power_state(); } @@ -2189,10 +2167,6 @@ bool OS_X11::is_disable_crash_handler() const { OS_X11::OS_X11() { -#ifdef RTAUDIO_ENABLED - AudioDriverManager::add_driver(&driver_rtaudio); -#endif - #ifdef PULSEAUDIO_ENABLED AudioDriverManager::add_driver(&driver_pulseaudio); #endif @@ -2201,11 +2175,6 @@ OS_X11::OS_X11() { AudioDriverManager::add_driver(&driver_alsa); #endif - if (AudioDriverManager::get_driver_count() == 0) { - WARN_PRINT("No sound driver found... Defaulting to dummy driver"); - AudioDriverManager::add_driver(&driver_dummy); - } - minimized = false; xim_style = 0L; mouse_mode = MOUSE_MODE_VISIBLE; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 14c737d45e..0e2430c650 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -38,11 +38,9 @@ //#include "servers/visual/visual_server_wrap_mt.h" #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" -#include "drivers/rtaudio/audio_driver_rtaudio.h" #include "joypad_linux.h" #include "main/input_default.h" #include "power_x11.h" -#include "servers/audio/audio_driver_dummy.h" #include "servers/audio_server.h" #include "servers/physics_2d/physics_2d_server_sw.h" #include "servers/physics_2d/physics_2d_server_wrap_mt.h" @@ -154,10 +152,6 @@ class OS_X11 : public OS_Unix { JoypadLinux *joypad; #endif -#ifdef RTAUDIO_ENABLED - AudioDriverRtAudio driver_rtaudio; -#endif - #ifdef ALSA_ENABLED AudioDriverALSA driver_alsa; #endif @@ -165,7 +159,6 @@ class OS_X11 : public OS_Unix { #ifdef PULSEAUDIO_ENABLED AudioDriverPulseAudio driver_pulseaudio; #endif - AudioDriverDummy driver_dummy; Atom net_wm_icon; @@ -269,7 +262,7 @@ public: virtual void set_use_vsync(bool p_enable); virtual bool is_vsync_enabled() const; - virtual PowerState get_power_state(); + virtual OS::PowerState get_power_state(); virtual int get_power_seconds_left(); virtual int get_power_percent_left(); diff --git a/platform/x11/power_x11.cpp b/platform/x11/power_x11.cpp index 32100354a6..76ff7f91fb 100644 --- a/platform/x11/power_x11.cpp +++ b/platform/x11/power_x11.cpp @@ -252,7 +252,7 @@ bool PowerX11::GetPowerInfo_Linux_proc_acpi() { this->nsecs_left = -1; this->percent_left = -1; - this->power_state = POWERSTATE_UNKNOWN; + this->power_state = OS::POWERSTATE_UNKNOWN; dirp->change_dir(proc_acpi_battery_path); Error err = dirp->list_dir_begin(); @@ -282,13 +282,13 @@ bool PowerX11::GetPowerInfo_Linux_proc_acpi() { } if (!have_battery) { - this->power_state = POWERSTATE_NO_BATTERY; + this->power_state = OS::POWERSTATE_NO_BATTERY; } else if (charging) { - this->power_state = POWERSTATE_CHARGING; + this->power_state = OS::POWERSTATE_CHARGING; } else if (have_ac) { - this->power_state = POWERSTATE_CHARGED; + this->power_state = OS::POWERSTATE_CHARGED; } else { - this->power_state = POWERSTATE_ON_BATTERY; + this->power_state = OS::POWERSTATE_ON_BATTERY; } return true; /* definitive answer. */ @@ -400,17 +400,17 @@ bool PowerX11::GetPowerInfo_Linux_proc_apm() { } if (battery_flag == 0xFF) { /* unknown state */ - this->power_state = POWERSTATE_UNKNOWN; + this->power_state = OS::POWERSTATE_UNKNOWN; } else if (battery_flag & (1 << 7)) { /* no battery */ - this->power_state = POWERSTATE_NO_BATTERY; + this->power_state = OS::POWERSTATE_NO_BATTERY; } else if (battery_flag & (1 << 3)) { /* charging */ - this->power_state = POWERSTATE_CHARGING; + this->power_state = OS::POWERSTATE_CHARGING; need_details = true; } else if (ac_status == 1) { - this->power_state = POWERSTATE_CHARGED; /* on AC, not charging. */ + this->power_state = OS::POWERSTATE_CHARGED; /* on AC, not charging. */ need_details = true; } else { - this->power_state = POWERSTATE_ON_BATTERY; + this->power_state = OS::POWERSTATE_ON_BATTERY; need_details = true; } @@ -445,7 +445,7 @@ bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, in return false; } - this->power_state = POWERSTATE_NO_BATTERY; /* assume we're just plugged in. */ + this->power_state = OS::POWERSTATE_NO_BATTERY; /* assume we're just plugged in. */ this->nsecs_left = -1; this->percent_left = -1; @@ -454,7 +454,7 @@ bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, in while (name != "") { bool choose = false; char str[64]; - PowerState st; + OS::PowerState st; int secs; int pct; @@ -475,17 +475,17 @@ bool PowerX11::GetPowerInfo_Linux_sys_class_power_supply(/*PowerState *state, in /* some drivers don't offer this, so if it's not explicitly reported assume it's present. */ if (read_power_file(base, name.utf8().get_data(), "present", str, sizeof(str)) && (String(str) == "0\n")) { - st = POWERSTATE_NO_BATTERY; + st = OS::POWERSTATE_NO_BATTERY; } else if (!read_power_file(base, name.utf8().get_data(), "status", str, sizeof(str))) { - st = POWERSTATE_UNKNOWN; /* uh oh */ + st = OS::POWERSTATE_UNKNOWN; /* uh oh */ } else if (String(str) == "Charging\n") { - st = POWERSTATE_CHARGING; + st = OS::POWERSTATE_CHARGING; } else if (String(str) == "Discharging\n") { - st = POWERSTATE_ON_BATTERY; + st = OS::POWERSTATE_ON_BATTERY; } else if ((String(str) == "Full\n") || (String(str) == "Not charging\n")) { - st = POWERSTATE_CHARGED; + st = OS::POWERSTATE_CHARGED; } else { - st = POWERSTATE_UNKNOWN; /* uh oh */ + st = OS::POWERSTATE_UNKNOWN; /* uh oh */ } if (!read_power_file(base, name.utf8().get_data(), "capacity", str, sizeof(str))) { @@ -543,17 +543,17 @@ bool PowerX11::UpdatePowerInfo() { } PowerX11::PowerX11() - : nsecs_left(-1), percent_left(-1), power_state(POWERSTATE_UNKNOWN) { + : nsecs_left(-1), percent_left(-1), power_state(OS::POWERSTATE_UNKNOWN) { } PowerX11::~PowerX11() { } -PowerState PowerX11::get_power_state() { +OS::PowerState PowerX11::get_power_state() { if (UpdatePowerInfo()) { return power_state; } else { - return POWERSTATE_UNKNOWN; + return OS::POWERSTATE_UNKNOWN; } } diff --git a/platform/x11/power_x11.h b/platform/x11/power_x11.h index e34223036d..7fc258bc0d 100644 --- a/platform/x11/power_x11.h +++ b/platform/x11/power_x11.h @@ -33,14 +33,14 @@ #include "os/dir_access.h" #include "os/file_access.h" -#include "os/power.h" +#include "os/os.h" class PowerX11 { private: int nsecs_left; int percent_left; - PowerState power_state; + OS::PowerState power_state; FileAccessRef open_power_file(const char *base, const char *node, const char *key); bool read_power_file(const char *base, const char *node, const char *key, char *buf, size_t buflen); @@ -58,7 +58,7 @@ public: PowerX11(); virtual ~PowerX11(); - PowerState get_power_state(); + OS::PowerState get_power_state(); int get_power_seconds_left(); int get_power_percent_left(); }; diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index e2764a6e8d..a840744c78 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -302,6 +302,9 @@ void CollisionPolygon2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "one_way_collision"), "set_one_way_collision", "is_one_way_collision_enabled"); + + BIND_ENUM_CONSTANT(BUILD_SOLIDS); + BIND_ENUM_CONSTANT(BUILD_SEGMENTS); } CollisionPolygon2D::CollisionPolygon2D() { diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index 1bca2c6f37..516acefe2a 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -443,6 +443,13 @@ void Light2D::_bind_methods() { BIND_ENUM_CONSTANT(MODE_SUB); BIND_ENUM_CONSTANT(MODE_MIX); BIND_ENUM_CONSTANT(MODE_MASK); + + BIND_ENUM_CONSTANT(SHADOW_FILTER_NONE); + BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF3); + BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF5); + BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF7); + BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF9); + BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF13); } Light2D::Light2D() { diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index c87a9a5b1e..d8cef5b937 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -28,13 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "line_2d.h" +#include "line_builder.h" #include "core_string_names.h" // Needed so we can bind functions -VARIANT_ENUM_CAST(LineJointMode) -VARIANT_ENUM_CAST(LineCapMode) -VARIANT_ENUM_CAST(LineTextureMode) +VARIANT_ENUM_CAST(Line2D::LineJointMode) +VARIANT_ENUM_CAST(Line2D::LineCapMode) +VARIANT_ENUM_CAST(Line2D::LineTextureMode) Line2D::Line2D() : Node2D() { @@ -134,7 +135,7 @@ void Line2D::set_texture_mode(const LineTextureMode mode) { update(); } -LineTextureMode Line2D::get_texture_mode() const { +Line2D::LineTextureMode Line2D::get_texture_mode() const { return _texture_mode; } @@ -143,7 +144,7 @@ void Line2D::set_joint_mode(LineJointMode mode) { update(); } -LineJointMode Line2D::get_joint_mode() const { +Line2D::LineJointMode Line2D::get_joint_mode() const { return _joint_mode; } @@ -152,7 +153,7 @@ void Line2D::set_begin_cap_mode(LineCapMode mode) { update(); } -LineCapMode Line2D::get_begin_cap_mode() const { +Line2D::LineCapMode Line2D::get_begin_cap_mode() const { return _begin_cap_mode; } @@ -161,7 +162,7 @@ void Line2D::set_end_cap_mode(LineCapMode mode) { update(); } -LineCapMode Line2D::get_end_cap_mode() const { +Line2D::LineCapMode Line2D::get_end_cap_mode() const { return _end_cap_mode; } diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h index 017ccf13ff..36aadfd265 100644 --- a/scene/2d/line_2d.h +++ b/scene/2d/line_2d.h @@ -30,7 +30,6 @@ #ifndef LINE2D_H #define LINE2D_H -#include "line_builder.h" #include "node_2d.h" class Line2D : public Node2D { @@ -38,6 +37,24 @@ class Line2D : public Node2D { GDCLASS(Line2D, Node2D) public: + enum LineJointMode { + LINE_JOINT_SHARP = 0, + LINE_JOINT_BEVEL, + LINE_JOINT_ROUND + }; + + enum LineCapMode { + LINE_CAP_NONE = 0, + LINE_CAP_BOX, + LINE_CAP_ROUND + }; + + enum LineTextureMode { + LINE_TEXTURE_NONE = 0, + LINE_TEXTURE_TILE + // TODO STRETCH mode + }; + Line2D(); void set_points(const PoolVector<Vector2> &p_points); diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp index 53db30e3ce..4873c47827 100644 --- a/scene/2d/line_builder.cpp +++ b/scene/2d/line_builder.cpp @@ -92,14 +92,14 @@ static inline Vector2 interpolate(const Rect2 &r, const Vector2 &v) { //---------------------------------------------------------------------------- LineBuilder::LineBuilder() { - joint_mode = LINE_JOINT_SHARP; + joint_mode = Line2D::LINE_JOINT_SHARP; width = 10; default_color = Color(0.4, 0.5, 1); gradient = NULL; sharp_limit = 2.f; round_precision = 8; - begin_cap_mode = LINE_CAP_NONE; - end_cap_mode = LINE_CAP_NONE; + begin_cap_mode = Line2D::LINE_CAP_NONE; + end_cap_mode = Line2D::LINE_CAP_NONE; _interpolate_color = false; _last_index[0] = 0; @@ -141,7 +141,7 @@ void LineBuilder::build() { float current_distance1 = 0.f; float total_distance = 0.f; _interpolate_color = gradient != NULL; - bool distance_required = _interpolate_color || texture_mode == LINE_TEXTURE_TILE; + bool distance_required = _interpolate_color || texture_mode == Line2D::LINE_TEXTURE_TILE; if (distance_required) total_distance = calculate_total_distance(points); if (_interpolate_color) @@ -153,7 +153,7 @@ void LineBuilder::build() { float uvx1 = 0.f; // Begin cap - if (begin_cap_mode == LINE_CAP_BOX) { + if (begin_cap_mode == Line2D::LINE_CAP_BOX) { // Push back first vertices a little bit pos_up0 -= f0 * hw; pos_down0 -= f0 * hw; @@ -161,8 +161,8 @@ void LineBuilder::build() { total_distance += width; current_distance0 += hw; current_distance1 = current_distance0; - } else if (begin_cap_mode == LINE_CAP_ROUND) { - if (texture_mode == LINE_TEXTURE_TILE) { + } else if (begin_cap_mode == Line2D::LINE_CAP_ROUND) { + if (texture_mode == Line2D::LINE_TEXTURE_TILE) { uvx0 = 0.5f; } new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, 1.f, 1.f)); @@ -247,15 +247,15 @@ void LineBuilder::build() { corner_pos_down = corner_pos_in; } - LineJointMode current_joint_mode = joint_mode; + Line2D::LineJointMode current_joint_mode = joint_mode; Vector2 pos_up1, pos_down1; if (intersection_result == SEGMENT_INTERSECT) { // Fallback on bevel if sharp angle is too high (because it would produce very long miters) - if (current_joint_mode == LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / hw_sq > sharp_limit_sq) { - current_joint_mode = LINE_JOINT_BEVEL; + if (current_joint_mode == Line2D::LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / hw_sq > sharp_limit_sq) { + current_joint_mode = Line2D::LINE_JOINT_BEVEL; } - if (current_joint_mode == LINE_JOINT_SHARP) { + if (current_joint_mode == Line2D::LINE_JOINT_SHARP) { // In this case, we won't create joint geometry, // The previous and next line quads will directly share an edge. pos_up1 = corner_pos_up; @@ -284,7 +284,7 @@ void LineBuilder::build() { if (_interpolate_color) { color1 = gradient->get_color_at_offset(current_distance1 / total_distance); } - if (texture_mode == LINE_TEXTURE_TILE) { + if (texture_mode == Line2D::LINE_TEXTURE_TILE) { uvx0 = current_distance0 / width; uvx1 = current_distance1 / width; } @@ -298,7 +298,7 @@ void LineBuilder::build() { pos0 = pos1; current_distance0 = current_distance1; if (intersection_result == SEGMENT_INTERSECT) { - if (current_joint_mode == LINE_JOINT_SHARP) { + if (current_joint_mode == Line2D::LINE_JOINT_SHARP) { pos_up0 = pos_up1; pos_down0 = pos_down1; } else { @@ -317,7 +317,7 @@ void LineBuilder::build() { // From this point, bu0 and bd0 concern the next segment // Add joint geometry - if (current_joint_mode != LINE_JOINT_SHARP) { + if (current_joint_mode != Line2D::LINE_JOINT_SHARP) { /* ________________ cbegin * / \ @@ -337,9 +337,9 @@ void LineBuilder::build() { cend = pos_up0; } - if (current_joint_mode == LINE_JOINT_BEVEL) { + if (current_joint_mode == Line2D::LINE_JOINT_BEVEL) { strip_add_tri(cend, orientation); - } else if (current_joint_mode == LINE_JOINT_ROUND) { + } else if (current_joint_mode == Line2D::LINE_JOINT_ROUND) { Vector2 vbegin = cbegin - pos1; Vector2 vend = cend - pos1; strip_add_arc(pos1, vbegin.angle_to(vend), orientation); @@ -360,7 +360,7 @@ void LineBuilder::build() { Vector2 pos_down1 = pos1 - u0 * hw; // End cap (box) - if (end_cap_mode == LINE_CAP_BOX) { + if (end_cap_mode == Line2D::LINE_CAP_BOX) { pos_up1 += f0 * hw; pos_down1 += f0 * hw; } @@ -371,14 +371,14 @@ void LineBuilder::build() { if (_interpolate_color) { color1 = gradient->get_color(gradient->get_points_count() - 1); } - if (texture_mode == LINE_TEXTURE_TILE) { + if (texture_mode == Line2D::LINE_TEXTURE_TILE) { uvx1 = current_distance1 / width; } strip_add_quad(pos_up1, pos_down1, color1, uvx1); // End cap (round) - if (end_cap_mode == LINE_CAP_ROUND) { + if (end_cap_mode == Line2D::LINE_CAP_ROUND) { // Note: color is not used in case we don't interpolate... Color color = _interpolate_color ? gradient->get_color(gradient->get_points_count() - 1) : Color(0, 0, 0); new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1 - 0.5f, 0.f, 1.f, 1.f)); @@ -396,7 +396,7 @@ void LineBuilder::strip_begin(Vector2 up, Vector2 down, Color color, float uvx) colors.push_back(color); } - if (texture_mode != LINE_TEXTURE_NONE) { + if (texture_mode != Line2D::LINE_TEXTURE_NONE) { uvs.push_back(Vector2(uvx, 0.f)); uvs.push_back(Vector2(uvx, 1.f)); } @@ -420,7 +420,7 @@ void LineBuilder::strip_new_quad(Vector2 up, Vector2 down, Color color, float uv colors.push_back(color); } - if (texture_mode != LINE_TEXTURE_NONE) { + if (texture_mode != Line2D::LINE_TEXTURE_NONE) { uvs.push_back(uvs[_last_index[UP]]); uvs.push_back(uvs[_last_index[DOWN]]); uvs.push_back(Vector2(uvx, UP)); @@ -449,7 +449,7 @@ void LineBuilder::strip_add_quad(Vector2 up, Vector2 down, Color color, float uv colors.push_back(color); } - if (texture_mode != LINE_TEXTURE_NONE) { + if (texture_mode != Line2D::LINE_TEXTURE_NONE) { uvs.push_back(Vector2(uvx, 0.f)); uvs.push_back(Vector2(uvx, 1.f)); } @@ -476,7 +476,7 @@ void LineBuilder::strip_add_tri(Vector2 up, Orientation orientation) { Orientation opposite_orientation = orientation == UP ? DOWN : UP; - if (texture_mode != LINE_TEXTURE_NONE) { + if (texture_mode != Line2D::LINE_TEXTURE_NONE) { // UVs are just one slice of the texture all along // (otherwise we can't share the bottom vertice) uvs.push_back(uvs[_last_index[opposite_orientation]]); @@ -541,7 +541,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col vertices.push_back(center); if (_interpolate_color) colors.push_back(color); - if (texture_mode != LINE_TEXTURE_NONE) + if (texture_mode != Line2D::LINE_TEXTURE_NONE) uvs.push_back(interpolate(uv_rect, Vector2(0.5f, 0.5f))); // Arc vertices @@ -552,7 +552,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col vertices.push_back(rpos); if (_interpolate_color) colors.push_back(color); - if (texture_mode != LINE_TEXTURE_NONE) { + if (texture_mode != Line2D::LINE_TEXTURE_NONE) { Vector2 tsc = Vector2(Math::cos(tt), Math::sin(tt)); uvs.push_back(interpolate(uv_rect, 0.5f * (tsc + Vector2(1.f, 1.f)))); tt += angle_step; @@ -565,7 +565,7 @@ void LineBuilder::new_arc(Vector2 center, Vector2 vbegin, float angle_delta, Col vertices.push_back(rpos); if (_interpolate_color) colors.push_back(color); - if (texture_mode != LINE_TEXTURE_NONE) { + if (texture_mode != Line2D::LINE_TEXTURE_NONE) { tt = tt_begin + angle_delta; Vector2 tsc = Vector2(Math::cos(tt), Math::sin(tt)); uvs.push_back(interpolate(uv_rect, 0.5f * (tsc + Vector2(1.f, 1.f)))); diff --git a/scene/2d/line_builder.h b/scene/2d/line_builder.h index 227e0abd08..f12fbf6f82 100644 --- a/scene/2d/line_builder.h +++ b/scene/2d/line_builder.h @@ -31,39 +31,22 @@ #define LINE_BUILDER_H #include "color.h" +#include "line_2d.h" #include "math_2d.h" #include "scene/resources/color_ramp.h" -enum LineJointMode { - LINE_JOINT_SHARP = 0, - LINE_JOINT_BEVEL, - LINE_JOINT_ROUND -}; - -enum LineCapMode { - LINE_CAP_NONE = 0, - LINE_CAP_BOX, - LINE_CAP_ROUND -}; - -enum LineTextureMode { - LINE_TEXTURE_NONE = 0, - LINE_TEXTURE_TILE - // TODO STRETCH mode -}; - class LineBuilder { public: // TODO Move in a struct and reference it // Input Vector<Vector2> points; - LineJointMode joint_mode; - LineCapMode begin_cap_mode; - LineCapMode end_cap_mode; + Line2D::LineJointMode joint_mode; + Line2D::LineCapMode begin_cap_mode; + Line2D::LineCapMode end_cap_mode; float width; Color default_color; Gradient *gradient; - LineTextureMode texture_mode; + Line2D::LineTextureMode texture_mode; float sharp_limit; int round_precision; // TODO offset_joints option (offers alternative implementation of round joints) diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp index c9bf6675d2..bf7c5a3ba4 100644 --- a/scene/2d/screen_button.cpp +++ b/scene/2d/screen_button.cpp @@ -399,6 +399,9 @@ void TouchScreenButton::_bind_methods() { ADD_SIGNAL(MethodInfo("pressed")); ADD_SIGNAL(MethodInfo("released")); + + BIND_ENUM_CONSTANT(VISIBILITY_ALWAYS); + BIND_ENUM_CONSTANT(VISIBILITY_TOUCHSCREEN_ONLY); } TouchScreenButton::TouchScreenButton() { diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp index 217cb71230..266bc5e381 100644 --- a/scene/3d/area.cpp +++ b/scene/3d/area.cpp @@ -729,6 +729,12 @@ void Area::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "reverb_bus_name", PROPERTY_HINT_ENUM, ""), "set_reverb_bus", "get_reverb_bus"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_amount", "get_reverb_amount"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "reverb_bus_uniformity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_reverb_uniformity", "get_reverb_uniformity"); + + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_DISABLED); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE_REPLACE); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE); + BIND_ENUM_CONSTANT(SPACE_OVERRIDE_REPLACE_COMBINE); } Area::Area() diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp index 966dd88a2c..147d3bf115 100644 --- a/scene/3d/arvr_nodes.cpp +++ b/scene/3d/arvr_nodes.cpp @@ -184,7 +184,7 @@ int ARVRController::get_joystick_id() const { int ARVRController::is_button_pressed(int p_button) const { int joy_id = get_joystick_id(); - if (joy_id == 0) { + if (joy_id == -1) { return false; }; @@ -193,7 +193,7 @@ int ARVRController::is_button_pressed(int p_button) const { float ARVRController::get_joystick_axis(int p_axis) const { int joy_id = get_joystick_id(); - if (joy_id == 0) { + if (joy_id == -1) { return 0.0; }; diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 096f787873..7402e664d9 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -405,6 +405,12 @@ void OmniLight::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::REAL, "omni_attenuation", PROPERTY_HINT_EXP_EASING), "set_param", "get_param", PARAM_ATTENUATION); ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_mode", PROPERTY_HINT_ENUM, "Dual Paraboloid,Cube"), "set_shadow_mode", "get_shadow_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "omni_shadow_detail", PROPERTY_HINT_ENUM, "Vertical,Horizontal"), "set_shadow_detail", "get_shadow_detail"); + + BIND_ENUM_CONSTANT(SHADOW_DUAL_PARABOLOID); + BIND_ENUM_CONSTANT(SHADOW_CUBE); + + BIND_ENUM_CONSTANT(SHADOW_DETAIL_VERTICAL); + BIND_ENUM_CONSTANT(SHADOW_DETAIL_HORIZONTAL); } OmniLight::OmniLight() diff --git a/scene/3d/light.h b/scene/3d/light.h index 6aa0220265..2f3ac8a5e7 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -150,7 +150,7 @@ public: void set_shadow_mode(ShadowMode p_mode); ShadowMode get_shadow_mode() const; - void set_shadow_depth_range(ShadowDepthRange p_mode); + void set_shadow_depth_range(ShadowDepthRange p_range); ShadowDepthRange get_shadow_depth_range() const; void set_blend_splits(bool p_enable); diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 7525eb5069..6551deabf2 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -874,6 +874,11 @@ void RigidBody::_bind_methods() { BIND_ENUM_CONSTANT(MODE_KINEMATIC); BIND_ENUM_CONSTANT(MODE_RIGID); BIND_ENUM_CONSTANT(MODE_CHARACTER); + + BIND_ENUM_CONSTANT(AXIS_LOCK_DISABLED); + BIND_ENUM_CONSTANT(AXIS_LOCK_X); + BIND_ENUM_CONSTANT(AXIS_LOCK_Y); + BIND_ENUM_CONSTANT(AXIS_LOCK_Z); } RigidBody::RigidBody() diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 0464a82f65..fa35d982eb 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -288,12 +288,13 @@ void GeometryInstance::_bind_methods() { //ADD_SIGNAL( MethodInfo("visibility_changed")); - BIND_CONSTANT(FLAG_MAX); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); - BIND_CONSTANT(SHADOW_CASTING_SETTING_OFF); - BIND_CONSTANT(SHADOW_CASTING_SETTING_ON); - BIND_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); - BIND_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); + BIND_ENUM_CONSTANT(FLAG_USE_BAKED_LIGHT); + BIND_ENUM_CONSTANT(FLAG_MAX); } GeometryInstance::GeometryInstance() { diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index 7a5c7e450b..38d0527288 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -1808,6 +1808,9 @@ void AnimationTreePlayer::_bind_methods() { BIND_ENUM_CONSTANT(NODE_TIMESCALE); BIND_ENUM_CONSTANT(NODE_TIMESEEK); BIND_ENUM_CONSTANT(NODE_TRANSITION); + + BIND_ENUM_CONSTANT(ANIMATION_PROCESS_FIXED); + BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE); } AnimationTreePlayer::AnimationTreePlayer() { diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index 6a582c9a3d..661d085dfd 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -308,6 +308,10 @@ void AudioStreamPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); ADD_SIGNAL(MethodInfo("finished")); + + BIND_ENUM_CONSTANT(MIX_TARGET_STEREO); + BIND_ENUM_CONSTANT(MIX_TARGET_SURROUND); + BIND_ENUM_CONSTANT(MIX_TARGET_CENTER); } AudioStreamPlayer::AudioStreamPlayer() { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 87dfd95724..2d5b54257a 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -809,9 +809,9 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName & // try with custom themes Control *theme_owner = data.theme_owner; - while (theme_owner) { + StringName class_name = type; - StringName class_name = type; + while (theme_owner) { while (class_name != StringName()) { if (theme_owner->data.theme->has_stylebox(p_name, class_name)) { @@ -829,6 +829,14 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName & theme_owner = NULL; } + class_name = type; + + while (class_name != StringName()) { + if (Theme::get_default()->has_stylebox(p_name, class_name)) + return Theme::get_default()->get_stylebox(p_name, class_name); + + class_name = ClassDB::get_parent_class_nocheck(class_name); + } return Theme::get_default()->get_stylebox(p_name, type); } Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 5b00aab2ef..4477e9ecf9 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -283,7 +283,7 @@ void GraphEdit::_notification(int p_what) { zoom_minus->set_icon(get_icon("minus")); zoom_reset->set_icon(get_icon("reset")); zoom_plus->set_icon(get_icon("more")); - snap_button->set_icon(get_icon("snap")); + snap_button->set_icon(get_icon("SnapGrid")); //zoom_icon->set_texture( get_icon("Zoom", "EditorIcons")); } if (p_what == NOTIFICATION_DRAW) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index ab2c2f445f..71b9c4ec72 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -540,14 +540,6 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int it = _get_next_item(it); - if (p_mode == PROCESS_POINTER && r_click_item && itp && !it && p_click_pos.y > p_ofs.y + y + lh) { - //at the end of all, return this - if (r_outside) *r_outside = true; - *r_click_item = itp; - *r_click_char = rchar; - return; - } - if (it && (p_line + 1 < p_frame->lines.size()) && p_frame->lines[p_line + 1].from == it) { if (p_mode == PROCESS_POINTER && r_click_item && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh) { diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index 16d1b320b7..41f4beb1c9 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -106,9 +106,9 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { if (ofs < grabber_ofs) { if (scrolling) { - target_scroll = target_scroll - get_page(); + target_scroll = CLAMP(target_scroll - get_page(), get_min(), get_max() - get_page()); } else { - target_scroll = get_value() - get_page(); + target_scroll = CLAMP(get_value() - get_page(), get_min(), get_max() - get_page()); } if (smooth_scroll_enabled) { @@ -130,9 +130,9 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { update(); } else { if (scrolling) { - target_scroll = target_scroll + get_page(); + target_scroll = CLAMP(target_scroll + get_page(), get_min(), get_max() - get_page()); } else { - target_scroll = get_value() + get_page(); + target_scroll = CLAMP(get_value() + get_page(), get_min(), get_max() - get_page()); } if (smooth_scroll_enabled) { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 461ae3444b..98a8db336e 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -208,6 +208,9 @@ void TabContainer::_notification(int p_what) { break; } + // Draw the tab area. + panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height)); + // Draw all visible tabs. int x = 0; for (int i = 0; i < tab_widths.size(); i++) { @@ -280,9 +283,6 @@ void TabContainer::_notification(int p_what) { Point2(x, y_center - (decrement->get_height() / 2)), Color(1, 1, 1, first_tab_cache > 0 ? 1.0 : 0.5)); } - - // Draw the tab area. - panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height)); } break; case NOTIFICATION_THEME_CHANGED: { if (get_tab_count() > 0) { @@ -655,6 +655,10 @@ void TabContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align"); ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible"); + + BIND_ENUM_CONSTANT(ALIGN_LEFT); + BIND_ENUM_CONSTANT(ALIGN_CENTER); + BIND_ENUM_CONSTANT(ALIGN_RIGHT); } TabContainer::TabContainer() { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1738e303aa..d30e0b9f25 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -36,6 +36,10 @@ #include "project_settings.h" #include "scene/main/viewport.h" +#ifdef TOOLS_ENABLED +#include "editor/editor_scale.h" +#endif + #define TAB_PIXELS static bool _is_text_char(CharType c) { @@ -729,15 +733,18 @@ void TextEdit::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color); } - if (text.is_breakpoint(line)) { - - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); - } - if (line == cursor.line) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color); } + if (text.is_breakpoint(line) && !draw_breakpoint_gutter) { +#ifdef TOOLS_ENABLED + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); +#else + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); +#endif + } + // draw breakpoint marker if (text.is_breakpoint(line)) { if (draw_breakpoint_gutter) { @@ -2793,12 +2800,16 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { int ini = selection.from_line; int end = selection.to_line; for (int i = ini; i <= end; i++) { - if (text[i][0] == '#') + if (get_line(i).begins_with("#")) _remove_text(i, 0, i, 1); } } else { - if (text[cursor.line][0] == '#') + if (get_line(cursor.line).begins_with("#")) { _remove_text(cursor.line, 0, cursor.line, 1); + if (cursor.column >= get_line(cursor.line).length()) { + cursor.column = MAX(0, get_line(cursor.line).length() - 1); + } + } } update(); } @@ -4255,6 +4266,10 @@ bool TextEdit::is_insert_mode() const { return insert_mode; } +bool TextEdit::is_insert_text_operation() { + return (current_op.type == TextOperation::TYPE_INSERT); +} + uint32_t TextEdit::get_version() const { return current_op.version; } diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 68ef559f46..7e61c4e8b1 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -386,6 +386,8 @@ public: void begin_complex_operation(); void end_complex_operation(); + bool is_insert_text_operation(); + void set_text(String p_text); void insert_text_at_cursor(const String &p_text); void insert_at(const String &p_text, int at); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 4975b66744..1aaea98798 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -771,6 +771,10 @@ void TreeItem::_bind_methods() { BIND_ENUM_CONSTANT(CELL_MODE_RANGE_EXPRESSION); BIND_ENUM_CONSTANT(CELL_MODE_ICON); BIND_ENUM_CONSTANT(CELL_MODE_CUSTOM); + + BIND_ENUM_CONSTANT(ALIGN_LEFT); + BIND_ENUM_CONSTANT(ALIGN_CENTER); + BIND_ENUM_CONSTANT(ALIGN_RIGHT); } void TreeItem::clear_children() { @@ -2006,7 +2010,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (!k->is_pressed()) return; - if (k->get_alt() || k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) + if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) return; if (!root) return; @@ -2021,48 +2025,47 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { break; \ } case KEY_RIGHT: { + bool dobreak = true; //TreeItem *next = NULL; if (!selected_item) break; - if (select_mode == SELECT_ROW) + if (select_mode == SELECT_ROW) { EXIT_BREAK; - if (selected_col >= (columns.size() - 1)) + } + if (selected_col > (columns.size() - 1)) { EXIT_BREAK; - if (select_mode == SELECT_MULTI) { - selected_col++; - emit_signal("cell_selected"); + } + if (k->get_alt()) { + selected_item->set_collapsed(false); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(false); + next = next->get_next_visible(); + } + } else if (selected_col == (columns.size() - 1)) { + if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { + selected_item->set_collapsed(false); + } else { + selected_col = 0; + dobreak = false; // fall through to key_down + } } else { + if (select_mode == SELECT_MULTI) { + selected_col++; + emit_signal("cell_selected"); + } else { - selected_item->select(selected_col + 1); + selected_item->select(selected_col + 1); + } } - update(); ensure_cursor_is_visible(); accept_event(); - - } break; - case KEY_LEFT: { - - //TreeItem *next = NULL; - if (!selected_item) + if (dobreak) { break; - if (select_mode == SELECT_ROW) - EXIT_BREAK; - if (selected_col <= 0) - EXIT_BREAK; - if (select_mode == SELECT_MULTI) { - selected_col--; - emit_signal("cell_selected"); - } else { - - selected_item->select(selected_col - 1); } - - update(); - accept_event(); - - } break; + } case KEY_DOWN: { TreeItem *next = NULL; @@ -2109,6 +2112,48 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { accept_event(); } break; + case KEY_LEFT: { + bool dobreak = true; + + //TreeItem *next = NULL; + if (!selected_item) + break; + if (select_mode == SELECT_ROW) { + EXIT_BREAK; + } + if (selected_col < 0) { + EXIT_BREAK; + } + if (k->get_alt()) { + selected_item->set_collapsed(true); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(true); + next = next->get_next_visible(); + } + } else if (selected_col == 0) { + if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) { + selected_item->set_collapsed(true); + } else { + selected_col = columns.size() - 1; + dobreak = false; // fall through to key_up + } + } else { + if (select_mode == SELECT_MULTI) { + selected_col--; + emit_signal("cell_selected"); + } else { + + selected_item->select(selected_col - 1); + } + } + update(); + accept_event(); + + if (dobreak) { + break; + } + } case KEY_UP: { TreeItem *prev = NULL; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 567b1dd7a1..d27a1a5641 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2762,6 +2762,15 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(MSAA_4X); BIND_ENUM_CONSTANT(MSAA_8X); BIND_ENUM_CONSTANT(MSAA_16X); + + BIND_ENUM_CONSTANT(USAGE_2D); + BIND_ENUM_CONSTANT(USAGE_2D_NO_SAMPLING); + BIND_ENUM_CONSTANT(USAGE_3D); + BIND_ENUM_CONSTANT(USAGE_3D_NO_EFFECTS); + + BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS); + BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER); + BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME); } Viewport::Viewport() { diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index 659322897a..dff0fb8588 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -536,6 +536,14 @@ void AudioStreamSample::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_rate"), "set_mix_rate", "get_mix_rate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stereo"), "set_stereo", "is_stereo"); ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); + + BIND_ENUM_CONSTANT(FORMAT_8_BITS); + BIND_ENUM_CONSTANT(FORMAT_16_BITS); + BIND_ENUM_CONSTANT(FORMAT_IMA_ADPCM); + + BIND_ENUM_CONSTANT(LOOP_DISABLED); + BIND_ENUM_CONSTANT(LOOP_FORWARD); + BIND_ENUM_CONSTANT(LOOP_PING_PONG); } AudioStreamSample::AudioStreamSample() { diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 2e89a739bd..1066848dd1 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -514,6 +514,10 @@ void Curve::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); ADD_SIGNAL(MethodInfo(SIGNAL_RANGE_CHANGED)); + + BIND_ENUM_CONSTANT(TANGENT_FREE); + BIND_ENUM_CONSTANT(TANGENT_LINEAR); + BIND_ENUM_CONSTANT(TANGENT_MODE_COUNT); } int Curve2D::get_point_count() const { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 1272e5a946..2fbd5ebdd3 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -879,7 +879,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png)); theme->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png)); theme->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png)); - theme->set_icon("snap", "GraphEdit", make_icon(icon_snap_png)); + theme->set_icon("SnapGrid", "GraphEdit", make_icon(icon_snap_grid_png)); theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5)); theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05)); theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2)); diff --git a/scene/resources/default_theme/icon_snap.png b/scene/resources/default_theme/icon_snap_grid.png Binary files differindex 93194d34e7..44db9bdfdc 100644 --- a/scene/resources/default_theme/icon_snap.png +++ b/scene/resources/default_theme/icon_snap_grid.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index bed4bdb760..6643b4ccc1 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -182,8 +182,8 @@ static const unsigned char icon_reload_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x1, 0x59, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0x4b, 0x3, 0x31, 0x18, 0x86, 0x9f, 0x5c, 0xe, 0xec, 0x20, 0x76, 0x70, 0x39, 0xd0, 0xe3, 0xba, 0x74, 0x51, 0x41, 0xdd, 0xfc, 0x7, 0xba, 0xb8, 0x8, 0x52, 0xec, 0x2e, 0x4e, 0x3a, 0x88, 0x3f, 0xa3, 0xa3, 0x53, 0x7, 0x47, 0x67, 0x41, 0x17, 0xdd, 0x9c, 0x5c, 0x3b, 0xd8, 0x82, 0x64, 0x68, 0xca, 0xd5, 0x55, 0x11, 0x3c, 0x1a, 0x87, 0x24, 0x2e, 0xd7, 0x72, 0x9e, 0x9e, 0xab, 0xbe, 0xd3, 0xc7, 0x1b, 0x9e, 0x37, 0xf9, 0xbe, 0x7c, 0xf0, 0xd7, 0x12, 0x3f, 0x99, 0x4a, 0xa9, 0xb9, 0x30, 0xc, 0x8f, 0x84, 0x10, 0x7, 0xc0, 0x5a, 0x6e, 0x3f, 0x3a, 0xe7, 0x2e, 0xad, 0xb5, 0xdd, 0x66, 0xb3, 0xf9, 0x51, 0x19, 0x90, 0xa6, 0xe9, 0x92, 0xb5, 0xf6, 0x6, 0x58, 0xaf, 0xb8, 0xb4, 0x27, 0xa5, 0xdc, 0x8d, 0xe3, 0xf8, 0x19, 0x20, 0x28, 0xdf, 0x5c, 0x80, 0x53, 0x60, 0xdf, 0x18, 0x53, 0x37, 0xc6, 0xd4, 0xbd, 0xf7, 0x7b, 0xc0, 0x13, 0xb0, 0x61, 0xad, 0xbd, 0x56, 0x4a, 0xcd, 0x1, 0x84, 0xc5, 0x80, 0x30, 0xc, 0x8f, 0xa6, 0xb0, 0x94, 0x72, 0x33, 0x8e, 0xe3, 0x97, 0xc2, 0xf1, 0xd5, 0x68, 0x34, 0xba, 0xf7, 0xde, 0xf7, 0x80, 0xd, 0x29, 0xe5, 0x21, 0x70, 0xfe, 0xe5, 0x5, 0x42, 0x88, 0x76, 0x5e, 0x9e, 0x96, 0x60, 0x0, 0x92, 0x24, 0x79, 0x75, 0xce, 0x9d, 0x1, 0x4, 0x41, 0xd0, 0xfe, 0xd6, 0x2, 0xb0, 0x2, 0x60, 0x8c, 0xb9, 0xab, 0xe8, 0x1f, 0x6b, 0xed, 0x6d, 0x5e, 0xae, 0xce, 0x2, 0xb4, 0xd6, 0x17, 0x5a, 0x6b, 0x7, 0xcc, 0x3, 0xd4, 0x6a, 0xb5, 0x37, 0xad, 0xf5, 0xc5, 0x4f, 0x1, 0x41, 0x10, 0x7c, 0x19, 0x7c, 0x90, 0x3, 0xc7, 0xc0, 0xa0, 0xe0, 0xf, 0x72, 0xef, 0x9b, 0x84, 0x10, 0xdb, 0x79, 0xd9, 0x9f, 0x5, 0x44, 0x51, 0x94, 0x9, 0x21, 0x5a, 0x40, 0x6, 0x64, 0x42, 0x88, 0x56, 0x14, 0x45, 0x59, 0x19, 0x1e, 0x8f, 0xc7, 0x8b, 0x52, 0xca, 0xe, 0x80, 0x73, 0xee, 0x12, 0xa, 0xbf, 0x90, 0x24, 0x49, 0x7f, 0x38, 0x1c, 0x1e, 0x3, 0x34, 0x1a, 0x8d, 0x7e, 0x11, 0x54, 0x4a, 0x2d, 0x48, 0x29, 0x77, 0xac, 0xb5, 0x1d, 0xef, 0xfd, 0x32, 0xd0, 0x9b, 0x4c, 0x26, 0x5d, 0xa8, 0xd8, 0xc4, 0xb2, 0xf2, 0xf9, 0x4c, 0x55, 0xbd, 0x48, 0xbf, 0xe8, 0x1d, 0x78, 0x70, 0xce, 0x9d, 0x64, 0x59, 0xb6, 0x35, 0x85, 0xff, 0x87, 0x3e, 0x1, 0x53, 0x7, 0x87, 0x11, 0xd3, 0x3a, 0x9b, 0x9e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; -static const unsigned char icon_snap_png[] = { - 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +static const unsigned char icon_snap_grid_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc4, 0x0, 0x0, 0xe, 0xc4, 0x1, 0x95, 0x2b, 0xe, 0x1b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; static const unsigned char icon_stop_png[] = { diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 04efe88102..db5d87d703 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -422,6 +422,46 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_FAN); + + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); + + BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); + + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BASE); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BONES); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX); + + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_16_BIT_BONES); + + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT); + + BIND_ENUM_CONSTANT(ARRAY_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COLOR); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_BONES); + BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_INDEX); + BIND_ENUM_CONSTANT(ARRAY_MAX); } Mesh::Mesh() { diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp index 9af8c42110..2ef20f67f5 100644 --- a/scene/resources/sky_box.cpp +++ b/scene/resources/sky_box.cpp @@ -419,10 +419,10 @@ void ProceduralSky::_queue_update() { call_deferred("_update_sky"); } -void ProceduralSky::_thread_done(const Ref<Image> &image) { +void ProceduralSky::_thread_done(const Ref<Image> &p_image) { - VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT); - VS::get_singleton()->texture_set_data(texture, image); + VS::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT); + VS::get_singleton()->texture_set_data(texture, p_image); _radiance_changed(); Thread::wait_to_finish(sky_thread); memdelete(sky_thread); diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 3d085f7166..4627c900ff 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -178,7 +178,7 @@ public: void set_border_width_all(int p_size); int get_border_width_min() const; - void set_border_width(Margin p_margin, int p_size); + void set_border_width(Margin p_margin, int p_width); int get_border_width(Margin p_margin) const; //blend @@ -214,7 +214,7 @@ public: int get_shadow_size() const; //ANTI_ALIASING - void set_anti_aliased(const bool &p_anit_aliasing); + void set_anti_aliased(const bool &p_anti_aliased); bool is_anti_aliased() const; //tempAA void set_aa_size(const int &p_aa_size); diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp index f2bcabc3cb..3e6280f033 100644 --- a/servers/audio/effects/audio_effect_distortion.cpp +++ b/servers/audio/effects/audio_effect_distortion.cpp @@ -175,6 +175,12 @@ void AudioEffectDistortion::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20000,1"), "set_keep_hf_hz", "get_keep_hf_hz"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain"); + + BIND_ENUM_CONSTANT(MODE_CLIP); + BIND_ENUM_CONSTANT(MODE_ATAN); + BIND_ENUM_CONSTANT(MODE_LOFI); + BIND_ENUM_CONSTANT(MODE_OVERDRIVE); + BIND_ENUM_CONSTANT(MODE_WAVESHAPE); } AudioEffectDistortion::AudioEffectDistortion() { diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp index 64a9db51a5..019494c74a 100644 --- a/servers/audio/effects/audio_effect_filter.cpp +++ b/servers/audio/effects/audio_effect_filter.cpp @@ -159,6 +159,11 @@ void AudioEffectFilter::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain"); ADD_PROPERTY(PropertyInfo(Variant::INT, "dB", PROPERTY_HINT_ENUM, "6db,12db,18db,24db"), "set_db", "get_db"); + + BIND_ENUM_CONSTANT(FILTER_6DB); + BIND_ENUM_CONSTANT(FILTER_12DB); + BIND_ENUM_CONSTANT(FILTER_18DB); + BIND_ENUM_CONSTANT(FILTER_24DB); } AudioEffectFilter::AudioEffectFilter(AudioFilterSW::Mode p_mode) { diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index ed62e65846..78efe85e16 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -32,6 +32,7 @@ #include "os/file_access.h" #include "os/os.h" #include "project_settings.h" +#include "servers/audio/audio_driver_dummy.h" #include "servers/audio/effects/audio_effect_compressor.h" #ifdef TOOLS_ENABLED @@ -107,6 +108,7 @@ AudioDriver::AudioDriver() { AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; int AudioDriverManager::driver_count = 0; +AudioDriverDummy AudioDriverManager::dummy_driver; void AudioDriverManager::add_driver(AudioDriver *p_driver) { @@ -118,6 +120,43 @@ int AudioDriverManager::get_driver_count() { return driver_count; } + +void AudioDriverManager::initialize(int p_driver) { + AudioDriver *driver; + int failed_driver = -1; + + // Check if there is a selected driver + if (p_driver >= 0 && p_driver < driver_count) { + if (drivers[p_driver]->init() == OK) { + drivers[p_driver]->set_singleton(); + return; + } else { + failed_driver = p_driver; + } + } + + // No selected driver, try them all in order + for (int i = 0; i < driver_count; i++) { + // Don't re-init the driver if it failed above + if (i == failed_driver) { + continue; + } + + if (drivers[i]->init() == OK) { + drivers[i]->set_singleton(); + return; + } + } + + // Fallback to our dummy driver + if (dummy_driver.init() == OK) { + ERR_PRINT("AudioDriverManager: all drivers failed, falling back to dummy driver"); + dummy_driver.set_singleton(); + } else { + ERR_PRINT("AudioDriverManager: dummy driver faild to init()"); + } +} + AudioDriver *AudioDriverManager::get_driver(int p_driver) { ERR_FAIL_INDEX_V(p_driver, driver_count, NULL); @@ -1094,6 +1133,10 @@ void AudioServer::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout); ADD_SIGNAL(MethodInfo("bus_layout_changed")); + + BIND_ENUM_CONSTANT(SPEAKER_MODE_STEREO); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_51); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_71); } AudioServer::AudioServer() { diff --git a/servers/audio_server.h b/servers/audio_server.h index c479d09a3c..55e9367308 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -35,6 +35,8 @@ #include "servers/audio/audio_effect.h" #include "variant.h" +class AudioDriverDummy; + class AudioDriver { static AudioDriver *singleton; @@ -90,8 +92,11 @@ class AudioDriverManager { static AudioDriver *drivers[MAX_DRIVERS]; static int driver_count; + static AudioDriverDummy dummy_driver; + public: static void add_driver(AudioDriver *p_driver); + static void initialize(int p_driver); static int get_driver_count(); static AudioDriver *get_driver(int p_driver); }; diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h index 51a24f4678..5c124c1792 100644 --- a/servers/physics/broad_phase_basic.h +++ b/servers/physics/broad_phase_basic.h @@ -82,7 +82,7 @@ class BroadPhaseBasic : public BroadPhaseSW { public: // 0 is an invalid ID - virtual ID create(CollisionObjectSW *p_object_, int p_subindex = 0); + virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0); virtual void move(ID p_id, const Rect3 &p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 779f0d54ac..8f22d1cd44 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -518,7 +518,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co body_aabb = body_aabb.grow(p_margin); static const int max_excluded_shape_pairs = 32; - Pair<Shape2DSW *, Shape2DSW *> excluded_shape_pairs[max_excluded_shape_pairs]; + ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs]; int excluded_shape_pair_count = 0; Transform2D body_transform = p_from; @@ -577,7 +577,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (!collided && cbk.invalid_by_dir > 0) { //this shape must be excluded if (excluded_shape_pair_count < max_excluded_shape_pairs) { - excluded_shape_pairs[excluded_shape_pair_count++] = Pair<Shape2DSW *, Shape2DSW *>(body_shape, against_shape); + ExcludedShapeSW esp; + esp.local_shape = body_shape; + esp.against_object = col_obj; + esp.against_shape_index = shape_idx; + excluded_shape_pairs[excluded_shape_pair_count++] = esp; } } } @@ -645,7 +649,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co for (int k = 0; k < excluded_shape_pair_count; k++) { - if (excluded_shape_pairs[k].first == body_shape && excluded_shape_pairs[k].second == against_shape) { + if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) { excluded = true; break; } @@ -776,7 +780,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co bool excluded = false; for (int k = 0; k < excluded_shape_pair_count; k++) { - if (excluded_shape_pairs[k].first == body_shape && excluded_shape_pairs[k].second == against_shape) { + if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) { excluded = true; break; } diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index ed6136e372..c7e7497397 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -71,6 +71,12 @@ public: }; private: + struct ExcludedShapeSW { + Shape2DSW *local_shape; + const CollisionObject2DSW *against_object; + int against_shape_index; + }; + uint64_t elapsed_time[ELAPSED_TIME_MAX]; Physics2DDirectSpaceStateSW *direct_access; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index d4e37be882..28ab31b8f6 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -704,6 +704,20 @@ void PhysicsServer::_bind_methods() { BIND_ENUM_CONSTANT(INFO_ACTIVE_OBJECTS); BIND_ENUM_CONSTANT(INFO_COLLISION_PAIRS); BIND_ENUM_CONSTANT(INFO_ISLAND_COUNT); + + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); + + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_DISABLED); + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_X); + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Y); + BIND_ENUM_CONSTANT(BODY_AXIS_LOCK_Z); } PhysicsServer::PhysicsServer() { |