diff options
40 files changed, 1054 insertions, 516 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index b47e611a51..12b892d873 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -413,6 +413,7 @@ String _OS::get_latin_keyboard_variant() const { case OS::LATIN_KEYBOARD_QZERTY: return "QZERTY"; case OS::LATIN_KEYBOARD_DVORAK: return "DVORAK"; case OS::LATIN_KEYBOARD_NEO: return "NEO"; + case OS::LATIN_KEYBOARD_COLEMAK: return "COLEMAK"; default: return "ERROR"; } } diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index 30e7d5e791..edf4f3e2f9 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -505,6 +505,27 @@ static const _KeyCodeReplace _keycode_replace_neo[] = { { 0, 0 } }; +static const _KeyCodeReplace _keycode_replace_colemak[] = { + { KEY_E, KEY_F }, + { KEY_R, KEY_P }, + { KEY_T, KEY_G }, + { KEY_Y, KEY_J }, + { KEY_U, KEY_L }, + { KEY_I, KEY_U }, + { KEY_O, KEY_Y }, + { KEY_P, KEY_SEMICOLON }, + { KEY_S, KEY_R }, + { KEY_D, KEY_S }, + { KEY_F, KEY_T }, + { KEY_G, KEY_D }, + { KEY_J, KEY_N }, + { KEY_K, KEY_E }, + { KEY_L, KEY_I }, + { KEY_SEMICOLON, KEY_O }, + { KEY_N, KEY_K }, + { 0, 0 } +}; + int keycode_get_count() { const _KeyCodeText *kct = &_keycodes[0]; @@ -537,6 +558,7 @@ int latin_keyboard_keycode_convert(int p_keycode) { case OS::LATIN_KEYBOARD_QZERTY: kcr = _keycode_replace_qzerty; break; case OS::LATIN_KEYBOARD_DVORAK: kcr = _keycode_replace_dvorak; break; case OS::LATIN_KEYBOARD_NEO: kcr = _keycode_replace_neo; break; + case OS::LATIN_KEYBOARD_COLEMAK: kcr = _keycode_replace_colemak; break; default: return p_keycode; } diff --git a/core/os/os.h b/core/os/os.h index 48effe99da..f5e479ac0b 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -409,6 +409,7 @@ public: LATIN_KEYBOARD_QZERTY, LATIN_KEYBOARD_DVORAK, LATIN_KEYBOARD_NEO, + LATIN_KEYBOARD_COLEMAK, }; virtual LatinKeyboardVariant get_latin_keyboard_variant() const; diff --git a/core/translation.cpp b/core/translation.cpp index 54dbaf6ed5..058db956e5 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -753,65 +753,17 @@ static const char *locale_names[] = { 0 }; -bool TranslationServer::is_locale_valid(const String &p_locale) { - - const char **ptr = locale_list; - - while (*ptr) { - - if (*ptr == p_locale) - return true; - ptr++; - } - - return false; -} - -Vector<String> TranslationServer::get_all_locales() { - - Vector<String> locales; - - const char **ptr = locale_list; - - while (*ptr) { - locales.push_back(*ptr); - ptr++; - } - - return locales; -} - -Vector<String> TranslationServer::get_all_locale_names() { - - Vector<String> locales; - - const char **ptr = locale_names; - - while (*ptr) { - locales.push_back(*ptr); - ptr++; - } - - return locales; -} +static const char *locale_renames[][2] = { + { "no", "nb" }, + { NULL, NULL } +}; static String get_trimmed_locale(const String &p_locale) { return p_locale.substr(0, 2); } -static bool is_valid_locale(const String &p_locale) { - - const char **ptr = locale_list; - - while (*ptr) { - if (p_locale == *ptr) - return true; - ptr++; - } - - return false; -} +/////////////////////////////////////////////// PoolVector<String> Translation::_get_messages() const { @@ -857,14 +809,13 @@ void Translation::_set_messages(const PoolVector<String> &p_messages) { void Translation::set_locale(const String &p_locale) { - // replaces '-' with '_' for macOS Sierra-style locales - String univ_locale = p_locale.replace("-", "_"); + String univ_locale = TranslationServer::standardize_locale(p_locale); - if (!is_valid_locale(univ_locale)) { + if (!TranslationServer::is_locale_valid(univ_locale)) { String trimmed_locale = get_trimmed_locale(univ_locale); - ERR_EXPLAIN("Invalid Locale: " + trimmed_locale); - ERR_FAIL_COND(!is_valid_locale(trimmed_locale)); + ERR_EXPLAIN("Invalid locale: " + trimmed_locale); + ERR_FAIL_COND(!TranslationServer::is_locale_valid(trimmed_locale)); locale = trimmed_locale; } else { @@ -929,16 +880,47 @@ Translation::Translation() /////////////////////////////////////////////// -void TranslationServer::set_locale(const String &p_locale) { +bool TranslationServer::is_locale_valid(const String &p_locale) { + + const char **ptr = locale_list; + + while (*ptr) { + + if (*ptr == p_locale) + return true; + ptr++; + } + + return false; +} - // replaces '-' with '_' for macOS Sierra-style locales +String TranslationServer::standardize_locale(const String &p_locale) { + + // Replaces '-' with '_' for macOS Sierra-style locales String univ_locale = p_locale.replace("-", "_"); - if (!is_valid_locale(univ_locale)) { + // Handles known non-ISO locale names used e.g. on Windows + int idx = 0; + while (locale_renames[idx][0] != NULL) { + if (locale_renames[idx][0] == univ_locale) { + univ_locale = locale_renames[idx][1]; + break; + } + idx++; + } + + return univ_locale; +} + +void TranslationServer::set_locale(const String &p_locale) { + + String univ_locale = standardize_locale(p_locale); + + if (!is_locale_valid(univ_locale)) { String trimmed_locale = get_trimmed_locale(univ_locale); - ERR_EXPLAIN("Invalid Locale: " + trimmed_locale); - ERR_FAIL_COND(!is_valid_locale(trimmed_locale)); + ERR_EXPLAIN("Invalid locale: " + trimmed_locale); + ERR_FAIL_COND(!is_locale_valid(trimmed_locale)); locale = trimmed_locale; } else { @@ -963,6 +945,34 @@ String TranslationServer::get_locale_name(const String &p_locale) const { return locale_name_map[p_locale]; } +Vector<String> TranslationServer::get_all_locales() { + + Vector<String> locales; + + const char **ptr = locale_list; + + while (*ptr) { + locales.push_back(*ptr); + ptr++; + } + + return locales; +} + +Vector<String> TranslationServer::get_all_locale_names() { + + Vector<String> locales; + + const char **ptr = locale_names; + + while (*ptr) { + locales.push_back(*ptr); + ptr++; + } + + return locales; +} + void TranslationServer::add_translation(const Ref<Translation> &p_translation) { translations.insert(p_translation); diff --git a/core/translation.h b/core/translation.h index 5fec1d9f45..0cdab3b0bc 100644 --- a/core/translation.h +++ b/core/translation.h @@ -85,8 +85,6 @@ class TranslationServer : public Object { public: _FORCE_INLINE_ static TranslationServer *get_singleton() { return singleton; } - //yes, portuguese is supported! - void set_enabled(bool p_enabled) { enabled = p_enabled; } _FORCE_INLINE_ bool is_enabled() const { return enabled; } @@ -103,6 +101,7 @@ public: static Vector<String> get_all_locales(); static Vector<String> get_all_locale_names(); static bool is_locale_valid(const String &p_locale); + static String standardize_locale(const String &p_locale); void set_tool_translation(const Ref<Translation> &p_translation); StringName tool_translate(const StringName &p_message) const; diff --git a/core/ustring.cpp b/core/ustring.cpp index b85996e3d1..80881f1adb 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -2476,6 +2476,11 @@ bool String::begins_with(const char *p_string) const { return *p_string == 0; } +bool String::is_enclosed_in(const String &p_string) const { + + return begins_with(p_string) && ends_with(p_string); +} + bool String::is_subsequence_of(const String &p_string) const { return _base_is_subsequence_of(p_string, false); @@ -2486,6 +2491,11 @@ bool String::is_subsequence_ofi(const String &p_string) const { return _base_is_subsequence_of(p_string, true); } +bool String::is_quoted() const { + + return is_enclosed_in("\"") || is_enclosed_in("'"); +} + bool String::_base_is_subsequence_of(const String &p_string, bool case_insensitive) const { int len = length(); @@ -3906,6 +3916,18 @@ String String::sprintf(const Array &values, bool *error) const { return formatted; } +String String::quote(String quotechar) const { + return quotechar + *this + quotechar; +} + +String String::unquote() const { + if (!is_quoted()) { + return *this; + } + + return substr(1, length() - 2); +} + #include "translation.h" #ifdef TOOLS_ENABLED diff --git a/core/ustring.h b/core/ustring.h index ab4e325f2c..aa4a5c910d 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -118,8 +118,10 @@ public: bool begins_with(const String &p_string) const; bool begins_with(const char *p_string) const; bool ends_with(const String &p_string) const; + bool is_enclosed_in(const String &p_string) const; bool is_subsequence_of(const String &p_string) const; bool is_subsequence_ofi(const String &p_string) const; + bool is_quoted() const; Vector<String> bigrams() const; float similarity(const String &p_string) const; String format(const Variant &values, String placeholder = "{_}") const; @@ -132,6 +134,8 @@ public: String lpad(int min_length, const String &character = " ") const; String rpad(int min_length, const String &character = " ") const; String sprintf(const Array &values, bool *error) const; + String quote(String quotechar = "\"") const; + String unquote() const; static String num(double p_num, int p_decimals = -1); static String num_scientific(double p_num); static String num_real(double p_num); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index d141621fbb..cdf1ea46a3 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -54,9 +54,8 @@ struct _VariantCall { Variant::Type return_type; bool _const; -#ifdef DEBUG_ENABLED bool returns; -#endif + VariantFunc func; _FORCE_INLINE_ bool verify_arguments(const Variant **p_args, Variant::CallError &r_error) { @@ -146,7 +145,7 @@ struct _VariantCall { #endif } - static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) { + static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, bool p_has_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) { FuncData funcdata; funcdata.func = p_func; @@ -154,7 +153,7 @@ struct _VariantCall { funcdata._const = p_const; #ifdef DEBUG_ENABLED funcdata.return_type = p_return; - funcdata.returns = p_return != Variant::NIL; + funcdata.returns = p_has_return; #endif if (p_argtype1.name) { @@ -1051,7 +1050,6 @@ Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, i return String(); // math types - case VECTOR2: return Vector2(); // 5 case RECT2: return Rect2(); @@ -1234,7 +1232,7 @@ Variant::Type Variant::get_method_return_type(Variant::Type p_type, const String return Variant::NIL; if (r_has_return) - *r_has_return = E->get().return_type; + *r_has_return = E->get().returns; return E->get().return_type; } @@ -1376,215 +1374,237 @@ void register_variant_methods() { _VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX); _VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX); +#define ADDFUNC0R(m_vtype, m_ret, m_class, m_method, m_defarg) \ + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); +#define ADDFUNC1R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); +#define ADDFUNC2R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); +#define ADDFUNC3R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); +#define ADDFUNC4R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); + +#define ADDFUNC0RNC(m_vtype, m_ret, m_class, m_method, m_defarg) \ + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); +#define ADDFUNC1RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); +#define ADDFUNC2RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); +#define ADDFUNC3RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); +#define ADDFUNC4RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); + #define ADDFUNC0(m_vtype, m_ret, m_class, m_method, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); #define ADDFUNC1(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); #define ADDFUNC2(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); #define ADDFUNC3(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); #define ADDFUNC4(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); + _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); #define ADDFUNC0NC(m_vtype, m_ret, m_class, m_method, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); #define ADDFUNC1NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); #define ADDFUNC2NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); #define ADDFUNC3NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); #define ADDFUNC4NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); + _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); /* STRING */ - ADDFUNC1(STRING, INT, String, casecmp_to, STRING, "to", varray()); - ADDFUNC1(STRING, INT, String, nocasecmp_to, STRING, "to", varray()); - ADDFUNC0(STRING, INT, String, length, varray()); - ADDFUNC2(STRING, STRING, String, substr, INT, "from", INT, "len", varray()); - - ADDFUNC2(STRING, INT, String, find, STRING, "what", INT, "from", varray(0)); - - ADDFUNC1(STRING, INT, String, find_last, STRING, "what", varray()); - ADDFUNC2(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0)); - ADDFUNC2(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1)); - ADDFUNC2(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1)); - ADDFUNC1(STRING, BOOL, String, match, STRING, "expr", varray()); - ADDFUNC1(STRING, BOOL, String, matchn, STRING, "expr", varray()); - ADDFUNC1(STRING, BOOL, String, begins_with, STRING, "text", varray()); - ADDFUNC1(STRING, BOOL, String, ends_with, STRING, "text", varray()); - ADDFUNC1(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray()); - ADDFUNC1(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray()); - ADDFUNC0(STRING, POOL_STRING_ARRAY, String, bigrams, varray()); - ADDFUNC1(STRING, REAL, String, similarity, STRING, "text", varray()); - - ADDFUNC2(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}")); - ADDFUNC2(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray()); - ADDFUNC2(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray()); - ADDFUNC2(STRING, STRING, String, insert, INT, "position", STRING, "what", varray()); - ADDFUNC0(STRING, STRING, String, capitalize, varray()); - ADDFUNC2(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true)); - ADDFUNC2(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true)); - - ADDFUNC0(STRING, STRING, String, to_upper, varray()); - ADDFUNC0(STRING, STRING, String, to_lower, varray()); - - ADDFUNC1(STRING, STRING, String, left, INT, "position", varray()); - ADDFUNC1(STRING, STRING, String, right, INT, "position", varray()); - ADDFUNC2(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true)); - ADDFUNC0(STRING, STRING, String, get_extension, varray()); - ADDFUNC0(STRING, STRING, String, get_basename, varray()); - ADDFUNC1(STRING, STRING, String, plus_file, STRING, "file", varray()); - ADDFUNC1(STRING, INT, String, ord_at, INT, "at", varray()); + ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray()); + ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray()); + ADDFUNC0R(STRING, INT, String, length, varray()); + ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray()); + + ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0)); + + ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray()); + ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0)); + ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1)); + ADDFUNC2R(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1)); + ADDFUNC1R(STRING, BOOL, String, match, STRING, "expr", varray()); + ADDFUNC1R(STRING, BOOL, String, matchn, STRING, "expr", varray()); + ADDFUNC1R(STRING, BOOL, String, begins_with, STRING, "text", varray()); + ADDFUNC1R(STRING, BOOL, String, ends_with, STRING, "text", varray()); + ADDFUNC1R(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray()); + ADDFUNC1R(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray()); + ADDFUNC0R(STRING, POOL_STRING_ARRAY, String, bigrams, varray()); + ADDFUNC1R(STRING, REAL, String, similarity, STRING, "text", varray()); + + ADDFUNC2R(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}")); + ADDFUNC2R(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray()); + ADDFUNC2R(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray()); + ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray()); + ADDFUNC0R(STRING, STRING, String, capitalize, varray()); + ADDFUNC2R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true)); + ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true)); + + ADDFUNC0R(STRING, STRING, String, to_upper, varray()); + ADDFUNC0R(STRING, STRING, String, to_lower, varray()); + + ADDFUNC1R(STRING, STRING, String, left, INT, "position", varray()); + ADDFUNC1R(STRING, STRING, String, right, INT, "position", varray()); + ADDFUNC2R(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true)); + ADDFUNC0R(STRING, STRING, String, get_extension, varray()); + ADDFUNC0R(STRING, STRING, String, get_basename, varray()); + ADDFUNC1R(STRING, STRING, String, plus_file, STRING, "file", varray()); + ADDFUNC1R(STRING, INT, String, ord_at, INT, "at", varray()); ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray()); - ADDFUNC0(STRING, INT, String, hash, varray()); - ADDFUNC0(STRING, STRING, String, md5_text, varray()); - ADDFUNC0(STRING, STRING, String, sha256_text, varray()); - ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray()); - ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray()); - ADDFUNC0(STRING, BOOL, String, empty, varray()); - ADDFUNC0(STRING, BOOL, String, is_abs_path, varray()); - ADDFUNC0(STRING, BOOL, String, is_rel_path, varray()); - ADDFUNC0(STRING, STRING, String, get_base_dir, varray()); - ADDFUNC0(STRING, STRING, String, get_file, varray()); - ADDFUNC0(STRING, STRING, String, xml_escape, varray()); - ADDFUNC0(STRING, STRING, String, xml_unescape, varray()); - ADDFUNC0(STRING, STRING, String, c_escape, varray()); - ADDFUNC0(STRING, STRING, String, c_unescape, varray()); - ADDFUNC0(STRING, STRING, String, json_escape, varray()); - ADDFUNC0(STRING, STRING, String, percent_encode, varray()); - ADDFUNC0(STRING, STRING, String, percent_decode, varray()); - ADDFUNC0(STRING, BOOL, String, is_valid_identifier, varray()); - ADDFUNC0(STRING, BOOL, String, is_valid_integer, varray()); - ADDFUNC0(STRING, BOOL, String, is_valid_float, varray()); - ADDFUNC0(STRING, BOOL, String, is_valid_html_color, varray()); - ADDFUNC0(STRING, BOOL, String, is_valid_ip_address, varray()); - ADDFUNC0(STRING, INT, String, to_int, varray()); - ADDFUNC0(STRING, REAL, String, to_float, varray()); - ADDFUNC0(STRING, INT, String, hex_to_int, varray()); - ADDFUNC1(STRING, STRING, String, pad_decimals, INT, "digits", varray()); - ADDFUNC1(STRING, STRING, String, pad_zeros, INT, "digits", varray()); - - ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray()); - ADDFUNC0(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray()); - - ADDFUNC0(VECTOR2, VECTOR2, Vector2, normalized, varray()); - ADDFUNC0(VECTOR2, REAL, Vector2, length, varray()); - ADDFUNC0(VECTOR2, REAL, Vector2, angle, varray()); - ADDFUNC0(VECTOR2, REAL, Vector2, length_squared, varray()); - ADDFUNC0(VECTOR2, BOOL, Vector2, is_normalized, varray()); - ADDFUNC1(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray()); - ADDFUNC1(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray()); - ADDFUNC1(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray()); - ADDFUNC1(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray()); - ADDFUNC2(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray()); - ADDFUNC4(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray()); - ADDFUNC0(VECTOR2, VECTOR2, Vector2, tangent, varray()); - ADDFUNC0(VECTOR2, VECTOR2, Vector2, floor, varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray()); - ADDFUNC0(VECTOR2, REAL, Vector2, aspect, varray()); - ADDFUNC1(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray()); - //ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray()); - ADDFUNC0(VECTOR2, VECTOR2, Vector2, abs, varray()); - ADDFUNC1(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray()); - - ADDFUNC0(RECT2, REAL, Rect2, get_area, varray()); - ADDFUNC1(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray()); - ADDFUNC1(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray()); - ADDFUNC0(RECT2, BOOL, Rect2, has_no_area, varray()); - ADDFUNC1(RECT2, RECT2, Rect2, clip, RECT2, "b", varray()); - ADDFUNC1(RECT2, RECT2, Rect2, merge, RECT2, "b", varray()); - ADDFUNC1(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray()); - ADDFUNC1(RECT2, RECT2, Rect2, grow, REAL, "by", varray()); - ADDFUNC2(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray()); - ADDFUNC4(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray()); - ADDFUNC1(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray()); - - ADDFUNC0(VECTOR3, INT, Vector3, min_axis, varray()); - ADDFUNC0(VECTOR3, INT, Vector3, max_axis, varray()); - ADDFUNC0(VECTOR3, REAL, Vector3, length, varray()); - ADDFUNC0(VECTOR3, REAL, Vector3, length_squared, varray()); - ADDFUNC0(VECTOR3, BOOL, Vector3, is_normalized, varray()); - ADDFUNC0(VECTOR3, VECTOR3, Vector3, normalized, varray()); - ADDFUNC0(VECTOR3, VECTOR3, Vector3, inverse, varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray()); - ADDFUNC2(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", REAL, "phi", varray()); - ADDFUNC2(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", REAL, "t", varray()); - ADDFUNC4(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray()); - ADDFUNC1(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray()); - ADDFUNC1(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray()); - ADDFUNC0(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray()); - ADDFUNC0(VECTOR3, VECTOR3, Vector3, abs, varray()); - ADDFUNC0(VECTOR3, VECTOR3, Vector3, floor, varray()); - ADDFUNC0(VECTOR3, VECTOR3, Vector3, ceil, varray()); - ADDFUNC1(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray()); - ADDFUNC1(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray()); - ADDFUNC1(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray()); - ADDFUNC1(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray()); - - ADDFUNC0(PLANE, PLANE, Plane, normalized, varray()); - ADDFUNC0(PLANE, VECTOR3, Plane, center, varray()); - ADDFUNC0(PLANE, VECTOR3, Plane, get_any_point, varray()); - ADDFUNC1(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray()); - ADDFUNC1(PLANE, REAL, Plane, distance_to, VECTOR3, "point", varray()); - ADDFUNC2(PLANE, BOOL, Plane, has_point, VECTOR3, "point", REAL, "epsilon", varray(CMP_EPSILON)); - ADDFUNC1(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray()); - ADDFUNC2(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray()); - ADDFUNC2(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray()); - ADDFUNC2(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray()); - - ADDFUNC0(QUAT, REAL, Quat, length, varray()); - ADDFUNC0(QUAT, REAL, Quat, length_squared, varray()); - ADDFUNC0(QUAT, QUAT, Quat, normalized, varray()); - ADDFUNC0(QUAT, BOOL, Quat, is_normalized, varray()); - ADDFUNC0(QUAT, QUAT, Quat, inverse, varray()); - ADDFUNC1(QUAT, REAL, Quat, dot, QUAT, "b", varray()); - ADDFUNC1(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray()); - ADDFUNC2(QUAT, QUAT, Quat, slerp, QUAT, "b", REAL, "t", varray()); - ADDFUNC2(QUAT, QUAT, Quat, slerpni, QUAT, "b", REAL, "t", varray()); - ADDFUNC4(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", REAL, "t", varray()); - - ADDFUNC0(COLOR, INT, Color, to_rgba32, varray()); - ADDFUNC0(COLOR, INT, Color, to_argb32, varray()); - ADDFUNC0(COLOR, REAL, Color, gray, varray()); - ADDFUNC0(COLOR, COLOR, Color, inverted, varray()); - ADDFUNC0(COLOR, COLOR, Color, contrasted, varray()); - ADDFUNC2(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray()); - ADDFUNC1(COLOR, COLOR, Color, blend, COLOR, "over", varray()); - ADDFUNC1(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true)); - - ADDFUNC0(_RID, INT, RID, get_id, varray()); - - ADDFUNC0(NODE_PATH, BOOL, NodePath, is_absolute, varray()); - ADDFUNC0(NODE_PATH, INT, NodePath, get_name_count, varray()); - ADDFUNC1(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray()); - ADDFUNC0(NODE_PATH, INT, NodePath, get_subname_count, varray()); - ADDFUNC1(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray()); - ADDFUNC0(NODE_PATH, STRING, NodePath, get_property, varray()); - ADDFUNC0(NODE_PATH, BOOL, NodePath, is_empty, varray()); - - ADDFUNC0(DICTIONARY, INT, Dictionary, size, varray()); - ADDFUNC0(DICTIONARY, BOOL, Dictionary, empty, varray()); + ADDFUNC0R(STRING, INT, String, hash, varray()); + ADDFUNC0R(STRING, STRING, String, md5_text, varray()); + ADDFUNC0R(STRING, STRING, String, sha256_text, varray()); + ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, md5_buffer, varray()); + ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, sha256_buffer, varray()); + ADDFUNC0R(STRING, BOOL, String, empty, varray()); + ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray()); + ADDFUNC0R(STRING, BOOL, String, is_rel_path, varray()); + ADDFUNC0R(STRING, STRING, String, get_base_dir, varray()); + ADDFUNC0R(STRING, STRING, String, get_file, varray()); + ADDFUNC0R(STRING, STRING, String, xml_escape, varray()); + ADDFUNC0R(STRING, STRING, String, xml_unescape, varray()); + ADDFUNC0R(STRING, STRING, String, c_escape, varray()); + ADDFUNC0R(STRING, STRING, String, c_unescape, varray()); + ADDFUNC0R(STRING, STRING, String, json_escape, varray()); + ADDFUNC0R(STRING, STRING, String, percent_encode, varray()); + ADDFUNC0R(STRING, STRING, String, percent_decode, varray()); + ADDFUNC0R(STRING, BOOL, String, is_valid_identifier, varray()); + ADDFUNC0R(STRING, BOOL, String, is_valid_integer, varray()); + ADDFUNC0R(STRING, BOOL, String, is_valid_float, varray()); + ADDFUNC0R(STRING, BOOL, String, is_valid_html_color, varray()); + ADDFUNC0R(STRING, BOOL, String, is_valid_ip_address, varray()); + ADDFUNC0R(STRING, INT, String, to_int, varray()); + ADDFUNC0R(STRING, REAL, String, to_float, varray()); + ADDFUNC0R(STRING, INT, String, hex_to_int, varray()); + ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray()); + ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray()); + + ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_ascii, varray()); + ADDFUNC0R(STRING, POOL_BYTE_ARRAY, String, to_utf8, varray()); + + ADDFUNC0R(VECTOR2, VECTOR2, Vector2, normalized, varray()); + ADDFUNC0R(VECTOR2, REAL, Vector2, length, varray()); + ADDFUNC0R(VECTOR2, REAL, Vector2, angle, varray()); + ADDFUNC0R(VECTOR2, REAL, Vector2, length_squared, varray()); + ADDFUNC0R(VECTOR2, BOOL, Vector2, is_normalized, varray()); + ADDFUNC1R(VECTOR2, REAL, Vector2, distance_to, VECTOR2, "to", varray()); + ADDFUNC1R(VECTOR2, REAL, Vector2, distance_squared_to, VECTOR2, "to", varray()); + ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to, VECTOR2, "to", varray()); + ADDFUNC1R(VECTOR2, REAL, Vector2, angle_to_point, VECTOR2, "to", varray()); + ADDFUNC2R(VECTOR2, VECTOR2, Vector2, linear_interpolate, VECTOR2, "b", REAL, "t", varray()); + ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", REAL, "t", varray()); + ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, REAL, "phi", varray()); + ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray()); + ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray()); + ADDFUNC1R(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray()); + ADDFUNC0R(VECTOR2, REAL, Vector2, aspect, varray()); + ADDFUNC1R(VECTOR2, REAL, Vector2, dot, VECTOR2, "with", varray()); + ADDFUNC1R(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray()); + ADDFUNC1R(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray()); + ADDFUNC1R(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray()); + //ADDFUNC1R(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray()); + ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray()); + ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, REAL, "length", varray()); + + ADDFUNC0R(RECT2, REAL, Rect2, get_area, varray()); + ADDFUNC1R(RECT2, BOOL, Rect2, intersects, RECT2, "b", varray()); + ADDFUNC1R(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray()); + ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray()); + ADDFUNC1R(RECT2, RECT2, Rect2, clip, RECT2, "b", varray()); + ADDFUNC1R(RECT2, RECT2, Rect2, merge, RECT2, "b", varray()); + ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray()); + ADDFUNC1R(RECT2, RECT2, Rect2, grow, REAL, "by", varray()); + ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", REAL, "by", varray()); + ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, REAL, "left", REAL, "top", REAL, "right", REAL, " bottom", varray()); + ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray()); + + ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray()); + ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray()); + ADDFUNC0R(VECTOR3, REAL, Vector3, length, varray()); + ADDFUNC0R(VECTOR3, REAL, Vector3, length_squared, varray()); + ADDFUNC0R(VECTOR3, BOOL, Vector3, is_normalized, varray()); + ADDFUNC0R(VECTOR3, VECTOR3, Vector3, normalized, varray()); + ADDFUNC0R(VECTOR3, VECTOR3, Vector3, inverse, varray()); + ADDFUNC1R(VECTOR3, VECTOR3, Vector3, snapped, REAL, "by", varray()); + ADDFUNC2R(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", REAL, "phi", varray()); + ADDFUNC2R(VECTOR3, VECTOR3, Vector3, linear_interpolate, VECTOR3, "b", REAL, "t", varray()); + ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", REAL, "t", varray()); + ADDFUNC1R(VECTOR3, REAL, Vector3, dot, VECTOR3, "b", varray()); + ADDFUNC1R(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray()); + ADDFUNC1R(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray()); + ADDFUNC0R(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray()); + ADDFUNC0R(VECTOR3, VECTOR3, Vector3, abs, varray()); + ADDFUNC0R(VECTOR3, VECTOR3, Vector3, floor, varray()); + ADDFUNC0R(VECTOR3, VECTOR3, Vector3, ceil, varray()); + ADDFUNC1R(VECTOR3, REAL, Vector3, distance_to, VECTOR3, "b", varray()); + ADDFUNC1R(VECTOR3, REAL, Vector3, distance_squared_to, VECTOR3, "b", varray()); + ADDFUNC1R(VECTOR3, REAL, Vector3, angle_to, VECTOR3, "to", varray()); + ADDFUNC1R(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray()); + ADDFUNC1R(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray()); + ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray()); + + ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray()); + ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray()); + ADDFUNC0R(PLANE, VECTOR3, Plane, get_any_point, varray()); + ADDFUNC1R(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray()); + ADDFUNC1R(PLANE, REAL, Plane, distance_to, VECTOR3, "point", varray()); + ADDFUNC2R(PLANE, BOOL, Plane, has_point, VECTOR3, "point", REAL, "epsilon", varray(CMP_EPSILON)); + ADDFUNC1R(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray()); + ADDFUNC2R(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray()); + ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray()); + ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray()); + + ADDFUNC0R(QUAT, REAL, Quat, length, varray()); + ADDFUNC0R(QUAT, REAL, Quat, length_squared, varray()); + ADDFUNC0R(QUAT, QUAT, Quat, normalized, varray()); + ADDFUNC0R(QUAT, BOOL, Quat, is_normalized, varray()); + ADDFUNC0R(QUAT, QUAT, Quat, inverse, varray()); + ADDFUNC1R(QUAT, REAL, Quat, dot, QUAT, "b", varray()); + ADDFUNC1R(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray()); + ADDFUNC2R(QUAT, QUAT, Quat, slerp, QUAT, "b", REAL, "t", varray()); + ADDFUNC2R(QUAT, QUAT, Quat, slerpni, QUAT, "b", REAL, "t", varray()); + ADDFUNC4R(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", REAL, "t", varray()); + + ADDFUNC0R(COLOR, INT, Color, to_rgba32, varray()); + ADDFUNC0R(COLOR, INT, Color, to_argb32, varray()); + ADDFUNC0R(COLOR, REAL, Color, gray, varray()); + ADDFUNC0R(COLOR, COLOR, Color, inverted, varray()); + ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray()); + ADDFUNC2R(COLOR, COLOR, Color, linear_interpolate, COLOR, "b", REAL, "t", varray()); + ADDFUNC1R(COLOR, COLOR, Color, blend, COLOR, "over", varray()); + ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true)); + + ADDFUNC0R(_RID, INT, RID, get_id, varray()); + + ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_absolute, varray()); + ADDFUNC0R(NODE_PATH, INT, NodePath, get_name_count, varray()); + ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray()); + ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray()); + ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray()); + ADDFUNC0R(NODE_PATH, STRING, NodePath, get_property, varray()); + ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray()); + + ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray()); + ADDFUNC0R(DICTIONARY, BOOL, Dictionary, empty, varray()); ADDFUNC0NC(DICTIONARY, NIL, Dictionary, clear, varray()); - ADDFUNC1(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray()); - ADDFUNC1(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray()); + ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray()); + ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray()); ADDFUNC1(DICTIONARY, NIL, Dictionary, erase, NIL, "key", varray()); - ADDFUNC0(DICTIONARY, INT, Dictionary, hash, varray()); - ADDFUNC0(DICTIONARY, ARRAY, Dictionary, keys, varray()); - ADDFUNC0(DICTIONARY, ARRAY, Dictionary, values, varray()); + ADDFUNC0R(DICTIONARY, INT, Dictionary, hash, varray()); + ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray()); + ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray()); - ADDFUNC0(ARRAY, INT, Array, size, varray()); - ADDFUNC0(ARRAY, BOOL, Array, empty, varray()); + ADDFUNC0R(ARRAY, INT, Array, size, varray()); + ADDFUNC0R(ARRAY, BOOL, Array, empty, varray()); ADDFUNC0NC(ARRAY, NIL, Array, clear, varray()); - ADDFUNC0(ARRAY, INT, Array, hash, varray()); + ADDFUNC0R(ARRAY, INT, Array, hash, varray()); ADDFUNC1NC(ARRAY, NIL, Array, push_back, NIL, "value", varray()); ADDFUNC1NC(ARRAY, NIL, Array, push_front, NIL, "value", varray()); ADDFUNC1NC(ARRAY, NIL, Array, append, NIL, "value", varray()); @@ -1592,165 +1612,160 @@ void register_variant_methods() { ADDFUNC2NC(ARRAY, NIL, Array, insert, INT, "position", NIL, "value", varray()); ADDFUNC1NC(ARRAY, NIL, Array, remove, INT, "position", varray()); ADDFUNC1NC(ARRAY, NIL, Array, erase, NIL, "value", varray()); - ADDFUNC0(ARRAY, NIL, Array, front, varray()); - ADDFUNC0(ARRAY, NIL, Array, back, varray()); - ADDFUNC2(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0)); - ADDFUNC2(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1)); - ADDFUNC1(ARRAY, INT, Array, find_last, NIL, "value", varray()); - ADDFUNC1(ARRAY, INT, Array, count, NIL, "value", varray()); - ADDFUNC1(ARRAY, BOOL, Array, has, NIL, "value", varray()); - ADDFUNC0NC(ARRAY, NIL, Array, pop_back, varray()); - ADDFUNC0NC(ARRAY, NIL, Array, pop_front, varray()); + ADDFUNC0R(ARRAY, NIL, Array, front, varray()); + ADDFUNC0R(ARRAY, NIL, Array, back, varray()); + ADDFUNC2R(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0)); + ADDFUNC2R(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1)); + ADDFUNC1R(ARRAY, INT, Array, find_last, NIL, "value", varray()); + ADDFUNC1R(ARRAY, INT, Array, count, NIL, "value", varray()); + ADDFUNC1R(ARRAY, BOOL, Array, has, NIL, "value", varray()); + ADDFUNC0RNC(ARRAY, NIL, Array, pop_back, varray()); + ADDFUNC0RNC(ARRAY, NIL, Array, pop_front, varray()); ADDFUNC0NC(ARRAY, NIL, Array, sort, varray()); ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray()); ADDFUNC0NC(ARRAY, NIL, Array, invert, varray()); - ADDFUNC0NC(ARRAY, ARRAY, Array, duplicate, varray()); + ADDFUNC0RNC(ARRAY, ARRAY, Array, duplicate, varray()); - ADDFUNC0(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray()); + ADDFUNC0R(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray()); ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray()); ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, push_back, INT, "byte", varray()); ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append, INT, "byte", varray()); ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, append_array, POOL_BYTE_ARRAY, "array", varray()); ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, remove, INT, "idx", varray()); - ADDFUNC2(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray()); + ADDFUNC2R(POOL_BYTE_ARRAY, INT, PoolByteArray, insert, INT, "idx", INT, "byte", varray()); ADDFUNC1(POOL_BYTE_ARRAY, NIL, PoolByteArray, resize, INT, "idx", varray()); ADDFUNC0(POOL_BYTE_ARRAY, NIL, PoolByteArray, invert, varray()); - ADDFUNC2(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray()); + ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, subarray, INT, "from", INT, "to", varray()); - ADDFUNC0(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray()); - ADDFUNC0(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray()); - ADDFUNC1(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0)); - ADDFUNC2(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); + ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray()); + ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray()); + ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0)); + ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); - ADDFUNC0(POOL_INT_ARRAY, INT, PoolIntArray, size, varray()); + ADDFUNC0R(POOL_INT_ARRAY, INT, PoolIntArray, size, varray()); ADDFUNC2(POOL_INT_ARRAY, NIL, PoolIntArray, set, INT, "idx", INT, "integer", varray()); ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, push_back, INT, "integer", varray()); ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append, INT, "integer", varray()); ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, append_array, POOL_INT_ARRAY, "array", varray()); ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, remove, INT, "idx", varray()); - ADDFUNC2(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray()); + ADDFUNC2R(POOL_INT_ARRAY, INT, PoolIntArray, insert, INT, "idx", INT, "integer", varray()); ADDFUNC1(POOL_INT_ARRAY, NIL, PoolIntArray, resize, INT, "idx", varray()); ADDFUNC0(POOL_INT_ARRAY, NIL, PoolIntArray, invert, varray()); - ADDFUNC0(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray()); + ADDFUNC0R(POOL_REAL_ARRAY, INT, PoolRealArray, size, varray()); ADDFUNC2(POOL_REAL_ARRAY, NIL, PoolRealArray, set, INT, "idx", REAL, "value", varray()); ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, push_back, REAL, "value", varray()); ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append, REAL, "value", varray()); ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, append_array, POOL_REAL_ARRAY, "array", varray()); ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, remove, INT, "idx", varray()); - ADDFUNC2(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray()); + ADDFUNC2R(POOL_REAL_ARRAY, INT, PoolRealArray, insert, INT, "idx", REAL, "value", varray()); ADDFUNC1(POOL_REAL_ARRAY, NIL, PoolRealArray, resize, INT, "idx", varray()); ADDFUNC0(POOL_REAL_ARRAY, NIL, PoolRealArray, invert, varray()); - ADDFUNC0(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray()); + ADDFUNC0R(POOL_STRING_ARRAY, INT, PoolStringArray, size, varray()); ADDFUNC2(POOL_STRING_ARRAY, NIL, PoolStringArray, set, INT, "idx", STRING, "string", varray()); ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, push_back, STRING, "string", varray()); ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append, STRING, "string", varray()); ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, append_array, POOL_STRING_ARRAY, "array", varray()); ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, remove, INT, "idx", varray()); - ADDFUNC2(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray()); + ADDFUNC2R(POOL_STRING_ARRAY, INT, PoolStringArray, insert, INT, "idx", STRING, "string", varray()); ADDFUNC1(POOL_STRING_ARRAY, NIL, PoolStringArray, resize, INT, "idx", varray()); ADDFUNC0(POOL_STRING_ARRAY, NIL, PoolStringArray, invert, varray()); ADDFUNC1(POOL_STRING_ARRAY, STRING, PoolStringArray, join, STRING, "delimiter", varray()); - ADDFUNC0(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray()); + ADDFUNC0R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, size, varray()); ADDFUNC2(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, set, INT, "idx", VECTOR2, "vector2", varray()); ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, push_back, VECTOR2, "vector2", varray()); ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append, VECTOR2, "vector2", varray()); ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, append_array, POOL_VECTOR2_ARRAY, "array", varray()); ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, remove, INT, "idx", varray()); - ADDFUNC2(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray()); + ADDFUNC2R(POOL_VECTOR2_ARRAY, INT, PoolVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray()); ADDFUNC1(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, resize, INT, "idx", varray()); ADDFUNC0(POOL_VECTOR2_ARRAY, NIL, PoolVector2Array, invert, varray()); - ADDFUNC0(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray()); + ADDFUNC0R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, size, varray()); ADDFUNC2(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, set, INT, "idx", VECTOR3, "vector3", varray()); ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, push_back, VECTOR3, "vector3", varray()); ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append, VECTOR3, "vector3", varray()); ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, append_array, POOL_VECTOR3_ARRAY, "array", varray()); ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, remove, INT, "idx", varray()); - ADDFUNC2(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray()); + ADDFUNC2R(POOL_VECTOR3_ARRAY, INT, PoolVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray()); ADDFUNC1(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, resize, INT, "idx", varray()); ADDFUNC0(POOL_VECTOR3_ARRAY, NIL, PoolVector3Array, invert, varray()); - ADDFUNC0(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray()); + ADDFUNC0R(POOL_COLOR_ARRAY, INT, PoolColorArray, size, varray()); ADDFUNC2(POOL_COLOR_ARRAY, NIL, PoolColorArray, set, INT, "idx", COLOR, "color", varray()); ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, push_back, COLOR, "color", varray()); ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append, COLOR, "color", varray()); ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, append_array, POOL_COLOR_ARRAY, "array", varray()); ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, remove, INT, "idx", varray()); - ADDFUNC2(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray()); + ADDFUNC2R(POOL_COLOR_ARRAY, INT, PoolColorArray, insert, INT, "idx", COLOR, "color", varray()); ADDFUNC1(POOL_COLOR_ARRAY, NIL, PoolColorArray, resize, INT, "idx", varray()); ADDFUNC0(POOL_COLOR_ARRAY, NIL, PoolColorArray, invert, varray()); //pointerbased - ADDFUNC0(RECT3, REAL, Rect3, get_area, varray()); - ADDFUNC0(RECT3, BOOL, Rect3, has_no_area, varray()); - ADDFUNC0(RECT3, BOOL, Rect3, has_no_surface, varray()); - ADDFUNC1(RECT3, BOOL, Rect3, intersects, RECT3, "with", varray()); - ADDFUNC1(RECT3, BOOL, Rect3, encloses, RECT3, "with", varray()); - ADDFUNC1(RECT3, RECT3, Rect3, merge, RECT3, "with", varray()); - ADDFUNC1(RECT3, RECT3, Rect3, intersection, RECT3, "with", varray()); - ADDFUNC1(RECT3, BOOL, Rect3, intersects_plane, PLANE, "plane", varray()); - ADDFUNC2(RECT3, BOOL, Rect3, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray()); - ADDFUNC1(RECT3, BOOL, Rect3, has_point, VECTOR3, "point", varray()); - ADDFUNC1(RECT3, VECTOR3, Rect3, get_support, VECTOR3, "dir", varray()); - ADDFUNC0(RECT3, VECTOR3, Rect3, get_longest_axis, varray()); - ADDFUNC0(RECT3, INT, Rect3, get_longest_axis_index, varray()); - ADDFUNC0(RECT3, REAL, Rect3, get_longest_axis_size, varray()); - ADDFUNC0(RECT3, VECTOR3, Rect3, get_shortest_axis, varray()); - ADDFUNC0(RECT3, INT, Rect3, get_shortest_axis_index, varray()); - ADDFUNC0(RECT3, REAL, Rect3, get_shortest_axis_size, varray()); - ADDFUNC1(RECT3, RECT3, Rect3, expand, VECTOR3, "to_point", varray()); - ADDFUNC1(RECT3, RECT3, Rect3, grow, REAL, "by", varray()); - ADDFUNC1(RECT3, VECTOR3, Rect3, get_endpoint, INT, "idx", varray()); - - ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray()); - ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray()); - ADDFUNC0(TRANSFORM2D, REAL, Transform2D, get_rotation, varray()); - ADDFUNC0(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray()); - ADDFUNC0(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray()); - ADDFUNC0(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray()); - ADDFUNC1(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray()); - ADDFUNC2(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray()); - - ADDFUNC0(BASIS, BASIS, Basis, inverse, varray()); - ADDFUNC0(BASIS, BASIS, Basis, transposed, varray()); - ADDFUNC0(BASIS, BASIS, Basis, orthonormalized, varray()); - ADDFUNC0(BASIS, REAL, Basis, determinant, varray()); - ADDFUNC2(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray()); - ADDFUNC1(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray()); - ADDFUNC0(BASIS, VECTOR3, Basis, get_scale, varray()); - ADDFUNC0(BASIS, VECTOR3, Basis, get_euler, varray()); - ADDFUNC1(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray()); - ADDFUNC1(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray()); - ADDFUNC1(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray()); - ADDFUNC1(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray()); - ADDFUNC1(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray()); - ADDFUNC0(BASIS, INT, Basis, get_orthogonal_index, varray()); - - ADDFUNC0(TRANSFORM, TRANSFORM, Transform, inverse, varray()); - ADDFUNC0(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray()); - ADDFUNC0(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray()); - ADDFUNC2(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", REAL, "phi", varray()); - ADDFUNC1(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray()); - ADDFUNC1(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "ofs", varray()); - ADDFUNC2(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray()); - ADDFUNC2(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", REAL, "weight", varray()); - ADDFUNC1(TRANSFORM, NIL, Transform, xform, NIL, "v", varray()); - ADDFUNC1(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray()); - -#ifdef DEBUG_ENABLED - _VariantCall::type_funcs[Variant::TRANSFORM].functions["xform"].returns = true; - _VariantCall::type_funcs[Variant::TRANSFORM].functions["xform_inv"].returns = true; -#endif + ADDFUNC0R(RECT3, REAL, Rect3, get_area, varray()); + ADDFUNC0R(RECT3, BOOL, Rect3, has_no_area, varray()); + ADDFUNC0R(RECT3, BOOL, Rect3, has_no_surface, varray()); + ADDFUNC1R(RECT3, BOOL, Rect3, intersects, RECT3, "with", varray()); + ADDFUNC1R(RECT3, BOOL, Rect3, encloses, RECT3, "with", varray()); + ADDFUNC1R(RECT3, RECT3, Rect3, merge, RECT3, "with", varray()); + ADDFUNC1R(RECT3, RECT3, Rect3, intersection, RECT3, "with", varray()); + ADDFUNC1R(RECT3, BOOL, Rect3, intersects_plane, PLANE, "plane", varray()); + ADDFUNC2R(RECT3, BOOL, Rect3, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray()); + ADDFUNC1R(RECT3, BOOL, Rect3, has_point, VECTOR3, "point", varray()); + ADDFUNC1R(RECT3, VECTOR3, Rect3, get_support, VECTOR3, "dir", varray()); + ADDFUNC0R(RECT3, VECTOR3, Rect3, get_longest_axis, varray()); + ADDFUNC0R(RECT3, INT, Rect3, get_longest_axis_index, varray()); + ADDFUNC0R(RECT3, REAL, Rect3, get_longest_axis_size, varray()); + ADDFUNC0R(RECT3, VECTOR3, Rect3, get_shortest_axis, varray()); + ADDFUNC0R(RECT3, INT, Rect3, get_shortest_axis_index, varray()); + ADDFUNC0R(RECT3, REAL, Rect3, get_shortest_axis_size, varray()); + ADDFUNC1R(RECT3, RECT3, Rect3, expand, VECTOR3, "to_point", varray()); + ADDFUNC1R(RECT3, RECT3, Rect3, grow, REAL, "by", varray()); + ADDFUNC1R(RECT3, VECTOR3, Rect3, get_endpoint, INT, "idx", varray()); + + ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray()); + ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray()); + ADDFUNC0R(TRANSFORM2D, REAL, Transform2D, get_rotation, varray()); + ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray()); + ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray()); + ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, REAL, "phi", varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, xform_inv, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, basis_xform_inv, NIL, "v", varray()); + ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", REAL, "weight", varray()); + + ADDFUNC0R(BASIS, BASIS, Basis, inverse, varray()); + ADDFUNC0R(BASIS, BASIS, Basis, transposed, varray()); + ADDFUNC0R(BASIS, BASIS, Basis, orthonormalized, varray()); + ADDFUNC0R(BASIS, REAL, Basis, determinant, varray()); + ADDFUNC2R(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", REAL, "phi", varray()); + ADDFUNC1R(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale, varray()); + ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler, varray()); + ADDFUNC1R(BASIS, REAL, Basis, tdotx, VECTOR3, "with", varray()); + ADDFUNC1R(BASIS, REAL, Basis, tdoty, VECTOR3, "with", varray()); + ADDFUNC1R(BASIS, REAL, Basis, tdotz, VECTOR3, "with", varray()); + ADDFUNC1R(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray()); + ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray()); + ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray()); + + ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray()); + ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray()); + ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray()); + ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", REAL, "phi", varray()); + ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray()); + ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "ofs", varray()); + ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray()); + ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", REAL, "weight", varray()); + ADDFUNC1R(TRANSFORM, NIL, Transform, xform, NIL, "v", varray()); + ADDFUNC1R(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray()); /* REGISTER CONSTRUCTORS */ diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 73b424eb12..2629e6740d 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -196,7 +196,7 @@ </return> <description> Returns the current latin keyboard variant as a String. - Possible return values are: "QWERTY", "AZERTY", "QZERTY", "DVORAK", "NEO" or "ERROR" + Possible return values are: "QWERTY", "AZERTY", "QZERTY", "DVORAK", "NEO", "COLEMAK" or "ERROR". </description> </method> <method name="get_locale" qualifiers="const"> diff --git a/doc/classes/OccluderPolygon2D.xml b/doc/classes/OccluderPolygon2D.xml index 99c1536ddf..7bc1f74762 100644 --- a/doc/classes/OccluderPolygon2D.xml +++ b/doc/classes/OccluderPolygon2D.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="OccluderPolygon2D" inherits="Resource" category="Core" version="3.0.alpha.custom_build"> <brief_description> + Defines a 2D polygon for LightOccluder2D. </brief_description> <description> + Editor facility that helps you draw a 2D polygon used as resource for [LightOccluder2D]. </description> <tutorials> </tutorials> @@ -54,18 +56,24 @@ </methods> <members> <member name="closed" type="bool" setter="set_closed" getter="is_closed"> + If [code]true[/code] closes the polygon. A closed OccluderPolygon2D occludes the light coming from any direction. An opened OccluderPolygon2D occludes the light only at its outline's direction. Default value [code]true[/code]. </member> <member name="cull_mode" type="int" setter="set_cull_mode" getter="get_cull_mode" enum="OccluderPolygon2D.CullMode"> + Set the direction of the occlusion culling when not [code]CULL_DISABLED[/code]. Default value [code]DISABLED[/code]. </member> <member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon"> + A [Vector2] array with the index for polygon's vertices positions. </member> </members> <constants> <constant name="CULL_DISABLED" value="0"> + Culling mode for the occlusion. Disabled means no culling. See [member cull_mode]. </constant> <constant name="CULL_CLOCKWISE" value="1"> + Culling mode for the occlusion. Sets the culling to be in clockwise direction. See [member cull_mode]. </constant> <constant name="CULL_COUNTER_CLOCKWISE" value="2"> + Culling mode for the occlusion. Sets the culling to be in counter clockwise direction. See [member cull_mode]. </constant> </constants> </class> diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index ddcb04fa7d..8ec988bec1 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1134,9 +1134,9 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m state.current_depth_draw = p_material->shader->spatial.depth_draw_mode; } -//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); + //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); -/* + /* if (p_material->flags[VS::MATERIAL_FLAG_WIREFRAME]) glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); else @@ -4023,6 +4023,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const state.ubo_data.shadow_dual_paraboloid_render_side = 0; state.ubo_data.shadow_dual_paraboloid_render_zfar = 0; + p_cam_projection.get_viewport_size(state.ubo_data.viewport_size[0], state.ubo_data.viewport_size[1]); + if (storage->frame.current_rt) { state.ubo_data.screen_pixel_size[0] = 1.0 / storage->frame.current_rt->width; state.ubo_data.screen_pixel_size[1] = 1.0 / storage->frame.current_rt->height; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ff691ddcec..69b43c7813 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -124,6 +124,7 @@ public: float z_slope_scale; float shadow_dual_paraboloid_render_zfar; float shadow_dual_paraboloid_render_side; + float viewport_size[2]; float screen_pixel_size[2]; float shadow_atlas_pixel_size[2]; float shadow_directional_pixel_size[2]; @@ -143,7 +144,7 @@ public: float fog_height_min; float fog_height_max; float fog_height_curve; - uint8_t padding[8]; + // make sure this struct is padded to be a multiple of 16 bytes for webgl } ubo_data; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index f39342b680..ad08c59de8 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -766,7 +766,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { //builtins actions[VS::SHADER_SPATIAL].renames["TIME"] = "time"; - //actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2; + actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index e4d76753cb..9880663143 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -80,6 +80,7 @@ layout(std140) uniform SceneData { //ubo:0 highp float shadow_dual_paraboloid_render_zfar; highp float shadow_dual_paraboloid_render_side; + highp vec2 viewport_size; highp vec2 screen_pixel_size; highp vec2 shadow_atlas_pixel_size; highp vec2 directional_shadow_pixel_size; @@ -566,6 +567,7 @@ in vec3 normal_interp; uniform bool no_ambient_light; + #ifdef USE_RADIANCE_MAP @@ -663,6 +665,7 @@ layout(std140) uniform SceneData { highp float shadow_dual_paraboloid_render_zfar; highp float shadow_dual_paraboloid_render_side; + highp vec2 viewport_size; highp vec2 screen_pixel_size; highp vec2 shadow_atlas_pixel_size; highp vec2 directional_shadow_pixel_size; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 799a8a2eb8..78cc215421 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -544,6 +544,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { { String lang_hint = "en"; String host_lang = OS::get_singleton()->get_locale(); + host_lang = TranslationServer::standardize_locale(host_lang); String best; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 5782edd321..34c0a3d439 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -222,41 +222,38 @@ 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) { +void CanvasItemEditor::_snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius) { float radius = p_radius / zoom; - float dist; + float dist = Math::abs(p_value - p_target_snap); + if (p_radius < 0 || dist < radius && (!r_snapped || dist < Math::abs(r_current_snap - p_value))) { + r_current_snap = p_target_snap; + r_snapped = true; + } +} +void CanvasItemEditor::_snap_if_closer_point(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) { 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; - } + _snap_if_closer_float(p_value.x, p_target_snap.x, r_current_snap.x, r_snapped[0], p_radius); + _snap_if_closer_float(p_value.y, p_target_snap.y, r_current_snap.y, r_snapped[1], p_radius); 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) { + if (canvas_item && (!p_to_snap || 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()) { + Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D(); + if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), 360.0) == 0.0) { 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()); + _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); + _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); } } for (int i = 0; i < p_current->get_child_count(); i++) { @@ -291,9 +288,9 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const } 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); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation); + _snap_if_closer_point(p_target, end, output, snapped, rotation); } } @@ -302,8 +299,8 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const 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); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(p_target, end, output, snapped, rotation); } } @@ -311,17 +308,34 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const 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); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(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); + } - // 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_guides && (p_modes & SNAP_GUIDES)) || (p_forced_modes & SNAP_GUIDES)) && fmod(rotation, 360.0) == 0.0) { + // Guides + if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); + for (int i = 0; i < vguides.size(); i++) { + _snap_if_closer_float(p_target.x, vguides[i], output.x, snapped[0]); + } + } + + if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { + Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); + for (int i = 0; i < hguides.size(); i++) { + _snap_if_closer_float(p_target.y, hguides[i], output.y, snapped[1]); + } } } - if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && rotation == 0.0) { + if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && fmod(rotation, 360.0) == 0.0) { // Grid Point2 offset = grid_offset; if (snap_relative) { @@ -335,7 +349,7 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const 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); + _snap_if_closer_point(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) { @@ -429,8 +443,10 @@ Dictionary CanvasItemEditor::get_state() const { state["snap_node_sides"] = snap_node_sides; state["snap_other_nodes"] = snap_other_nodes; state["snap_grid"] = snap_grid; + state["snap_guides"] = snap_guides; state["show_grid"] = show_grid; state["show_rulers"] = show_rulers; + state["show_guides"] = show_guides; state["show_helpers"] = show_helpers; state["snap_rotation"] = snap_rotation; state["snap_relative"] = snap_relative; @@ -497,6 +513,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { smartsnap_config_popup->set_item_checked(idx, snap_other_nodes); } + if (state.has("snap_guides")) { + snap_guides = state["snap_guides"]; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES); + smartsnap_config_popup->set_item_checked(idx, snap_guides); + } + if (state.has("snap_grid")) { snap_grid = state["snap_grid"]; int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); @@ -515,6 +537,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { view_menu->get_popup()->set_item_checked(idx, show_rulers); } + if (state.has("show_guides")) { + show_guides = state["show_guides"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES); + view_menu->get_popup()->set_item_checked(idx, show_guides); + } + if (state.has("show_helpers")) { show_helpers = state["show_helpers"]; int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS); @@ -1200,10 +1228,202 @@ void CanvasItemEditor::_update_cursor() { void CanvasItemEditor::_gui_input_viewport_base(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> b = p_event; + if (b.is_valid()) { + if (b->get_button_index() == BUTTON_LEFT && b->is_pressed()) { + if (show_guides && show_rulers && EditorNode::get_singleton()->get_edited_scene()) { + Transform2D xform = viewport_scrollable->get_transform() * transform; + // Retreive the guide lists + Array vguides; + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); + } + Array hguides; + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { + hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); + } + + // Press button + if (b->get_position().x < RULER_WIDTH && b->get_position().y < RULER_WIDTH) { + // Drag a new double guide + drag = DRAG_DOUBLE_GUIDE; + edited_guide_index = -1; + } else if (b->get_position().x < RULER_WIDTH) { + // Check if we drag an existing horizontal guide + float minimum = 1e20; + edited_guide_index = -1; + for (int i = 0; i < hguides.size(); i++) { + if (ABS(xform.xform(Point2(0, hguides[i])).y - b->get_position().y) < MIN(minimum, 8)) { + edited_guide_index = i; + } + } + + if (edited_guide_index >= 0) { + // Drag an existing horizontal guide + drag = DRAG_H_GUIDE; + } else { + // Drag a new vertical guide + drag = DRAG_V_GUIDE; + } + } else if (b->get_position().y < RULER_WIDTH) { + // Check if we drag an existing vertical guide + float minimum = 1e20; + edited_guide_index = -1; + for (int i = 0; i < vguides.size(); i++) { + if (ABS(xform.xform(Point2(vguides[i], 0)).x - b->get_position().x) < MIN(minimum, 8)) { + edited_guide_index = i; + } + } + + if (edited_guide_index >= 0) { + // Drag an existing vertical guide + drag = DRAG_V_GUIDE; + } else { + // Drag a new vertical guide + drag = DRAG_H_GUIDE; + } + } + } + } + + if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed()) { + // Release button + if (show_guides && EditorNode::get_singleton()->get_edited_scene()) { + Transform2D xform = viewport_scrollable->get_transform() * transform; + + // Retreive the guide lists + Array vguides; + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); + } + Array hguides; + if (EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { + hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); + } + + Point2 edited = snap_point(xform.affine_inverse().xform(b->get_position()), SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES); + if (drag == DRAG_V_GUIDE) { + Array prev_vguides = vguides.duplicate(); + if (b->get_position().x > RULER_WIDTH) { + // Adds a new vertical guide + if (edited_guide_index >= 0) { + vguides[edited_guide_index] = edited.x; + undo_redo->create_action(TTR("Move vertical guide")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } else { + vguides.push_back(edited.x); + undo_redo->create_action(TTR("Create new vertical guide")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } + } else { + if (edited_guide_index >= 0) { + vguides.remove(edited_guide_index); + undo_redo->create_action(TTR("Remove vertical guide")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } + } + } else if (drag == DRAG_H_GUIDE) { + Array prev_hguides = hguides.duplicate(); + if (b->get_position().y > RULER_WIDTH) { + // Adds a new horizontal guide + if (edited_guide_index >= 0) { + hguides[edited_guide_index] = edited.y; + undo_redo->create_action(TTR("Move horizontal guide")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } else { + hguides.push_back(edited.y); + undo_redo->create_action(TTR("Create new horizontal guide")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } + } else { + if (edited_guide_index >= 0) { + hguides.remove(edited_guide_index); + undo_redo->create_action(TTR("Remove horizontal guide")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } + } + } else if (drag == DRAG_DOUBLE_GUIDE) { + Array prev_hguides = hguides.duplicate(); + Array prev_vguides = vguides.duplicate(); + if (b->get_position().x > RULER_WIDTH && b->get_position().y > RULER_WIDTH) { + // Adds a new horizontal guide a new vertical guide + vguides.push_back(edited.x); + hguides.push_back(edited.y); + undo_redo->create_action(TTR("Create new horizontal and vertical guides")); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", vguides); + undo_redo->add_do_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", hguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_vertical_guides_", prev_vguides); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_edited_scene(), "set_meta", "_edit_horizontal_guides_", prev_hguides); + undo_redo->add_undo_method(viewport_base, "update"); + undo_redo->commit_action(); + } + } + } + if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE || drag == DRAG_H_GUIDE) { + drag = DRAG_NONE; + viewport_base->update(); + } + } + } + Ref<InputEventMouseMotion> m = p_event; if (m.is_valid()) { - if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) + if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) { viewport_base->call_deferred("grab_focus"); + } + if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE || drag == DRAG_V_GUIDE) { + Transform2D xform = viewport_scrollable->get_transform() * transform; + Point2 mouse_pos = m->get_position(); + mouse_pos = xform.affine_inverse().xform(mouse_pos); + mouse_pos = xform.xform(snap_point(mouse_pos, SNAP_GRID | SNAP_PIXEL | SNAP_OTHER_NODES)); + + edited_guide_pos = mouse_pos; + viewport_base->update(); + } + } + + Ref<InputEventKey> k = p_event; + if (k.is_valid()) { + if (k->is_pressed() && drag == DRAG_NONE) { + // Move the object with the arrow keys + KeyMoveMODE move_mode = MOVE_VIEW_BASE; + if (k->get_alt()) move_mode = MOVE_LOCAL_BASE; + if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT; + + if (k->get_scancode() == KEY_UP) + _key_move(Vector2(0, -1), k->get_shift(), move_mode); + else if (k->get_scancode() == KEY_DOWN) + _key_move(Vector2(0, 1), k->get_shift(), move_mode); + else if (k->get_scancode() == KEY_LEFT) + _key_move(Vector2(-1, 0), k->get_shift(), move_mode); + else if (k->get_scancode() == KEY_RIGHT) + _key_move(Vector2(1, 0), k->get_shift(), move_mode); + else if (k->get_scancode() == KEY_ESCAPE) { + editor_selection->clear(); + viewport->update(); + } else + return; + + accept_event(); + } } } @@ -1741,7 +1961,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { 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)); + Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_GUIDES | 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); @@ -1777,7 +1997,7 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { } dfrom = drag_point_from; - dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, _get_single_item()); + dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL, _get_single_item()); drag_vector = canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) - @@ -2001,32 +2221,6 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { } } } - - Ref<InputEventKey> k = p_event; - if (k.is_valid()) { - if (k->is_pressed() && drag == DRAG_NONE) { - // Move the object with the arrow keys - KeyMoveMODE move_mode = MOVE_VIEW_BASE; - if (k->get_alt()) move_mode = MOVE_LOCAL_BASE; - if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT; - - if (k->get_scancode() == KEY_UP) - _key_move(Vector2(0, -1), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_DOWN) - _key_move(Vector2(0, 1), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_LEFT) - _key_move(Vector2(-1, 0), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_RIGHT) - _key_move(Vector2(1, 0), k->get_shift(), move_mode); - else if (k->get_scancode() == KEY_ESCAPE) { - editor_selection->clear(); - viewport->update(); - } else - return; - - accept_event(); - } - } } void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) { @@ -2065,6 +2259,58 @@ void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_posi } } +void CanvasItemEditor::_draw_focus() { + // Draw the focus around the base viewport + if (viewport_base->has_focus()) { + get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size())); + } +} + +void CanvasItemEditor::_draw_guides() { + + Color guide_color = Color(0.6, 0.0, 0.8); + Transform2D xform = viewport_scrollable->get_transform() * transform; + + // Guides already there + if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_vertical_guides_")) { + Array vguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_vertical_guides_"); + for (int i = 0; i < vguides.size(); i++) { + if (drag == DRAG_V_GUIDE && i == edited_guide_index) + continue; + float x = xform.xform(Point2(vguides[i], 0)).x; + viewport_base->draw_line(Point2(x, 0), Point2(x, viewport_base->get_size().y), guide_color); + } + } + + if (EditorNode::get_singleton()->get_edited_scene() && EditorNode::get_singleton()->get_edited_scene()->has_meta("_edit_horizontal_guides_")) { + Array hguides = EditorNode::get_singleton()->get_edited_scene()->get_meta("_edit_horizontal_guides_"); + for (int i = 0; i < hguides.size(); i++) { + if (drag == DRAG_H_GUIDE && i == edited_guide_index) + continue; + float y = xform.xform(Point2(0, hguides[i])).y; + viewport_base->draw_line(Point2(0, y), Point2(viewport_base->get_size().x, y), guide_color); + } + } + + // Dragged guide + Color text_color = get_color("font_color", "Editor"); + text_color.a = 0.5; + if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_V_GUIDE) { + String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).x); + Ref<Font> font = get_font("font", "Label"); + Size2 text_size = font->get_string_size(str); + viewport_base->draw_string(font, Point2(edited_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color); + viewport_base->draw_line(Point2(edited_guide_pos.x, 0), Point2(edited_guide_pos.x, viewport_base->get_size().y), guide_color); + } + if (drag == DRAG_DOUBLE_GUIDE || drag == DRAG_H_GUIDE) { + String str = vformat("%d px", xform.affine_inverse().xform(edited_guide_pos).y); + Ref<Font> font = get_font("font", "Label"); + Size2 text_size = font->get_string_size(str); + viewport_base->draw_string(font, Point2(RULER_WIDTH + 10, edited_guide_pos.y + text_size.y / 2 + 10), str, text_color); + viewport_base->draw_line(Point2(0, edited_guide_pos.y), Point2(viewport_base->get_size().x, edited_guide_pos.y), guide_color); + } +} + void CanvasItemEditor::_draw_rulers() { Color graduation_color = get_color("font_color", "Editor"); graduation_color.a = 0.5; @@ -2149,12 +2395,6 @@ void CanvasItemEditor::_draw_rulers() { 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 @@ -2640,6 +2880,8 @@ void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const void CanvasItemEditor::_draw_viewport_base() { if (show_rulers) _draw_rulers(); + if (show_guides) + _draw_guides(); _draw_focus(); } @@ -3126,6 +3368,11 @@ void CanvasItemEditor::_popup_callback(int p_op) { 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_GUIDES: { + snap_guides = !snap_guides; + int idx = smartsnap_config_popup->get_item_index(SNAP_USE_GUIDES); + smartsnap_config_popup->set_item_checked(idx, snap_guides); + } break; case SNAP_USE_GRID: { snap_grid = !snap_grid; int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID); @@ -3171,6 +3418,13 @@ void CanvasItemEditor::_popup_callback(int p_op) { viewport->update(); viewport_base->update(); } break; + case SHOW_GUIDES: { + show_guides = !show_guides; + int idx = view_menu->get_popup()->get_item_index(SHOW_GUIDES); + view_menu->get_popup()->set_item_checked(idx, show_guides); + viewport->update(); + viewport_base->update(); + } break; case LOCK_SELECTED: { @@ -3884,6 +4138,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { 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); + smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_guides", TTR("Snap to guides")), SNAP_USE_GUIDES); hb->add_child(memnew(VSeparator)); @@ -3935,6 +4190,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { 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_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show guides"), KEY_Y), SHOW_GUIDES); 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); @@ -4022,9 +4278,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_rot = true; key_scale = false; + edited_guide_pos = Point2(); + edited_guide_index = -1; + show_grid = false; show_helpers = false; show_rulers = false; + show_guides = true; zoom = 1; grid_offset = Point2(); grid_step = Point2(10, 10); @@ -4037,6 +4297,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { snap_node_sides = true; snap_other_nodes = true; snap_grid = true; + snap_guides = true; snap_rotation = false; snap_pixel = false; skeleton_show_bones = true; diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index a8183ba286..97e3b03569 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -87,6 +87,7 @@ class CanvasItemEditor : public VBoxContainer { SNAP_USE_NODE_SIDES, SNAP_USE_OTHER_NODES, SNAP_USE_GRID, + SNAP_USE_GUIDES, SNAP_USE_ROTATION, SNAP_RELATIVE, SNAP_CONFIGURE, @@ -94,6 +95,7 @@ class CanvasItemEditor : public VBoxContainer { SHOW_GRID, SHOW_HELPERS, SHOW_RULERS, + SHOW_GUIDES, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -183,6 +185,9 @@ class CanvasItemEditor : public VBoxContainer { DRAG_ROTATE, DRAG_PIVOT, DRAG_NODE_2D, + DRAG_V_GUIDE, + DRAG_H_GUIDE, + DRAG_DOUBLE_GUIDE, }; enum KeyMoveMODE { @@ -213,6 +218,7 @@ class CanvasItemEditor : public VBoxContainer { Transform2D transform; bool show_grid; bool show_rulers; + bool show_guides; bool show_helpers; float zoom; @@ -228,6 +234,7 @@ class CanvasItemEditor : public VBoxContainer { bool snap_node_sides; bool snap_other_nodes; bool snap_grid; + bool snap_guides; bool snap_rotation; bool snap_relative; bool snap_pixel; @@ -333,6 +340,9 @@ class CanvasItemEditor : public VBoxContainer { Point2 display_rotate_from; Point2 display_rotate_to; + int edited_guide_index; + Point2 edited_guide_pos; + Ref<StyleBoxTexture> select_sb; Ref<Texture> select_handle; Ref<Texture> anchor_handle; @@ -402,6 +412,7 @@ class CanvasItemEditor : public VBoxContainer { void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side); void _draw_rulers(); + void _draw_guides(); void _draw_focus(); void _draw_grid(); void _draw_selection(); @@ -417,8 +428,9 @@ class CanvasItemEditor : public VBoxContainer { 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 _snap_if_closer_float(float p_value, float p_target_snap, float &r_current_snap, bool &r_snapped, float p_radius = 10.0); + void _snap_if_closer_point(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 = NULL); void _set_anchors_preset(Control::LayoutPreset p_preset); void _set_margins_preset(Control::LayoutPreset p_preset); @@ -476,13 +488,14 @@ protected: public: 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, + SNAP_GUIDES = 1 << 1, + SNAP_PIXEL = 1 << 2, + SNAP_NODE_PARENT = 1 << 3, + SNAP_NODE_ANCHORS = 1 << 4, + SNAP_NODE_SIDES = 1 << 5, + SNAP_OTHER_NODES = 1 << 6, + + SNAP_DEFAULT = 0x07, }; Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0); diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp index fcbf282758..443cd2e41f 100644 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ b/editor/plugins/gi_probe_editor_plugin.cpp @@ -60,6 +60,27 @@ void GIProbeEditorPlugin::make_visible(bool p_visible) { } } +EditorProgress *GIProbeEditorPlugin::tmp_progress = NULL; + +void GIProbeEditorPlugin::bake_func_begin(int p_steps) { + + ERR_FAIL_COND(tmp_progress != NULL); + + tmp_progress = memnew(EditorProgress("bake_gi", TTR("Bake GI Probe"), p_steps)); +} + +void GIProbeEditorPlugin::bake_func_step(int p_step, const String &p_description) { + + ERR_FAIL_COND(tmp_progress == NULL); + tmp_progress->step(p_description, p_step); +} + +void GIProbeEditorPlugin::bake_func_end() { + ERR_FAIL_COND(tmp_progress == NULL); + memdelete(tmp_progress); + tmp_progress = NULL; +} + void GIProbeEditorPlugin::_bind_methods() { ClassDB::bind_method("_bake", &GIProbeEditorPlugin::_bake); @@ -70,10 +91,15 @@ GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { editor = p_node; bake = memnew(Button); bake->set_icon(editor->get_gui_base()->get_icon("BakedLight", "EditorIcons")); + bake->set_text(TTR("Bake GI Probe")); bake->hide(); bake->connect("pressed", this, "_bake"); add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, bake); gi_probe = NULL; + + GIProbe::bake_begin_function = bake_func_begin; + GIProbe::bake_step_function = bake_func_step; + GIProbe::bake_end_function = bake_func_end; } GIProbeEditorPlugin::~GIProbeEditorPlugin() { diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h index a1fecd2911..527f420510 100644 --- a/editor/plugins/gi_probe_editor_plugin.h +++ b/editor/plugins/gi_probe_editor_plugin.h @@ -44,6 +44,11 @@ class GIProbeEditorPlugin : public EditorPlugin { Button *bake; EditorNode *editor; + static EditorProgress *tmp_progress; + static void bake_func_begin(int p_steps); + static void bake_func_step(int p_step, const String &p_description); + static void bake_func_end(); + void _bake(); protected: diff --git a/methods.py b/methods.py index 0ae831f942..b62dfc6544 100644 --- a/methods.py +++ b/methods.py @@ -1710,9 +1710,13 @@ def generate_vs_project(env, num_jobs): env.AddToVSProject(env.servers_sources) env.AddToVSProject(env.editor_sources) - env['MSVSBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir)" platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs)) - env['MSVSREBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir)" platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs)) - env['MSVSCLEANCOM'] = build_commandline('scons --directory="$(ProjectDir)" --clean platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs)) + # windows allows us to have spaces in paths, so we need + # to double quote off the directory. However, the path ends + # in a backslash, so we need to remove this, lest it escape the + # last double quote off, confusing MSBuild + env['MSVSBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs)) + env['MSVSREBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs)) + env['MSVSCLEANCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" --clean platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs)) # This version information (Win32, x64, Debug, Release, Release_Debug seems to be # required for Visual Studio to understand that it needs to generate an NMAKE diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index bcb998aee0..d9b10ff3fa 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -2111,9 +2111,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base for (List<String>::Element *E = opts.front(); E; E = E->next()) { String opt = E->get().strip_edges(); - if (opt.begins_with("\"") && opt.ends_with("\"")) { + if (opt.is_quoted()) { r_forced = true; - String idopt = opt.substr(1, opt.length() - 2); + String idopt = opt.unquote(); if (idopt.replace("/", "_").is_valid_identifier()) { options.insert(idopt); } else { diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 9f90a7b70c..27e60c4623 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -97,29 +97,31 @@ def find_msbuild_unix(filename): def find_msbuild_windows(): import mono_reg_utils as monoreg - msbuild_tools_path = monoreg.find_msbuild_tools_path_reg() + bits = env['bits'] - if msbuild_tools_path: - return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), '') + if bits == '32': + if os.getenv('MONO32_PREFIX'): + mono_root = os.getenv('MONO32_PREFIX') + else: + mono_root = monoreg.find_mono_root_dir(bits) else: - bits = env['bits'] - - if bits == '32': - if os.getenv('MONO32_PREFIX'): - mono_root = os.getenv('MONO32_PREFIX') - else: - mono_root = monoreg.find_mono_root_dir(bits) + if os.getenv('MONO64_PREFIX'): + mono_root = os.getenv('MONO64_PREFIX') else: - if os.getenv('MONO64_PREFIX'): - mono_root = os.getenv('MONO64_PREFIX') - else: - mono_root = monoreg.find_mono_root_dir(bits) + mono_root = monoreg.find_mono_root_dir(bits) - if mono_root: - msbuild_mono = os.path.join(mono_root, 'bin', 'msbuild.bat') + if not mono_root: + raise RuntimeError('Cannot find mono root directory') + + msbuild_tools_path = monoreg.find_msbuild_tools_path_reg() + + if msbuild_tools_path: + return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), os.path.join(mono_root, 'lib', 'mono', '4.5')) + else: + msbuild_mono = os.path.join(mono_root, 'bin', 'msbuild.bat') - if os.path.isfile(msbuild_mono): - return (msbuild_mono, os.path.join(mono_root, 'lib', 'mono', '4.5')) + if os.path.isfile(msbuild_mono): + return (msbuild_mono, '') return None diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp index aaea1bc839..83d2bb1471 100644 --- a/modules/mono/editor/godotsharp_builds.cpp +++ b/modules/mono/editor/godotsharp_builds.cpp @@ -32,6 +32,7 @@ #include "main/main.h" #include "../godotsharp_dirs.h" +#include "../mono_gd/gd_mono.h" #include "../mono_gd/gd_mono_class.h" #include "../mono_gd/gd_mono_marshal.h" #include "../utils/path_utils.h" @@ -84,10 +85,16 @@ void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, Mono if (!msbuild_tools_path.ends_with("\\")) msbuild_tools_path += "\\"; - *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); - // FrameworkPathOverride - *r_framework_path = GDMonoMarshal::mono_string_from_godot(GDMono::get_singleton()->get_mono_reg_info().assembly_dir); + const MonoRegInfo &mono_reg_info = GDMono::get_singleton()->get_mono_reg_info(); + if (mono_reg_info.assembly_dir.length()) { + *r_msbuild_path = GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe"); + + String framework_path = path_join(mono_reg_info.assembly_dir, "mono", "4.5"); + *r_framework_path = GDMonoMarshal::mono_string_from_godot(framework_path); + } else { + ERR_PRINT("Cannot find Mono's assemblies directory in the registry"); + } return; } @@ -130,6 +137,7 @@ void godot_icall_BuildInstance_get_MSBuildInfo(MonoString **r_msbuild_path, Mono return; #else + ERR_PRINT("Not implemented on this platform"); return; #endif } diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index 39c57ee0be..837dbfde66 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -171,11 +171,6 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); monodevel_instance->execute(script_path); } break; - case EDITOR_VISUAL_STUDIO: - // TODO - // devenv <PathToSolutionFolder> - // devenv /edit <PathToCsFile> /command "edit.goto <Line>" - // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7 default: return ERR_UNAVAILABLE; } @@ -229,7 +224,7 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) { if (!ed_settings->has_setting("mono/editor/external_editor")) { ed_settings->set_setting("mono/editor/external_editor", EDITOR_NONE); } - ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio,Visual Studio Code")); + ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio Code")); } GodotSharpEditor::~GodotSharpEditor() { diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h index 7b4b50b172..0f2c163582 100644 --- a/modules/mono/editor/godotsharp_editor.h +++ b/modules/mono/editor/godotsharp_editor.h @@ -69,7 +69,6 @@ public: enum ExternalEditor { EDITOR_NONE, EDITOR_MONODEVELOP, - EDITOR_VISUAL_STUDIO, EDITOR_CODE, }; diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 0d9b137f99..7dc7043eec 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -107,10 +107,11 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5")); } - while (assemblies_path) { - if (*assemblies_path) + if (assemblies_path) { + while (*assemblies_path) { search_dirs.push_back(*assemblies_path); - ++assemblies_path; + ++assemblies_path; + } } } diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index c8581f6122..105c2c981e 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -56,9 +56,6 @@ String path_which(const String &p_name) { for (int i = 0; i < env_path.size(); i++) { String p = path_join(env_path[i], p_name); - if (FileAccess::exists(p)) - return p; - #ifdef WINDOWS_ENABLED for (int j = 0; j < exts.size(); j++) { String p2 = p + exts[j]; @@ -66,6 +63,9 @@ String path_which(const String &p_name) { if (FileAccess::exists(p2)) return p2; } +#else + if (FileAccess::exists(p)) + return p; #endif } diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index cc29ad8956..a2988d9c60 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -13,7 +13,7 @@ def get_name(): def can_build(): - return ("EMSCRIPTEN_ROOT" in os.environ) + return ("EMSCRIPTEN_ROOT" in os.environ or "EMSCRIPTEN" in os.environ) def get_opts(): @@ -66,7 +66,10 @@ def configure(env): ## Compiler configuration env['ENV'] = os.environ - env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT']) + if ("EMSCRIPTEN_ROOT" in os.environ): + env.PrependENVPath('PATH', os.environ['EMSCRIPTEN_ROOT']) + elif ("EMSCRIPTEN" in os.environ): + env.PrependENVPath('PATH', os.environ['EMSCRIPTEN']) env['CC'] = 'emcc' env['CXX'] = 'em++' env['LINK'] = 'emcc' diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index d67bc653c9..33586086dc 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1834,6 +1834,8 @@ OS::LatinKeyboardVariant OS_OSX::get_latin_keyboard_variant() const { layout = LATIN_KEYBOARD_DVORAK; } else if ([test isEqualToString:@"xvlcwk"]) { layout = LATIN_KEYBOARD_NEO; + } else if ([test isEqualToString:@"qwfpgj"]) { + layout = LATIN_KEYBOARD_COLEMAK; } [test release]; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 48e2d8f81e..09193e0a2b 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -2253,6 +2253,38 @@ Error OS_X11::move_to_trash(const String &p_path) { return err; } +OS::LatinKeyboardVariant OS_X11::get_latin_keyboard_variant() const { + + XkbDescRec *xkbdesc = XkbAllocKeyboard(); + ERR_FAIL_COND_V(!xkbdesc, LATIN_KEYBOARD_QWERTY); + + XkbGetNames(x11_display, XkbSymbolsNameMask, xkbdesc); + ERR_FAIL_COND_V(!xkbdesc->names, LATIN_KEYBOARD_QWERTY); + ERR_FAIL_COND_V(!xkbdesc->names->symbols, LATIN_KEYBOARD_QWERTY); + + char *layout = XGetAtomName(x11_display, xkbdesc->names->symbols); + ERR_FAIL_COND_V(!layout, LATIN_KEYBOARD_QWERTY); + + Vector<String> info = String(layout).split("+"); + ERR_FAIL_INDEX_V(1, info.size(), LATIN_KEYBOARD_QWERTY); + + if (info[1].find("colemak") != -1) { + return LATIN_KEYBOARD_COLEMAK; + } else if (info[1].find("qwertz") != -1) { + return LATIN_KEYBOARD_QWERTZ; + } else if (info[1].find("azerty") != -1) { + return LATIN_KEYBOARD_AZERTY; + } else if (info[1].find("qzerty") != -1) { + return LATIN_KEYBOARD_QZERTY; + } else if (info[1].find("dvorak") != -1) { + return LATIN_KEYBOARD_DVORAK; + } else if (info[1].find("neo") != -1) { + return LATIN_KEYBOARD_NEO; + } + + return LATIN_KEYBOARD_QWERTY; +} + OS_X11::OS_X11() { #ifdef PULSEAUDIO_ENABLED diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 36355f11bc..b71b456d49 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -275,6 +275,8 @@ public: virtual Error move_to_trash(const String &p_path); + virtual LatinKeyboardVariant get_latin_keyboard_variant() const; + OS_X11(); }; diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index d5a030b35c..c0ca358717 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -1134,6 +1134,10 @@ void GIProbe::_find_meshes(Node *p_at_node, Baker *p_baker) { } } +GIProbe::BakeBeginFunc GIProbe::bake_begin_function = NULL; +GIProbe::BakeStepFunc GIProbe::bake_step_function = NULL; +GIProbe::BakeEndFunc GIProbe::bake_end_function = NULL; + void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { Baker baker; @@ -1177,14 +1181,25 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { _find_meshes(p_from_node ? p_from_node : get_parent(), &baker); + if (bake_begin_function) { + bake_begin_function(baker.mesh_list.size() + 1); + } + int pmc = 0; for (List<Baker::PlotMesh>::Element *E = baker.mesh_list.front(); E; E = E->next()) { - print_line("plotting mesh " + itos(pmc++) + "/" + itos(baker.mesh_list.size())); + if (bake_step_function) { + bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(baker.mesh_list.size())); + } + + pmc++; _plot_mesh(E->get().local_xform, E->get().mesh, &baker, E->get().instance_materials, E->get().override_material); } + if (bake_step_function) { + bake_step_function(pmc++, RTR("Finishing Plot")); + } _fixup_plot(0, 0, 0, 0, 0, &baker); @@ -1282,6 +1297,10 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug) { set_probe_data(probe_data); } + + if (bake_end_function) { + bake_end_function(); + } } void GIProbe::_debug_mesh(int p_idx, int p_level, const Rect3 &p_aabb, Ref<MultiMesh> &p_multimesh, int &idx, Baker *p_baker) { diff --git a/scene/3d/gi_probe.h b/scene/3d/gi_probe.h index 5a06984a47..50d0c33d4f 100644 --- a/scene/3d/gi_probe.h +++ b/scene/3d/gi_probe.h @@ -95,6 +95,10 @@ public: }; + typedef void (*BakeBeginFunc)(int); + typedef void (*BakeStepFunc)(int, const String &); + typedef void (*BakeEndFunc)(); + private: //stuff used for bake struct Baker { @@ -190,6 +194,10 @@ protected: static void _bind_methods(); public: + static BakeBeginFunc bake_begin_function; + static BakeStepFunc bake_step_function; + static BakeEndFunc bake_end_function; + void set_probe_data(const Ref<GIProbeData> &p_data); Ref<GIProbeData> get_probe_data() const; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 623a110263..3203b38d40 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -781,9 +781,7 @@ void ItemList::_notification(int p_what) { } if (has_focus()) { - VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true); draw_style_box(get_stylebox("bg_focus"), Rect2(Point2(), size)); - VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false); } if (shape_changed) { @@ -1429,7 +1427,6 @@ ItemList::ItemList() { allow_rmb_select = false; icon_scale = 1.0f; - set_clip_contents(true); } ItemList::~ItemList() { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ed8eff436c..40e2dba6c2 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -161,13 +161,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { } break; - case (KEY_Z): { // Simple One level undo - + case (KEY_Z): { // undo / redo if (editable) { - - undo(); + if (k->get_shift()) { + redo(); + } else { + undo(); + } } - } break; case (KEY_U): { // Delete from start to cursor @@ -175,7 +176,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (editable) { selection_clear(); - undo_text = text; text = text.substr(cursor_pos, text.length() - cursor_pos); Ref<Font> font = get_font("font"); @@ -205,7 +205,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (editable) { selection_clear(); - undo_text = text; text = text.substr(0, cursor_pos); _text_changed(); } @@ -245,7 +244,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { break; if (selection.enabled) { - undo_text = text; selection_delete(); break; } @@ -276,7 +274,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { set_cursor_position(cc); } else { - undo_text = text; delete_char(); } @@ -382,7 +379,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { } if (selection.enabled) { - undo_text = text; selection_delete(); break; } @@ -417,7 +413,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { delete_text(cursor_pos, cc); } else { - undo_text = text; set_cursor_position(cursor_pos + 1); delete_char(); } @@ -778,7 +773,6 @@ void LineEdit::copy_text() { void LineEdit::cut_text() { if (selection.enabled) { - undo_text = text; OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin)); selection_delete(); } @@ -798,23 +792,33 @@ void LineEdit::paste_text() { } void LineEdit::undo() { - - int old_cursor_pos = cursor_pos; - text = undo_text; - - Ref<Font> font = get_font("font"); - - cached_width = 0; - for (int i = 0; i < text.length(); i++) - cached_width += font->get_char_size(text[i]).width; - - if (old_cursor_pos > text.length()) { - set_cursor_position(text.length()); - } else { - set_cursor_position(old_cursor_pos); + if (undo_stack_pos == NULL) { + if (undo_stack.size() <= 1) { + return; + } + undo_stack_pos = undo_stack.back(); + } else if (undo_stack_pos == undo_stack.front()) { + return; } + undo_stack_pos = undo_stack_pos->prev(); + TextOperation op = undo_stack_pos->get(); + text = op.text; + set_cursor_position(op.cursor_pos); + _emit_text_change(); +} - _text_changed(); +void LineEdit::redo() { + if (undo_stack_pos == NULL) { + return; + } + if (undo_stack_pos == undo_stack.back()) { + return; + } + undo_stack_pos = undo_stack_pos->next(); + TextOperation op = undo_stack_pos->get(); + text = op.text; + set_cursor_position(op.cursor_pos); + _emit_text_change(); } void LineEdit::shift_selection_check_pre(bool p_shift) { @@ -947,8 +951,6 @@ void LineEdit::delete_char() { void LineEdit::delete_text(int p_from_column, int p_to_column) { - undo_text = text; - if (text.size() > 0) { Ref<Font> font = get_font("font"); if (font != NULL) { @@ -1036,9 +1038,11 @@ void LineEdit::set_cursor_position(int p_pos) { Ref<StyleBox> style = get_stylebox("normal"); Ref<Font> font = get_font("font"); - if (cursor_pos < window_pos) { + if (cursor_pos <= window_pos) { /* Adjust window if cursor goes too much to the left */ - set_window_pos(cursor_pos); + if (window_pos > 0) + set_window_pos(window_pos - 1); + } else if (cursor_pos > window_pos) { /* Adjust window if cursor goes too much to the right */ int window_width = get_size().width - style->get_minimum_size().width; @@ -1086,8 +1090,6 @@ void LineEdit::append_at_cursor(String p_text) { if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) { - undo_text = text; - Ref<Font> font = get_font("font"); if (font != NULL) { for (int i = 0; i < p_text.length(); i++) @@ -1105,6 +1107,7 @@ void LineEdit::append_at_cursor(String p_text) { void LineEdit::clear_internal() { + _clear_undo_stack(); cached_width = 0; cursor_pos = 0; window_pos = 0; @@ -1275,6 +1278,11 @@ void LineEdit::menu_option(int p_option) { undo(); } } break; + case MENU_REDO: { + if (editable) { + redo(); + } + } } } @@ -1312,10 +1320,43 @@ void LineEdit::_text_changed() { if (expand_to_text_length) minimum_size_changed(); + _emit_text_change(); + _clear_redo(); +} + +void LineEdit::_emit_text_change() { emit_signal("text_changed", text); _change_notify("text"); } +void LineEdit::_clear_redo() { + _create_undo_state(); + if (undo_stack_pos == NULL) { + return; + } + + undo_stack_pos = undo_stack_pos->next(); + while (undo_stack_pos) { + List<TextOperation>::Element *elem = undo_stack_pos; + undo_stack_pos = undo_stack_pos->next(); + undo_stack.erase(elem); + } + _create_undo_state(); +} + +void LineEdit::_clear_undo_stack() { + undo_stack.clear(); + undo_stack_pos = NULL; + _create_undo_state(); +} + +void LineEdit::_create_undo_state() { + TextOperation op; + op.text = text; + op.cursor_pos = cursor_pos; + undo_stack.push_back(op); +} + void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret); @@ -1369,6 +1410,7 @@ void LineEdit::_bind_methods() { BIND_ENUM_CONSTANT(MENU_CLEAR); BIND_ENUM_CONSTANT(MENU_SELECT_ALL); BIND_ENUM_CONSTANT(MENU_UNDO); + BIND_ENUM_CONSTANT(MENU_REDO); BIND_ENUM_CONSTANT(MENU_MAX); ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); @@ -1388,6 +1430,8 @@ void LineEdit::_bind_methods() { LineEdit::LineEdit() { + undo_stack_pos = NULL; + _create_undo_state(); align = ALIGN_LEFT; cached_width = 0; cursor_pos = 0; @@ -1421,6 +1465,7 @@ LineEdit::LineEdit() { menu->add_item(TTR("Clear"), MENU_CLEAR); menu->add_separator(); menu->add_item(TTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z); + menu->add_item(TTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z); menu->connect("id_pressed", this, "menu_option"); expand_to_text_length = false; } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 661f9b60b9..bece29a37d 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -56,6 +56,7 @@ public: MENU_CLEAR, MENU_SELECT_ALL, MENU_UNDO, + MENU_REDO, MENU_MAX }; @@ -92,10 +93,22 @@ private: bool drag_attempt; } selection; + struct TextOperation { + int cursor_pos; + String text; + }; + List<TextOperation> undo_stack; + List<TextOperation>::Element *undo_stack_pos; + + void _clear_undo_stack(); + void _clear_redo(); + void _create_undo_state(); + Timer *caret_blink_timer; static void _ime_text_callback(void *p_self, String p_text, Point2 p_selection); void _text_changed(); + void _emit_text_change(); bool expand_to_text_length; bool caret_blink_enabled; @@ -166,6 +179,7 @@ public: void cut_text(); void paste_text(); void undo(); + void redo(); void set_editable(bool p_editable); bool is_editable() const; diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index cfe924ecd4..581034ddee 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -90,6 +90,10 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { return; } + // Do not activate tabs when tabs is empty + if (get_tab_count() == 0) + return; + Vector<Control *> tabs = _get_tabs(); // Handle navigation buttons. @@ -298,6 +302,8 @@ void TabContainer::_notification(int p_what) { } int TabContainer::_get_tab_width(int p_index) const { + + ERR_FAIL_INDEX_V(p_index, get_tab_count(), 0); Control *control = Object::cast_to<Control>(_get_tabs()[p_index]); if (!control || control->is_set_as_toplevel()) return 0; @@ -669,6 +675,7 @@ void TabContainer::_bind_methods() { TabContainer::TabContainer() { first_tab_cache = 0; + last_tab_cache = 0; buttons_visible_cache = false; tabs_ofs_cache = 0; current = 0; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index acf6d55eb5..2d55c077f1 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4489,7 +4489,13 @@ void TextEdit::_update_completion_candidates() { completion_index = 0; completion_base = s; Vector<float> sim_cache; + bool single_quote = s.begins_with("'"); + for (int i = 0; i < completion_strings.size(); i++) { + if (single_quote && completion_strings[i].is_quoted()) { + completion_strings[i] = completion_strings[i].unquote().quote("'"); + } + if (s == completion_strings[i]) { // A perfect match, stop completion _cancel_completion(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 4d3e2c709c..eaa16069cf 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -542,6 +542,7 @@ void register_scene_types() { ClassDB::register_class<StyleBoxEmpty>(); ClassDB::register_class<StyleBoxTexture>(); ClassDB::register_class<StyleBoxFlat>(); + ClassDB::register_class<StyleBoxLine>(); ClassDB::register_class<Theme>(); ClassDB::register_class<PolygonPathFinder>(); diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index c644fd2d55..69e2d1c162 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -102,6 +102,7 @@ void VisualServerRaster::draw() { VSG::viewport->draw_viewports(); VSG::scene->render_probes(); + _draw_margins(); VSG::rasterizer->end_frame(); while (frame_drawn_callbacks.front()) { @@ -119,8 +120,6 @@ void VisualServerRaster::draw() { frame_drawn_callbacks.pop_front(); } - - _draw_margins(); } void VisualServerRaster::sync() { } |