diff options
344 files changed, 4565 insertions, 4146 deletions
diff --git a/.gitignore b/.gitignore index ca27e42016..d9537edbf2 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,11 @@ gmon.out *.cflags *.cxxflags +# Code::Blocks files +*.cbp +*.layout +*.depend + # Eclipse CDT files .cproject .settings/ diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index e81351a3a6..267391c4d6 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -498,18 +498,10 @@ Dictionary _OS::get_time_zone_info() const { return infod; } -uint64_t _OS::get_unix_time() const { +double _OS::get_unix_time() const { return OS::get_singleton()->get_unix_time(); } -uint64_t _OS::get_system_time_secs() const { - return OS::get_singleton()->get_system_time_secs(); -} - -uint64_t _OS::get_system_time_msecs() const { - return OS::get_singleton()->get_system_time_msecs(); -} - void _OS::delay_usec(uint32_t p_usec) const { OS::get_singleton()->delay_usec(p_usec); } @@ -729,8 +721,6 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("get_unix_time"), &_OS::get_unix_time); ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"), &_OS::get_datetime_from_unix_time); ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"), &_OS::get_unix_time_from_datetime); - ClassDB::bind_method(D_METHOD("get_system_time_secs"), &_OS::get_system_time_secs); - ClassDB::bind_method(D_METHOD("get_system_time_msecs"), &_OS::get_system_time_msecs); ClassDB::bind_method(D_METHOD("get_exit_code"), &_OS::get_exit_code); ClassDB::bind_method(D_METHOD("set_exit_code", "code"), &_OS::set_exit_code); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 26d0f7b8af..f9f5a4e7d7 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -199,9 +199,7 @@ public: Dictionary get_datetime_from_unix_time(int64_t unix_time_val) const; int64_t get_unix_time_from_datetime(Dictionary datetime) const; Dictionary get_time_zone_info() const; - uint64_t get_unix_time() const; - uint64_t get_system_time_secs() const; - uint64_t get_system_time_msecs() const; + double get_unix_time() const; uint64_t get_static_memory_usage() const; uint64_t get_static_memory_peak_usage() const; diff --git a/core/crypto/aes_context.cpp b/core/crypto/aes_context.cpp new file mode 100644 index 0000000000..8ef1f4f1d4 --- /dev/null +++ b/core/crypto/aes_context.cpp @@ -0,0 +1,116 @@ +/*************************************************************************/ +/* aes_context.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core/crypto/aes_context.h" + +Error AESContext::start(Mode p_mode, PackedByteArray p_key, PackedByteArray p_iv) { + ERR_FAIL_COND_V_MSG(mode != MODE_MAX, ERR_ALREADY_IN_USE, "AESContext already started. Call 'finish' before starting a new one."); + ERR_FAIL_COND_V_MSG(p_mode < 0 || p_mode >= MODE_MAX, ERR_INVALID_PARAMETER, "Invalid mode requested."); + // Key check. + int key_bits = p_key.size() << 3; + ERR_FAIL_COND_V_MSG(key_bits != 128 && key_bits != 256, ERR_INVALID_PARAMETER, "AES key must be either 16 or 32 bytes"); + // Initialization vector. + if (p_mode == MODE_CBC_ENCRYPT || p_mode == MODE_CBC_DECRYPT) { + ERR_FAIL_COND_V_MSG(p_iv.size() != 16, ERR_INVALID_PARAMETER, "The initialization vector (IV) must be exactly 16 bytes."); + iv.resize(0); + iv.append_array(p_iv); + } + // Encryption/decryption key. + if (p_mode == MODE_CBC_ENCRYPT || p_mode == MODE_ECB_ENCRYPT) { + ctx.set_encode_key(p_key.ptr(), key_bits); + } else { + ctx.set_decode_key(p_key.ptr(), key_bits); + } + mode = p_mode; + return OK; +} + +PackedByteArray AESContext::update(PackedByteArray p_src) { + ERR_FAIL_COND_V_MSG(mode < 0 || mode >= MODE_MAX, PackedByteArray(), "AESContext not started. Call 'start' before calling 'update'."); + int len = p_src.size(); + ERR_FAIL_COND_V_MSG(len % 16, PackedByteArray(), "The number of bytes to be encrypted must be multiple of 16. Add padding if needed"); + PackedByteArray out; + out.resize(len); + const uint8_t *src_ptr = p_src.ptr(); + uint8_t *out_ptr = out.ptrw(); + switch (mode) { + case MODE_ECB_ENCRYPT: { + for (int i = 0; i < len; i += 16) { + Error err = ctx.encrypt_ecb(src_ptr + i, out_ptr + i); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); + } + } break; + case MODE_ECB_DECRYPT: { + for (int i = 0; i < len; i += 16) { + Error err = ctx.decrypt_ecb(src_ptr + i, out_ptr + i); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); + } + } break; + case MODE_CBC_ENCRYPT: { + Error err = ctx.encrypt_cbc(len, iv.ptrw(), p_src.ptr(), out.ptrw()); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); + } break; + case MODE_CBC_DECRYPT: { + Error err = ctx.decrypt_cbc(len, iv.ptrw(), p_src.ptr(), out.ptrw()); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); + } break; + default: + ERR_FAIL_V_MSG(PackedByteArray(), "Bug!"); + } + return out; +} + +PackedByteArray AESContext::get_iv_state() { + ERR_FAIL_COND_V_MSG(mode != MODE_CBC_ENCRYPT && mode != MODE_CBC_DECRYPT, PackedByteArray(), "Calling 'get_iv_state' only makes sense when the context is started in CBC mode."); + PackedByteArray out; + out.append_array(iv); + return out; +} + +void AESContext::finish() { + mode = MODE_MAX; + iv.resize(0); +} + +void AESContext::_bind_methods() { + ClassDB::bind_method(D_METHOD("start", "mode", "key", "iv"), &AESContext::start, DEFVAL(PackedByteArray())); + ClassDB::bind_method(D_METHOD("update", "src"), &AESContext::update); + ClassDB::bind_method(D_METHOD("get_iv_state"), &AESContext::get_iv_state); + ClassDB::bind_method(D_METHOD("finish"), &AESContext::finish); + BIND_ENUM_CONSTANT(MODE_ECB_ENCRYPT); + BIND_ENUM_CONSTANT(MODE_ECB_DECRYPT); + BIND_ENUM_CONSTANT(MODE_CBC_ENCRYPT); + BIND_ENUM_CONSTANT(MODE_CBC_DECRYPT); + BIND_ENUM_CONSTANT(MODE_MAX); +} + +AESContext::AESContext() { + mode = MODE_MAX; +} diff --git a/platform/haiku/context_gl_haiku.h b/core/crypto/aes_context.h index c5d258915d..006ecee2ad 100644 --- a/platform/haiku/context_gl_haiku.h +++ b/core/crypto/aes_context.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* context_gl_haiku.h */ +/* aes_context.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,35 +28,41 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONTEXT_GL_HAIKU_H -#define CONTEXT_GL_HAIKU_H +#ifndef AES_CONTEXT_H +#define AES_CONTEXT_H -#if defined(OPENGL_ENABLED) +#include "core/crypto/crypto_core.h" +#include "core/reference.h" -#include "haiku_direct_window.h" -#include "haiku_gl_view.h" +class AESContext : public Reference { + GDCLASS(AESContext, Reference); + +public: + enum Mode { + MODE_ECB_ENCRYPT, + MODE_ECB_DECRYPT, + MODE_CBC_ENCRYPT, + MODE_CBC_DECRYPT, + MODE_MAX + }; -class ContextGL_Haiku { private: - HaikuGLView *view; - HaikuDirectWindow *window; + Mode mode; + CryptoCore::AESContext ctx; + PackedByteArray iv; - bool use_vsync; +protected: + static void _bind_methods(); public: - Error initialize(); - void release_current(); - void make_current(); - void swap_buffers(); - int get_window_width(); - int get_window_height(); - - void set_use_vsync(bool p_use); - bool is_using_vsync() const; - - ContextGL_Haiku(HaikuDirectWindow *p_window); - ~ContextGL_Haiku(); + Error start(Mode p_mode, PackedByteArray p_key, PackedByteArray p_iv = PackedByteArray()); + PackedByteArray update(PackedByteArray p_src); + PackedByteArray get_iv_state(); + void finish(); + + AESContext(); }; -#endif -#endif +VARIANT_ENUM_CAST(AESContext::Mode); + +#endif // AES_CONTEXT_H diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index a9a7cabee9..29d02e11df 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -45,8 +45,11 @@ CryptoKey *CryptoKey::create() { } void CryptoKey::_bind_methods() { - ClassDB::bind_method(D_METHOD("save", "path"), &CryptoKey::save); - ClassDB::bind_method(D_METHOD("load", "path"), &CryptoKey::load); + ClassDB::bind_method(D_METHOD("save", "path", "public_only"), &CryptoKey::save, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("load", "path", "public_only"), &CryptoKey::load, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("is_public_only"), &CryptoKey::is_public_only); + ClassDB::bind_method(D_METHOD("save_to_string", "public_only"), &CryptoKey::save_to_string, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("load_from_string", "string_key", "public_only"), &CryptoKey::load_from_string, DEFVAL(false)); } X509Certificate *(*X509Certificate::_create)() = nullptr; @@ -83,6 +86,10 @@ void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes); ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa); ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000")); + ClassDB::bind_method(D_METHOD("sign", "hash_type", "hash", "key"), &Crypto::sign); + ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify); + ClassDB::bind_method(D_METHOD("encrypt", "key", "plaintext"), &Crypto::encrypt); + ClassDB::bind_method(D_METHOD("decrypt", "key", "ciphertext"), &Crypto::decrypt); } /// Resource loader/saver @@ -98,9 +105,14 @@ RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_origi } else if (el == "key") { CryptoKey *key = CryptoKey::create(); if (key) { - key->load(p_path); + key->load(p_path, false); } return key; + } else if (el == "pub") { + CryptoKey *key = CryptoKey::create(); + if (key) + key->load(p_path, true); + return key; } return nullptr; } @@ -108,6 +120,7 @@ RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_origi void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const { p_extensions->push_back("crt"); p_extensions->push_back("key"); + p_extensions->push_back("pub"); } bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const { @@ -118,7 +131,7 @@ String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const String el = p_path.get_extension().to_lower(); if (el == "crt") { return "X509Certificate"; - } else if (el == "key") { + } else if (el == "key" || el == "pub") { return "CryptoKey"; } return ""; @@ -131,7 +144,8 @@ Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resourc if (cert.is_valid()) { err = cert->save(p_path); } else if (key.is_valid()) { - err = key->save(p_path); + String el = p_path.get_extension().to_lower(); + err = key->save(p_path, el == "pub"); } else { ERR_FAIL_V(ERR_INVALID_PARAMETER); } @@ -146,7 +160,10 @@ void ResourceFormatSaverCrypto::get_recognized_extensions(const RES &p_resource, p_extensions->push_back("crt"); } if (key) { - p_extensions->push_back("key"); + if (!key->is_public_only()) { + p_extensions->push_back("key"); + } + p_extensions->push_back("pub"); } } diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index 6cc5f46164..916f7798eb 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -31,6 +31,7 @@ #ifndef CRYPTO_H #define CRYPTO_H +#include "core/crypto/hashing_context.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/reference.h" @@ -45,8 +46,11 @@ protected: public: static CryptoKey *create(); - virtual Error load(String p_path) = 0; - virtual Error save(String p_path) = 0; + virtual Error load(String p_path, bool p_public_only = false) = 0; + virtual Error save(String p_path, bool p_public_only = false) = 0; + virtual String save_to_string(bool p_public_only = false) = 0; + virtual Error load_from_string(String p_string_key, bool p_public_only = false) = 0; + virtual bool is_public_only() const = 0; }; class X509Certificate : public Resource { @@ -79,6 +83,11 @@ public: virtual Ref<CryptoKey> generate_rsa(int p_bytes) = 0; virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) = 0; + virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) = 0; + virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) = 0; + virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext) = 0; + virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext) = 0; + Crypto() {} }; diff --git a/core/crypto/crypto_core.cpp b/core/crypto/crypto_core.cpp index ec25ee0d38..b0dc47e655 100644 --- a/core/crypto/crypto_core.cpp +++ b/core/crypto/crypto_core.cpp @@ -145,6 +145,16 @@ Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst return ret ? FAILED : OK; } +Error CryptoCore::AESContext::encrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst) { + int ret = mbedtls_aes_crypt_cbc((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_length, r_iv, p_src, r_dst); + return ret ? FAILED : OK; +} + +Error CryptoCore::AESContext::decrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst) { + int ret = mbedtls_aes_crypt_cbc((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_length, r_iv, p_src, r_dst); + return ret ? FAILED : OK; +} + // CryptoCore String CryptoCore::b64_encode_str(const uint8_t *p_src, int p_src_len) { int b64len = p_src_len / 3 * 4 + 4 + 1; diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h index 36d8ace723..82df9c23a8 100644 --- a/core/crypto/crypto_core.h +++ b/core/crypto/crypto_core.h @@ -86,6 +86,8 @@ public: Error set_decode_key(const uint8_t *p_key, size_t p_bits); Error encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]); Error decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]); + Error encrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst); + Error decrypt_cbc(size_t p_length, uint8_t r_iv[16], const uint8_t *p_src, uint8_t *r_dst); }; static String b64_encode_str(const uint8_t *p_src, int p_src_len); diff --git a/core/error_macros.h b/core/error_macros.h index 46a1623115..d7366be453 100644 --- a/core/error_macros.h +++ b/core/error_macros.h @@ -285,7 +285,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, the current function returns. */ #define ERR_FAIL_NULL(m_param) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ return; \ } else \ @@ -296,7 +296,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, prints `m_msg` and the current function returns. */ #define ERR_FAIL_NULL_MSG(m_param, m_msg) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ return; \ } else \ @@ -310,7 +310,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, the current function returns `m_retval`. */ #define ERR_FAIL_NULL_V(m_param, m_retval) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null."); \ return m_retval; \ } else \ @@ -321,7 +321,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If it is null, prints `m_msg` and the current function returns `m_retval`. */ #define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \ - if (unlikely(!m_param)) { \ + if (unlikely(m_param == nullptr)) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", DEBUG_STR(m_msg)); \ return m_retval; \ } else \ diff --git a/core/image.cpp b/core/image.cpp index 0f15574053..45f10625a9 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -678,34 +678,35 @@ static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict enum { FRAC_BITS = 8, FRAC_LEN = (1 << FRAC_BITS), + FRAC_HALF = (FRAC_LEN >> 1), FRAC_MASK = FRAC_LEN - 1 - }; for (uint32_t i = 0; i < p_dst_height; i++) { - uint32_t src_yofs_up_fp = (i * p_src_height * FRAC_LEN / p_dst_height); - uint32_t src_yofs_frac = src_yofs_up_fp & FRAC_MASK; - uint32_t src_yofs_up = src_yofs_up_fp >> FRAC_BITS; - - uint32_t src_yofs_down = (i + 1) * p_src_height / p_dst_height; + // Add 0.5 in order to interpolate based on pixel center + uint32_t src_yofs_up_fp = (i + 0.5) * p_src_height * FRAC_LEN / p_dst_height; + // Calculate nearest src pixel center above current, and truncate to get y index + uint32_t src_yofs_up = src_yofs_up_fp >= FRAC_HALF ? (src_yofs_up_fp - FRAC_HALF) >> FRAC_BITS : 0; + uint32_t src_yofs_down = (src_yofs_up_fp + FRAC_HALF) >> FRAC_BITS; if (src_yofs_down >= p_src_height) { src_yofs_down = p_src_height - 1; } - - //src_yofs_up*=CC; - //src_yofs_down*=CC; + // Calculate distance to pixel center of src_yofs_up + uint32_t src_yofs_frac = src_yofs_up_fp & FRAC_MASK; + src_yofs_frac = src_yofs_frac >= FRAC_HALF ? src_yofs_frac - FRAC_HALF : src_yofs_frac + FRAC_HALF; uint32_t y_ofs_up = src_yofs_up * p_src_width * CC; uint32_t y_ofs_down = src_yofs_down * p_src_width * CC; for (uint32_t j = 0; j < p_dst_width; j++) { - uint32_t src_xofs_left_fp = (j * p_src_width * FRAC_LEN / p_dst_width); - uint32_t src_xofs_frac = src_xofs_left_fp & FRAC_MASK; - uint32_t src_xofs_left = src_xofs_left_fp >> FRAC_BITS; - uint32_t src_xofs_right = (j + 1) * p_src_width / p_dst_width; + uint32_t src_xofs_left_fp = (j + 0.5) * p_src_width * FRAC_LEN / p_dst_width; + uint32_t src_xofs_left = src_xofs_left_fp >= FRAC_HALF ? (src_xofs_left_fp - FRAC_HALF) >> FRAC_BITS : 0; + uint32_t src_xofs_right = (src_xofs_left_fp + FRAC_HALF) >> FRAC_BITS; if (src_xofs_right >= p_src_width) { src_xofs_right = p_src_width - 1; } + uint32_t src_xofs_frac = src_xofs_left_fp & FRAC_MASK; + src_xofs_frac = src_xofs_frac >= FRAC_HALF ? src_xofs_frac - FRAC_HALF : src_xofs_frac + FRAC_HALF; src_xofs_left *= CC; src_xofs_right *= CC; diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 3cb4b43a26..ac032b7d10 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -48,7 +48,7 @@ void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("action_has_event", "action", "event"), &InputMap::action_has_event); ClassDB::bind_method(D_METHOD("action_erase_event", "action", "event"), &InputMap::action_erase_event); ClassDB::bind_method(D_METHOD("action_erase_events", "action"), &InputMap::action_erase_events); - ClassDB::bind_method(D_METHOD("get_action_list", "action"), &InputMap::_get_action_list); + ClassDB::bind_method(D_METHOD("action_get_events", "action"), &InputMap::_action_get_events); ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action); ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals); } @@ -152,9 +152,9 @@ void InputMap::action_erase_events(const StringName &p_action) { input_map[p_action].inputs.clear(); } -Array InputMap::_get_action_list(const StringName &p_action) { +Array InputMap::_action_get_events(const StringName &p_action) { Array ret; - const List<Ref<InputEvent>> *al = get_action_list(p_action); + const List<Ref<InputEvent>> *al = action_get_events(p_action); if (al) { for (const List<Ref<InputEvent>>::Element *E = al->front(); E; E = E->next()) { ret.push_back(E->get()); @@ -164,7 +164,7 @@ Array InputMap::_get_action_list(const StringName &p_action) { return ret; } -const List<Ref<InputEvent>> *InputMap::get_action_list(const StringName &p_action) { +const List<Ref<InputEvent>> *InputMap::action_get_events(const StringName &p_action) { const Map<StringName, Action>::Element *E = input_map.find(p_action); if (!E) { return nullptr; diff --git a/core/input/input_map.h b/core/input/input_map.h index 3abc224ccf..548553ed31 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -56,7 +56,7 @@ private: List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr) const; - Array _get_action_list(const StringName &p_action); + Array _action_get_events(const StringName &p_action); Array _get_actions(); protected: @@ -76,7 +76,7 @@ public: void action_erase_event(const StringName &p_action, const Ref<InputEvent> &p_event); void action_erase_events(const StringName &p_action); - const List<Ref<InputEvent>> *get_action_list(const StringName &p_action); + const List<Ref<InputEvent>> *action_get_events(const StringName &p_action); bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const; bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr) const; diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h index 61c0fa7489..99d5ce903d 100644 --- a/core/io/file_access_buffered.h +++ b/core/io/file_access_buffered.h @@ -51,16 +51,16 @@ protected: Error set_error(Error p_error) const; mutable struct File { - bool open; - int size; - int offset; + bool open = false; + int size = 0; + int offset = 0; String name; - int access_flags; + int access_flags = 0; } file; mutable struct Cache { Vector<uint8_t> buffer; - int offset; + int offset = 0; } cache; virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = nullptr) const = 0; diff --git a/core/math/basis.cpp b/core/math/basis.cpp index cbfd09810c..df5199b0f9 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -428,12 +428,9 @@ Vector3 Basis::get_euler_xyz() const { // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy Vector3 euler; -#ifdef MATH_CHECKS - ERR_FAIL_COND_V(!is_rotation(), euler); -#endif real_t sy = elements[0][2]; - if (sy < 1.0) { - if (sy > -1.0) { + if (sy < (1.0 - CMP_EPSILON)) { + if (sy > -(1.0 - CMP_EPSILON)) { // is this a pure Y rotation? if (elements[1][0] == 0.0 && elements[0][1] == 0.0 && elements[1][2] == 0 && elements[2][1] == 0 && elements[1][1] == 1) { // return the simplest form (human friendlier in editor and scripts) @@ -446,12 +443,12 @@ Vector3 Basis::get_euler_xyz() const { euler.z = Math::atan2(-elements[0][1], elements[0][0]); } } else { - euler.x = -Math::atan2(elements[0][1], elements[1][1]); + euler.x = Math::atan2(elements[2][1], elements[1][1]); euler.y = -Math_PI / 2.0; euler.z = 0.0; } } else { - euler.x = Math::atan2(elements[0][1], elements[1][1]); + euler.x = Math::atan2(elements[2][1], elements[1][1]); euler.y = Math_PI / 2.0; euler.z = 0.0; } @@ -481,15 +478,106 @@ void Basis::set_euler_xyz(const Vector3 &p_euler) { *this = xmat * (ymat * zmat); } +Vector3 Basis::get_euler_xzy() const { + // Euler angles in XZY convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cz*cy -sz cz*sy + // sx*sy+cx*cy*sz cx*cz cx*sz*sy-cy*sx + // cy*sx*sz cz*sx cx*cy+sx*sz*sy + + Vector3 euler; + real_t sz = elements[0][1]; + if (sz < (1.0 - CMP_EPSILON)) { + if (sz > -(1.0 - CMP_EPSILON)) { + euler.x = Math::atan2(elements[2][1], elements[1][1]); + euler.y = Math::atan2(elements[0][2], elements[0][0]); + euler.z = Math::asin(-sz); + } else { + // It's -1 + euler.x = -Math::atan2(elements[1][2], elements[2][2]); + euler.y = 0.0; + euler.z = Math_PI / 2.0; + } + } else { + // It's 1 + euler.x = -Math::atan2(elements[1][2], elements[2][2]); + euler.y = 0.0; + euler.z = -Math_PI / 2.0; + } + return euler; +} + +void Basis::set_euler_xzy(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = xmat * zmat * ymat; +} + +Vector3 Basis::get_euler_yzx() const { + // Euler angles in YZX convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx + // sz cz*cx -cz*sx + // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx + + Vector3 euler; + real_t sz = elements[1][0]; + if (sz < (1.0 - CMP_EPSILON)) { + if (sz > -(1.0 - CMP_EPSILON)) { + euler.x = Math::atan2(-elements[1][2], elements[1][1]); + euler.y = Math::atan2(-elements[2][0], elements[0][0]); + euler.z = Math::asin(sz); + } else { + // It's -1 + euler.x = Math::atan2(elements[2][1], elements[2][2]); + euler.y = 0.0; + euler.z = -Math_PI / 2.0; + } + } else { + // It's 1 + euler.x = Math::atan2(elements[2][1], elements[2][2]); + euler.y = 0.0; + euler.z = Math_PI / 2.0; + } + return euler; +} + +void Basis::set_euler_yzx(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = ymat * zmat * xmat; +} + // get_euler_yxz returns a vector containing the Euler angles in the YXZ convention, // as in first-Z, then-X, last-Y. The angles for X, Y, and Z rotations are returned // as the x, y, and z components of a Vector3 respectively. Vector3 Basis::get_euler_yxz() const { - /* checking this is a bad idea, because obtaining from scaled transform is a valid use case -#ifdef MATH_CHECKS - ERR_FAIL_COND(!is_rotation()); -#endif -*/ // Euler angles in YXZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // @@ -501,8 +589,8 @@ Vector3 Basis::get_euler_yxz() const { real_t m12 = elements[1][2]; - if (m12 < 1) { - if (m12 > -1) { + if (m12 < (1 - CMP_EPSILON)) { + if (m12 > -(1 - CMP_EPSILON)) { // is this a pure X rotation? if (elements[1][0] == 0 && elements[0][1] == 0 && elements[0][2] == 0 && elements[2][0] == 0 && elements[0][0] == 1) { // return the simplest form (human friendlier in editor and scripts) @@ -516,12 +604,12 @@ Vector3 Basis::get_euler_yxz() const { } } else { // m12 == -1 euler.x = Math_PI * 0.5; - euler.y = -atan2(-elements[0][1], elements[0][0]); + euler.y = atan2(elements[0][1], elements[0][0]); euler.z = 0; } } else { // m12 == 1 euler.x = -Math_PI * 0.5; - euler.y = -atan2(-elements[0][1], elements[0][0]); + euler.y = -atan2(elements[0][1], elements[0][0]); euler.z = 0; } @@ -551,6 +639,100 @@ void Basis::set_euler_yxz(const Vector3 &p_euler) { *this = ymat * xmat * zmat; } +Vector3 Basis::get_euler_zxy() const { + // Euler angles in ZXY convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx + // cy*sz+cz*sx*sy cz*cx sz*sy-cz*cy*sx + // -cx*sy sx cx*cy + Vector3 euler; + real_t sx = elements[2][1]; + if (sx < (1.0 - CMP_EPSILON)) { + if (sx > -(1.0 - CMP_EPSILON)) { + euler.x = Math::asin(sx); + euler.y = Math::atan2(-elements[2][0], elements[2][2]); + euler.z = Math::atan2(-elements[0][1], elements[1][1]); + } else { + // It's -1 + euler.x = -Math_PI / 2.0; + euler.y = Math::atan2(elements[0][2], elements[0][0]); + euler.z = 0; + } + } else { + // It's 1 + euler.x = Math_PI / 2.0; + euler.y = Math::atan2(elements[0][2], elements[0][0]); + euler.z = 0; + } + return euler; +} + +void Basis::set_euler_zxy(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = zmat * xmat * ymat; +} + +Vector3 Basis::get_euler_zyx() const { + // Euler angles in ZYX convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // + // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*cy + // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx + // -sy cy*sx cy*cx + Vector3 euler; + real_t sy = elements[2][0]; + if (sy < (1.0 - CMP_EPSILON)) { + if (sy > -(1.0 - CMP_EPSILON)) { + euler.x = Math::atan2(elements[2][1], elements[2][2]); + euler.y = Math::asin(-sy); + euler.z = Math::atan2(elements[1][0], elements[0][0]); + } else { + // It's -1 + euler.x = 0; + euler.y = Math_PI / 2.0; + euler.z = -Math::atan2(elements[0][1], elements[1][1]); + } + } else { + // It's 1 + euler.x = 0; + euler.y = -Math_PI / 2.0; + euler.z = -Math::atan2(elements[0][1], elements[1][1]); + } + return euler; +} + +void Basis::set_euler_zyx(const Vector3 &p_euler) { + real_t c, s; + + c = Math::cos(p_euler.x); + s = Math::sin(p_euler.x); + Basis xmat(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); + + c = Math::cos(p_euler.y); + s = Math::sin(p_euler.y); + Basis ymat(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0, c); + + c = Math::cos(p_euler.z); + s = Math::sin(p_euler.z); + Basis zmat(c, -s, 0.0, s, c, 0.0, 0.0, 0.0, 1.0); + + *this = zmat * ymat * xmat; +} + bool Basis::is_equal_approx(const Basis &p_basis) const { return elements[0].is_equal_approx(p_basis.elements[0]) && elements[1].is_equal_approx(p_basis.elements[1]) && elements[2].is_equal_approx(p_basis.elements[2]); } diff --git a/core/math/basis.h b/core/math/basis.h index d870a6b099..985fb0e44f 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -88,9 +88,22 @@ public: Vector3 get_euler_xyz() const; void set_euler_xyz(const Vector3 &p_euler); + + Vector3 get_euler_xzy() const; + void set_euler_xzy(const Vector3 &p_euler); + + Vector3 get_euler_yzx() const; + void set_euler_yzx(const Vector3 &p_euler); + Vector3 get_euler_yxz() const; void set_euler_yxz(const Vector3 &p_euler); + Vector3 get_euler_zxy() const; + void set_euler_zxy(const Vector3 &p_euler); + + Vector3 get_euler_zyx() const; + void set_euler_zyx(const Vector3 &p_euler); + Quat get_quat() const; void set_quat(const Quat &p_quat); diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index dee1b3b23e..180aeaa0af 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -78,12 +78,7 @@ void Transform2D::set_skew(float p_angle) { } real_t Transform2D::get_rotation() const { - real_t det = basis_determinant(); - Transform2D m = orthonormalized(); - if (det < 0) { - m.scale_basis(Size2(1, -1)); // convention to separate rotation and reflection for 2D is to absorb a flip along y into scaling. - } - return Math::atan2(m[0].y, m[0].x); + return Math::atan2(elements[0].y, elements[0].x); } void Transform2D::set_rotation(real_t p_rot) { diff --git a/core/os/os.cpp b/core/os/os.cpp index 56755bcf51..c842be333c 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -83,15 +83,7 @@ uint64_t OS::get_splash_tick_msec() const { return _msec_splash; } -uint64_t OS::get_unix_time() const { - return 0; -} - -uint64_t OS::get_system_time_secs() const { - return 0; -} - -uint64_t OS::get_system_time_msecs() const { +double OS::get_unix_time() const { return 0; } diff --git a/core/os/os.h b/core/os/os.h index 9ca034a01c..04e10518dc 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -209,9 +209,7 @@ public: virtual Time get_time(bool local = false) const = 0; virtual TimeZoneInfo get_time_zone_info() const = 0; virtual String get_iso_date_time(bool local = false) const; - virtual uint64_t get_unix_time() const; - virtual uint64_t get_system_time_secs() const; - virtual uint64_t get_system_time_msecs() const; + virtual double get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const = 0; virtual uint64_t get_ticks_usec() const = 0; diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index c0f9eea76d..5dac42cacb 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -34,6 +34,7 @@ #include "core/class_db.h" #include "core/compressed_translation.h" #include "core/core_string_names.h" +#include "core/crypto/aes_context.h" #include "core/crypto/crypto.h" #include "core/crypto/hashing_context.h" #include "core/engine.h" @@ -165,6 +166,7 @@ void register_core_types() { // Crypto ClassDB::register_class<HashingContext>(); + ClassDB::register_class<AESContext>(); ClassDB::register_custom_instance_class<X509Certificate>(); ClassDB::register_custom_instance_class<CryptoKey>(); ClassDB::register_custom_instance_class<Crypto>(); diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 90750f2c6e..1dcbb0cd6b 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -435,6 +435,7 @@ Variant UndoRedo::_add_do_method(const Variant **p_args, int p_argcount, Callabl v[i] = *p_args[i + 2]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); add_do_method(object, method, v[0], v[1], v[2], v[3], v[4]); return Variant(); } @@ -471,6 +472,7 @@ Variant UndoRedo::_add_undo_method(const Variant **p_args, int p_argcount, Calla v[i] = *p_args[i + 2]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); add_undo_method(object, method, v[0], v[1], v[2], v[3], v[4]); return Variant(); } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index f1b2a1547d..a8beac1e44 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -923,6 +923,18 @@ struct _VariantCall { VCALL_PTR1R(Basis, scaled); VCALL_PTR0R(Basis, get_scale); VCALL_PTR0R(Basis, get_euler); + VCALL_PTR0R(Basis, get_euler_xyz); + VCALL_PTR1(Basis, set_euler_xyz); + VCALL_PTR0R(Basis, get_euler_xzy); + VCALL_PTR1(Basis, set_euler_xzy); + VCALL_PTR0R(Basis, get_euler_yzx); + VCALL_PTR1(Basis, set_euler_yzx); + VCALL_PTR0R(Basis, get_euler_yxz); + VCALL_PTR1(Basis, set_euler_yxz); + VCALL_PTR0R(Basis, get_euler_zxy); + VCALL_PTR1(Basis, set_euler_zxy); + VCALL_PTR0R(Basis, get_euler_zyx); + VCALL_PTR1(Basis, set_euler_zyx); VCALL_PTR1R(Basis, tdotx); VCALL_PTR1R(Basis, tdoty); VCALL_PTR1R(Basis, tdotz); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 41811a48b1..9a28a0d085 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -33,6 +33,9 @@ <member name="Geometry3D" type="Geometry3D" setter="" getter=""> The [Geometry3D] singleton. </member> + <member name="GodotSharp" type="GodotSharp" setter="" getter=""> + The [GodotSharp] singleton. + </member> <member name="IP" type="IP" setter="" getter=""> The [IP] singleton. </member> diff --git a/doc/classes/AESContext.xml b/doc/classes/AESContext.xml new file mode 100644 index 0000000000..ab4d0e0bc3 --- /dev/null +++ b/doc/classes/AESContext.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="AESContext" inherits="Reference" version="4.0"> + <brief_description> + Interface to low level AES encryption features. + </brief_description> + <description> + This class provides access to AES encryption/decryption of raw data. Both AES-ECB and AES-CBC mode are supported. + [codeblock] + extends Node + + var aes = AESContext.new() + + func _ready(): + var key = "My secret key!!!" # Key must be either 16 or 32 bytes. + var data = "My secret text!!" # Data size must be multiple of 16 bytes, apply padding if needed. + # Encrypt ECB + aes.start(AESContext.MODE_ECB_ENCRYPT, key.to_utf8()) + var encrypted = aes.update(data.to_utf8()) + aes.finish() + # Decrypt ECB + aes.start(AESContext.MODE_ECB_DECRYPT, key.to_utf8()) + var decrypted = aes.update(encrypted) + aes.finish() + # Check ECB + assert(decrypted == data.to_utf8()) + + var iv = "My secret iv!!!!" # IV must be of exactly 16 bytes. + # Encrypt CBC + aes.start(AESContext.MODE_CBC_ENCRYPT, key.to_utf8(), iv.to_utf8()) + encrypted = aes.update(data.to_utf8()) + aes.finish() + # Decrypt CBC + aes.start(AESContext.MODE_CBC_DECRYPT, key.to_utf8(), iv.to_utf8()) + decrypted = aes.update(encrypted) + aes.finish() + # Check CBC + assert(decrypted == data.to_utf8()) + [/codeblock] + </description> + <tutorials> + </tutorials> + <methods> + <method name="finish"> + <return type="void"> + </return> + <description> + Close this AES context so it can be started again. See [method start]. + </description> + </method> + <method name="get_iv_state"> + <return type="PackedByteArray"> + </return> + <description> + Get the current IV state for this context (IV gets updated when calling [method update]). You normally don't need this funciton. + Note: This function only makes sense when the context is started with [constant MODE_CBC_ENCRYPT] or [constant MODE_CBC_DECRYPT]. + </description> + </method> + <method name="start"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="mode" type="int" enum="AESContext.Mode"> + </argument> + <argument index="1" name="key" type="PackedByteArray"> + </argument> + <argument index="2" name="iv" type="PackedByteArray" default="PackedByteArray( )"> + </argument> + <description> + Start the AES context in the given [code]mode[/code]. A [code]key[/code] of either 16 or 32 bytes must always be provided, while an [code]iv[/code] (initialization vector) of exactly 16 bytes, is only needed when [code]mode[/code] is either [constant MODE_CBC_ENCRYPT] or [constant MODE_CBC_DECRYPT]. + </description> + </method> + <method name="update"> + <return type="PackedByteArray"> + </return> + <argument index="0" name="src" type="PackedByteArray"> + </argument> + <description> + Run the desired operation for this AES context. Will return a [PackedByteArray] containing the result of encrypting (or decrypting) the given [code]src[/code]. See [method start] for mode of operation. + Note: The size of [code]src[/code] must be a multiple of 16. Apply some padding if needed. + </description> + </method> + </methods> + <constants> + <constant name="MODE_ECB_ENCRYPT" value="0" enum="Mode"> + AES electronic codebook encryption mode. + </constant> + <constant name="MODE_ECB_DECRYPT" value="1" enum="Mode"> + AES electronic codebook decryption mode. + </constant> + <constant name="MODE_CBC_ENCRYPT" value="2" enum="Mode"> + AES cipher blocker chaining encryption mode. + </constant> + <constant name="MODE_CBC_DECRYPT" value="3" enum="Mode"> + AES cipher blocker chaining decryption mode. + </constant> + <constant name="MODE_MAX" value="4" enum="Mode"> + Maximum value for the mode enum. + </constant> + </constants> +</class> diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml index b35d4fb36a..17b474531e 100644 --- a/doc/classes/Color.xml +++ b/doc/classes/Color.xml @@ -5,8 +5,9 @@ </brief_description> <description> A color is represented by red, green, and blue [code](r, g, b)[/code] components. Additionally, [code]a[/code] represents the alpha component, often used for transparency. Values are in floating-point and usually range from 0 to 1. Some properties (such as [member CanvasItem.modulate]) may accept values greater than 1. - You can also create a color from standardized color names by using [method @GDScript.ColorN] or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url]. + You can also create a color from standardized color names by using [method @GDScript.ColorN] or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url]. If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8]. + [b]Note:[/b] In a boolean context, a Color will evaluate to [code]false[/code] if it's equal to [code]Color(0, 0, 0, 1)[/code] (opaque black). Otherwise, a Color will always evaluate to [code]true[/code]. </description> <tutorials> </tutorials> diff --git a/doc/classes/Crypto.xml b/doc/classes/Crypto.xml index 10f1f18f0d..4edb3eda0a 100644 --- a/doc/classes/Crypto.xml +++ b/doc/classes/Crypto.xml @@ -5,7 +5,7 @@ </brief_description> <description> The Crypto class allows you to access some more advanced cryptographic functionalities in Godot. - For now, this includes generating cryptographically secure random bytes, and RSA keys and self-signed X509 certificates generation. More functionalities are planned for future releases. + For now, this includes generating cryptographically secure random bytes, RSA keys and self-signed X509 certificates generation, asymmetric key encryption/decryption, and signing/verification. [codeblock] extends Node @@ -21,12 +21,48 @@ # Save key and certificate in the user folder. key.save("user://generated.key") cert.save("user://generated.crt") + # Encryption + var data = "Some data" + var encrypted = crypto.encrypt(key, data.to_utf8()) + # Decryption + var decrypted = crypto.decrypt(key, encrypted) + # Signing + var signature = crypto.sign(HashingContext.HASH_SHA256, data.sha256_buffer(), key) + # Verifying + var verified = crypto.verify(HashingContext.HASH_SHA256, data.sha256_buffer(), signature, key) + # Checks + assert(verified) + assert(data.to_utf8() == decrypted) [/codeblock] [b]Note:[/b] Not available in HTML5 exports. </description> <tutorials> </tutorials> <methods> + <method name="decrypt"> + <return type="PackedByteArray"> + </return> + <argument index="0" name="key" type="CryptoKey"> + </argument> + <argument index="1" name="ciphertext" type="PackedByteArray"> + </argument> + <description> + Decrypt the given [code]ciphertext[/code] with the provided private [code]key[/code]. + [b]Note[/b]: The maximum size of accepted ciphertext is limited by the key size. + </description> + </method> + <method name="encrypt"> + <return type="PackedByteArray"> + </return> + <argument index="0" name="key" type="CryptoKey"> + </argument> + <argument index="1" name="plaintext" type="PackedByteArray"> + </argument> + <description> + Encrypt the given [code]plaintext[/code] with the provided public [code]key[/code]. + [b]Note[/b]: The maximum size of accepted plaintext is limited by the key size. + </description> + </method> <method name="generate_random_bytes"> <return type="PackedByteArray"> </return> @@ -68,6 +104,34 @@ [/codeblock] </description> </method> + <method name="sign"> + <return type="PackedByteArray"> + </return> + <argument index="0" name="hash_type" type="int" enum="HashingContext.HashType"> + </argument> + <argument index="1" name="hash" type="PackedByteArray"> + </argument> + <argument index="2" name="key" type="CryptoKey"> + </argument> + <description> + Sign a given [code]hash[/code] of type [code]hash_type[/code] with the provided private [code]key[/code]. + </description> + </method> + <method name="verify"> + <return type="bool"> + </return> + <argument index="0" name="hash_type" type="int" enum="HashingContext.HashType"> + </argument> + <argument index="1" name="hash" type="PackedByteArray"> + </argument> + <argument index="2" name="signature" type="PackedByteArray"> + </argument> + <argument index="3" name="key" type="CryptoKey"> + </argument> + <description> + Verify that a given [code]signature[/code] for [code]hash[/code] of type [code]hash_type[/code] against the provided public [code]key[/code]. + </description> + </method> </methods> <constants> </constants> diff --git a/doc/classes/CryptoKey.xml b/doc/classes/CryptoKey.xml index fe7f4b63f0..410c2262f9 100644 --- a/doc/classes/CryptoKey.xml +++ b/doc/classes/CryptoKey.xml @@ -11,13 +11,34 @@ <tutorials> </tutorials> <methods> + <method name="is_public_only" qualifiers="const"> + <return type="bool"> + </return> + <description> + Return [code]true[/code] if this CryptoKey only has the public part, and not the private one. + </description> + </method> <method name="load"> <return type="int" enum="Error"> </return> <argument index="0" name="path" type="String"> </argument> + <argument index="1" name="public_only" type="bool" default="false"> + </argument> + <description> + Loads a key from [code]path[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be loaded. + [b]Note[/b]: [code]path[/code] should should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise. + </description> + </method> + <method name="load_from_string"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="string_key" type="String"> + </argument> + <argument index="1" name="public_only" type="bool" default="false"> + </argument> <description> - Loads a key from [code]path[/code] ("*.key" file). + Loads a key from the given [code]string[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be loaded. </description> </method> <method name="save"> @@ -25,8 +46,20 @@ </return> <argument index="0" name="path" type="String"> </argument> + <argument index="1" name="public_only" type="bool" default="false"> + </argument> + <description> + Saves a key to the given [code]path[/code]. If [code]public_only[/code] is [code]true[/code], only the public key will be saved. + [b]Note[/b]: [code]path[/code] should should be a "*.pub" file if [code]public_only[/code] is [code]true[/code], a "*.key" file otherwise. + </description> + </method> + <method name="save_to_string"> + <return type="String"> + </return> + <argument index="0" name="public_only" type="bool" default="false"> + </argument> <description> - Saves a key to the given [code]path[/code] (should be a "*.key" file). + Returns a string containing the key in PEM format. If [code]public_only[/code] is [code]true[/code], only the public key will be included. </description> </method> </methods> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 19583fca28..2fa791a9df 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -22,7 +22,7 @@ </description> </method> <method name="add_control_to_bottom_panel"> - <return type="ToolButton"> + <return type="Button"> </return> <argument index="0" name="control" type="Control"> </argument> diff --git a/doc/classes/InputMap.xml b/doc/classes/InputMap.xml index da93d7fb53..03212538c9 100644 --- a/doc/classes/InputMap.xml +++ b/doc/classes/InputMap.xml @@ -41,6 +41,15 @@ Removes all events from an action. </description> </method> + <method name="action_get_events"> + <return type="Array"> + </return> + <argument index="0" name="action" type="StringName"> + </argument> + <description> + Returns an array of [InputEvent]s associated with a given action. + </description> + </method> <method name="action_has_event"> <return type="bool"> </return> @@ -95,15 +104,6 @@ Returns [code]true[/code] if the given event is part of an existing action. This method ignores keyboard modifiers if the given [InputEvent] is not pressed (for proper release detection). See [method action_has_event] if you don't want this behavior. </description> </method> - <method name="get_action_list"> - <return type="Array"> - </return> - <argument index="0" name="action" type="StringName"> - </argument> - <description> - Returns an array of [InputEvent]s associated with a given action. - </description> - </method> <method name="get_actions"> <return type="Array"> </return> diff --git a/doc/classes/Joint2D.xml b/doc/classes/Joint2D.xml index fb0e184c26..b055293b9d 100644 --- a/doc/classes/Joint2D.xml +++ b/doc/classes/Joint2D.xml @@ -15,7 +15,7 @@ When [member node_a] and [member node_b] move in different directions the [code]bias[/code] controls how fast the joint pulls them back to their original position. The lower the [code]bias[/code] the more the two bodies can pull on the joint. </member> <member name="disable_collision" type="bool" setter="set_exclude_nodes_from_collision" getter="get_exclude_nodes_from_collision" default="true"> - If [code]true[/code], [member node_a] and [member node_b] can collide. + If [code]true[/code], [member node_a] and [member node_b] can not collide. </member> <member name="node_a" type="NodePath" setter="set_node_a" getter="get_node_a" default="NodePath("")"> The first body attached to the joint. Must derive from [PhysicsBody2D]. diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 03203e2ebb..105def21ca 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -205,7 +205,7 @@ <return type="String"> </return> <description> - Returns the name of the host OS. Possible values are: [code]"Android"[/code], [code]"Haiku"[/code], [code]"iOS"[/code], [code]"HTML5"[/code], [code]"OSX"[/code], [code]"Server"[/code], [code]"Windows"[/code], [code]"UWP"[/code], [code]"X11"[/code]. + Returns the name of the host OS. Possible values are: [code]"Android"[/code], [code]"iOS"[/code], [code]"HTML5"[/code], [code]"OSX"[/code], [code]"Server"[/code], [code]"Windows"[/code], [code]"UWP"[/code], [code]"X11"[/code]. </description> </method> <method name="get_process_id" qualifiers="const"> @@ -254,20 +254,6 @@ [b]Note:[/b] This method is implemented on Android, Linux, macOS and Windows. </description> </method> - <method name="get_system_time_msecs" qualifiers="const"> - <return type="int"> - </return> - <description> - Returns the epoch time of the operating system in milliseconds. - </description> - </method> - <method name="get_system_time_secs" qualifiers="const"> - <return type="int"> - </return> - <description> - Returns the epoch time of the operating system in seconds. - </description> - </method> <method name="get_tablet_driver_count" qualifiers="const"> <return type="int"> </return> @@ -325,7 +311,7 @@ </description> </method> <method name="get_unix_time" qualifiers="const"> - <return type="int"> + <return type="float"> </return> <description> Returns the current UNIX epoch timestamp. diff --git a/doc/classes/PhysicsMaterial.xml b/doc/classes/PhysicsMaterial.xml index 6410626496..0889c238dc 100644 --- a/doc/classes/PhysicsMaterial.xml +++ b/doc/classes/PhysicsMaterial.xml @@ -12,6 +12,7 @@ </methods> <members> <member name="absorbent" type="bool" setter="set_absorbent" getter="is_absorbent" default="false"> + If [code]true[/code], subtracts the bounciness from the colliding object's bounciness instead of adding it. </member> <member name="bounce" type="float" setter="set_bounce" getter="get_bounce" default="0.0"> The body's bounciness. Values range from [code]0[/code] (no bounce) to [code]1[/code] (full bounciness). @@ -20,6 +21,7 @@ The body's friction. Values range from [code]0[/code] (frictionless) to [code]1[/code] (maximum friction). </member> <member name="rough" type="bool" setter="set_rough" getter="is_rough" default="false"> + If [code]true[/code], the physics engine will use the friction of the object marked as "rough" when two objects collide. If [code]false[/code], the physics engine will use the lowest friction of all colliding objects instead. If [code]true[/code] for both colliding objects, the physics engine will use the highest friction. </member> </members> <constants> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 92e5b4a84f..7191492098 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -821,6 +821,8 @@ </member> <member name="mono/profiler/enabled" type="bool" setter="" getter="" default="false"> </member> + <member name="mono/project/auto_update_project" type="bool" setter="" getter="" default="true"> + </member> <member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0"> </member> <member name="network/limits/debugger/max_chars_per_second" type="int" setter="" getter="" default="32768"> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index d8be6d4bd7..8832c0ec4d 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -3009,6 +3009,11 @@ </description> </method> </methods> + <members> + <member name="render_loop_enabled" type="bool" setter="set_render_loop_enabled" getter="is_render_loop_enabled"> + If [code]false[/code], disables rendering completely, but the engine logic is still being processed. You can call [method force_draw] to draw a frame even with rendering disabled. + </member> + </members> <signals> <signal name="frame_post_draw"> <description> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index db036d7d88..d4eba77ffa 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -294,6 +294,10 @@ The currently installed custom effects. This is an array of [RichTextEffect]s. To add a custom effect, it's more convenient to use [method install_effect]. </member> + <member name="fit_content_height" type="bool" setter="set_fit_content_height" getter="is_fit_content_height_enabled" default="false"> + If [code]true[/code], the label's height will be automatically updated to fit its content. + [b]Note:[/b] This property is used as a workaround to fix issues with [RichTextLabel] in [Container]s, but it's unreliable in some cases and will be removed in future versions. + </member> <member name="meta_underlined" type="bool" setter="set_meta_underline" getter="is_meta_underlined" default="true"> If [code]true[/code], the label underlines meta tags such as [code][url]{text}[/url][/code]. </member> diff --git a/doc/classes/Shape2D.xml b/doc/classes/Shape2D.xml index 9e913cb44d..5f41d05816 100644 --- a/doc/classes/Shape2D.xml +++ b/doc/classes/Shape2D.xml @@ -74,6 +74,17 @@ This method needs the transformation matrix for this shape ([code]local_xform[/code]), the movement to test on this shape ([code]local_motion[/code]), the shape to check collisions with ([code]with_shape[/code]), the transformation matrix of that shape ([code]shape_xform[/code]), and the movement to test onto the other object ([code]shape_motion[/code]). </description> </method> + <method name="draw"> + <return type="void"> + </return> + <argument index="0" name="canvas_item" type="RID"> + </argument> + <argument index="1" name="color" type="Color"> + </argument> + <description> + Draws a solid shape onto a [CanvasItem] with the [RenderingServer] API filled with the specified [code]color[/code]. The exact drawing method is specific for each shape and cannot be configured. + </description> + </method> </methods> <members> <member name="custom_solver_bias" type="float" setter="set_custom_solver_bias" getter="get_custom_solver_bias" default="0.0"> diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index 640cbe84f5..183fd5396f 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -31,6 +31,16 @@ [i]Deprecated soon.[/i] </description> </method> + <method name="bone_transform_to_world_transform"> + <return type="Transform"> + </return> + <argument index="0" name="bone_transform" type="Transform"> + </argument> + <description> + Takes the given bone pose/transform and converts it to a world transform, relative to the [Skeleton3D] node. + This is useful for using the bone transform in calculations with transforms from [Node3D]-based nodes. + </description> + </method> <method name="clear_bones"> <return type="void"> </return> @@ -42,6 +52,7 @@ <return type="void"> </return> <description> + Removes the global pose override on all bones in the skeleton. </description> </method> <method name="find_bone" qualifiers="const"> @@ -136,12 +147,14 @@ <argument index="0" name="bone_idx" type="int"> </argument> <description> + Returns whether the bone rest for the bone at [code]bone_idx[/code] is disabled. </description> </method> <method name="localize_rests"> <return type="void"> </return> <description> + Returns all bones in the skeleton to their rest poses. </description> </method> <method name="physical_bones_add_collision_exception"> @@ -150,6 +163,8 @@ <argument index="0" name="exception" type="RID"> </argument> <description> + Adds a collision exception to the physical bone. + Works just like the [RigidBody3D] node. </description> </method> <method name="physical_bones_remove_collision_exception"> @@ -158,6 +173,8 @@ <argument index="0" name="exception" type="RID"> </argument> <description> + Removes a collision exception to the physical bone. + Works just like the [RigidBody3D] node. </description> </method> <method name="physical_bones_start_simulation"> @@ -166,12 +183,15 @@ <argument index="0" name="bones" type="StringName[]" default="[ ]"> </argument> <description> + Tells the [PhysicalBone3D] nodes in the Skeleton to start simulating and reacting to the physics world. + Optionally, a list of bone names can be passed-in, allowing only the passed-in bones to be simulated. </description> </method> <method name="physical_bones_stop_simulation"> <return type="void"> </return> <description> + Tells the [PhysicalBone3D] nodes in the Skeleton to stop simulating. </description> </method> <method name="register_skin"> @@ -180,6 +200,7 @@ <argument index="0" name="skin" type="Skin"> </argument> <description> + Binds the given Skin to the Skeleton. </description> </method> <method name="set_bone_custom_pose"> @@ -190,6 +211,8 @@ <argument index="1" name="custom_pose" type="Transform"> </argument> <description> + Sets the custom pose transform, [code]custom_pose[/code], for the bone at [code]bone_idx[/code]. This pose is an addition to the bone rest pose. + [b]Note[/b]: The pose transform needs to be in bone space. Use [method world_transform_to_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space. </description> </method> <method name="set_bone_disable_rest"> @@ -200,6 +223,7 @@ <argument index="1" name="disable" type="bool"> </argument> <description> + Disables the rest pose for the bone at [code]bone_idx[/code] if [code]true[/code], enables the bone rest if [code]false[/code]. </description> </method> <method name="set_bone_global_pose_override"> @@ -214,6 +238,9 @@ <argument index="3" name="persistent" type="bool" default="false"> </argument> <description> + Sets the global pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code]. + [code]amount[/code] is the interpolation strengh that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain. + [b]Note[/b]: The pose transform needs to be in bone space. Use [method world_transform_to_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space. </description> </method> <method name="set_bone_parent"> @@ -237,6 +264,7 @@ </argument> <description> Returns the pose transform for bone [code]bone_idx[/code]. + [b]Note[/b]: The pose transform needs to be in bone space. Use [method world_transform_to_bone_transform] to convert a world transform, like one you can get from a [Node3D], to bone space. </description> </method> <method name="set_bone_rest"> @@ -267,6 +295,17 @@ <argument index="0" name="bone_idx" type="int"> </argument> <description> + Unparents the bone at [code]bone_idx[/code] and sets its rest position to that of it's parent prior to being reset. + </description> + </method> + <method name="world_transform_to_bone_transform"> + <return type="Transform"> + </return> + <argument index="0" name="world_transform" type="Transform"> + </argument> + <description> + Takes the given world transform, relative to the [Skeleton3D], and converts it to a bone pose/transform. + This is useful for using setting bone poses using transforms from [Node3D]-based nodes. </description> </method> </methods> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 24d92b822a..6d9def7ccb 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -381,7 +381,7 @@ <return type="bool"> </return> <description> - Returns [code]true[/code] if the string is empty. + Returns [code]true[/code] if the length of the string equals [code]0[/code]. </description> </method> <method name="ends_with"> diff --git a/doc/classes/ToolButton.xml b/doc/classes/ToolButton.xml deleted file mode 100644 index f78627b163..0000000000 --- a/doc/classes/ToolButton.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="ToolButton" inherits="Button" version="4.0"> - <brief_description> - Flat button helper class. - </brief_description> - <description> - This is a helper class to generate a flat [Button] (see [member Button.flat]), creating a [ToolButton] is equivalent to: - [codeblock] - var btn = Button.new() - btn.flat = true - [/codeblock] - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <members> - <member name="flat" type="bool" setter="set_flat" getter="is_flat" override="true" default="true" /> - </members> - <constants> - </constants> - <theme_items> - <theme_item name="disabled" type="StyleBox"> - [StyleBox] used when the [ToolButton] is disabled. - </theme_item> - <theme_item name="focus" type="StyleBox"> - [StyleBox] used when the [ToolButton] is focused. It is displayed over the current [StyleBox], so using [StyleBoxEmpty] will just disable the focus visual effect. - </theme_item> - <theme_item name="font" type="Font"> - [Font] of the [ToolButton]'s text. - </theme_item> - <theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> - Default text [Color] of the [ToolButton]. - </theme_item> - <theme_item name="font_color_disabled" type="Color" default="Color( 0.9, 0.95, 1, 0.3 )"> - Text [Color] used when the [ToolButton] is disabled. - </theme_item> - <theme_item name="font_color_hover" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )"> - Text [Color] used when the [ToolButton] is being hovered. - </theme_item> - <theme_item name="font_color_pressed" type="Color" default="Color( 1, 1, 1, 1 )"> - Text [Color] used when the [ToolButton] is being pressed. - </theme_item> - <theme_item name="hover" type="StyleBox"> - [StyleBox] used when the [ToolButton] is being hovered. - </theme_item> - <theme_item name="hseparation" type="int" default="3"> - The horizontal space between [ToolButton]'s icon and text. - </theme_item> - <theme_item name="normal" type="StyleBox"> - Default [StyleBox] for the [ToolButton]. - </theme_item> - <theme_item name="pressed" type="StyleBox"> - [StyleBox] used when the [ToolButton] is being pressed. - </theme_item> - </theme_items> -</class> diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml index 1938a3facb..56ccaaf383 100644 --- a/doc/classes/Tween.xml +++ b/doc/classes/Tween.xml @@ -15,7 +15,7 @@ tween.start() [/codeblock] Many methods require a property name, such as [code]"position"[/code] above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using [code]"property:component"[/code] (eg. [code]position:x[/code]), where it would only apply to that particular component. - Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls the where [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best. + Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best. [url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url] </description> <tutorials> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 64ebc1fa09..7f4a212679 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -5,7 +5,8 @@ </brief_description> <description> 2-element structure that can be used to represent positions in 2D space or any other pair of numeric values. - It uses floating point coordinates. + It uses floating-point coordinates. See [Vector2i] for its integer counterpart. + [b]Note:[/b] In a boolean context, a Vector2 will evaluate to [code]false[/code] if it's equal to [code]Vector2(0, 0)[/code]. Otherwise, a Vector2 will always evaluate to [code]true[/code]. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> diff --git a/doc/classes/Vector2i.xml b/doc/classes/Vector2i.xml index 71c7aaa4e5..2f7ca985b2 100644 --- a/doc/classes/Vector2i.xml +++ b/doc/classes/Vector2i.xml @@ -5,7 +5,8 @@ </brief_description> <description> 2-element structure that can be used to represent positions in 2D space or any other pair of numeric values. - It uses integer coordinates. + It uses integer coordinates and is therefore preferable to [Vector2] when exact precision is required. + [b]Note:[/b] In a boolean context, a Vector2i will evaluate to [code]false[/code] if it's equal to [code]Vector2i(0, 0)[/code]. Otherwise, a Vector2i will always evaluate to [code]true[/code]. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 29222bb4d1..0c861e5ee2 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -5,7 +5,8 @@ </brief_description> <description> 3-element structure that can be used to represent positions in 3D space or any other pair of numeric values. - It uses floating point coordinates. + It uses floating-point coordinates. See [Vector3i] for its integer counterpart. + [b]Note:[/b] In a boolean context, a Vector3 will evaluate to [code]false[/code] if it's equal to [code]Vector3(0, 0, 0)[/code]. Otherwise, a Vector3 will always evaluate to [code]true[/code]. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml index c5aa3d0347..91d64ea609 100644 --- a/doc/classes/Vector3i.xml +++ b/doc/classes/Vector3i.xml @@ -5,7 +5,8 @@ </brief_description> <description> 3-element structure that can be used to represent positions in 3D space or any other pair of numeric values. - It uses integer coordinates. + It uses integer coordinates and is therefore preferable to [Vector3] when exact precision is required. + [b]Note:[/b] In a boolean context, a Vector3i will evaluate to [code]false[/code] if it's equal to [code]Vector3i(0, 0, 0)[/code]. Otherwise, a Vector3i will always evaluate to [code]true[/code]. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/math/index.html</link> diff --git a/doc/classes/VisualShaderNodeSample3D.xml b/doc/classes/VisualShaderNodeSample3D.xml new file mode 100644 index 0000000000..cf6933ab55 --- /dev/null +++ b/doc/classes/VisualShaderNodeSample3D.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeSample3D" inherits="VisualShaderNode" version="4.0"> + <brief_description> + A base node for nodes which samples 3D textures in the visual shader graph. + </brief_description> + <description> + A virtual class, use the descendants instead. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="source" type="int" setter="set_source" getter="get_source" enum="VisualShaderNodeSample3D.Source" default="0"> + An input source type. + </member> + </members> + <constants> + <constant name="SOURCE_TEXTURE" value="0" enum="Source"> + Creates internal uniform and provides a way to assign it within node. + </constant> + <constant name="SOURCE_PORT" value="1" enum="Source"> + Use the uniform texture from sampler port. + </constant> + </constants> +</class> diff --git a/doc/classes/VisualShaderNodeTexture2DArray.xml b/doc/classes/VisualShaderNodeTexture2DArray.xml new file mode 100644 index 0000000000..3c6d328ed0 --- /dev/null +++ b/doc/classes/VisualShaderNodeTexture2DArray.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeTexture2DArray" inherits="VisualShaderNodeSample3D" version="4.0"> + <brief_description> + A 2D texture uniform array to be used within the visual shader graph. + </brief_description> + <description> + Translated to [code]uniform sampler2DArray[/code] in the shader language. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="texture_array" type="Texture2DArray" setter="set_texture_array" getter="get_texture_array"> + A source texture array. Used if [member VisualShaderNodeSample3D.source] is set to [constant VisualShaderNodeSample3D.SOURCE_TEXTURE]. + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml index 4482a280b2..869fc14d40 100644 --- a/doc/classes/bool.xml +++ b/doc/classes/bool.xml @@ -4,14 +4,14 @@ Boolean built-in type. </brief_description> <description> - Boolean is a built-in type. It can represent any data type that is either a true or false value. You can think of it as an switch with on or off (1 or 0) setting. It's often used as part of programming logic in condition statements like [code]if[/code] statements. - [b]Note:[/b] In a code below [code]if can_shoot[/code] is equivalent of [code]if can_shoot == true[/code]. It is good practice to follow the natural spoken language structure when possible. Use [code]if can_shoot[/code] rather than [code]if can_shoot == true[/code] and use [code]if not can_shoot[/code] rather than [code]if can_shoot == false[/code]. + Boolean is a built-in type. There are two boolean values: [code]true[/code] and [code]false[/code]. You can think of it as an switch with on or off (1 or 0) setting. Booleans are used in programming for logic in condition statements, like [code]if[/code] statements. + Booleans can be directly used in [code]if[/code] statements. The code below demonstrates this on the [code]if can_shoot:[/code] line. You don't need to use [code]== true[/code], you only need [code]if can_shoot:[/code]. Similarly, use [code]if not can_shoot:[/code] rather than [code]== false[/code]. [codeblock] var can_shoot = true func shoot(): if can_shoot: - # Perform shooting actions here. + pass # Perform shooting actions here. [/codeblock] The following code will only create a bullet if both conditions are met: action "shoot" is pressed and if [code]can_shoot[/code] is [code]true[/code]. [b]Note:[/b] [code]Input.is_action_pressed("shoot")[/code] is also a boolean that is [code]true[/code] when "shoot" is pressed and [code]false[/code] when "shoot" isn't pressed. @@ -46,7 +46,7 @@ <argument index="0" name="from" type="int"> </argument> <description> - Cast an [int] value to a boolean value, this method will return [code]true[/code] if called with an integer value different to 0 and [code]false[/code] in other case. + Cast an [int] value to a boolean value, this method will return [code]false[/code] if [code]0[/code] is passed in, and [code]true[/code] for all other ints. </description> </method> <method name="bool"> @@ -55,7 +55,7 @@ <argument index="0" name="from" type="float"> </argument> <description> - Cast a [float] value to a boolean value, this method will return [code]true[/code] if called with a floating-point value different to 0 and [code]false[/code] in other case. + Cast a [float] value to a boolean value, this method will return [code]false[/code] if [code]0.0[/code] is passed in, and [code]true[/code] for all other floats. </description> </method> <method name="bool"> @@ -64,7 +64,8 @@ <argument index="0" name="from" type="String"> </argument> <description> - Cast a [String] value to a boolean value, this method will return [code]true[/code] if called with a non-empty string and [code]false[/code] in other case. Examples: [code]bool("False")[/code] returns [code]true[/code], [code]bool("")[/code] returns [code]false[/code]. + Cast a [String] value to a boolean value, this method will return [code]false[/code] if [code]""[/code] is passed in, and [code]true[/code] for all non-empty strings. + Examples: [code]bool("False")[/code] returns [code]true[/code], [code]bool("")[/code] returns [code]false[/code]. </description> </method> </methods> diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 083cd64116..9a5fc6d1a4 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -163,21 +163,11 @@ String OS_Unix::get_name() const { return "Unix"; } -uint64_t OS_Unix::get_unix_time() const { - return time(nullptr); -}; - -uint64_t OS_Unix::get_system_time_secs() const { - struct timeval tv_now; - gettimeofday(&tv_now, nullptr); - return uint64_t(tv_now.tv_sec); -} - -uint64_t OS_Unix::get_system_time_msecs() const { +double OS_Unix::get_unix_time() const { struct timeval tv_now; gettimeofday(&tv_now, nullptr); - return uint64_t(tv_now.tv_sec) * 1000 + uint64_t(tv_now.tv_usec) / 1000; -} + return (double)tv_now.tv_sec + double(tv_now.tv_usec) / 1000000; +}; OS::Date OS_Unix::get_date(bool utc) const { time_t t = time(nullptr); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 7d235803dc..2982e0c55c 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -77,9 +77,7 @@ public: virtual Time get_time(bool utc) const; virtual TimeZoneInfo get_time_zone_info() const; - virtual uint64_t get_unix_time() const; - virtual uint64_t get_system_time_secs() const; - virtual uint64_t get_system_time_msecs() const; + virtual double get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const; virtual uint64_t get_ticks_usec() const; diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 8fd1f5951e..f36e84dab6 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1783,7 +1783,8 @@ AnimationTimelineEdit::AnimationTimelineEdit() { length->set_tooltip(TTR("Animation length (seconds)")); length->connect("value_changed", callable_mp(this, &AnimationTimelineEdit::_anim_length_changed)); len_hb->add_child(length); - loop = memnew(ToolButton); + loop = memnew(Button); + loop->set_flat(true); loop->set_tooltip(TTR("Animation Looping")); loop->connect("pressed", callable_mp(this, &AnimationTimelineEdit::_anim_loop_pressed)); loop->set_toggle_mode(true); @@ -2786,7 +2787,8 @@ Variant AnimationTrackEdit::get_drag_data(const Point2 &p_point) { drag_data["group"] = base_path; drag_data["index"] = track; - ToolButton *tb = memnew(ToolButton); + Button *tb = memnew(Button); + tb->set_flat(true); tb->set_text(path_cache); tb->set_icon(icon_cache); set_drag_preview(tb); @@ -5640,14 +5642,16 @@ AnimationTrackEditor::AnimationTrackEditor() { bottom_hb->add_spacer(); - selected_filter = memnew(ToolButton); + selected_filter = memnew(Button); + selected_filter->set_flat(true); selected_filter->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); //same function works the same selected_filter->set_toggle_mode(true); selected_filter->set_tooltip(TTR("Only show tracks from nodes selected in tree.")); bottom_hb->add_child(selected_filter); - view_group = memnew(ToolButton); + view_group = memnew(Button); + view_group->set_flat(true); view_group->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); view_group->set_toggle_mode(true); view_group->set_tooltip(TTR("Group tracks by node or display them as plain list.")); @@ -5655,7 +5659,8 @@ AnimationTrackEditor::AnimationTrackEditor() { bottom_hb->add_child(view_group); bottom_hb->add_child(memnew(VSeparator)); - snap = memnew(ToolButton); + snap = memnew(Button); + snap->set_flat(true); snap->set_text(TTR("Snap:") + " "); bottom_hb->add_child(snap); snap->set_disabled(true); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 6a46a1e3ff..911280dc3b 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -44,7 +44,6 @@ #include "scene/gui/spin_box.h" #include "scene/gui/tab_container.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" #include "scene/resources/animation.h" #include "scene_tree_editor.h" @@ -59,7 +58,7 @@ class AnimationTimelineEdit : public Range { HBoxContainer *len_hb; EditorSpinSlider *length; - ToolButton *loop; + Button *loop; TextureRect *time_icon; MenuButton *add_track; @@ -310,7 +309,7 @@ class AnimationTrackEditor : public VBoxContainer { HSlider *zoom; EditorSpinSlider *step; TextureRect *zoom_icon; - ToolButton *snap; + Button *snap; OptionButton *snap_mode; Button *imported_anim_warning; @@ -457,8 +456,8 @@ class AnimationTrackEditor : public VBoxContainer { void _anim_duplicate_keys(bool transpose); void _view_group_toggle(); - ToolButton *view_group; - ToolButton *selected_filter; + Button *view_group; + Button *selected_filter; void _selection_changed(); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 95c7cc0bf1..b73a27214d 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -166,20 +166,47 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) } void FindReplaceBar::_replace() { - if (result_line != -1 && result_col != -1) { - text_edit->begin_complex_operation(); + bool selection_enabled = text_edit->is_selection_active(); + Point2i selection_begin, selection_end; + if (selection_enabled) { + selection_begin = Point2i(text_edit->get_selection_from_line(), text_edit->get_selection_from_column()); + selection_end = Point2i(text_edit->get_selection_to_line(), text_edit->get_selection_to_column()); + } - text_edit->unfold_line(result_line); - text_edit->select(result_line, result_col, result_line, result_col + get_search_text().length()); - text_edit->insert_text_at_cursor(get_replace_text()); + String replace_text = get_replace_text(); + int search_text_len = get_search_text().length(); - text_edit->end_complex_operation(); + text_edit->begin_complex_operation(); + if (selection_enabled && is_selection_only()) { // To restrict search_current() to selected region + text_edit->cursor_set_line(selection_begin.width); + text_edit->cursor_set_column(selection_begin.height); + } - results_count = -1; + if (search_current()) { + text_edit->unfold_line(result_line); + text_edit->select(result_line, result_col, result_line, result_col + search_text_len); + + if (selection_enabled && is_selection_only()) { + Point2i match_from(result_line, result_col); + Point2i match_to(result_line, result_col + search_text_len); + if (!(match_from < selection_begin || match_to > selection_end)) { + text_edit->insert_text_at_cursor(replace_text); + if (match_to.x == selection_end.x) { // Adjust selection bounds if necessary + selection_end.y += replace_text.length() - search_text_len; + } + } + } else { + text_edit->insert_text_at_cursor(replace_text); + } } + text_edit->end_complex_operation(); + results_count = -1; - if (!search_current()) { - search_next(); + if (selection_enabled && is_selection_only()) { + // Reselect in order to keep 'Replace' restricted to selection + text_edit->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); + } else { + text_edit->deselect(); } } @@ -601,12 +628,14 @@ FindReplaceBar::FindReplaceBar() { hbc_button_search->add_child(matches_label); matches_label->hide(); - find_prev = memnew(ToolButton); + find_prev = memnew(Button); + find_prev->set_flat(true); hbc_button_search->add_child(find_prev); find_prev->set_focus_mode(FOCUS_NONE); find_prev->connect("pressed", callable_mp(this, &FindReplaceBar::search_prev)); - find_next = memnew(ToolButton); + find_next = memnew(Button); + find_next->set_flat(true); hbc_button_search->add_child(find_next); find_next->set_focus_mode(FOCUS_NONE); find_next->connect("pressed", callable_mp(this, &FindReplaceBar::search_next)); @@ -1512,7 +1541,7 @@ void CodeTextEditor::_toggle_scripts_pressed() { void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - emit_signal("error_pressed"); + goto_error(); } } @@ -1622,7 +1651,6 @@ void CodeTextEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("validate_script")); ADD_SIGNAL(MethodInfo("load_theme_settings")); ADD_SIGNAL(MethodInfo("show_warnings_panel")); - ADD_SIGNAL(MethodInfo("error_pressed")); } void CodeTextEditor::set_code_complete_func(CodeTextEditorCodeCompleteFunc p_code_complete_func, void *p_ud) { @@ -1679,7 +1707,8 @@ CodeTextEditor::CodeTextEditor() { error_line = 0; error_column = 0; - toggle_scripts_button = memnew(ToolButton); + toggle_scripts_button = memnew(Button); + toggle_scripts_button->set_flat(true); toggle_scripts_button->connect("pressed", callable_mp(this, &CodeTextEditor::_toggle_scripts_pressed)); status_bar->add_child(toggle_scripts_button); toggle_scripts_button->hide(); @@ -1699,7 +1728,8 @@ CodeTextEditor::CodeTextEditor() { find_replace_bar->connect("error", callable_mp(error, &Label::set_text)); // Warnings - warning_button = memnew(ToolButton); + warning_button = memnew(Button); + warning_button->set_flat(true); status_bar->add_child(warning_button); warning_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); warning_button->set_default_cursor_shape(CURSOR_POINTING_HAND); diff --git a/editor/code_editor.h b/editor/code_editor.h index d806be885f..ab298202bd 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -37,7 +37,6 @@ #include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" #include "scene/gui/text_edit.h" -#include "scene/gui/tool_button.h" #include "scene/main/timer.h" class GotoLineDialog : public ConfirmationDialog { @@ -63,8 +62,8 @@ class FindReplaceBar : public HBoxContainer { LineEdit *search_text; Label *matches_label; - ToolButton *find_prev; - ToolButton *find_next; + Button *find_prev; + Button *find_next; CheckBox *case_sensitive; CheckBox *whole_words; TextureButton *hide_button; @@ -142,8 +141,8 @@ class CodeTextEditor : public VBoxContainer { FindReplaceBar *find_replace_bar; HBoxContainer *status_bar; - ToolButton *toggle_scripts_button; - ToolButton *warning_button; + Button *toggle_scripts_button; + Button *warning_button; Label *warning_count_label; Label *line_and_col_txt; diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index 6507956d07..facd57418d 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -108,17 +108,26 @@ public: * Signal automatically called by parent dialog. */ void ConnectDialog::ok_pressed() { - if (dst_method->get_text() == "") { + String method_name = dst_method->get_text(); + + if (method_name == "") { error->set_text(TTR("Method in target node must be specified.")); error->popup_centered(); return; } + + if (!method_name.strip_edges().is_valid_identifier()) { + error->set_text(TTR("Method name must be a valid identifier.")); + error->popup_centered(); + return; + } + Node *target = tree->get_selected(); if (!target) { return; // Nothing selected in the tree, not an error. } if (target->get_script().is_null()) { - if (!target->has_method(dst_method->get_text())) { + if (!target->has_method(method_name)) { error->set_text(TTR("Target method not found. Specify a valid method or attach a script to the target node.")); error->popup_centered(); return; diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 73468f8ce0..310de9dd90 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -673,7 +673,8 @@ Variant CreateDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) { d["type"] = "create_favorite_drag"; d["class"] = ti->get_text(0); - ToolButton *tb = memnew(ToolButton); + Button *tb = memnew(Button); + tb->set_flat(true); tb->set_icon(ti->get_icon(0)); tb->set_text(ti->get_text(0)); favorites->set_drag_preview(tb); diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 49137f76fa..6b010fbfb5 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -743,18 +743,19 @@ void ScriptEditorDebugger::_performance_draw() { info_message->hide(); - Ref<StyleBox> graph_sb = get_theme_stylebox("normal", "TextEdit"); - Ref<Font> graph_font = get_theme_font("font", "TextEdit"); + const Ref<StyleBox> graph_sb = get_theme_stylebox("normal", "TextEdit"); + const Ref<Font> graph_font = get_theme_font("font", "TextEdit"); - int cols = Math::ceil(Math::sqrt((float)which.size())); + const int cols = Math::ceil(Math::sqrt((float)which.size())); int rows = Math::ceil((float)which.size() / cols); if (which.size() == 1) { rows = 1; } - int margin = 3; - int point_sep = 5; - Size2i s = Size2i(perf_draw->get_size()) / Size2i(cols, rows); + const int margin = 3; + const int point_sep = 5; + const Size2i s = Size2i(perf_draw->get_size()) / Size2i(cols, rows); + for (int i = 0; i < which.size(); i++) { Point2i p(i % cols, i / cols); Rect2i r(p * s, s); @@ -763,22 +764,78 @@ void ScriptEditorDebugger::_performance_draw() { perf_draw->draw_style_box(graph_sb, r); r.position += graph_sb->get_offset(); r.size -= graph_sb->get_minimum_size(); - int pi = which[i]; - Color c = get_theme_color("accent_color", "Editor"); - float h = (float)which[i] / (float)(perf_items.size()); - // Use a darker color on light backgrounds for better visibility - float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55; - c.set_hsv(Math::fmod(h + 0.4, 0.9), c.get_s() * 0.9, c.get_v() * value_multiplier); - - c.a = 0.6; - perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent()), perf_items[pi]->get_text(0), c, r.size.x); - c.a = 0.9; - perf_draw->draw_string(graph_font, r.position + Point2(0, graph_font->get_ascent() + graph_font->get_height()), perf_items[pi]->get_text(1), c, r.size.y); - - float spacing = point_sep / float(cols); + const int pi = which[i]; + + // Draw horizontal lines with labels. + + int nb_lines = 5; + // Draw less lines if the monitor isn't tall enough to display 5 labels. + if (r.size.height <= 160 * EDSCALE) { + nb_lines = 3; + } else if (r.size.height <= 240 * EDSCALE) { + nb_lines = 4; + } + + const float inv_nb_lines = 1.0 / nb_lines; + + for (int line = 0; line < nb_lines; line += 1) { + const int from_x = r.position.x; + const int to_x = r.position.x + r.size.width; + const int y = r.position.y + (r.size.height * inv_nb_lines + line * inv_nb_lines * r.size.height); + perf_draw->draw_line( + Point2(from_x, y), + Point2i(to_x, y), + Color(0.5, 0.5, 0.5, 0.25), + Math::round(EDSCALE)); + + String label; + switch (Performance::MonitorType((int)perf_items[pi]->get_metadata(1))) { + case Performance::MONITOR_TYPE_MEMORY: { + label = String::humanize_size(Math::ceil((1 - inv_nb_lines - inv_nb_lines * line) * perf_max[pi])); + } break; + case Performance::MONITOR_TYPE_TIME: { + label = rtos((1 - inv_nb_lines - inv_nb_lines * line) * perf_max[pi] * 1000).pad_decimals(2) + " ms"; + } break; + default: { + label = itos(Math::ceil((1 - inv_nb_lines - inv_nb_lines * line) * perf_max[pi])); + } break; + } + + perf_draw->draw_string( + graph_font, + Point2(from_x, y - graph_font->get_ascent() * 0.25), + label, + Color(0.5, 0.5, 0.5, 1.0)); + } + + const float h = (float)which[i] / (float)(perf_items.size()); + // Use a darker color on light backgrounds for better visibility. + const float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55; + Color color = get_theme_color("accent_color", "Editor"); + color.set_hsv(Math::fmod(h + 0.4, 0.9), color.get_s() * 0.9, color.get_v() * value_multiplier); + + // Draw the monitor name in the top-left corner. + color.a = 0.6; + perf_draw->draw_string( + graph_font, + r.position + Point2(0, graph_font->get_ascent()), + perf_items[pi]->get_text(0), + color, + r.size.x); + + // Draw the monitor value in the top-left corner, just below the name. + color.a = 0.9; + perf_draw->draw_string( + graph_font, + r.position + Point2(0, graph_font->get_ascent() + graph_font->get_height()), + perf_items[pi]->get_text(1), + color, + r.size.y); + + const float spacing = point_sep / float(cols); float from = r.size.width; - List<Vector<float>>::Element *E = perf_history.front(); + const List<Vector<float>>::Element *E = perf_history.front(); float prev = -1; while (from >= 0 && E) { float m = perf_max[pi]; @@ -789,7 +846,11 @@ void ScriptEditorDebugger::_performance_draw() { h2 = (1.0 - h2) * r.size.y; if (E != perf_history.front()) { - perf_draw->draw_line(r.position + Point2(from, h2), r.position + Point2(from + spacing, prev), c, Math::round(EDSCALE)); + perf_draw->draw_line( + r.position + Point2(from, h2), + r.position + Point2(from + spacing, prev), + color, + Math::round(EDSCALE)); } prev = h2; E = E->next(); @@ -1517,27 +1578,31 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { hbc->add_child(memnew(VSeparator)); - skip_breakpoints = memnew(ToolButton); + skip_breakpoints = memnew(Button); + skip_breakpoints->set_flat(true); hbc->add_child(skip_breakpoints); skip_breakpoints->set_tooltip(TTR("Skip Breakpoints")); skip_breakpoints->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_skip_breakpoints)); hbc->add_child(memnew(VSeparator)); - copy = memnew(ToolButton); + copy = memnew(Button); + copy->set_flat(true); hbc->add_child(copy); copy->set_tooltip(TTR("Copy Error")); copy->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_copy)); hbc->add_child(memnew(VSeparator)); - step = memnew(ToolButton); + step = memnew(Button); + step->set_flat(true); hbc->add_child(step); step->set_tooltip(TTR("Step Into")); step->set_shortcut(ED_GET_SHORTCUT("debugger/step_into")); step->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_step)); - next = memnew(ToolButton); + next = memnew(Button); + next->set_flat(true); hbc->add_child(next); next->set_tooltip(TTR("Step Over")); next->set_shortcut(ED_GET_SHORTCUT("debugger/step_over")); @@ -1545,13 +1610,15 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { hbc->add_child(memnew(VSeparator)); - dobreak = memnew(ToolButton); + dobreak = memnew(Button); + dobreak->set_flat(true); hbc->add_child(dobreak); dobreak->set_tooltip(TTR("Break")); dobreak->set_shortcut(ED_GET_SHORTCUT("debugger/break")); dobreak->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_break)); - docontinue = memnew(ToolButton); + docontinue = memnew(Button); + docontinue->set_flat(true); hbc->add_child(docontinue); docontinue->set_tooltip(TTR("Continue")); docontinue->set_shortcut(ED_GET_SHORTCUT("debugger/continue")); @@ -1730,9 +1797,11 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { vmem_total->set_editable(false); vmem_total->set_custom_minimum_size(Size2(100, 0) * EDSCALE); vmem_hb->add_child(vmem_total); - vmem_refresh = memnew(ToolButton); + vmem_refresh = memnew(Button); + vmem_refresh->set_flat(true); vmem_hb->add_child(vmem_refresh); - vmem_export = memnew(ToolButton); + vmem_export = memnew(Button); + vmem_export->set_flat(true); vmem_export->set_tooltip(TTR("Export list to a CSV file")); vmem_hb->add_child(vmem_export); vmem_vb->add_child(vmem_hb); diff --git a/editor/doc_data.cpp b/editor/doc_data.cpp index c52d91b03d..54acbe9559 100644 --- a/editor/doc_data.cpp +++ b/editor/doc_data.cpp @@ -662,18 +662,19 @@ void DocData::generate(bool p_basic_types) { } } - //built in script reference + // Built-in script reference. + // We only add a doc entry for languages which actually define any built-in + // methods or constants. { for (int i = 0; i < ScriptServer::get_language_count(); i++) { ScriptLanguage *lang = ScriptServer::get_language(i); String cname = "@" + lang->get_name(); - class_list[cname] = ClassDoc(); - ClassDoc &c = class_list[cname]; + ClassDoc c; c.name = cname; + // Get functions. List<MethodInfo> minfo; - lang->get_public_functions(&minfo); for (List<MethodInfo>::Element *E = minfo.front(); E; E = E->next()) { @@ -706,6 +707,7 @@ void DocData::generate(bool p_basic_types) { c.methods.push_back(md); } + // Get constants. List<Pair<String, Variant>> cinfo; lang->get_public_constants(&cinfo); @@ -715,6 +717,13 @@ void DocData::generate(bool p_basic_types) { cd.value = E->get().second; c.constants.push_back(cd); } + + // Skip adding the lang if it doesn't expose anything (e.g. C#). + if (c.methods.empty() && c.constants.empty()) { + continue; + } + + class_list[cname] = c; } } } diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 5cf5201b18..10825973ae 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -782,19 +782,22 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { HBoxContainer *hbc = memnew(HBoxContainer); vb->add_child(hbc); - solo = memnew(ToolButton); + solo = memnew(Button); + solo->set_flat(true); solo->set_toggle_mode(true); solo->set_tooltip(TTR("Solo")); solo->set_focus_mode(FOCUS_NONE); solo->connect("pressed", callable_mp(this, &EditorAudioBus::_solo_toggled)); hbc->add_child(solo); - mute = memnew(ToolButton); + mute = memnew(Button); + mute->set_flat(true); mute->set_toggle_mode(true); mute->set_tooltip(TTR("Mute")); mute->set_focus_mode(FOCUS_NONE); mute->connect("pressed", callable_mp(this, &EditorAudioBus::_mute_toggled)); hbc->add_child(mute); - bypass = memnew(ToolButton); + bypass = memnew(Button); + bypass->set_flat(true); bypass->set_toggle_mode(true); bypass->set_tooltip(TTR("Bypass")); bypass->set_focus_mode(FOCUS_NONE); diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h index 65caf84f0f..5d5502002d 100644 --- a/editor/editor_audio_buses.h +++ b/editor/editor_audio_buses.h @@ -45,7 +45,6 @@ #include "scene/gui/slider.h" #include "scene/gui/texture_progress.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" class EditorAudioBuses; diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 25594bf7c8..951bec2c83 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -100,7 +100,6 @@ void EditorExportPreset::update_files_to_export() { for (int i = 0; i < to_remove.size(); ++i) { selected_files.erase(to_remove[i]); } - EditorExport::singleton->save_presets(); } Vector<String> EditorExportPreset::get_files_to_export() const { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 5ae5d1cb31..663f3dd856 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -1455,11 +1455,14 @@ EditorFileDialog::EditorFileDialog() { HBoxContainer *pathhb = memnew(HBoxContainer); - dir_prev = memnew(ToolButton); + dir_prev = memnew(Button); + dir_prev->set_flat(true); dir_prev->set_tooltip(TTR("Go to previous folder.")); - dir_next = memnew(ToolButton); + dir_next = memnew(Button); + dir_next->set_flat(true); dir_next->set_tooltip(TTR("Go to next folder.")); - dir_up = memnew(ToolButton); + dir_up = memnew(Button); + dir_up->set_flat(true); dir_up->set_tooltip(TTR("Go to parent folder.")); pathhb->add_child(dir_prev); @@ -1479,18 +1482,21 @@ EditorFileDialog::EditorFileDialog() { pathhb->add_child(dir); dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); - refresh = memnew(ToolButton); + refresh = memnew(Button); + refresh->set_flat(true); refresh->set_tooltip(TTR("Refresh files.")); refresh->connect("pressed", callable_mp(this, &EditorFileDialog::update_file_list)); pathhb->add_child(refresh); - favorite = memnew(ToolButton); + favorite = memnew(Button); + favorite->set_flat(true); favorite->set_toggle_mode(true); favorite->set_tooltip(TTR("(Un)favorite current folder.")); favorite->connect("pressed", callable_mp(this, &EditorFileDialog::_favorite_pressed)); pathhb->add_child(favorite); - show_hidden = memnew(ToolButton); + show_hidden = memnew(Button); + show_hidden->set_flat(true); show_hidden->set_toggle_mode(true); show_hidden->set_pressed(is_showing_hidden_files()); show_hidden->set_tooltip(TTR("Toggle the visibility of hidden files.")); @@ -1502,7 +1508,8 @@ EditorFileDialog::EditorFileDialog() { Ref<ButtonGroup> view_mode_group; view_mode_group.instance(); - mode_thumbnails = memnew(ToolButton); + mode_thumbnails = memnew(Button); + mode_thumbnails->set_flat(true); mode_thumbnails->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode), varray(DISPLAY_THUMBNAILS)); mode_thumbnails->set_toggle_mode(true); mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS); @@ -1510,7 +1517,8 @@ EditorFileDialog::EditorFileDialog() { mode_thumbnails->set_tooltip(TTR("View items as a grid of thumbnails.")); pathhb->add_child(mode_thumbnails); - mode_list = memnew(ToolButton); + mode_list = memnew(Button); + mode_list->set_flat(true); mode_list->connect("pressed", callable_mp(this, &EditorFileDialog::set_display_mode), varray(DISPLAY_LIST)); mode_list->set_toggle_mode(true); mode_list->set_pressed(display_mode == DISPLAY_LIST); @@ -1547,10 +1555,12 @@ EditorFileDialog::EditorFileDialog() { fav_vb->add_child(fav_hb); fav_hb->add_child(memnew(Label(TTR("Favorites:")))); fav_hb->add_spacer(); - fav_up = memnew(ToolButton); + fav_up = memnew(Button); + fav_up->set_flat(true); fav_hb->add_child(fav_up); fav_up->connect("pressed", callable_mp(this, &EditorFileDialog::_favorite_move_up)); - fav_down = memnew(ToolButton); + fav_down = memnew(Button); + fav_down->set_flat(true); fav_hb->add_child(fav_down); fav_down->connect("pressed", callable_mp(this, &EditorFileDialog::_favorite_move_down)); diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h index cbedfc72a6..1e224b933d 100644 --- a/editor/editor_file_dialog.h +++ b/editor/editor_file_dialog.h @@ -40,7 +40,6 @@ #include "scene/gui/separator.h" #include "scene/gui/split_container.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" class DependencyRemoveDialog; @@ -95,9 +94,9 @@ private: bool can_create_dir; LineEdit *dir; - ToolButton *dir_prev; - ToolButton *dir_next; - ToolButton *dir_up; + Button *dir_prev; + Button *dir_next; + Button *dir_up; HBoxContainer *drives_container; HBoxContainer *shortcuts_container; @@ -116,15 +115,15 @@ private: ConfirmationDialog *confirm_save; DependencyRemoveDialog *remove_dialog; - ToolButton *mode_thumbnails; - ToolButton *mode_list; + Button *mode_thumbnails; + Button *mode_list; - ToolButton *refresh; - ToolButton *favorite; - ToolButton *show_hidden; + Button *refresh; + Button *favorite; + Button *show_hidden; - ToolButton *fav_up; - ToolButton *fav_down; + Button *fav_up; + Button *fav_down; ItemList *favorites; ItemList *recent; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index bad2203423..2a59aadd61 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -243,6 +243,9 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview if (p_overview) { class_desc->push_cell(); class_desc->push_align(RichTextLabel::ALIGN_RIGHT); + } else { + static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + class_desc->add_text(String(prefix)); } _add_type(p_method.return_type, p_method.return_enum); @@ -378,7 +381,6 @@ void EditorHelp::_update_doc() { class_desc->push_color(title_color); class_desc->push_font(doc_font); class_desc->add_text(TTR("Inherits:") + " "); - class_desc->pop(); String inherits = cd.inherits; @@ -393,6 +395,7 @@ void EditorHelp::_update_doc() { } class_desc->pop(); + class_desc->pop(); class_desc->add_newline(); } @@ -401,13 +404,12 @@ void EditorHelp::_update_doc() { bool found = false; bool prev = false; + class_desc->push_font(doc_font); for (Map<String, DocData::ClassDoc>::Element *E = doc->class_list.front(); E; E = E->next()) { if (E->get().inherits == cd.name) { if (!found) { class_desc->push_color(title_color); - class_desc->push_font(doc_font); class_desc->add_text(TTR("Inherited by:") + " "); - class_desc->pop(); found = true; } @@ -419,6 +421,7 @@ void EditorHelp::_update_doc() { prev = true; } } + class_desc->pop(); if (found) { class_desc->pop(); @@ -758,6 +761,8 @@ void EditorHelp::_update_doc() { signal_line[cd.signals[i].name] = class_desc->get_line_count() - 2; //gets overridden if description class_desc->push_font(doc_code_font); // monofont class_desc->push_color(headline_color); + static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + class_desc->add_text(String(prefix)); _add_text(cd.signals[i].name); class_desc->pop(); class_desc->push_color(symbol_color); @@ -835,10 +840,10 @@ void EditorHelp::_update_doc() { for (Map<String, Vector<DocData::ConstantDoc>>::Element *E = enums.front(); E; E = E->next()) { enum_line[E->key()] = class_desc->get_line_count() - 2; + class_desc->push_font(doc_code_font); class_desc->push_color(title_color); class_desc->add_text("enum "); class_desc->pop(); - class_desc->push_font(doc_code_font); String e = E->key(); if ((e.get_slice_count(".") > 1) && (e.get_slice(".", 0) == edited_class)) { e = e.get_slice(".", 1); @@ -851,6 +856,8 @@ void EditorHelp::_update_doc() { class_desc->push_color(symbol_color); class_desc->add_text(":"); class_desc->pop(); + + class_desc->add_newline(); class_desc->add_newline(); class_desc->push_indent(1); @@ -869,6 +876,8 @@ void EditorHelp::_update_doc() { class_desc->push_font(doc_code_font); class_desc->push_color(headline_color); + static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + class_desc->add_text(String(prefix)); _add_text(enum_list[i].name); class_desc->pop(); class_desc->push_color(symbol_color); @@ -880,14 +889,15 @@ void EditorHelp::_update_doc() { class_desc->pop(); if (enum_list[i].description != "") { class_desc->push_font(doc_font); - //class_desc->add_text(" "); - class_desc->push_indent(1); class_desc->push_color(comment_color); + static const CharType dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 }; + class_desc->add_text(String(dash)); _add_text(DTR(enum_list[i].description)); class_desc->pop(); class_desc->pop(); - class_desc->pop(); // indent - class_desc->add_newline(); + if (DTR(enum_list[i].description).find("\n") > 0) { + class_desc->add_newline(); + } } class_desc->add_newline(); @@ -931,6 +941,9 @@ void EditorHelp::_update_doc() { class_desc->add_text(String(prefix)); class_desc->pop(); } + } else { + static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + class_desc->add_text(String(prefix)); } class_desc->push_color(headline_color); @@ -946,13 +959,15 @@ void EditorHelp::_update_doc() { class_desc->pop(); if (constants[i].description != "") { class_desc->push_font(doc_font); - class_desc->push_indent(1); class_desc->push_color(comment_color); + static const CharType dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 }; + class_desc->add_text(String(dash)); _add_text(DTR(constants[i].description)); class_desc->pop(); class_desc->pop(); - class_desc->pop(); // indent - class_desc->add_newline(); + if (DTR(constants[i].description).find("\n") > 0) { + class_desc->add_newline(); + } } class_desc->add_newline(); @@ -987,6 +1002,9 @@ void EditorHelp::_update_doc() { class_desc->push_cell(); class_desc->push_font(doc_code_font); + static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + class_desc->add_text(String(prefix)); + _add_type(cd.properties[i].type, cd.properties[i].enumeration); class_desc->add_text(" "); class_desc->pop(); // font @@ -1015,6 +1033,11 @@ void EditorHelp::_update_doc() { class_desc->pop(); // font class_desc->pop(); // cell + Map<String, DocData::MethodDoc> method_map; + for (int j = 0; j < methods.size(); j++) { + method_map[methods[j].name] = methods[j]; + } + if (cd.properties[i].setter != "") { class_desc->push_cell(); class_desc->pop(); // cell @@ -1022,7 +1045,14 @@ void EditorHelp::_update_doc() { class_desc->push_cell(); class_desc->push_font(doc_code_font); class_desc->push_color(text_color); - class_desc->add_text(cd.properties[i].setter + TTR("(value)")); + if (method_map[cd.properties[i].setter].arguments.size() > 1) { + // Setters with additional arguments are exposed in the method list, so we link them here for quick access. + class_desc->push_meta("@method " + cd.properties[i].setter); + class_desc->add_text(cd.properties[i].setter + TTR("(value)")); + class_desc->pop(); + } else { + class_desc->add_text(cd.properties[i].setter + TTR("(value)")); + } class_desc->pop(); // color class_desc->push_color(comment_color); class_desc->add_text(" setter"); @@ -1039,7 +1069,14 @@ void EditorHelp::_update_doc() { class_desc->push_cell(); class_desc->push_font(doc_code_font); class_desc->push_color(text_color); - class_desc->add_text(cd.properties[i].getter + "()"); + if (method_map[cd.properties[i].getter].arguments.size() > 0) { + // Getters with additional arguments are exposed in the method list, so we link them here for quick access. + class_desc->push_meta("@method " + cd.properties[i].getter); + class_desc->add_text(cd.properties[i].getter + "()"); + class_desc->pop(); + } else { + class_desc->add_text(cd.properties[i].getter + "()"); + } class_desc->pop(); //color class_desc->push_color(comment_color); class_desc->add_text(" getter"); @@ -1627,12 +1664,14 @@ FindBar::FindBar() { add_child(matches_label); matches_label->hide(); - find_prev = memnew(ToolButton); + find_prev = memnew(Button); + find_prev->set_flat(true); add_child(find_prev); find_prev->set_focus_mode(FOCUS_NONE); find_prev->connect("pressed", callable_mp(this, &FindBar::search_prev)); - find_next = memnew(ToolButton); + find_next = memnew(Button); + find_next->set_flat(true); add_child(find_next); find_next->set_focus_mode(FOCUS_NONE); find_next->connect("pressed", callable_mp(this, &FindBar::search_next)); diff --git a/editor/editor_help.h b/editor/editor_help.h index 4d42c1d38a..7c3edeb299 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -47,8 +47,8 @@ class FindBar : public HBoxContainer { GDCLASS(FindBar, HBoxContainer); LineEdit *search_text; - ToolButton *find_prev; - ToolButton *find_next; + Button *find_prev; + Button *find_next; Label *matches_label; TextureButton *hide_button; String prev_search; diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 5bfcbf06fc..d2b9405552 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -201,14 +201,16 @@ EditorHelpSearch::EditorHelpSearch() { register_text_enter(search_box); hbox->add_child(search_box); - case_sensitive_button = memnew(ToolButton); + case_sensitive_button = memnew(Button); + case_sensitive_button->set_flat(true); case_sensitive_button->set_tooltip(TTR("Case Sensitive")); case_sensitive_button->connect("pressed", callable_mp(this, &EditorHelpSearch::_update_results)); case_sensitive_button->set_toggle_mode(true); case_sensitive_button->set_focus_mode(Control::FOCUS_NONE); hbox->add_child(case_sensitive_button); - hierarchy_button = memnew(ToolButton); + hierarchy_button = memnew(Button); + hierarchy_button->set_flat(true); hierarchy_button->set_tooltip(TTR("Show Hierarchy")); hierarchy_button->connect("pressed", callable_mp(this, &EditorHelpSearch::_update_results)); hierarchy_button->set_toggle_mode(true); diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h index f7dbc5c3ad..b37f74fd7e 100644 --- a/editor/editor_help_search.h +++ b/editor/editor_help_search.h @@ -54,8 +54,8 @@ class EditorHelpSearch : public ConfirmationDialog { }; LineEdit *search_box; - ToolButton *case_sensitive_button; - ToolButton *hierarchy_button; + Button *case_sensitive_button; + Button *hierarchy_button; OptionButton *filter_combo; Tree *results_tree; bool old_search; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index ea5f73acd1..9595eb8a72 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -124,7 +124,7 @@ void EditorLog::add_message(const String &p_msg, MessageType p_type) { } } -void EditorLog::set_tool_button(ToolButton *p_tool_button) { +void EditorLog::set_tool_button(Button *p_tool_button) { tool_button = p_tool_button; } diff --git a/editor/editor_log.h b/editor/editor_log.h index 1c9a2d4062..3bf5615346 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -31,17 +31,16 @@ #ifndef EDITOR_LOG_H #define EDITOR_LOG_H -#include "scene/gui/control.h" -#include "scene/gui/label.h" -#include "scene/gui/rich_text_label.h" -#include "scene/gui/texture_button.h" -//#include "scene/gui/empty_control.h" #include "core/os/thread.h" #include "pane_drag.h" #include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/control.h" +#include "scene/gui/label.h" #include "scene/gui/panel_container.h" +#include "scene/gui/rich_text_label.h" +#include "scene/gui/texture_button.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" class EditorLog : public VBoxContainer { GDCLASS(EditorLog, VBoxContainer); @@ -52,7 +51,7 @@ class EditorLog : public VBoxContainer { RichTextLabel *log; HBoxContainer *title_hb; //PaneDrag *pd; - ToolButton *tool_button; + Button *tool_button; static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); @@ -78,7 +77,7 @@ public: }; void add_message(const String &p_msg, MessageType p_type = MSG_TYPE_STD); - void set_tool_button(ToolButton *p_tool_button); + void set_tool_button(Button *p_tool_button); void deinit(); void clear(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 9a9a1bfdeb..d8bc555d6d 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -58,7 +58,6 @@ #include "scene/gui/tab_container.h" #include "scene/gui/tabs.h" #include "scene/gui/texture_progress.h" -#include "scene/gui/tool_button.h" #include "scene/resources/packed_scene.h" #include "servers/navigation_server_2d.h" #include "servers/navigation_server_3d.h" @@ -485,7 +484,7 @@ void EditorNode::_notification(int p_what) { // update_icons for (int i = 0; i < singleton->main_editor_buttons.size(); i++) { - ToolButton *tb = singleton->main_editor_buttons[i]; + Button *tb = singleton->main_editor_buttons[i]; EditorPlugin *p_editor = singleton->editor_table[i]; Ref<Texture2D> icon = p_editor->get_icon(); @@ -2776,7 +2775,8 @@ void EditorNode::select_editor_by_name(const String &p_name) { void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed) { if (p_editor->has_main_screen()) { - ToolButton *tb = memnew(ToolButton); + Button *tb = memnew(Button); + tb->set_flat(true); tb->set_toggle_mode(true); tb->connect("pressed", callable_mp(singleton, &EditorNode::_editor_select), varray(singleton->main_editor_buttons.size())); tb->set_text(p_editor->get_name()); @@ -3642,17 +3642,12 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } if (ScriptServer::is_global_class(p_class)) { - String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(p_class); - Ref<ImageTexture> icon = _load_custom_class_icon(icon_path); - if (icon.is_valid()) { - return icon; - } - - Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class), "Script"); + Ref<ImageTexture> icon; + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class); while (script.is_valid()) { - String current_icon_path; - script->get_language()->get_global_class_name(script->get_path(), nullptr, ¤t_icon_path); + StringName name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); icon = _load_custom_class_icon(current_icon_path); if (icon.is_valid()) { return icon; @@ -4621,8 +4616,9 @@ void EditorNode::_scene_tab_changed(int p_tab) { editor_data.get_undo_redo().commit_action(); } -ToolButton *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) { - ToolButton *tb = memnew(ToolButton); +Button *EditorNode::add_bottom_panel_item(String p_text, Control *p_item) { + Button *tb = memnew(Button); + tb->set_flat(true); tb->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_switch), varray(bottom_panel_items.size())); tb->set_text(p_text); tb->set_toggle_mode(true); @@ -5698,7 +5694,8 @@ EditorNode::EditorNode() { dock_select_popup->add_child(dock_vb); HBoxContainer *dock_hb = memnew(HBoxContainer); - dock_tab_move_left = memnew(ToolButton); + dock_tab_move_left = memnew(Button); + dock_tab_move_left->set_flat(true); dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons")); dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE); dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left)); @@ -5710,7 +5707,8 @@ EditorNode::EditorNode() { dock_label->set_align(Label::ALIGN_CENTER); dock_hb->add_child(dock_label); - dock_tab_move_right = memnew(ToolButton); + dock_tab_move_right = memnew(Button); + dock_tab_move_right->set_flat(true); dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons")); dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE); dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right)); @@ -5804,7 +5802,8 @@ EditorNode::EditorNode() { srt->add_child(tabbar_container); tabbar_container->add_child(scene_tabs); - distraction_free = memnew(ToolButton); + distraction_free = memnew(Button); + distraction_free->set_flat(true); #ifdef OSX_ENABLED distraction_free->set_shortcut(ED_SHORTCUT("editor/distraction_free_mode", TTR("Distraction Free Mode"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D)); #else @@ -5815,7 +5814,8 @@ EditorNode::EditorNode() { distraction_free->set_icon(gui_base->get_theme_icon("DistractionFree", "EditorIcons")); distraction_free->set_toggle_mode(true); - scene_tab_add = memnew(ToolButton); + scene_tab_add = memnew(Button); + scene_tab_add->set_flat(true); tabbar_container->add_child(scene_tab_add); tabbar_container->add_child(distraction_free); scene_tab_add->set_tooltip(TTR("Add a new scene.")); @@ -5852,7 +5852,8 @@ EditorNode::EditorNode() { file_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox("MenuHover", "EditorStyles")); left_menu_hb->add_child(file_menu); - prev_scene = memnew(ToolButton); + prev_scene = memnew(Button); + prev_scene->set_flat(true); prev_scene->set_icon(gui_base->get_theme_icon("PrevScene", "EditorIcons")); prev_scene->set_tooltip(TTR("Go to previously opened scene.")); prev_scene->set_disabled(true); @@ -6081,7 +6082,8 @@ EditorNode::EditorNode() { HBoxContainer *play_hb = memnew(HBoxContainer); menu_hb->add_child(play_hb); - play_button = memnew(ToolButton); + play_button = memnew(Button); + play_button->set_flat(true); play_hb->add_child(play_button); play_button->set_toggle_mode(true); play_button->set_icon(gui_base->get_theme_icon("MainPlay", "EditorIcons")); @@ -6094,7 +6096,8 @@ EditorNode::EditorNode() { play_button->set_shortcut(ED_SHORTCUT("editor/play", TTR("Play"), KEY_F5)); #endif - pause_button = memnew(ToolButton); + pause_button = memnew(Button); + pause_button->set_flat(true); pause_button->set_toggle_mode(true); pause_button->set_icon(gui_base->get_theme_icon("Pause", "EditorIcons")); pause_button->set_focus_mode(Control::FOCUS_NONE); @@ -6107,7 +6110,8 @@ EditorNode::EditorNode() { pause_button->set_shortcut(ED_SHORTCUT("editor/pause_scene", TTR("Pause Scene"), KEY_F7)); #endif - stop_button = memnew(ToolButton); + stop_button = memnew(Button); + stop_button->set_flat(true); play_hb->add_child(stop_button); stop_button->set_focus_mode(Control::FOCUS_NONE); stop_button->set_icon(gui_base->get_theme_icon("Stop", "EditorIcons")); @@ -6124,7 +6128,8 @@ EditorNode::EditorNode() { play_hb->add_child(run_native); run_native->connect("native_run", callable_mp(this, &EditorNode::_run_native)); - play_scene_button = memnew(ToolButton); + play_scene_button = memnew(Button); + play_scene_button->set_flat(true); play_hb->add_child(play_scene_button); play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); @@ -6137,7 +6142,8 @@ EditorNode::EditorNode() { play_scene_button->set_shortcut(ED_SHORTCUT("editor/play_scene", TTR("Play Scene"), KEY_F6)); #endif - play_custom_scene_button = memnew(ToolButton); + play_custom_scene_button = memnew(Button); + play_custom_scene_button->set_flat(true); play_hb->add_child(play_custom_scene_button); play_custom_scene_button->set_toggle_mode(true); play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE); @@ -6298,7 +6304,8 @@ EditorNode::EditorNode() { version_label->set_self_modulate(Color(1, 1, 1, 0.6)); bottom_panel_hb->add_child(version_label); - bottom_panel_raise = memnew(ToolButton); + bottom_panel_raise = memnew(Button); + bottom_panel_raise->set_flat(true); bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons")); bottom_panel_raise->set_shortcut(ED_SHORTCUT("editor/bottom_panel_expand", TTR("Expand Bottom Panel"), KEY_MASK_SHIFT | KEY_F12)); @@ -6309,7 +6316,7 @@ EditorNode::EditorNode() { bottom_panel_raise->connect("toggled", callable_mp(this, &EditorNode::_bottom_panel_raise_toggled)); log = memnew(EditorLog); - ToolButton *output_button = add_bottom_panel_item(TTR("Output"), log); + Button *output_button = add_bottom_panel_item(TTR("Output"), log); log->set_tool_button(output_button); old_split_ofs = 0; diff --git a/editor/editor_node.h b/editor/editor_node.h index 7c9cf44d6c..b0e0c5614c 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -83,7 +83,7 @@ class ScriptCreateDialog; class TabContainer; class Tabs; class TextureProgress; -class ToolButton; +class Button; class VSplitContainer; class Window; class SubViewport; @@ -265,15 +265,15 @@ private: MenuButton *settings_menu; MenuButton *help_menu; PopupMenu *tool_menu; - ToolButton *export_button; - ToolButton *prev_scene; - ToolButton *play_button; - ToolButton *pause_button; - ToolButton *stop_button; - ToolButton *run_settings_button; - ToolButton *play_scene_button; - ToolButton *play_custom_scene_button; - ToolButton *search_button; + Button *export_button; + Button *prev_scene; + Button *play_button; + Button *pause_button; + Button *stop_button; + Button *run_settings_button; + Button *play_scene_button; + Button *play_custom_scene_button; + Button *search_button; TextureProgress *audio_vu; Timer *screenshot_timer; @@ -336,7 +336,7 @@ private: EditorQuickOpen *quick_run; HBoxContainer *main_editor_button_vb; - Vector<ToolButton *> main_editor_buttons; + Vector<Button *> main_editor_buttons; Vector<EditorPlugin *> editor_table; AudioStreamPreviewGenerator *preview_gen; @@ -358,15 +358,15 @@ private: PopupPanel *dock_select_popup; Control *dock_select; Button *dock_float; - ToolButton *dock_tab_move_left; - ToolButton *dock_tab_move_right; + Button *dock_tab_move_left; + Button *dock_tab_move_right; int dock_popup_selected; Timer *dock_drag_timer; bool docks_visible; HBoxContainer *tabbar_container; - ToolButton *distraction_free; - ToolButton *scene_tab_add; + Button *distraction_free; + Button *scene_tab_add; bool scene_distraction; bool script_distraction; @@ -412,7 +412,7 @@ private: struct BottomPanelItem { String name; Control *control; - ToolButton *button; + Button *button; }; Vector<BottomPanelItem> bottom_panel_items; @@ -422,7 +422,7 @@ private: HBoxContainer *bottom_panel_hb_editors; VBoxContainer *bottom_panel_vb; Label *version_label; - ToolButton *bottom_panel_raise; + Button *bottom_panel_raise; void _bottom_panel_raise_toggled(bool); @@ -821,9 +821,9 @@ public: bool is_exiting() const { return exiting; } - ToolButton *get_pause_button() { return pause_button; } + Button *get_pause_button() { return pause_button; } - ToolButton *add_bottom_panel_item(String p_text, Control *p_item); + Button *add_bottom_panel_item(String p_text, Control *p_item); bool are_bottom_panels_hidden() const; void make_bottom_panel_item_visible(Control *p_item); void raise_bottom_panel_item(Control *p_item); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 6d93e92555..32b799cd61 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -332,7 +332,7 @@ void EditorPlugin::remove_autoload_singleton(const String &p_name) { EditorNode::get_singleton()->get_project_settings()->get_autoload_settings()->autoload_remove(p_name); } -ToolButton *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { +Button *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) { ERR_FAIL_NULL_V(p_control, nullptr); return EditorNode::get_singleton()->add_bottom_panel_item(p_title, p_control); } diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index aac36bfdfd..e84984d57a 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -37,7 +37,6 @@ #include "editor/import/editor_import_plugin.h" #include "editor/import/resource_importer_scene.h" #include "editor/script_create_dialog.h" -#include "scene/gui/tool_button.h" #include "scene/main/node.h" #include "scene/resources/texture.h" @@ -161,7 +160,7 @@ public: void add_control_to_container(CustomControlContainer p_location, Control *p_control); void remove_control_from_container(CustomControlContainer p_location, Control *p_control); - ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title); + Button *add_control_to_bottom_panel(Control *p_control, const String &p_title); void add_control_to_dock(DockSlot p_slot, Control *p_control); void remove_control_from_docks(Control *p_control); void remove_control_from_bottom_panel(Control *p_control); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index cfa0c7a063..eee610e9a8 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -164,7 +164,8 @@ EditorPropertyMultilineText::EditorPropertyMultilineText() { add_focusable(text); hb->add_child(text); text->set_h_size_flags(SIZE_EXPAND_FILL); - open_big_text = memnew(ToolButton); + open_big_text = memnew(Button); + open_big_text->set_flat(true); open_big_text->connect("pressed", callable_mp(this, &EditorPropertyMultilineText::_open_big_text)); hb->add_child(open_big_text); big_text_dialog = nullptr; @@ -1283,14 +1284,25 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) { } void EditorPropertyVector3::update_property() { - Vector3 val = get_edited_object()->get(get_edited_property()); + update_using_vector(get_edited_object()->get(get_edited_property())); +} + +void EditorPropertyVector3::update_using_vector(Vector3 p_vector) { setting = true; - spin[0]->set_value(val.x); - spin[1]->set_value(val.y); - spin[2]->set_value(val.z); + spin[0]->set_value(p_vector.x); + spin[1]->set_value(p_vector.y); + spin[2]->set_value(p_vector.z); setting = false; } +Vector3 EditorPropertyVector3::get_vector() { + Vector3 v3; + v3.x = spin[0]->get_value(); + v3.y = spin[1]->get_value(); + v3.z = spin[2]->get_value(); + return v3; +} + void EditorPropertyVector3::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { Color base = get_theme_color("accent_color", "Editor"); @@ -1434,7 +1446,7 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) { setting = false; } -///////////////////// RECT2 ///////////////////////// +///////////////////// RECT2i ///////////////////////// void EditorPropertyRect2i::_value_changed(double val, const String &p_name) { if (setting) { @@ -1520,7 +1532,7 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) { setting = false; } -///////////////////// VECTOR3 ///////////////////////// +///////////////////// VECTOR3i ///////////////////////// void EditorPropertyVector3i::_value_changed(double val, const String &p_name) { if (setting) { @@ -2029,21 +2041,23 @@ void EditorPropertyTransform::_value_changed(double val, const String &p_name) { } void EditorPropertyTransform::update_property() { - Transform val = get_edited_object()->get(get_edited_property()); - setting = true; - spin[0]->set_value(val.basis[0][0]); - spin[1]->set_value(val.basis[1][0]); - spin[2]->set_value(val.basis[2][0]); - spin[3]->set_value(val.basis[0][1]); - spin[4]->set_value(val.basis[1][1]); - spin[5]->set_value(val.basis[2][1]); - spin[6]->set_value(val.basis[0][2]); - spin[7]->set_value(val.basis[1][2]); - spin[8]->set_value(val.basis[2][2]); - spin[9]->set_value(val.origin[0]); - spin[10]->set_value(val.origin[1]); - spin[11]->set_value(val.origin[2]); + update_using_transform(get_edited_object()->get(get_edited_property())); +} +void EditorPropertyTransform::update_using_transform(Transform p_transform) { + setting = true; + spin[0]->set_value(p_transform.basis[0][0]); + spin[1]->set_value(p_transform.basis[1][0]); + spin[2]->set_value(p_transform.basis[2][0]); + spin[3]->set_value(p_transform.basis[0][1]); + spin[4]->set_value(p_transform.basis[1][1]); + spin[5]->set_value(p_transform.basis[2][1]); + spin[6]->set_value(p_transform.basis[0][2]); + spin[7]->set_value(p_transform.basis[1][2]); + spin[8]->set_value(p_transform.basis[2][2]); + spin[9]->set_value(p_transform.origin[0]); + spin[10]->set_value(p_transform.origin[1]); + spin[11]->set_value(p_transform.origin[2]); setting = false; } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 61c11f4534..35e6c10d90 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -392,6 +392,8 @@ protected: public: virtual void update_property(); + virtual void update_using_vector(Vector3 p_vector); + virtual Vector3 get_vector(); void setup(double p_min, double p_max, double p_step, bool p_no_slider); EditorPropertyVector3(bool p_force_wide = false); }; @@ -536,6 +538,7 @@ protected: public: virtual void update_property(); + virtual void update_using_transform(Transform p_transform); void setup(double p_min, double p_max, double p_step, bool p_no_slider); EditorPropertyTransform(); }; diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index ace106cd3e..a93763810b 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -570,17 +570,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("focus", "PopupMenu", style_menu); theme->set_stylebox("disabled", "PopupMenu", style_menu); - theme->set_stylebox("normal", "ToolButton", style_menu); - theme->set_stylebox("hover", "ToolButton", style_menu); - theme->set_stylebox("pressed", "ToolButton", style_menu); - theme->set_stylebox("focus", "ToolButton", style_menu); - theme->set_stylebox("disabled", "ToolButton", style_menu); - theme->set_color("font_color", "MenuButton", font_color); theme->set_color("font_color_hover", "MenuButton", font_color_hl); - theme->set_color("font_color", "ToolButton", font_color); - theme->set_color("font_color_hover", "ToolButton", font_color_hl); - theme->set_color("font_color_pressed", "ToolButton", accent_color); theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 4fdc3dc080..c700fdccad 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2085,7 +2085,32 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, } } if (!to_move.empty()) { - _move_operation_confirm(to_dir); + if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + for (int i = 0; i < to_move.size(); i++) { + String new_path; + String new_path_base; + + if (to_move[i].is_file) { + new_path = to_dir.plus_file(to_move[i].path.get_file()); + new_path_base = new_path.get_basename() + " (%d)." + new_path.get_extension(); + } else { + PackedStringArray path_split = to_move[i].path.split("/"); + new_path = to_dir.plus_file(path_split[path_split.size() - 2]); + new_path_base = new_path + " (%d)"; + } + + int exist_counter = 1; + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + while (da->file_exists(new_path) || da->dir_exists(new_path)) { + exist_counter++; + new_path = vformat(new_path_base, exist_counter); + } + _try_duplicate_item(to_move[i], new_path); + } + _rescan(); + } else { + _move_operation_confirm(to_dir); + } } } else if (favorite) { // Add the files from favorites. @@ -2518,13 +2543,15 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { toolbar_hbc->add_theme_constant_override("separation", 0); top_vbc->add_child(toolbar_hbc); - button_hist_prev = memnew(ToolButton); + button_hist_prev = memnew(Button); + button_hist_prev->set_flat(true); button_hist_prev->set_disabled(true); button_hist_prev->set_focus_mode(FOCUS_NONE); button_hist_prev->set_tooltip(TTR("Previous Folder/File")); toolbar_hbc->add_child(button_hist_prev); - button_hist_next = memnew(ToolButton); + button_hist_next = memnew(Button); + button_hist_next->set_flat(true); button_hist_next->set_disabled(true); button_hist_next->set_focus_mode(FOCUS_NONE); button_hist_next->set_tooltip(TTR("Next Folder/File")); @@ -2602,7 +2629,8 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { file_list_search_box->connect("text_changed", callable_mp(this, &FileSystemDock::_search_changed), varray(file_list_search_box)); path_hb->add_child(file_list_search_box); - button_file_list_display_mode = memnew(ToolButton); + button_file_list_display_mode = memnew(Button); + button_file_list_display_mode->set_flat(true); path_hb->add_child(button_file_list_display_mode); files = memnew(ItemList); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 08c2124ae8..b0118f11aa 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -40,7 +40,6 @@ #include "scene/gui/option_button.h" #include "scene/gui/progress_bar.h" #include "scene/gui/split_container.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" #include "scene/main/timer.h" diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 1bc0de1ab0..53c52b94cc 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -719,22 +719,20 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin // Do this first because it resets properties of the cell... item->set_cell_mode(text_index, TreeItem::CELL_MODE_CUSTOM); - String item_text = vformat("%3s: %s", line_number, text.replace("\t", " ")); + // Trim result item line + int old_text_size = text.size(); + text = text.strip_edges(true, false); + int chars_removed = old_text_size - text.size(); + String start = vformat("%3s: ", line_number); - item->set_text(text_index, item_text); + item->set_text(text_index, start + text); item->set_custom_draw(text_index, this, "_draw_result_text"); - Ref<Font> font = _results_display->get_theme_font("font"); - - float raw_text_width = font->get_string_size(text).x; - float item_text_width = font->get_string_size(item_text).x; - Result r; r.line_number = line_number; r.begin = begin; r.end = end; - r.draw_begin = (item_text_width - raw_text_width) + font->get_string_size(text.left(r.begin)).x; - r.draw_width = font->get_string_size(text.substr(r.begin, r.end - r.begin)).x; + r.begin_trimmed = begin - chars_removed + start.size() - 1; _result_items[item] = r; if (_with_replace) { @@ -755,10 +753,12 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) { return; } Result r = E->value(); + String item_text = item->get_text(_with_replace ? 1 : 0); + Ref<Font> font = _results_display->get_theme_font("font"); Rect2 match_rect = rect; - match_rect.position.x += r.draw_begin; - match_rect.size.x = r.draw_width; + match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed)).x; + match_rect.size.x = font->get_string_size(_search_text_label->get_text()).x; match_rect.position.y += 1 * EDSCALE; match_rect.size.y -= 2 * EDSCALE; diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 41adb156b6..9815296be8 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -191,8 +191,7 @@ private: int line_number; int begin; int end; - float draw_begin; - float draw_width; + int begin_trimmed; }; void apply_replaces_in_file(String fpath, const Vector<Result> &locations, String new_text); diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 98b216acda..4e6e2d0237 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -477,7 +477,8 @@ GroupDialog::GroupDialog() { vbc_buttons->set_h_size_flags(Control::SIZE_SHRINK_CENTER); vbc_buttons->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - add_button = memnew(ToolButton); + add_button = memnew(Button); + add_button->set_flat(true); add_button->set_text(TTR("Add")); add_button->connect("pressed", callable_mp(this, &GroupDialog::_add_pressed)); @@ -486,7 +487,8 @@ GroupDialog::GroupDialog() { vbc_buttons->add_spacer(); vbc_buttons->add_spacer(); - remove_button = memnew(ToolButton); + remove_button = memnew(Button); + remove_button->set_flat(true); remove_button->set_text(TTR("Remove")); remove_button->connect("pressed", callable_mp(this, &GroupDialog::_removed_pressed)); diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 911c82e7f0..d5daaa19eb 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -38,7 +38,6 @@ #include "scene/gui/item_list.h" #include "scene/gui/line_edit.h" #include "scene/gui/popup.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" class GroupDialog : public AcceptDialog { @@ -63,8 +62,8 @@ class GroupDialog : public AcceptDialog { Label *group_empty; - ToolButton *add_button; - ToolButton *remove_button; + Button *add_button; + Button *remove_button; String selected_group; diff --git a/editor/icons/AssetLib.svg b/editor/icons/AssetLib.svg index 72b20ec047..22307efde3 100644 --- a/editor/icons/AssetLib.svg +++ b/editor/icons/AssetLib.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1c-1.6569 0-3 1.3431-3 3v2h-3c-.66446.0003505-1.1438.6366-.96094 1.2754l2 7c.12287.42881.51487.7244.96094.72461h8c.44606-.000209.83806-.2958.96094-.72461l2-7c.1829-.63879-.29648-1.275-.96094-1.2754h-3v-2c0-1.6569-1.3431-3-3-3zm0 2c.55228 0 1 .44772 1 1v2h-2v-2c0-.55228.44772-1 1-1z" fill="#e0e0e0"/></svg>
\ No newline at end of file +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"><path d="m8 1v9l4-4"/><path d="m8 10-4-4"/><path d="m2 10v4h12v-4" stroke-linecap="round"/></g></svg> diff --git a/editor/icons/Crosshair.svg b/editor/icons/Crosshair.svg deleted file mode 100644 index b6fa5ec654..0000000000 --- a/editor/icons/Crosshair.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m6 1v5h-5v1 3h5v5h4v-5h5v-4h-5v-5z" fill-opacity=".627451"/><path d="m2 7v2l5.0000803.0000197-.0000803 4.9999803h2l-.0000803-4.9999803 5.0000803-.0000197v-2l-5.0000803.0001803.0000803-5.0001803h-2l.0000803 5.0001803z" fill="#fefefe" fill-opacity=".862745"/></svg>
\ No newline at end of file diff --git a/editor/icons/ToolButton.svg b/editor/icons/ToolButton.svg deleted file mode 100644 index 98a41d2a08..0000000000 --- a/editor/icons/ToolButton.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11 1.1738c-1.1979.4235-1.999 1.5557-2 2.8262.0009552 1.2705.80214 2.4027 2 2.8262v7.1738c0 .554.446 1 1 1s1-.446 1-1v-7.1758c1.1972-.4232 1.9982-1.5544 2-2.8242-.0018-1.2698-.80282-2.401-2-2.8242v2.8242c0 .5523-.44772 1-1 1s-1-.4477-1-1zm-7 1.8262v3.1328l-1.4453-.96484-1.1094 1.6641 3 2c.3359.22389.77347.22389 1.1094 0l3-2-1.1094-1.6641-1.4453.96484v-3.1328zm-.5 8c-.831 0-1.5.669-1.5 1.5v.5h-1v2h8v-2h-1v-.5c0-.831-.669-1.5-1.5-1.5z" fill="#a5efac"/></svg>
\ No newline at end of file diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp index 1a232658fe..683db0e31d 100644 --- a/editor/import/editor_scene_importer_gltf.cpp +++ b/editor/import/editor_scene_importer_gltf.cpp @@ -2877,6 +2877,7 @@ void EditorSceneImporterGLTF::_import_animation(GLTFState &state, AnimationPlaye int track_idx = animation->get_track_count(); animation->add_track(Animation::TYPE_TRANSFORM); animation->track_set_path(track_idx, node_path); + animation->track_set_imported(track_idx, true); //first determine animation length const float increment = 1.0 / float(bake_fps); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index ec82f78e75..65ebf9dc4f 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -943,9 +943,9 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String ERR_CONTINUE(anim.is_null()); if (!p_animations.has(anim)) { - //mark what comes from the file first, this helps eventually keep user data + // We are making external files so they are modifiable for (int i = 0; i < anim->get_track_count(); i++) { - anim->track_set_imported(i, true); + anim->track_set_imported(i, false); } String ext_name; diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index 2b26851140..903d9a2d31 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -493,14 +493,16 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { HBoxContainer *general_options_hb = memnew(HBoxContainer); add_child(general_options_hb); - resource_new_button = memnew(ToolButton); + resource_new_button = memnew(Button); + resource_new_button->set_flat(true); resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it.")); resource_new_button->set_icon(get_theme_icon("New", "EditorIcons")); general_options_hb->add_child(resource_new_button); resource_new_button->connect("pressed", callable_mp(this, &InspectorDock::_new_resource)); resource_new_button->set_focus_mode(Control::FOCUS_NONE); - resource_load_button = memnew(ToolButton); + resource_load_button = memnew(Button); + resource_load_button->set_flat(true); resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it.")); resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons")); general_options_hb->add_child(resource_load_button); @@ -519,7 +521,8 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { general_options_hb->add_spacer(); - backward_button = memnew(ToolButton); + backward_button = memnew(Button); + backward_button->set_flat(true); general_options_hb->add_child(backward_button); backward_button->set_icon(get_theme_icon("Back", "EditorIcons")); backward_button->set_flat(true); @@ -527,7 +530,8 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { backward_button->set_disabled(true); backward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_back)); - forward_button = memnew(ToolButton); + forward_button = memnew(Button); + forward_button->set_flat(true); general_options_hb->add_child(forward_button); forward_button->set_icon(get_theme_icon("Forward", "EditorIcons")); forward_button->set_flat(true); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 2a99a7db45..551d3d1643 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -42,7 +42,6 @@ #include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/popup_menu.h" -#include "scene/gui/tool_button.h" class EditorNode; @@ -74,13 +73,13 @@ class InspectorDock : public VBoxContainer { Object *current; - ToolButton *backward_button; - ToolButton *forward_button; + Button *backward_button; + Button *forward_button; EditorFileDialog *load_resource_dialog; CreateDialog *new_resource_dialog; - ToolButton *resource_new_button; - ToolButton *resource_load_button; + Button *resource_new_button; + Button *resource_load_button; MenuButton *resource_save_button; MenuButton *history_menu; LineEdit *search; diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index 9b9cfad9eb..2c89517008 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -92,7 +92,8 @@ NodeDock::NodeDock() { add_child(mode_hb); mode_hb->hide(); - connections_button = memnew(ToolButton); + connections_button = memnew(Button); + connections_button->set_flat(true); connections_button->set_text(TTR("Signals")); connections_button->set_toggle_mode(true); connections_button->set_pressed(true); @@ -101,7 +102,8 @@ NodeDock::NodeDock() { mode_hb->add_child(connections_button); connections_button->connect("pressed", callable_mp(this, &NodeDock::show_connections)); - groups_button = memnew(ToolButton); + groups_button = memnew(Button); + groups_button->set_flat(true); groups_button->set_text(TTR("Groups")); groups_button->set_toggle_mode(true); groups_button->set_pressed(false); diff --git a/editor/node_dock.h b/editor/node_dock.h index c165974678..8e10db5eb3 100644 --- a/editor/node_dock.h +++ b/editor/node_dock.h @@ -37,8 +37,8 @@ class NodeDock : public VBoxContainer { GDCLASS(NodeDock, VBoxContainer); - ToolButton *connections_button; - ToolButton *groups_button; + Button *connections_button; + Button *groups_button; ConnectionsDock *connections; GroupsEditor *groups; diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index b905c8db12..e99ffe2b83 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -703,17 +703,20 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi edge_point = PosVertex(); add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); + button_create = memnew(Button); + button_create->set_flat(true); add_child(button_create); button_create->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_edit = memnew(ToolButton); + button_edit = memnew(Button); + button_edit->set_flat(true); add_child(button_edit); button_edit->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_EDIT)); button_edit->set_toggle_mode(true); - button_delete = memnew(ToolButton); + button_delete = memnew(Button); + button_delete->set_flat(true); add_child(button_delete); button_delete->connect("pressed", callable_mp(this, &AbstractPolygon2DEditor::_menu_option), varray(MODE_DELETE)); button_delete->set_toggle_mode(true); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index d5b3a916d1..b3a17f7660 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -34,16 +34,15 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/2d/polygon_2d.h" -#include "scene/gui/tool_button.h" class CanvasItemEditor; class AbstractPolygon2DEditor : public HBoxContainer { GDCLASS(AbstractPolygon2DEditor, HBoxContainer); - ToolButton *button_create; - ToolButton *button_edit; - ToolButton *button_delete; + Button *button_create; + Button *button_edit; + Button *button_delete; struct Vertex { Vertex() {} diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 75eacf56ec..959301907c 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -595,7 +595,8 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { Ref<ButtonGroup> bg; bg.instance(); - tool_blend = memnew(ToolButton); + tool_blend = memnew(Button); + tool_blend->set_flat(true); tool_blend->set_toggle_mode(true); tool_blend->set_button_group(bg); top_hb->add_child(tool_blend); @@ -603,14 +604,16 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_blend->set_tooltip(TTR("Set the blending position within the space")); tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(3)); - tool_select = memnew(ToolButton); + tool_select = memnew(Button); + tool_select->set_flat(true); tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); top_hb->add_child(tool_select); tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch), varray(0)); - tool_create = memnew(ToolButton); + tool_create = memnew(Button); + tool_create->set_flat(true); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); top_hb->add_child(tool_create); @@ -619,14 +622,16 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_erase_sep = memnew(VSeparator); top_hb->add_child(tool_erase_sep); - tool_erase = memnew(ToolButton); + tool_erase = memnew(Button); + tool_erase->set_flat(true); top_hb->add_child(tool_erase); tool_erase->set_tooltip(TTR("Erase points.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_erase_selected)); top_hb->add_child(memnew(VSeparator)); - snap = memnew(ToolButton); + snap = memnew(Button); + snap->set_flat(true); snap->set_toggle_mode(true); top_hb->add_child(snap); snap->set_pressed(true); diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 8cfd6714ad..c319b648ba 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -47,15 +47,15 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeBlendSpace1D> blend_space; HBoxContainer *goto_parent_hb; - ToolButton *goto_parent; + Button *goto_parent; PanelContainer *panel; - ToolButton *tool_blend; - ToolButton *tool_select; - ToolButton *tool_create; + Button *tool_blend; + Button *tool_select; + Button *tool_create; VSeparator *tool_erase_sep; - ToolButton *tool_erase; - ToolButton *snap; + Button *tool_erase; + Button *snap; SpinBox *snap_value; LineEdit *label_value; diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index a7d5c2207b..1ab114fc01 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -819,7 +819,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { Ref<ButtonGroup> bg; bg.instance(); - tool_blend = memnew(ToolButton); + tool_blend = memnew(Button); + tool_blend->set_flat(true); tool_blend->set_toggle_mode(true); tool_blend->set_button_group(bg); top_hb->add_child(tool_blend); @@ -827,21 +828,24 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_blend->set_tooltip(TTR("Set the blending position within the space")); tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(3)); - tool_select = memnew(ToolButton); + tool_select = memnew(Button); + tool_select->set_flat(true); tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); top_hb->add_child(tool_select); tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(0)); - tool_create = memnew(ToolButton); + tool_create = memnew(Button); + tool_create->set_flat(true); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); top_hb->add_child(tool_create); tool_create->set_tooltip(TTR("Create points.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch), varray(1)); - tool_triangle = memnew(ToolButton); + tool_triangle = memnew(Button); + tool_triangle->set_flat(true); tool_triangle->set_toggle_mode(true); tool_triangle->set_button_group(bg); top_hb->add_child(tool_triangle); @@ -850,7 +854,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_erase_sep = memnew(VSeparator); top_hb->add_child(tool_erase_sep); - tool_erase = memnew(ToolButton); + tool_erase = memnew(Button); + tool_erase->set_flat(true); top_hb->add_child(tool_erase); tool_erase->set_tooltip(TTR("Erase points and triangles.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_erase_selected)); @@ -858,7 +863,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(memnew(VSeparator)); - auto_triangles = memnew(ToolButton); + auto_triangles = memnew(Button); + auto_triangles->set_flat(true); top_hb->add_child(auto_triangles); auto_triangles->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled)); auto_triangles->set_toggle_mode(true); @@ -866,7 +872,8 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(memnew(VSeparator)); - snap = memnew(ToolButton); + snap = memnew(Button); + snap->set_flat(true); snap->set_toggle_mode(true); top_hb->add_child(snap); snap->set_pressed(true); diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index b430a12297..659b96cefa 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -47,18 +47,18 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeBlendSpace2D> blend_space; PanelContainer *panel; - ToolButton *tool_blend; - ToolButton *tool_select; - ToolButton *tool_create; - ToolButton *tool_triangle; + Button *tool_blend; + Button *tool_select; + Button *tool_create; + Button *tool_triangle; VSeparator *tool_erase_sep; - ToolButton *tool_erase; - ToolButton *snap; + Button *tool_erase; + Button *snap; SpinBox *snap_x; SpinBox *snap_y; OptionButton *interpolation; - ToolButton *auto_triangles; + Button *auto_triangles; LineEdit *label_x; LineEdit *label_y; diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 1e0a9535e2..035526ca55 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -380,26 +380,25 @@ void AnimationPlayerEditor::_animation_save_as(const Ref<Resource> &p_resource) file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } + String path; //file->set_current_path(current_path); if (p_resource->get_path() != "") { - file->set_current_path(p_resource->get_path()); + path = p_resource->get_path(); if (extensions.size()) { - String ext = p_resource->get_path().get_extension().to_lower(); - if (extensions.find(ext) == nullptr) { - file->set_current_path(p_resource->get_path().replacen("." + ext, "." + extensions.front()->get())); + if (extensions.find(p_resource->get_path().get_extension().to_lower()) == nullptr) { + path = p_resource->get_path().get_base_dir() + p_resource->get_name() + "." + extensions.front()->get(); } } } else { - String existing; if (extensions.size()) { if (p_resource->get_name() != "") { - existing = p_resource->get_name() + "." + extensions.front()->get().to_lower(); + path = p_resource->get_name() + "." + extensions.front()->get().to_lower(); } else { - existing = "new_" + p_resource->get_class().to_lower() + "." + extensions.front()->get().to_lower(); + path = "new_" + p_resource->get_class().to_lower() + "." + extensions.front()->get().to_lower(); } } - file->set_current_path(existing); } + file->set_current_path(path); file->popup_centered_ratio(); file->set_title(TTR("Save Resource As...")); current_option = RESOURCE_SAVE; @@ -1503,24 +1502,29 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay HBoxContainer *hb = memnew(HBoxContainer); add_child(hb); - play_bw_from = memnew(ToolButton); + play_bw_from = memnew(Button); + play_bw_from->set_flat(true); play_bw_from->set_tooltip(TTR("Play selected animation backwards from current pos. (A)")); hb->add_child(play_bw_from); - play_bw = memnew(ToolButton); + play_bw = memnew(Button); + play_bw->set_flat(true); play_bw->set_tooltip(TTR("Play selected animation backwards from end. (Shift+A)")); hb->add_child(play_bw); - stop = memnew(ToolButton); + stop = memnew(Button); + stop->set_flat(true); stop->set_toggle_mode(true); hb->add_child(stop); stop->set_tooltip(TTR("Stop animation playback. (S)")); - play = memnew(ToolButton); + play = memnew(Button); + play->set_flat(true); play->set_tooltip(TTR("Play selected animation from start. (Shift+D)")); hb->add_child(play); - play_from = memnew(ToolButton); + play_from = memnew(Button); + play_from->set_flat(true); play_from->set_tooltip(TTR("Play selected animation from current pos. (D)")); hb->add_child(play_from); @@ -1572,7 +1576,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay animation->set_tooltip(TTR("Display list of animations in player.")); animation->set_clip_text(true); - autoplay = memnew(ToolButton); + autoplay = memnew(Button); + autoplay->set_flat(true); hb->add_child(autoplay); autoplay->set_tooltip(TTR("Autoplay on Load")); @@ -1584,7 +1589,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay hb->add_child(memnew(VSeparator)); - onion_toggle = memnew(ToolButton); + onion_toggle = memnew(Button); + onion_toggle->set_flat(true); onion_toggle->set_toggle_mode(true); onion_toggle->set_tooltip(TTR("Enable Onion Skinning")); onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu), varray(ONION_SKINNING_ENABLE)); @@ -1609,7 +1615,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay hb->add_child(memnew(VSeparator)); - pin = memnew(ToolButton); + pin = memnew(Button); + pin->set_flat(true); pin->set_toggle_mode(true); pin->set_tooltip(TTR("Pin AnimationPlayer")); hb->add_child(pin); diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 18f2d3b25e..fe96deecf2 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -96,9 +96,9 @@ class AnimationPlayerEditor : public VBoxContainer { Button *autoplay; MenuButton *tool_anim; - ToolButton *onion_toggle; + Button *onion_toggle; MenuButton *onion_skinning; - ToolButton *pin; + Button *pin; SpinBox *frame; LineEdit *scale; LineEdit *name; diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index a435b1c482..0970608853 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -1208,7 +1208,8 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { Ref<ButtonGroup> bg; bg.instance(); - tool_select = memnew(ToolButton); + tool_select = memnew(Button); + tool_select->set_flat(true); top_hb->add_child(tool_select); tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); @@ -1216,14 +1217,16 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_select->set_tooltip(TTR("Select and move nodes.\nRMB to add new nodes.\nShift+LMB to create connections.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); - tool_create = memnew(ToolButton); + tool_create = memnew(Button); + tool_create->set_flat(true); top_hb->add_child(tool_create); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); tool_create->set_tooltip(TTR("Create new nodes.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), varray(), CONNECT_DEFERRED); - tool_connect = memnew(ToolButton); + tool_connect = memnew(Button); + tool_connect->set_flat(true); top_hb->add_child(tool_connect); tool_connect->set_toggle_mode(true); tool_connect->set_button_group(bg); @@ -1233,7 +1236,8 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_erase_hb = memnew(HBoxContainer); top_hb->add_child(tool_erase_hb); tool_erase_hb->add_child(memnew(VSeparator)); - tool_erase = memnew(ToolButton); + tool_erase = memnew(Button); + tool_erase->set_flat(true); tool_erase->set_tooltip(TTR("Remove selected node or transition.")); tool_erase_hb->add_child(tool_erase); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected)); @@ -1241,13 +1245,15 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_erase_hb->add_child(memnew(VSeparator)); - tool_autoplay = memnew(ToolButton); + tool_autoplay = memnew(Button); + tool_autoplay->set_flat(true); tool_autoplay->set_tooltip(TTR("Toggle autoplay this animation on start, restart or seek to zero.")); tool_erase_hb->add_child(tool_autoplay); tool_autoplay->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_autoplay_selected)); tool_autoplay->set_disabled(true); - tool_end = memnew(ToolButton); + tool_end = memnew(Button); + tool_end->set_flat(true); tool_end->set_tooltip(TTR("Set the end animation. This is useful for sub-transitions.")); tool_erase_hb->add_child(tool_end); tool_end->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_end_selected)); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index 022c32ef48..c4caf2e52b 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -46,16 +46,16 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeStateMachine> state_machine; - ToolButton *tool_select; - ToolButton *tool_create; - ToolButton *tool_connect; + Button *tool_select; + Button *tool_create; + Button *tool_connect; Popup *name_edit_popup; LineEdit *name_edit; HBoxContainer *tool_erase_hb; - ToolButton *tool_erase; - ToolButton *tool_autoplay; - ToolButton *tool_end; + Button *tool_erase; + Button *tool_autoplay; + Button *tool_end; OptionButton *transition_mode; OptionButton *play_mode; diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 3b7a9320f0..b0f65af245 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -220,12 +220,14 @@ AudioStreamEditor::AudioStreamEditor() { hbox->add_theme_constant_override("separation", 0); vbox->add_child(hbox); - _play_button = memnew(ToolButton); + _play_button = memnew(Button); + _play_button->set_flat(true); hbox->add_child(_play_button); _play_button->set_focus_mode(Control::FOCUS_NONE); _play_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_play)); - _stop_button = memnew(ToolButton); + _stop_button = memnew(Button); + _stop_button->set_flat(true); hbox->add_child(_stop_button); _stop_button->set_focus_mode(Control::FOCUS_NONE); _stop_button->connect("pressed", callable_mp(this, &AudioStreamEditor::_stop)); diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h index dd7caaa15e..de176aab49 100644 --- a/editor/plugins/audio_stream_editor_plugin.h +++ b/editor/plugins/audio_stream_editor_plugin.h @@ -47,8 +47,8 @@ class AudioStreamEditor : public ColorRect { Label *_current_label; Label *_duration_label; - ToolButton *_play_button; - ToolButton *_stop_button; + Button *_play_button; + Button *_stop_button; float _current; bool _dragging; diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp index 8fbe1646f7..ee9feb7f74 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ b/editor/plugins/baked_lightmap_editor_plugin.cpp @@ -117,7 +117,8 @@ void BakedLightmapEditorPlugin::_bind_methods() { BakedLightmapEditorPlugin::BakedLightmapEditorPlugin(EditorNode *p_node) { editor = p_node; - bake = memnew(ToolButton); + bake = memnew(Button); + bake->set_flat(true); bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake Lightmaps")); bake->hide(); diff --git a/editor/plugins/baked_lightmap_editor_plugin.h b/editor/plugins/baked_lightmap_editor_plugin.h index 67fb368a86..54eb0f71ec 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.h +++ b/editor/plugins/baked_lightmap_editor_plugin.h @@ -41,7 +41,7 @@ class BakedLightmapEditorPlugin : public EditorPlugin { BakedLightmap *lightmap; - ToolButton *bake; + Button *bake; EditorNode *editor; EditorFileDialog *file_dialog; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 2f7080b1a5..bf698a5ceb 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1207,7 +1207,26 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bool p_already_accepted) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid() && !p_already_accepted) { - bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control(); + const bool pan_on_scroll = bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan")) && !b->get_control(); + + if (pan_on_scroll) { + // Perform horizontal scrolling first so we can check for Shift being held. + if (b->is_pressed() && + (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_UP))) { + // Pan left + view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + update_viewport(); + return true; + } + + if (b->is_pressed() && + (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_shift() && b->get_button_index() == BUTTON_WHEEL_DOWN))) { + // Pan right + view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); + update_viewport(); + return true; + } + } if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) { // Scroll or pan down @@ -1239,24 +1258,6 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo return true; } - if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_LEFT) { - // Pan left - if (pan_on_scroll) { - view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - return true; - } - } - - if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_RIGHT) { - // Pan right - if (pan_on_scroll) { - view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor(); - update_viewport(); - return true; - } - } - if (!panning) { if (b->is_pressed() && (b->get_button_index() == BUTTON_MIDDLE || @@ -4447,7 +4448,7 @@ void CanvasItemEditor::_button_override_camera(bool p_pressed) { } void CanvasItemEditor::_button_tool_select(int p_index) { - ToolButton *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button }; + Button *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button }; for (int i = 0; i < TOOL_MAX; i++) { tb[i]->set_pressed(i == p_index); } @@ -5577,13 +5578,15 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { viewport->add_child(controls_vb); - zoom_minus = memnew(ToolButton); + zoom_minus = memnew(Button); + zoom_minus->set_flat(true); zoom_hb->add_child(zoom_minus); zoom_minus->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_minus)); zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS)); zoom_minus->set_focus_mode(FOCUS_NONE); - zoom_reset = memnew(ToolButton); + zoom_reset = memnew(Button); + zoom_reset->set_flat(true); zoom_hb->add_child(zoom_reset); zoom_reset->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_reset)); zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0)); @@ -5592,7 +5595,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { // Prevent the button's size from changing when the text size changes zoom_reset->set_custom_minimum_size(Size2(75 * EDSCALE, 0)); - zoom_plus = memnew(ToolButton); + zoom_plus = memnew(Button); + zoom_plus->set_flat(true); zoom_hb->add_child(zoom_plus); zoom_plus->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_plus)); zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KEY_MASK_CMD | KEY_EQUAL)); // Usually direct access key for PLUS @@ -5600,7 +5604,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { updating_scroll = false; - select_button = memnew(ToolButton); + select_button = memnew(Button); + select_button->set_flat(true); hb->add_child(select_button); select_button->set_toggle_mode(true); select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SELECT)); @@ -5610,21 +5615,24 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - move_button = memnew(ToolButton); + move_button = memnew(Button); + move_button->set_flat(true); hb->add_child(move_button); move_button->set_toggle_mode(true); move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), KEY_W)); move_button->set_tooltip(TTR("Move Mode")); - rotate_button = memnew(ToolButton); + rotate_button = memnew(Button); + rotate_button->set_flat(true); hb->add_child(rotate_button); rotate_button->set_toggle_mode(true); rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_ROTATE)); rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), KEY_E)); rotate_button->set_tooltip(TTR("Rotate Mode")); - scale_button = memnew(ToolButton); + scale_button = memnew(Button); + scale_button->set_flat(true); hb->add_child(scale_button); scale_button->set_toggle_mode(true); scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_SCALE)); @@ -5633,26 +5641,30 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - list_select_button = memnew(ToolButton); + list_select_button = memnew(Button); + list_select_button->set_flat(true); hb->add_child(list_select_button); list_select_button->set_toggle_mode(true); list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_LIST_SELECT)); list_select_button->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); - pivot_button = memnew(ToolButton); + pivot_button = memnew(Button); + pivot_button->set_flat(true); hb->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_EDIT_PIVOT)); pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); - pan_button = memnew(ToolButton); + pan_button = memnew(Button); + pan_button->set_flat(true); hb->add_child(pan_button); pan_button->set_toggle_mode(true); pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_PAN)); pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), KEY_G)); pan_button->set_tooltip(TTR("Pan Mode")); - ruler_button = memnew(ToolButton); + ruler_button = memnew(Button); + ruler_button->set_flat(true); hb->add_child(ruler_button); ruler_button->set_toggle_mode(true); ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select), make_binds(TOOL_RULER)); @@ -5661,14 +5673,16 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - smart_snap_button = memnew(ToolButton); + smart_snap_button = memnew(Button); + smart_snap_button->set_flat(true); hb->add_child(smart_snap_button); smart_snap_button->set_toggle_mode(true); smart_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_smart_snap)); smart_snap_button->set_tooltip(TTR("Toggle smart snapping.")); smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KEY_MASK_SHIFT | KEY_S)); - grid_snap_button = memnew(ToolButton); + grid_snap_button = memnew(Button); + grid_snap_button->set_flat(true); hb->add_child(grid_snap_button); grid_snap_button->set_toggle_mode(true); grid_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_grid_snap)); @@ -5707,23 +5721,27 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - lock_button = memnew(ToolButton); + lock_button = memnew(Button); + lock_button->set_flat(true); hb->add_child(lock_button); lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(LOCK_SELECTED)); lock_button->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); - unlock_button = memnew(ToolButton); + unlock_button = memnew(Button); + unlock_button->set_flat(true); hb->add_child(unlock_button); unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNLOCK_SELECTED)); unlock_button->set_tooltip(TTR("Unlock the selected object (can be moved).")); - group_button = memnew(ToolButton); + group_button = memnew(Button); + group_button->set_flat(true); hb->add_child(group_button); group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(GROUP_SELECTED)); group_button->set_tooltip(TTR("Makes sure the object's children are not selectable.")); - ungroup_button = memnew(ToolButton); + ungroup_button = memnew(Button); + ungroup_button->set_flat(true); hb->add_child(ungroup_button); ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(UNGROUP_SELECTED)); ungroup_button->set_tooltip(TTR("Restores the object's children's ability to be selected.")); @@ -5748,7 +5766,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); - override_camera_button = memnew(ToolButton); + override_camera_button = memnew(Button); + override_camera_button->set_flat(true); hb->add_child(override_camera_button); override_camera_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_override_camera)); override_camera_button->set_toggle_mode(true); @@ -5795,7 +5814,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { anchors_popup->set_name("Anchors"); anchors_popup->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); - anchor_mode_button = memnew(ToolButton); + anchor_mode_button = memnew(Button); + anchor_mode_button->set_flat(true); hb->add_child(anchor_mode_button); anchor_mode_button->set_toggle_mode(true); anchor_mode_button->hide(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 765d5f81d0..c5d74c6fc9 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -228,9 +228,9 @@ private: VScrollBar *v_scroll; HBoxContainer *hb; - ToolButton *zoom_minus; - ToolButton *zoom_reset; - ToolButton *zoom_plus; + Button *zoom_minus; + Button *zoom_reset; + Button *zoom_plus; Map<Control *, Timer *> popup_temporarily_timers; @@ -336,31 +336,31 @@ private: }; List<PoseClipboard> pose_clipboard; - ToolButton *select_button; + Button *select_button; - ToolButton *move_button; - ToolButton *scale_button; - ToolButton *rotate_button; + Button *move_button; + Button *scale_button; + Button *rotate_button; - ToolButton *list_select_button; - ToolButton *pivot_button; - ToolButton *pan_button; + Button *list_select_button; + Button *pivot_button; + Button *pan_button; - ToolButton *ruler_button; + Button *ruler_button; - ToolButton *smart_snap_button; - ToolButton *grid_snap_button; + Button *smart_snap_button; + Button *grid_snap_button; MenuButton *snap_config_menu; PopupMenu *smartsnap_config_popup; - ToolButton *lock_button; - ToolButton *unlock_button; + Button *lock_button; + Button *unlock_button; - ToolButton *group_button; - ToolButton *ungroup_button; + Button *group_button; + Button *ungroup_button; MenuButton *skeleton_menu; - ToolButton *override_camera_button; + Button *override_camera_button; MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; @@ -369,7 +369,7 @@ private: PopupMenu *anchors_and_margins_popup; PopupMenu *anchors_popup; - ToolButton *anchor_mode_button; + Button *anchor_mode_button; Button *key_loc_button; Button *key_rot_button; diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index d9d9cf6a87..6eb17685f6 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -501,12 +501,14 @@ CollisionPolygon3DEditor::CollisionPolygon3DEditor(EditorNode *p_editor) { undo_redo = EditorNode::get_undo_redo(); add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); + button_create = memnew(Button); + button_create->set_flat(true); add_child(button_create); button_create->connect("pressed", callable_mp(this, &CollisionPolygon3DEditor::_menu_option), varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_edit = memnew(ToolButton); + button_edit = memnew(Button); + button_edit->set_flat(true); add_child(button_edit); button_edit->connect("pressed", callable_mp(this, &CollisionPolygon3DEditor::_menu_option), varray(MODE_EDIT)); button_edit->set_toggle_mode(true); diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.h b/editor/plugins/collision_polygon_3d_editor_plugin.h index 5215cbb678..05b8df520c 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.h +++ b/editor/plugins/collision_polygon_3d_editor_plugin.h @@ -36,7 +36,6 @@ #include "scene/3d/collision_polygon_3d.h" #include "scene/3d/immediate_geometry_3d.h" #include "scene/3d/mesh_instance_3d.h" -#include "scene/gui/tool_button.h" class CanvasItemEditor; @@ -53,8 +52,8 @@ class CollisionPolygon3DEditor : public HBoxContainer { Mode mode; - ToolButton *button_create; - ToolButton *button_edit; + Button *button_create; + Button *button_edit; Ref<StandardMaterial3D> line_material; Ref<StandardMaterial3D> handle_material; diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 9cb167b41c..2889cb50a0 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -127,7 +127,8 @@ Ref<Texture2D> EditorTexturePreviewPlugin::generate(const RES &p_from, const Siz if (new_size.y > p_size.y) { new_size = Vector2(new_size.x * p_size.y / new_size.y, p_size.y); } - img->resize(new_size.x, new_size.y, Image::INTERPOLATE_CUBIC); + Vector2i new_size_i(MAX(1, (int)new_size.x), MAX(1, (int)new_size.y)); + img->resize(new_size_i.x, new_size_i.y, Image::INTERPOLATE_CUBIC); post_process_preview(img); diff --git a/editor/plugins/gi_probe_editor_plugin.cpp b/editor/plugins/gi_probe_editor_plugin.cpp index 94f771e643..1b48e17772 100644 --- a/editor/plugins/gi_probe_editor_plugin.cpp +++ b/editor/plugins/gi_probe_editor_plugin.cpp @@ -144,7 +144,8 @@ GIProbeEditorPlugin::GIProbeEditorPlugin(EditorNode *p_node) { bake_hb = memnew(HBoxContainer); bake_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); bake_hb->hide(); - bake = memnew(ToolButton); + bake = memnew(Button); + bake->set_flat(true); bake->set_icon(editor->get_gui_base()->get_theme_icon("Bake", "EditorIcons")); bake->set_text(TTR("Bake GI Probe")); bake->connect("pressed", callable_mp(this, &GIProbeEditorPlugin::_bake)); diff --git a/editor/plugins/gi_probe_editor_plugin.h b/editor/plugins/gi_probe_editor_plugin.h index 508c3d825b..e55f287908 100644 --- a/editor/plugins/gi_probe_editor_plugin.h +++ b/editor/plugins/gi_probe_editor_plugin.h @@ -43,7 +43,7 @@ class GIProbeEditorPlugin : public EditorPlugin { HBoxContainer *bake_hb; Label *bake_info; - ToolButton *bake; + Button *bake; EditorNode *editor; EditorFileDialog *probe_file; diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index 7402baad57..b4dcbdfe20 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -325,7 +325,8 @@ ItemListEditor::ItemListEditor() { selected_idx = -1; item_list = nullptr; - toolbar_button = memnew(ToolButton); + toolbar_button = memnew(Button); + toolbar_button->set_flat(true); toolbar_button->set_text(TTR("Items")); add_child(toolbar_button); toolbar_button->connect("pressed", callable_mp(this, &ItemListEditor::_edit_items)); diff --git a/editor/plugins/item_list_editor_plugin.h b/editor/plugins/item_list_editor_plugin.h index 61dd617e3b..d89631633c 100644 --- a/editor/plugins/item_list_editor_plugin.h +++ b/editor/plugins/item_list_editor_plugin.h @@ -198,7 +198,7 @@ class ItemListEditor : public HBoxContainer { Node *item_list; - ToolButton *toolbar_button; + Button *toolbar_button; AcceptDialog *dialog; EditorInspector *property_editor; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 796dd3f8b2..961ae10f46 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2106,12 +2106,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons cursor.x_rot += p_relative.y * radians_per_pixel; } cursor.y_rot += p_relative.x * radians_per_pixel; - if (cursor.x_rot > Math_PI / 2.0) { - cursor.x_rot = Math_PI / 2.0; - } - if (cursor.x_rot < -Math_PI / 2.0) { - cursor.x_rot = -Math_PI / 2.0; - } + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); name = ""; _update_name(); } @@ -2139,12 +2134,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const cursor.x_rot += p_relative.y * radians_per_pixel; } cursor.y_rot += p_relative.x * radians_per_pixel; - if (cursor.x_rot > Math_PI / 2.0) { - cursor.x_rot = Math_PI / 2.0; - } - if (cursor.x_rot < -Math_PI / 2.0) { - cursor.x_rot = -Math_PI / 2.0; - } + cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57); // Look is like the opposite of Orbit: the focus point rotates around the camera Transform camera_transform = to_camera_transform(cursor); @@ -2174,6 +2164,8 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) { freelook_speed = base_speed * cursor.distance; } + previous_mouse_position = get_local_mouse_position(); + // Hide mouse like in an FPS (warping doesn't work) Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED); @@ -2183,6 +2175,11 @@ void Node3DEditorViewport::set_freelook_active(bool active_now) { // Restore mouse Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + + // Restore the previous mouse position when leaving freelook mode. + // This is done because leaving `Input.MOUSE_MODE_CAPTURED` will center the cursor + // due to OS limitations. + warp_mouse(previous_mouse_position); } freelook_active = active_now; @@ -2341,13 +2338,6 @@ void Node3DEditorViewport::_notification(int p_what) { call_deferred("update_transform_gizmo_view"); } - if (p_what == NOTIFICATION_READY) { - // The crosshair icon doesn't depend on the editor theme. - crosshair->set_texture(get_theme_icon("Crosshair", "EditorIcons")); - // Set the anchors and margins after changing the icon to ensure it's centered correctly. - crosshair->set_anchors_and_margins_preset(PRESET_CENTER); - } - if (p_what == NOTIFICATION_PROCESS) { real_t delta = get_process_delta_time(); @@ -2473,10 +2463,6 @@ void Node3DEditorViewport::_notification(int p_what) { current_camera = camera; } - // Display the crosshair only while freelooking. Hide it otherwise, - // as the crosshair can be distracting. - crosshair->set_visible(freelook_active); - if (show_info) { String text; text += "X: " + rtos(current_camera->get_translation().x).pad_decimals(1) + "\n"; @@ -2583,14 +2569,14 @@ void Node3DEditorViewport::_notification(int p_what) { } } -static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture2D> icon) { +static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2D> icon, const Ref<Font> font, const String &text) { // Adjust bar size from control height - Vector2 surface_size = surface.get_size(); - real_t h = surface_size.y / 2.0; - real_t y = (surface_size.y - h) / 2.0; + const Vector2 surface_size = surface.get_size(); + const real_t h = surface_size.y / 2.0; + const real_t y = (surface_size.y - h) / 2.0; - Rect2 r(10, y, 6, h); - real_t sy = r.size.y * fill; + const Rect2 r(10 * EDSCALE, y, 6 * EDSCALE, h); + const real_t sy = r.size.y * fill; // Note: because this bar appears over the viewport, it has to stay readable for any background color // Draw both neutral dark and bright colors to account this @@ -2598,9 +2584,12 @@ static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture2D> ico surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); surface.draw_rect(r.grow(1), Color(0, 0, 0, 0.7), false, Math::round(EDSCALE)); - Vector2 icon_size = icon->get_size(); - Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2); + const Vector2 icon_size = icon->get_size(); + const Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2 * EDSCALE); surface.draw_texture(icon, icon_pos); + + // Draw text below the bar (for speed/zoom information). + surface.draw_string(font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), text); } void Node3DEditorViewport::_draw() { @@ -2697,7 +2686,14 @@ void Node3DEditorViewport::_draw() { logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); } - draw_indicator_bar(*surface, 1.0 - logscale_t, get_theme_icon("ViewportSpeed", "EditorIcons")); + // Display the freelook speed to help the user get a better sense of scale. + const int precision = freelook_speed < 1.0 ? 2 : 1; + draw_indicator_bar( + *surface, + 1.0 - logscale_t, + get_theme_icon("ViewportSpeed", "EditorIcons"), + get_theme_font("font", "Label"), + vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision))); } } else { @@ -2716,7 +2712,14 @@ void Node3DEditorViewport::_draw() { logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); } - draw_indicator_bar(*surface, logscale_t, get_theme_icon("ViewportZoom", "EditorIcons")); + // Display the zoom center distance to help the user get a better sense of scale. + const int precision = cursor.distance < 1.0 ? 2 : 1; + draw_indicator_bar( + *surface, + logscale_t, + get_theme_icon("ViewportZoom", "EditorIcons"), + get_theme_font("font", "Label"), + vformat("%s u", String::num(cursor.distance).pad_decimals(precision))); } } } @@ -3205,7 +3208,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() { Vector3 camz = -camera_xform.get_basis().get_axis(2).normalized(); Vector3 camy = -camera_xform.get_basis().get_axis(1).normalized(); Plane p(camera_xform.origin, camz); - float gizmo_d = Math::abs(p.distance_to(xform.origin)); + float gizmo_d = MAX(Math::abs(p.distance_to(xform.origin)), CMP_EPSILON); float d0 = camera->unproject_position(camera_xform.origin + camz * gizmo_d).y; float d1 = camera->unproject_position(camera_xform.origin + camz * gizmo_d + camy).y; float dd = Math::abs(d0 - d1); @@ -3849,10 +3852,6 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito camera->make_current(); surface->set_focus_mode(FOCUS_ALL); - crosshair = memnew(TextureRect); - crosshair->set_mouse_filter(MOUSE_FILTER_IGNORE); - surface->add_child(crosshair); - VBoxContainer *vbox = memnew(VBoxContainer); surface->add_child(vbox); vbox->set_position(Point2(10, 10) * EDSCALE); @@ -6039,7 +6038,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { button_binds.resize(1); String sct; - tool_button[TOOL_MODE_SELECT] = memnew(ToolButton); + tool_button[TOOL_MODE_SELECT] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_SELECT]); tool_button[TOOL_MODE_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_SELECT]->set_flat(true); @@ -6051,7 +6050,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_button[TOOL_MODE_MOVE] = memnew(ToolButton); + tool_button[TOOL_MODE_MOVE] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); tool_button[TOOL_MODE_MOVE]->set_toggle_mode(true); tool_button[TOOL_MODE_MOVE]->set_flat(true); @@ -6059,7 +6058,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_MOVE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_MOVE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_move", TTR("Move Mode"), KEY_W)); - tool_button[TOOL_MODE_ROTATE] = memnew(ToolButton); + tool_button[TOOL_MODE_ROTATE] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_ROTATE]); tool_button[TOOL_MODE_ROTATE]->set_toggle_mode(true); tool_button[TOOL_MODE_ROTATE]->set_flat(true); @@ -6067,7 +6066,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_ROTATE]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_ROTATE]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Rotate Mode"), KEY_E)); - tool_button[TOOL_MODE_SCALE] = memnew(ToolButton); + tool_button[TOOL_MODE_SCALE] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_SCALE]); tool_button[TOOL_MODE_SCALE]->set_toggle_mode(true); tool_button[TOOL_MODE_SCALE]->set_flat(true); @@ -6077,7 +6076,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_button[TOOL_MODE_LIST_SELECT] = memnew(ToolButton); + tool_button[TOOL_MODE_LIST_SELECT] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_MODE_LIST_SELECT]); tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); @@ -6085,25 +6084,25 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show a list of all objects at the position clicked\n(same as Alt+RMB in select mode).")); - tool_button[TOOL_LOCK_SELECTED] = memnew(ToolButton); + tool_button[TOOL_LOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_LOCK_SELECTED]); button_binds.write[0] = MENU_LOCK_SELECTED; tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock the selected object in place (can't be moved).")); - tool_button[TOOL_UNLOCK_SELECTED] = memnew(ToolButton); + tool_button[TOOL_UNLOCK_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNLOCK_SELECTED]); button_binds.write[0] = MENU_UNLOCK_SELECTED; tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock the selected object (can be moved).")); - tool_button[TOOL_GROUP_SELECTED] = memnew(ToolButton); + tool_button[TOOL_GROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_GROUP_SELECTED]); button_binds.write[0] = MENU_GROUP_SELECTED; tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Makes sure the object's children are not selectable.")); - tool_button[TOOL_UNGROUP_SELECTED] = memnew(ToolButton); + tool_button[TOOL_UNGROUP_SELECTED] = memnew(Button); hbc_menu->add_child(tool_button[TOOL_UNGROUP_SELECTED]); button_binds.write[0] = MENU_UNGROUP_SELECTED; tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); @@ -6111,7 +6110,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(ToolButton); + tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(Button); hbc_menu->add_child(tool_option_button[TOOL_OPT_LOCAL_COORDS]); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_toggle_mode(true); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_flat(true); @@ -6119,7 +6118,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { tool_option_button[TOOL_OPT_LOCAL_COORDS]->connect("toggled", callable_mp(this, &Node3DEditor::_menu_item_toggled), button_binds); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_shortcut(ED_SHORTCUT("spatial_editor/local_coords", TTR("Use Local Space"), KEY_T)); - tool_option_button[TOOL_OPT_USE_SNAP] = memnew(ToolButton); + tool_option_button[TOOL_OPT_USE_SNAP] = memnew(Button); hbc_menu->add_child(tool_option_button[TOOL_OPT_USE_SNAP]); tool_option_button[TOOL_OPT_USE_SNAP]->set_toggle_mode(true); tool_option_button[TOOL_OPT_USE_SNAP]->set_flat(true); @@ -6129,7 +6128,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(ToolButton); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(Button); hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true); tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 83173b5ad2..2fe1938f28 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -284,8 +284,8 @@ private: bool freelook_active; real_t freelook_speed; + Vector2 previous_mouse_position; - TextureRect *crosshair; Label *info_label; Label *cinema_label; Label *locked_label; diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index a3dab665b8..f79098ce5d 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -532,35 +532,40 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { sep = memnew(VSeparator); base_hb->add_child(sep); - curve_edit = memnew(ToolButton); + curve_edit = memnew(Button); + curve_edit->set_flat(true); curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT)); base_hb->add_child(curve_edit); - curve_edit_curve = memnew(ToolButton); + curve_edit_curve = memnew(Button); + curve_edit_curve->set_flat(true); curve_edit_curve->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCurve", "EditorIcons")); curve_edit_curve->set_toggle_mode(true); curve_edit_curve->set_focus_mode(Control::FOCUS_NONE); curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)")); curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_EDIT_CURVE)); base_hb->add_child(curve_edit_curve); - curve_create = memnew(ToolButton); + curve_create = memnew(Button); + curve_create->set_flat(true); curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)")); curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_CREATE)); base_hb->add_child(curve_create); - curve_del = memnew(ToolButton); + curve_del = memnew(Button); + curve_del->set_flat(true); curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected), varray(MODE_DELETE)); base_hb->add_child(curve_del); - curve_close = memnew(ToolButton); + curve_close = memnew(Button); + curve_close->set_flat(true); curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->set_focus_mode(Control::FOCUS_NONE); curve_close->set_tooltip(TTR("Close Curve")); diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index 390dfdfdf7..d0c02b28d4 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -34,7 +34,6 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" #include "scene/2d/path_2d.h" -#include "scene/gui/tool_button.h" class CanvasItemEditor; @@ -60,11 +59,11 @@ class Path2DEditor : public HBoxContainer { }; Mode mode; - ToolButton *curve_create; - ToolButton *curve_edit; - ToolButton *curve_edit_curve; - ToolButton *curve_del; - ToolButton *curve_close; + Button *curve_create; + Button *curve_edit; + Button *curve_edit_curve; + Button *curve_del; + Button *curve_close; MenuButton *handle_menu; bool mirror_handle_angle; diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 25cffa3d6c..f53130c24d 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -557,28 +557,32 @@ Path3DEditorPlugin::Path3DEditorPlugin(EditorNode *p_node) { sep = memnew(VSeparator); sep->hide(); Node3DEditor::get_singleton()->add_control_to_menu_panel(sep); - curve_edit = memnew(ToolButton); + curve_edit = memnew(Button); + curve_edit->set_flat(true); curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit); - curve_create = memnew(ToolButton); + curve_create = memnew(Button); + curve_create->set_flat(true); curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->hide(); curve_create->set_focus_mode(Control::FOCUS_NONE); curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_create); - curve_del = memnew(ToolButton); + curve_del = memnew(Button); + curve_del->set_flat(true); curve_del->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveDelete", "EditorIcons")); curve_del->set_toggle_mode(true); curve_del->hide(); curve_del->set_focus_mode(Control::FOCUS_NONE); curve_del->set_tooltip(TTR("Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_del); - curve_close = memnew(ToolButton); + curve_close = memnew(Button); + curve_close->set_flat(true); curve_close->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("CurveClose", "EditorIcons")); curve_close->hide(); curve_close->set_focus_mode(Control::FOCUS_NONE); diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index 8bec5df797..3a75717b73 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -68,10 +68,10 @@ class Path3DEditorPlugin : public EditorPlugin { GDCLASS(Path3DEditorPlugin, EditorPlugin); Separator *sep; - ToolButton *curve_create; - ToolButton *curve_edit; - ToolButton *curve_del; - ToolButton *curve_close; + Button *curve_create; + Button *curve_edit; + Button *curve_del; + Button *curve_close; MenuButton *handle_menu; EditorNode *editor; diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp index bcbf88e7dc..30bf827b3c 100644 --- a/editor/plugins/physical_bone_3d_editor_plugin.cpp +++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp @@ -55,7 +55,8 @@ PhysicalBone3DEditor::PhysicalBone3DEditor(EditorNode *p_editor) : spatial_editor_hb->add_child(memnew(VSeparator)); - button_transform_joint = memnew(ToolButton); + button_transform_joint = memnew(Button); + button_transform_joint->set_flat(true); spatial_editor_hb->add_child(button_transform_joint); button_transform_joint->set_text(TTR("Move Joint")); diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h index 79c7cc4bb1..8699176fe0 100644 --- a/editor/plugins/physical_bone_3d_editor_plugin.h +++ b/editor/plugins/physical_bone_3d_editor_plugin.h @@ -38,7 +38,7 @@ class PhysicalBone3DEditor : public Object { EditorNode *editor; HBoxContainer *spatial_editor_hb; - ToolButton *button_transform_joint; + Button *button_transform_joint; PhysicalBone3D *selected = nullptr; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 1f98c0139b..633863041f 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -485,7 +485,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else { Vector2 tuv = mtx.affine_inverse().xform(snap_point(Vector2(mb->get_position().x, mb->get_position().y))); - if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < 8) { + // Close the polygon if selected point is near start. Threshold for closing scaled by zoom level + if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < (8 / uv_draw_zoom)) { undo_redo->create_action(TTR("Create Polygon & UV")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); undo_redo->add_undo_method(node, "set_uv", uv_create_uv_prev); @@ -1214,7 +1215,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : use_snap = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_enabled", false); snap_show_grid = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "show_grid", false); - button_uv = memnew(ToolButton); + button_uv = memnew(Button); + button_uv->set_flat(true); add_child(button_uv); button_uv->set_tooltip(TTR("Open Polygon 2D UV editor.")); button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option), varray(MODE_EDIT_UV)); @@ -1231,16 +1233,16 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_group.instance(); - uv_edit_mode[0] = memnew(ToolButton); + uv_edit_mode[0] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[0]); uv_edit_mode[0]->set_toggle_mode(true); - uv_edit_mode[1] = memnew(ToolButton); + uv_edit_mode[1] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[1]); uv_edit_mode[1]->set_toggle_mode(true); - uv_edit_mode[2] = memnew(ToolButton); + uv_edit_mode[2] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[2]); uv_edit_mode[2]->set_toggle_mode(true); - uv_edit_mode[3] = memnew(ToolButton); + uv_edit_mode[3] = memnew(Button); uv_mode_hb->add_child(uv_edit_mode[3]); uv_edit_mode[3]->set_toggle_mode(true); @@ -1264,7 +1266,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_main_vb->add_child(uv_mode_hb); for (int i = 0; i < UV_MODE_MAX; i++) { - uv_button[i] = memnew(ToolButton); + uv_button[i] = memnew(Button); uv_button[i]->set_toggle_mode(true); uv_mode_hb->add_child(uv_button[i]); uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode), varray(i)); @@ -1334,7 +1336,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_mode_hb->add_child(memnew(VSeparator)); - b_snap_enable = memnew(ToolButton); + b_snap_enable = memnew(Button); + b_snap_enable->set_flat(true); uv_mode_hb->add_child(b_snap_enable); b_snap_enable->set_text(TTR("Snap")); b_snap_enable->set_focus_mode(FOCUS_NONE); @@ -1343,7 +1346,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : b_snap_enable->set_tooltip(TTR("Enable Snap")); b_snap_enable->connect("toggled", callable_mp(this, &Polygon2DEditor::_set_use_snap)); - b_snap_grid = memnew(ToolButton); + b_snap_grid = memnew(Button); + b_snap_grid->set_flat(true); uv_mode_hb->add_child(b_snap_grid); b_snap_grid->set_text(TTR("Grid")); b_snap_grid->set_focus_mode(FOCUS_NONE); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index b94ae53e2b..33ea7722ac 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -60,16 +60,16 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { UV_MODE_MAX }; - ToolButton *uv_edit_mode[4]; + Button *uv_edit_mode[4]; Ref<ButtonGroup> uv_edit_group; Polygon2D *node; UVMode uv_mode; AcceptDialog *uv_edit; - ToolButton *uv_button[UV_MODE_MAX]; - ToolButton *b_snap_enable; - ToolButton *b_snap_grid; + Button *uv_button[UV_MODE_MAX]; + Button *b_snap_enable; + Button *b_snap_grid; Panel *uv_edit_draw; HSlider *uv_zoom; SpinBox *uv_zoom_value; @@ -115,7 +115,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { AcceptDialog *error; - ToolButton *button_uv; + Button *button_uv; bool use_snap; bool snap_show_grid; diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 48a9febcf9..96079d5418 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -2988,7 +2988,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { filename->add_theme_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_theme_stylebox("normal", "LineEdit")); buttons_hbox->add_child(filename); - members_overview_alphabeta_sort_button = memnew(ToolButton); + members_overview_alphabeta_sort_button = memnew(Button); + members_overview_alphabeta_sort_button->set_flat(true); members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list.")); members_overview_alphabeta_sort_button->set_toggle_mode(true); members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically")); @@ -3049,7 +3050,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save", TTR("Save"), KEY_MASK_ALT | KEY_MASK_CMD | KEY_S), FILE_SAVE); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_as", TTR("Save As...")), FILE_SAVE_AS); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/save_all", TTR("Save All"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_S), FILE_SAVE_ALL); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/reload_script_soft", TTR("Soft Reload Script"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_R), FILE_TOOL_RELOAD_SOFT); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/copy_path", TTR("Copy Script Path")), FILE_COPY_PATH); @@ -3115,13 +3116,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_spacer(); - site_search = memnew(ToolButton); + site_search = memnew(Button); + site_search->set_flat(true); site_search->set_text(TTR("Online Docs")); site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_WEBSITE)); menu_hb->add_child(site_search); site_search->set_tooltip(TTR("Open Godot online documentation.")); - help_search = memnew(ToolButton); + help_search = memnew(Button); + help_search->set_flat(true); help_search->set_text(TTR("Search Help")); help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option), varray(SEARCH_HELP)); menu_hb->add_child(help_search); @@ -3129,13 +3132,15 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(memnew(VSeparator)); - script_back = memnew(ToolButton); + script_back = memnew(Button); + script_back->set_flat(true); script_back->connect("pressed", callable_mp(this, &ScriptEditor::_history_back)); menu_hb->add_child(script_back); script_back->set_disabled(true); script_back->set_tooltip(TTR("Go to previous edited document.")); - script_forward = memnew(ToolButton); + script_forward = memnew(Button); + script_forward->set_flat(true); script_forward->connect("pressed", callable_mp(this, &ScriptEditor::_history_forward)); menu_hb->add_child(script_forward); script_forward->set_disabled(true); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index f7352be7e8..8c4b7de27d 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -43,7 +43,6 @@ #include "scene/gui/split_container.h" #include "scene/gui/tab_container.h" #include "scene/gui/text_edit.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" #include "scene/main/timer.h" #include "scene/resources/text_file.h" @@ -211,7 +210,7 @@ class ScriptEditor : public PanelContainer { VBoxContainer *overview_vbox; HBoxContainer *buttons_hbox; Label *filename; - ToolButton *members_overview_alphabeta_sort_button; + Button *members_overview_alphabeta_sort_button; bool members_overview_enabled; ItemList *help_overview; bool help_overview_enabled; @@ -221,15 +220,15 @@ class ScriptEditor : public PanelContainer { AcceptDialog *error_dialog; ConfirmationDialog *erase_tab_confirm; ScriptCreateDialog *script_create_dialog; - ToolButton *scripts_visible; + Button *scripts_visible; String current_theme; TextureRect *script_icon; Label *script_name_label; - ToolButton *script_back; - ToolButton *script_forward; + Button *script_back; + Button *script_forward; FindInFilesDialog *find_in_files_dialog; FindInFilesPanel *find_in_files; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 4b79d8c344..1c9dadc0dd 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -383,10 +383,6 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) { warnings_panel->set_visible(p_show); } -void ScriptTextEditor::_error_pressed() { - code_editor->goto_error(); -} - void ScriptTextEditor::_warning_clicked(Variant p_line) { if (p_line.get_type() == Variant::INT) { code_editor->get_text_edit()->cursor_set_line(p_line.operator int64_t()); @@ -1759,7 +1755,6 @@ ScriptTextEditor::ScriptTextEditor() { warnings_panel->set_focus_mode(FOCUS_CLICK); warnings_panel->hide(); - code_editor->connect("error_pressed", callable_mp(this, &ScriptTextEditor::_error_pressed)); code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel)); warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked)); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index adcd0218bc..8fa380b64d 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -159,7 +159,6 @@ protected: void _load_theme_settings(); void _set_theme_for_script(); void _show_warnings_panel(bool p_show); - void _error_pressed(); void _warning_clicked(Variant p_line); void _notification(int p_what); diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 2586f17fe1..52da8dea19 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -62,125 +62,56 @@ void BoneTransformEditor::create_editors() { enabled_checkbox->set_visible(toggle_enabled); section->get_vbox()->add_child(enabled_checkbox); - Label *l1 = memnew(Label(TTR("Translation"))); - section->get_vbox()->add_child(l1); - - translation_grid = memnew(GridContainer()); - translation_grid->set_columns(TRANSLATION_COMPONENTS); - section->get_vbox()->add_child(translation_grid); - - Label *l2 = memnew(Label(TTR("Rotation Degrees"))); - section->get_vbox()->add_child(l2); - - rotation_grid = memnew(GridContainer()); - rotation_grid->set_columns(ROTATION_DEGREES_COMPONENTS); - section->get_vbox()->add_child(rotation_grid); - - Label *l3 = memnew(Label(TTR("Scale"))); - section->get_vbox()->add_child(l3); - - scale_grid = memnew(GridContainer()); - scale_grid->set_columns(SCALE_COMPONENTS); - section->get_vbox()->add_child(scale_grid); - - Label *l4 = memnew(Label(TTR("Transform"))); - section->get_vbox()->add_child(l4); - - transform_grid = memnew(GridContainer()); - transform_grid->set_columns(TRANSFORM_CONTROL_COMPONENTS); - section->get_vbox()->add_child(transform_grid); - - static const char *desc[TRANSFORM_COMPONENTS] = { "x", "y", "z", "x", "y", "z", "x", "y", "z", "x", "y", "z" }; - - for (int i = 0; i < TRANSFORM_CONTROL_COMPONENTS; ++i) { - translation_slider[i] = memnew(EditorSpinSlider()); - translation_slider[i]->set_label(desc[i]); - setup_spinner(translation_slider[i], false); - translation_grid->add_child(translation_slider[i]); - - rotation_slider[i] = memnew(EditorSpinSlider()); - rotation_slider[i]->set_label(desc[i]); - setup_spinner(rotation_slider[i], false); - rotation_grid->add_child(rotation_slider[i]); - - scale_slider[i] = memnew(EditorSpinSlider()); - scale_slider[i]->set_label(desc[i]); - setup_spinner(scale_slider[i], false); - scale_grid->add_child(scale_slider[i]); - } - - for (int i = 0; i < TRANSFORM_COMPONENTS; ++i) { - transform_slider[i] = memnew(EditorSpinSlider()); - transform_slider[i]->set_label(desc[i]); - setup_spinner(transform_slider[i], true); - transform_grid->add_child(transform_slider[i]); - } -} - -void BoneTransformEditor::setup_spinner(EditorSpinSlider *spinner, const bool is_transform_spinner) { - spinner->set_flat(true); - spinner->set_min(-10000); - spinner->set_max(10000); - spinner->set_step(0.001f); - spinner->set_hide_slider(true); - spinner->set_allow_greater(true); - spinner->set_allow_lesser(true); - spinner->set_h_size_flags(SIZE_EXPAND_FILL); - - spinner->connect_compat("value_changed", this, "_value_changed", varray(is_transform_spinner)); + // Translation property + translation_property = memnew(EditorPropertyVector3()); + translation_property->setup(-10000, 10000, 0.001f, true); + translation_property->set_label("Translation"); + translation_property->set_use_folding(true); + translation_property->set_read_only(false); + translation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3)); + section->get_vbox()->add_child(translation_property); + + // Rotation property + rotation_property = memnew(EditorPropertyVector3()); + rotation_property->setup(-10000, 10000, 0.001f, true); + rotation_property->set_label("Rotation Degrees"); + rotation_property->set_use_folding(true); + rotation_property->set_read_only(false); + rotation_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3)); + section->get_vbox()->add_child(rotation_property); + + // Scale property + scale_property = memnew(EditorPropertyVector3()); + scale_property->setup(-10000, 10000, 0.001f, true); + scale_property->set_label("Scale"); + scale_property->set_use_folding(true); + scale_property->set_read_only(false); + scale_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_vector3)); + section->get_vbox()->add_child(scale_property); + + // Transform/Matrix section + transform_section = memnew(EditorInspectorSection); + transform_section->setup("trf_properties_transform", "Matrix", this, section_color, true); + section->get_vbox()->add_child(transform_section); + + // Transform/Matrix property + transform_property = memnew(EditorPropertyTransform()); + transform_property->setup(-10000, 10000, 0.001f, true); + transform_property->set_label("Transform"); + transform_property->set_use_folding(true); + transform_property->set_read_only(false); + transform_property->connect("property_changed", callable_mp(this, &BoneTransformEditor::_value_changed_transform)); + transform_section->get_vbox()->add_child(transform_property); } void BoneTransformEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { create_editors(); - key_button->connect_compat("pressed", this, "_key_button_pressed"); - enabled_checkbox->connect_compat("toggled", this, "_checkbox_toggled"); + key_button->connect("pressed", callable_mp(this, &BoneTransformEditor::_key_button_pressed)); + enabled_checkbox->connect("toggled", callable_mp(this, &BoneTransformEditor::_checkbox_toggled)); [[fallthrough]]; } - case NOTIFICATION_THEME_CHANGED: { - const Color base = get_theme_color("accent_color", "Editor"); - const Color bg_color = get_theme_color("property_color", "Editor"); - const Color bg_lbl_color(bg_color.r, bg_color.g, bg_color.b, 0.5); - - for (int i = 0; i < TRANSLATION_COMPONENTS; i++) { - Color c = base; - c.set_hsv(float(i % TRANSLATION_COMPONENTS) / TRANSLATION_COMPONENTS + 0.05, c.get_s() * 0.75, c.get_v()); - if (!translation_slider[i]) { - continue; - } - translation_slider[i]->set_custom_label_color(true, c); - } - - for (int i = 0; i < ROTATION_DEGREES_COMPONENTS; i++) { - Color c = base; - c.set_hsv(float(i % ROTATION_DEGREES_COMPONENTS) / ROTATION_DEGREES_COMPONENTS + 0.05, c.get_s() * 0.75, c.get_v()); - if (!rotation_slider[i]) { - continue; - } - rotation_slider[i]->set_custom_label_color(true, c); - } - - for (int i = 0; i < SCALE_COMPONENTS; i++) { - Color c = base; - c.set_hsv(float(i % SCALE_COMPONENTS) / SCALE_COMPONENTS + 0.05, c.get_s() * 0.75, c.get_v()); - if (!scale_slider[i]) { - continue; - } - scale_slider[i]->set_custom_label_color(true, c); - } - - for (int i = 0; i < TRANSFORM_COMPONENTS; i++) { - Color c = base; - c.set_hsv(float(i % TRANSFORM_COMPONENTS) / TRANSFORM_COMPONENTS + 0.05, c.get_s() * 0.75, c.get_v()); - if (!transform_slider[i]) { - continue; - } - transform_slider[i]->set_custom_label_color(true, c); - } - - break; - } case NOTIFICATION_SORT_CHILDREN: { const Ref<Font> font = get_theme_font("font", "Tree"); @@ -189,8 +120,8 @@ void BoneTransformEditor::_notification(int p_what) { buffer.y += font->get_height(); buffer.y += get_theme_constant("vseparation", "Tree"); - const float vector_height = translation_grid->get_size().y; - const float transform_height = transform_grid->get_size().y; + const float vector_height = translation_property->get_size().y; + const float transform_height = transform_property->get_size().y; const float button_height = key_button->get_size().y; const float width = get_size().x - get_theme_constant("inspector_margin", "Editor"); @@ -202,10 +133,10 @@ void BoneTransformEditor::_notification(int p_what) { } if (section->get_vbox()->is_visible()) { - input_rects.push_back(Rect2(translation_grid->get_position() + buffer, Size2(width, vector_height))); - input_rects.push_back(Rect2(rotation_grid->get_position() + buffer, Size2(width, vector_height))); - input_rects.push_back(Rect2(scale_grid->get_position() + buffer, Size2(width, vector_height))); - input_rects.push_back(Rect2(transform_grid->get_position() + buffer, Size2(width, transform_height))); + input_rects.push_back(Rect2(translation_property->get_position() + buffer, Size2(width, vector_height))); + input_rects.push_back(Rect2(rotation_property->get_position() + buffer, Size2(width, vector_height))); + input_rects.push_back(Rect2(scale_property->get_position() + buffer, Size2(width, vector_height))); + input_rects.push_back(Rect2(transform_property->get_position() + buffer, Size2(width, transform_height))); } else { const int32_t start = input_rects.size(); const int32_t empty_input_rect_elements = 4; @@ -234,49 +165,53 @@ void BoneTransformEditor::_notification(int p_what) { } } -void BoneTransformEditor::_value_changed(const double p_value, const bool p_from_transform) { +void BoneTransformEditor::_value_changed(const double p_value) { if (updating) return; - if (property.get_slicec('/', 0) == "bones" && property.get_slicec('/', 2) == "custom_pose") { - const Transform tform = compute_transform(p_from_transform); + Transform tform = compute_transform_from_vector3s(); + _change_transform(tform); +} +void BoneTransformEditor::_value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean) { + if (updating) + return; + Transform tform = compute_transform_from_vector3s(); + _change_transform(tform); +} + +Transform BoneTransformEditor::compute_transform_from_vector3s() const { + // Convert rotation from degrees to radians. + Vector3 prop_rotation = rotation_property->get_vector(); + prop_rotation.x = Math::deg2rad(prop_rotation.x); + prop_rotation.y = Math::deg2rad(prop_rotation.y); + prop_rotation.z = Math::deg2rad(prop_rotation.z); + + return Transform( + Basis(prop_rotation, scale_property->get_vector()), + translation_property->get_vector()); +} + +void BoneTransformEditor::_value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean) { + if (updating) + return; + _change_transform(p_transform); +} + +void BoneTransformEditor::_change_transform(Transform p_new_transform) { + if (property.get_slicec('/', 0) == "bones" && property.get_slicec('/', 2) == "custom_pose") { undo_redo->create_action(TTR("Set Custom Bone Pose Transform"), UndoRedo::MERGE_ENDS); undo_redo->add_undo_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), skeleton->get_bone_custom_pose(property.get_slicec('/', 1).to_int())); - undo_redo->add_do_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), tform); + undo_redo->add_do_method(skeleton, "set_bone_custom_pose", property.get_slicec('/', 1).to_int(), p_new_transform); undo_redo->commit_action(); } else if (property.get_slicec('/', 0) == "bones") { - const Transform tform = compute_transform(p_from_transform); - undo_redo->create_action(TTR("Set Bone Transform"), UndoRedo::MERGE_ENDS); undo_redo->add_undo_property(skeleton, property, skeleton->get(property)); - undo_redo->add_do_property(skeleton, property, tform); + undo_redo->add_do_property(skeleton, property, p_new_transform); undo_redo->commit_action(); } } -Transform BoneTransformEditor::compute_transform(const bool p_from_transform) const { - // Last modified was a raw transform column... - if (p_from_transform) { - Transform tform; - - for (int i = 0; i < BASIS_COMPONENTS; ++i) { - tform.basis[i / BASIS_SPLIT_COMPONENTS][i % BASIS_SPLIT_COMPONENTS] = transform_slider[i]->get_value(); - } - - for (int i = 0; i < TRANSLATION_COMPONENTS; ++i) { - tform.origin[i] = transform_slider[i + BASIS_COMPONENTS]->get_value(); - } - - return tform; - } - - return Transform( - Basis(Vector3(Math::deg2rad(rotation_slider[0]->get_value()), Math::deg2rad(rotation_slider[1]->get_value()), Math::deg2rad(rotation_slider[2]->get_value())), - Vector3(scale_slider[0]->get_value(), scale_slider[1]->get_value(), scale_slider[2]->get_value())), - Vector3(translation_slider[0]->get_value(), translation_slider[1]->get_value(), translation_slider[2]->get_value())); -} - void BoneTransformEditor::update_enabled_checkbox() { if (enabled_checkbox) { const String path = "bones/" + property.get_slicec('/', 1) + "/enabled"; @@ -285,12 +220,6 @@ void BoneTransformEditor::update_enabled_checkbox() { } } -void BoneTransformEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_value_changed", "value"), &BoneTransformEditor::_value_changed); - ClassDB::bind_method(D_METHOD("_key_button_pressed"), &BoneTransformEditor::_key_button_pressed); - ClassDB::bind_method(D_METHOD("_checkbox_toggled", "toggled"), &BoneTransformEditor::_checkbox_toggled); -} - void BoneTransformEditor::_update_properties() { if (updating) return; @@ -318,47 +247,22 @@ void BoneTransformEditor::_update_custom_pose_properties() { } void BoneTransformEditor::_update_transform_properties(Transform tform) { - Quat rot = tform.get_basis(); - Vector3 rot_rad = rot.get_euler(); - Vector3 rot_degrees = Vector3(Math::rad2deg(rot_rad.x), Math::rad2deg(rot_rad.y), Math::rad2deg(rot_rad.z)); - Vector3 tr = tform.get_origin(); + Basis rotation_basis = tform.get_basis(); + Vector3 rotation_radians = rotation_basis.get_rotation_euler(); + Vector3 rotation_degrees = Vector3(Math::rad2deg(rotation_radians.x), Math::rad2deg(rotation_radians.y), Math::rad2deg(rotation_radians.z)); + Vector3 translation = tform.get_origin(); Vector3 scale = tform.basis.get_scale(); - for (int i = 0; i < TRANSLATION_COMPONENTS; i++) { - translation_slider[i]->set_value(tr[i]); - } - - for (int i = 0; i < ROTATION_DEGREES_COMPONENTS; i++) { - rotation_slider[i]->set_value(rot_degrees[i]); - } - - for (int i = 0; i < SCALE_COMPONENTS; i++) { - scale_slider[i]->set_value(scale[i]); - } - - transform_slider[0]->set_value(tform.get_basis()[Vector3::AXIS_X].x); - transform_slider[1]->set_value(tform.get_basis()[Vector3::AXIS_X].y); - transform_slider[2]->set_value(tform.get_basis()[Vector3::AXIS_X].z); - transform_slider[3]->set_value(tform.get_basis()[Vector3::AXIS_Y].x); - transform_slider[4]->set_value(tform.get_basis()[Vector3::AXIS_Y].y); - transform_slider[5]->set_value(tform.get_basis()[Vector3::AXIS_Y].z); - transform_slider[6]->set_value(tform.get_basis()[Vector3::AXIS_Z].x); - transform_slider[7]->set_value(tform.get_basis()[Vector3::AXIS_Z].y); - transform_slider[8]->set_value(tform.get_basis()[Vector3::AXIS_Z].z); - - for (int i = 0; i < TRANSLATION_COMPONENTS; i++) { - transform_slider[BASIS_COMPONENTS + i]->set_value(tform.get_origin()[i]); - } + translation_property->update_using_vector(translation); + rotation_property->update_using_vector(rotation_degrees); + scale_property->update_using_vector(scale); + transform_property->update_using_transform(tform); update_enabled_checkbox(); updating = false; } BoneTransformEditor::BoneTransformEditor(Skeleton3D *p_skeleton) : - translation_slider(), - rotation_slider(), - scale_slider(), - transform_slider(), skeleton(p_skeleton), key_button(nullptr), enabled_checkbox(nullptr), @@ -397,7 +301,7 @@ void BoneTransformEditor::_key_button_pressed() { return; // Need to normalize the basis before you key it - Transform tform = compute_transform(true); + Transform tform = compute_transform_from_vector3s(); tform.orthonormalize(); AnimationPlayerEditor::singleton->get_track_editor()->insert_transform_key(skeleton, name, tform); } @@ -627,8 +531,7 @@ void Skeleton3DEditor::update_joint_tree() { items.insert(-1, root); const Vector<int> &joint_porder = skeleton->get_bone_process_orders(); - - Ref<Texture> bone_icon = get_theme_icon("Skeleton3D", "EditorIcons"); + Ref<Texture> bone_icon = get_theme_icon("BoneAttachment3D", "EditorIcons"); for (int i = 0; i < joint_porder.size(); ++i) { const int b_idx = joint_porder[i]; @@ -714,11 +617,11 @@ void Skeleton3DEditor::_notification(int p_what) { update_joint_tree(); update_editors(); - get_tree()->connect_compat("node_removed", this, "_node_removed", Vector<Variant>(), Object::CONNECT_ONESHOT); - joint_tree->connect_compat("item_selected", this, "_joint_tree_selection_changed"); - joint_tree->connect_compat("item_rmb_selected", this, "_joint_tree_rmb_select"); + get_tree()->connect("node_removed", callable_mp(this, &Skeleton3DEditor::_node_removed), Vector<Variant>(), Object::CONNECT_ONESHOT); + joint_tree->connect("item_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_selection_changed)); + joint_tree->connect("item_rmb_selected", callable_mp(this, &Skeleton3DEditor::_joint_tree_rmb_select)); #ifdef TOOLS_ENABLED - skeleton->connect_compat("pose_updated", this, "_update_properties"); + skeleton->connect("pose_updated", callable_mp(this, &Skeleton3DEditor::_update_properties)); #endif // TOOLS_ENABLED break; diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h index 8b0639ed92..a5b8ce80a9 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.h +++ b/editor/plugins/skeleton_3d_editor_plugin.h @@ -41,30 +41,19 @@ class PhysicalBone3D; class Skeleton3DEditorPlugin; class Button; class CheckBox; +class EditorPropertyTransform; +class EditorPropertyVector3; class BoneTransformEditor : public VBoxContainer { GDCLASS(BoneTransformEditor, VBoxContainer); - static const int32_t TRANSLATION_COMPONENTS = 3; - static const int32_t ROTATION_DEGREES_COMPONENTS = 3; - static const int32_t SCALE_COMPONENTS = 3; - static const int32_t BASIS_COMPONENTS = 9; - static const int32_t BASIS_SPLIT_COMPONENTS = 3; - static const int32_t TRANSFORM_COMPONENTS = 12; - static const int32_t TRANSFORM_SPLIT_COMPONENTS = 3; - static const int32_t TRANSFORM_CONTROL_COMPONENTS = 3; - EditorInspectorSection *section; - GridContainer *translation_grid; - GridContainer *rotation_grid; - GridContainer *scale_grid; - GridContainer *transform_grid; - - EditorSpinSlider *translation_slider[TRANSLATION_COMPONENTS]; - EditorSpinSlider *rotation_slider[ROTATION_DEGREES_COMPONENTS]; - EditorSpinSlider *scale_slider[SCALE_COMPONENTS]; - EditorSpinSlider *transform_slider[TRANSFORM_COMPONENTS]; + EditorPropertyVector3 *translation_property; + EditorPropertyVector3 *rotation_property; + EditorPropertyVector3 *scale_property; + EditorInspectorSection *transform_section; + EditorPropertyTransform *transform_property; Rect2 background_rects[5]; @@ -83,17 +72,22 @@ class BoneTransformEditor : public VBoxContainer { String label; void create_editors(); - void setup_spinner(EditorSpinSlider *spinner, const bool is_transform_spinner); - void _value_changed(const double p_value, const bool p_from_transform); - - Transform compute_transform(const bool p_from_transform) const; + // Called when one of the EditorSpinSliders are changed. + void _value_changed(const double p_value); + // Called when the one of the EditorPropertyVector3 are updated. + void _value_changed_vector3(const String p_property_name, const Vector3 p_vector, const StringName p_edited_property_name, const bool p_boolean); + // Called when the transform_property is updated. + void _value_changed_transform(const String p_property_name, const Transform p_transform, const StringName p_edited_property_name, const bool p_boolean); + // Changes the transform to the given transform and updates the UI accordingly. + void _change_transform(Transform p_new_transform); + // Creates a Transform using the EditorPropertyVector3 properties. + Transform compute_transform_from_vector3s() const; void update_enabled_checkbox(); protected: void _notification(int p_what); - static void _bind_methods(); public: BoneTransformEditor(Skeleton3D *p_skeleton); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 859fec1628..7102faf58a 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -873,12 +873,14 @@ SpriteFramesEditor::SpriteFramesEditor() { HBoxContainer *hbc_animlist = memnew(HBoxContainer); sub_vb->add_child(hbc_animlist); - new_anim = memnew(ToolButton); + new_anim = memnew(Button); + new_anim->set_flat(true); new_anim->set_tooltip(TTR("New Animation")); hbc_animlist->add_child(new_anim); new_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_add)); - remove_anim = memnew(ToolButton); + remove_anim = memnew(Button); + remove_anim->set_flat(true); remove_anim->set_tooltip(TTR("Remove Animation")); hbc_animlist->add_child(remove_anim); remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove)); @@ -913,45 +915,54 @@ SpriteFramesEditor::SpriteFramesEditor() { HBoxContainer *hbc = memnew(HBoxContainer); sub_vb->add_child(hbc); - load = memnew(ToolButton); + load = memnew(Button); + load->set_flat(true); load->set_tooltip(TTR("Add a Texture from File")); hbc->add_child(load); - load_sheet = memnew(ToolButton); + load_sheet = memnew(Button); + load_sheet->set_flat(true); load_sheet->set_tooltip(TTR("Add Frames from a Sprite Sheet")); hbc->add_child(load_sheet); hbc->add_child(memnew(VSeparator)); - copy = memnew(ToolButton); + copy = memnew(Button); + copy->set_flat(true); copy->set_tooltip(TTR("Copy")); hbc->add_child(copy); - paste = memnew(ToolButton); + paste = memnew(Button); + paste->set_flat(true); paste->set_tooltip(TTR("Paste")); hbc->add_child(paste); hbc->add_child(memnew(VSeparator)); - empty = memnew(ToolButton); + empty = memnew(Button); + empty->set_flat(true); empty->set_tooltip(TTR("Insert Empty (Before)")); hbc->add_child(empty); - empty2 = memnew(ToolButton); + empty2 = memnew(Button); + empty2->set_flat(true); empty2->set_tooltip(TTR("Insert Empty (After)")); hbc->add_child(empty2); hbc->add_child(memnew(VSeparator)); - move_up = memnew(ToolButton); + move_up = memnew(Button); + move_up->set_flat(true); move_up->set_tooltip(TTR("Move (Before)")); hbc->add_child(move_up); - move_down = memnew(ToolButton); + move_down = memnew(Button); + move_down->set_flat(true); move_down->set_tooltip(TTR("Move (After)")); hbc->add_child(move_down); - _delete = memnew(ToolButton); + _delete = memnew(Button); + _delete->set_flat(true); _delete->set_tooltip(TTR("Delete")); hbc->add_child(_delete); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 45646eb9e4..c050ae484b 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -43,22 +43,22 @@ class SpriteFramesEditor : public HSplitContainer { GDCLASS(SpriteFramesEditor, HSplitContainer); - ToolButton *load; - ToolButton *load_sheet; - ToolButton *_delete; - ToolButton *copy; - ToolButton *paste; - ToolButton *empty; - ToolButton *empty2; - ToolButton *move_up; - ToolButton *move_down; + Button *load; + Button *load_sheet; + Button *_delete; + Button *copy; + Button *paste; + Button *empty; + Button *empty2; + Button *move_up; + Button *move_down; ItemList *tree; bool loading_scene; int sel; HSplitContainer *split; - ToolButton *new_anim; - ToolButton *remove_anim; + Button *new_anim; + Button *remove_anim; Tree *animations; SpinBox *anim_speed; diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 9b8b111be5..3a92818779 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -1037,17 +1037,20 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { edit_draw->add_child(zoom_hb); zoom_hb->set_begin(Point2(5, 5)); - zoom_out = memnew(ToolButton); + zoom_out = memnew(Button); + zoom_out->set_flat(true); zoom_out->set_tooltip(TTR("Zoom Out")); zoom_out->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_out)); zoom_hb->add_child(zoom_out); - zoom_reset = memnew(ToolButton); + zoom_reset = memnew(Button); + zoom_reset->set_flat(true); zoom_reset->set_tooltip(TTR("Zoom Reset")); zoom_reset->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_reset)); zoom_hb->add_child(zoom_reset); - zoom_in = memnew(ToolButton); + zoom_in = memnew(Button); + zoom_in->set_flat(true); zoom_in->set_tooltip(TTR("Zoom In")); zoom_in->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_in)); zoom_hb->add_child(zoom_in); diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index 93da23fd50..8991603c0f 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -56,9 +56,9 @@ class TextureRegionEditor : public VBoxContainer { friend class TextureRegionEditorPlugin; OptionButton *snap_mode_button; - ToolButton *zoom_in; - ToolButton *zoom_reset; - ToolButton *zoom_out; + Button *zoom_in; + Button *zoom_reset; + Button *zoom_out; HBoxContainer *hb_grid; //For showing/hiding the grid controls when changing the SnapMode SpinBox *sb_step_y; SpinBox *sb_step_x; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index eb028659fd..43ace737c0 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -672,8 +672,9 @@ ThemeEditor::ThemeEditor() { bt->set_text(TTR("Disabled Button")); bt->set_disabled(true); first_vb->add_child(bt); - ToolButton *tb = memnew(ToolButton); - tb->set_text("ToolButton"); + Button *tb = memnew(Button); + tb->set_flat(true); + tb->set_text("Button"); first_vb->add_child(tb); CheckButton *cb = memnew(CheckButton); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 3281a59c1c..158f9e8587 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -91,7 +91,7 @@ void TileMapEditor::_notification(int p_what) { } void TileMapEditor::_update_button_tool() { - ToolButton *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button }; + Button *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button }; // Unpress all buttons for (int i = 0; i < 4; i++) { tb[i]->set_pressed(false); @@ -1959,26 +1959,30 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { toolbar->add_child(memnew(VSeparator)); // Tools. - paint_button = memnew(ToolButton); + paint_button = memnew(Button); + paint_button->set_flat(true); paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P)); paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint")); paint_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_NONE)); paint_button->set_toggle_mode(true); toolbar->add_child(paint_button); - bucket_fill_button = memnew(ToolButton); + bucket_fill_button = memnew(Button); + bucket_fill_button->set_flat(true); bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B)); bucket_fill_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_BUCKET)); bucket_fill_button->set_toggle_mode(true); toolbar->add_child(bucket_fill_button); - picker_button = memnew(ToolButton); + picker_button = memnew(Button); + picker_button->set_flat(true); picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_I)); picker_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_PICKING)); picker_button->set_toggle_mode(true); toolbar->add_child(picker_button); - select_button = memnew(ToolButton); + select_button = memnew(Button); + select_button->set_flat(true); select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_M)); select_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_SELECTING)); select_button->set_toggle_mode(true); @@ -2017,35 +2021,40 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { p->add_item(TTR("Fix Invalid Tiles"), OPTION_FIX_INVALID); p->connect("id_pressed", callable_mp(this, &TileMapEditor::_menu_option)); - rotate_left_button = memnew(ToolButton); + rotate_left_button = memnew(Button); + rotate_left_button->set_flat(true); rotate_left_button->set_tooltip(TTR("Rotate Left")); rotate_left_button->set_focus_mode(FOCUS_NONE); rotate_left_button->connect("pressed", callable_mp(this, &TileMapEditor::_rotate), varray(-1)); rotate_left_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_left", TTR("Rotate Left"), KEY_A)); tool_hb->add_child(rotate_left_button); - rotate_right_button = memnew(ToolButton); + rotate_right_button = memnew(Button); + rotate_right_button->set_flat(true); rotate_right_button->set_tooltip(TTR("Rotate Right")); rotate_right_button->set_focus_mode(FOCUS_NONE); rotate_right_button->connect("pressed", callable_mp(this, &TileMapEditor::_rotate), varray(1)); rotate_right_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rotate_right", TTR("Rotate Right"), KEY_S)); tool_hb->add_child(rotate_right_button); - flip_horizontal_button = memnew(ToolButton); + flip_horizontal_button = memnew(Button); + flip_horizontal_button->set_flat(true); flip_horizontal_button->set_tooltip(TTR("Flip Horizontally")); flip_horizontal_button->set_focus_mode(FOCUS_NONE); flip_horizontal_button->connect("pressed", callable_mp(this, &TileMapEditor::_flip_horizontal)); flip_horizontal_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_horizontal", TTR("Flip Horizontally"), KEY_X)); tool_hb->add_child(flip_horizontal_button); - flip_vertical_button = memnew(ToolButton); + flip_vertical_button = memnew(Button); + flip_vertical_button->set_flat(true); flip_vertical_button->set_tooltip(TTR("Flip Vertically")); flip_vertical_button->set_focus_mode(FOCUS_NONE); flip_vertical_button->connect("pressed", callable_mp(this, &TileMapEditor::_flip_vertical)); flip_vertical_button->set_shortcut(ED_SHORTCUT("tile_map_editor/flip_vertical", TTR("Flip Vertically"), KEY_Z)); tool_hb->add_child(flip_vertical_button); - clear_transform_button = memnew(ToolButton); + clear_transform_button = memnew(Button); + clear_transform_button->set_flat(true); clear_transform_button->set_tooltip(TTR("Clear Transform")); clear_transform_button->set_focus_mode(FOCUS_NONE); clear_transform_button->connect("pressed", callable_mp(this, &TileMapEditor::_clear_transform)); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index e25e2d2add..1d2ecdb61f 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -38,7 +38,6 @@ #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/menu_button.h" -#include "scene/gui/tool_button.h" class TileMapEditor : public VBoxContainer { GDCLASS(TileMapEditor, VBoxContainer); @@ -88,16 +87,16 @@ class TileMapEditor : public VBoxContainer { Label *tile_info; MenuButton *options; - ToolButton *paint_button; - ToolButton *bucket_fill_button; - ToolButton *picker_button; - ToolButton *select_button; + Button *paint_button; + Button *bucket_fill_button; + Button *picker_button; + Button *select_button; - ToolButton *flip_horizontal_button; - ToolButton *flip_vertical_button; - ToolButton *rotate_left_button; - ToolButton *rotate_right_button; - ToolButton *clear_transform_button; + Button *flip_horizontal_button; + Button *flip_vertical_button; + Button *rotate_left_button; + Button *rotate_right_button; + Button *clear_transform_button; CheckBox *manual_button; CheckBox *priority_button; diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index b3d4b391d3..a37cf7e426 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -341,12 +341,12 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { HBoxContainer *tileset_toolbar_container = memnew(HBoxContainer); left_container->add_child(tileset_toolbar_container); - tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE] = memnew(ToolButton); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE] = memnew(Button); tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tileset_toolbar_button_pressed), varray(TOOL_TILESET_ADD_TEXTURE)); tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]); tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_tooltip(TTR("Add Texture(s) to TileSet.")); - tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE] = memnew(ToolButton); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE] = memnew(Button); tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tileset_toolbar_button_pressed), varray(TOOL_TILESET_REMOVE_TEXTURE)); tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]); tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_tooltip(TTR("Remove selected Texture from TileSet.")); @@ -402,13 +402,13 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tool_hb->add_child(spacer); tool_hb->move_child(spacer, WORKSPACE_CREATE_SINGLE); - tools[SELECT_NEXT] = memnew(ToolButton); + tools[SELECT_NEXT] = memnew(Button); tool_hb->add_child(tools[SELECT_NEXT]); tool_hb->move_child(tools[SELECT_NEXT], WORKSPACE_CREATE_SINGLE); tools[SELECT_NEXT]->set_shortcut(ED_SHORTCUT("tileset_editor/next_shape", TTR("Next Coordinate"), KEY_PAGEDOWN)); tools[SELECT_NEXT]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SELECT_NEXT)); tools[SELECT_NEXT]->set_tooltip(TTR("Select the next shape, subtile, or Tile.")); - tools[SELECT_PREVIOUS] = memnew(ToolButton); + tools[SELECT_PREVIOUS] = memnew(Button); tool_hb->add_child(tools[SELECT_PREVIOUS]); tool_hb->move_child(tools[SELECT_PREVIOUS], WORKSPACE_CREATE_SINGLE); tools[SELECT_PREVIOUS]->set_shortcut(ED_SHORTCUT("tileset_editor/previous_shape", TTR("Previous Coordinate"), KEY_PAGEUP)); @@ -465,7 +465,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { toolbar = memnew(HBoxContainer); Ref<ButtonGroup> tg(memnew(ButtonGroup)); - tools[TOOL_SELECT] = memnew(ToolButton); + tools[TOOL_SELECT] = memnew(Button); toolbar->add_child(tools[TOOL_SELECT]); tools[TOOL_SELECT]->set_toggle_mode(true); tools[TOOL_SELECT]->set_button_group(tg); @@ -474,40 +474,42 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { separator_bitmask = memnew(VSeparator); toolbar->add_child(separator_bitmask); - tools[BITMASK_COPY] = memnew(ToolButton); + tools[BITMASK_COPY] = memnew(Button); tools[BITMASK_COPY]->set_tooltip(TTR("Copy bitmask.")); tools[BITMASK_COPY]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(BITMASK_COPY)); toolbar->add_child(tools[BITMASK_COPY]); - tools[BITMASK_PASTE] = memnew(ToolButton); + tools[BITMASK_PASTE] = memnew(Button); tools[BITMASK_PASTE]->set_tooltip(TTR("Paste bitmask.")); tools[BITMASK_PASTE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(BITMASK_PASTE)); toolbar->add_child(tools[BITMASK_PASTE]); - tools[BITMASK_CLEAR] = memnew(ToolButton); + tools[BITMASK_CLEAR] = memnew(Button); tools[BITMASK_CLEAR]->set_tooltip(TTR("Erase bitmask.")); tools[BITMASK_CLEAR]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(BITMASK_CLEAR)); toolbar->add_child(tools[BITMASK_CLEAR]); - tools[SHAPE_NEW_RECTANGLE] = memnew(ToolButton); + tools[SHAPE_NEW_RECTANGLE] = memnew(Button); toolbar->add_child(tools[SHAPE_NEW_RECTANGLE]); tools[SHAPE_NEW_RECTANGLE]->set_toggle_mode(true); tools[SHAPE_NEW_RECTANGLE]->set_button_group(tg); tools[SHAPE_NEW_RECTANGLE]->set_tooltip(TTR("Create a new rectangle.")); + tools[SHAPE_NEW_RECTANGLE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_NEW_RECTANGLE)); - tools[SHAPE_NEW_POLYGON] = memnew(ToolButton); + tools[SHAPE_NEW_POLYGON] = memnew(Button); toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); tools[SHAPE_NEW_POLYGON]->set_button_group(tg); tools[SHAPE_NEW_POLYGON]->set_tooltip(TTR("Create a new polygon.")); + tools[SHAPE_NEW_POLYGON]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_NEW_POLYGON)); separator_shape_toggle = memnew(VSeparator); toolbar->add_child(separator_shape_toggle); - tools[SHAPE_TOGGLE_TYPE] = memnew(ToolButton); + tools[SHAPE_TOGGLE_TYPE] = memnew(Button); tools[SHAPE_TOGGLE_TYPE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_TOGGLE_TYPE)); toolbar->add_child(tools[SHAPE_TOGGLE_TYPE]); separator_delete = memnew(VSeparator); toolbar->add_child(separator_delete); - tools[SHAPE_DELETE] = memnew(ToolButton); + tools[SHAPE_DELETE] = memnew(Button); tools[SHAPE_DELETE]->connect("pressed", callable_mp(this, &TileSetEditor::_on_tool_clicked), varray(SHAPE_DELETE)); toolbar->add_child(tools[SHAPE_DELETE]); @@ -531,12 +533,12 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { separator_grid = memnew(VSeparator); toolbar->add_child(separator_grid); - tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); + tools[SHAPE_KEEP_INSIDE_TILE] = memnew(Button); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_pressed(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_tooltip(TTR("Keep polygon inside region Rect.")); toolbar->add_child(tools[SHAPE_KEEP_INSIDE_TILE]); - tools[TOOL_GRID_SNAP] = memnew(ToolButton); + tools[TOOL_GRID_SNAP] = memnew(Button); tools[TOOL_GRID_SNAP]->set_toggle_mode(true); tools[TOOL_GRID_SNAP]->set_tooltip(TTR("Enable snap and show grid (configurable via the Inspector).")); tools[TOOL_GRID_SNAP]->connect("toggled", callable_mp(this, &TileSetEditor::_on_grid_snap_toggled)); @@ -546,20 +548,20 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { separator->set_h_size_flags(SIZE_EXPAND_FILL); toolbar->add_child(separator); - tools[ZOOM_OUT] = memnew(ToolButton); + tools[ZOOM_OUT] = memnew(Button); tools[ZOOM_OUT]->connect("pressed", callable_mp(this, &TileSetEditor::_zoom_out)); toolbar->add_child(tools[ZOOM_OUT]); tools[ZOOM_OUT]->set_tooltip(TTR("Zoom Out")); - tools[ZOOM_1] = memnew(ToolButton); + tools[ZOOM_1] = memnew(Button); tools[ZOOM_1]->connect("pressed", callable_mp(this, &TileSetEditor::_zoom_reset)); toolbar->add_child(tools[ZOOM_1]); tools[ZOOM_1]->set_tooltip(TTR("Zoom Reset")); - tools[ZOOM_IN] = memnew(ToolButton); + tools[ZOOM_IN] = memnew(Button); tools[ZOOM_IN]->connect("pressed", callable_mp(this, &TileSetEditor::_zoom_in)); toolbar->add_child(tools[ZOOM_IN]); tools[ZOOM_IN]->set_tooltip(TTR("Zoom In")); - tools[VISIBLE_INFO] = memnew(ToolButton); + tools[VISIBLE_INFO] = memnew(Button); tools[VISIBLE_INFO]->set_toggle_mode(true); tools[VISIBLE_INFO]->set_tooltip(TTR("Display Tile Names (Hold Alt Key)")); toolbar->add_child(tools[VISIBLE_INFO]); @@ -1908,7 +1910,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { } } } - } else if (p_tool == TOOL_SELECT) { + } else if (p_tool == TOOL_SELECT || p_tool == SHAPE_NEW_POLYGON || p_tool == SHAPE_NEW_RECTANGLE) { if (creating_shape) { // Cancel Creation creating_shape = false; diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index 2955dda244..d2687e7a4b 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -46,7 +46,7 @@ class TileSetEditor : public HSplitContainer { GDCLASS(TileSetEditor, HSplitContainer); - enum TextureToolButtons { + enum TextureButtons { TOOL_TILESET_ADD_TEXTURE, TOOL_TILESET_REMOVE_TEXTURE, TOOL_TILESET_CREATE_SCENE, @@ -111,7 +111,7 @@ class TileSetEditor : public HSplitContainer { ItemList *texture_list; int option; - ToolButton *tileset_toolbar_buttons[TOOL_TILESET_MAX]; + Button *tileset_toolbar_buttons[TOOL_TILESET_MAX]; MenuButton *tileset_toolbar_tools; Map<RID, Ref<Texture2D>> texture_map; @@ -146,7 +146,7 @@ class TileSetEditor : public HSplitContainer { Button *tool_editmode[EDITMODE_MAX]; HSeparator *separator_editmode; HBoxContainer *toolbar; - ToolButton *tools[TOOL_MAX]; + Button *tools[TOOL_MAX]; VSeparator *separator_shape_toggle; VSeparator *separator_bitmask; VSeparator *separator_delete; diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index a1436e123d..cfbe54ef61 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -300,7 +300,7 @@ void VersionControlEditorPlugin::register_editor() { TabContainer *dock_vbc = (TabContainer *)version_commit_dock->get_parent_control(); dock_vbc->set_tab_title(version_commit_dock->get_index(), TTR("Commit")); - ToolButton *vc = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock); + Button *vc = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock); set_version_control_tool_button(vc); } } diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h index 664e38d65f..248a1435fd 100644 --- a/editor/plugins/version_control_editor_plugin.h +++ b/editor/plugins/version_control_editor_plugin.h @@ -90,7 +90,7 @@ private: Label *commit_status; PanelContainer *version_control_dock; - ToolButton *version_control_dock_button; + Button *version_control_dock_button; VBoxContainer *diff_vbc; HBoxContainer *diff_hbc; Button *diff_refresh_button; @@ -121,7 +121,7 @@ public: static VersionControlEditorPlugin *get_singleton(); void popup_vcs_set_up_dialog(const Control *p_gui_base); - void set_version_control_tool_button(ToolButton *p_button) { version_control_dock_button = p_button; } + void set_version_control_tool_button(Button *p_button) { version_control_dock_button = p_button; } PopupMenu *get_version_control_actions_panel() const { return version_control_actions; } VBoxContainer *get_version_commit_dock() const { return version_commit_dock; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 92bdba93e7..89ab747cde 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -2341,13 +2341,15 @@ VisualShaderEditor::VisualShaderEditor() { graph->get_zoom_hbox()->add_child(edit_type); graph->get_zoom_hbox()->move_child(edit_type, 0); - add_node = memnew(ToolButton); + add_node = memnew(Button); + add_node->set_flat(true); graph->get_zoom_hbox()->add_child(add_node); add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); add_node->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_members_dialog), varray(false)); - preview_shader = memnew(ToolButton); + preview_shader = memnew(Button); + preview_shader->set_flat(true); preview_shader->set_toggle_mode(true); preview_shader->set_tooltip(TTR("Show resulted shader code.")); graph->get_zoom_hbox()->add_child(preview_shader); @@ -2750,8 +2752,10 @@ VisualShaderEditor::VisualShaderEditor() { texture_node_option_idx = add_options.size(); add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the texture lookup."), -1, -1)); add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), -1, -1)); + add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), -1, -1, -1, -1, -1)); add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, -1)); add_options.push_back(AddOption("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), -1, -1, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Texture2DArrayUniform", "Textures", "Variables", "VisualShaderNodeTexture2DArrayUniform", TTR("2D array of textures uniform lookup."), -1, -1, -1, -1, -1)); // TRANSFORM diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index d2f10d9407..b7c0fb8e45 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -60,8 +60,8 @@ class VisualShaderEditor : public VBoxContainer { Ref<VisualShader> visual_shader; HSplitContainer *main_box; GraphEdit *graph; - ToolButton *add_node; - ToolButton *preview_shader; + Button *add_node; + Button *preview_shader; OptionButton *edit_type; diff --git a/editor/project_export.cpp b/editor/project_export.cpp index c53a59604a..67ab925a4f 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -1064,10 +1064,12 @@ ProjectExportDialog::ProjectExportDialog() { //presets->set_drag_forwarding(this); mc->add_child(presets); presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset)); - duplicate_preset = memnew(ToolButton); + duplicate_preset = memnew(Button); + duplicate_preset->set_flat(true); preset_hb->add_child(duplicate_preset); duplicate_preset->connect("pressed", callable_mp(this, &ProjectExportDialog::_duplicate_preset)); - delete_preset = memnew(ToolButton); + delete_preset = memnew(Button); + delete_preset->set_flat(true); preset_hb->add_child(delete_preset); delete_preset->connect("pressed", callable_mp(this, &ProjectExportDialog::_delete_preset)); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index cbba4b4834..a800f9e8eb 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -50,7 +50,6 @@ #include "scene/gui/panel_container.h" #include "scene/gui/separator.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" #include "scene/main/window.h" #include "servers/display_server.h" diff --git a/editor/project_manager.h b/editor/project_manager.h index e5471bd392..66b38d0746 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -35,7 +35,6 @@ #include "scene/gui/dialogs.h" #include "scene/gui/file_dialog.h" #include "scene/gui/scroll_container.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" class ProjectDialog; diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index a7c260c0f8..a8029e1e2b 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1865,14 +1865,15 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { restart_icon->set_v_size_flags(Control::SIZE_SHRINK_CENTER); restart_hb->add_child(restart_icon); restart_label = memnew(Label); - restart_label->set_text(TTR("The editor must be restarted for changes to take effect.")); + restart_label->set_text(TTR("Changed settings will be applied to the editor after restarting.")); restart_hb->add_child(restart_label); restart_hb->add_spacer(); Button *restart_button = memnew(Button); restart_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_editor_restart)); restart_hb->add_child(restart_button); restart_button->set_text(TTR("Save & Restart")); - restart_close_button = memnew(ToolButton); + restart_close_button = memnew(Button); + restart_close_button->set_flat(true); restart_close_button->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_editor_restart_close)); restart_hb->add_child(restart_close_button); restart_container->hide(); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 445ef58351..728f31efa8 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -174,7 +174,7 @@ class ProjectSettingsEditor : public AcceptDialog { Label *restart_label; TextureRect *restart_icon; PanelContainer *restart_container; - ToolButton *restart_close_button; + Button *restart_close_button; void _editor_restart_request(); void _editor_restart(); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 5795d85e66..dd42ed9760 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1076,7 +1076,8 @@ void SceneTreeDock::_notification(int p_what) { top_row->add_child(memnew(Label(TTR("Create Root Node:")))); top_row->add_spacer(); - ToolButton *node_shortcuts_toggle = memnew(ToolButton); + Button *node_shortcuts_toggle = memnew(Button); + node_shortcuts_toggle->set_flat(true); node_shortcuts_toggle->set_name("NodeShortcutsToggle"); node_shortcuts_toggle->set_icon(get_theme_icon("Favorites", "EditorIcons")); node_shortcuts_toggle->set_toggle_mode(true); @@ -2801,13 +2802,15 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT | KEY_DELETE); ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE); - button_add = memnew(ToolButton); + button_add = memnew(Button); + button_add->set_flat(true); button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_NEW, false)); button_add->set_tooltip(TTR("Add/Create a New Node.")); button_add->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node")); filter_hbc->add_child(button_add); - button_instance = memnew(ToolButton); + button_instance = memnew(Button); + button_instance->set_flat(true); button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_INSTANCE, false)); button_instance->set_tooltip(TTR("Instance a scene file as a Node. Creates an inherited scene if no root node exists.")); button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene")); @@ -2821,14 +2824,16 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel filter->add_theme_constant_override("minimum_spaces", 0); filter->connect("text_changed", callable_mp(this, &SceneTreeDock::_filter_changed)); - button_create_script = memnew(ToolButton); + button_create_script = memnew(Button); + button_create_script->set_flat(true); button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_ATTACH_SCRIPT, false)); button_create_script->set_tooltip(TTR("Attach a new or existing script to the selected node.")); button_create_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script")); filter_hbc->add_child(button_create_script); button_create_script->hide(); - button_detach_script = memnew(ToolButton); + button_detach_script = memnew(Button); + button_detach_script->set_flat(true); button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(TOOL_DETACH_SCRIPT, false)); button_detach_script->set_tooltip(TTR("Detach the script from the selected node.")); button_detach_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/detach_script")); @@ -2838,14 +2843,16 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel button_hb = memnew(HBoxContainer); vbc->add_child(button_hb); - edit_remote = memnew(ToolButton); + edit_remote = memnew(Button); + edit_remote->set_flat(true); button_hb->add_child(edit_remote); edit_remote->set_h_size_flags(SIZE_EXPAND_FILL); edit_remote->set_text(TTR("Remote")); edit_remote->set_toggle_mode(true); edit_remote->connect("pressed", callable_mp(this, &SceneTreeDock::_remote_tree_selected)); - edit_local = memnew(ToolButton); + edit_local = memnew(Button); + edit_local->set_flat(true); button_hb->add_child(edit_local); edit_local->set_h_size_flags(SIZE_EXPAND_FILL); edit_local->set_text(TTR("Local")); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 72be3fb02f..150c1976ef 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -46,7 +46,6 @@ #include "scene/gui/control.h" #include "scene/gui/label.h" #include "scene/gui/popup_menu.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" #include "scene_tree_editor.h" @@ -106,15 +105,15 @@ class SceneTreeDock : public VBoxContainer { CreateDialog *create_dialog; RenameDialog *rename_dialog; - ToolButton *button_add; - ToolButton *button_instance; - ToolButton *button_create_script; - ToolButton *button_detach_script; + Button *button_add; + Button *button_instance; + Button *button_create_script; + Button *button_detach_script; Button *button_3d; HBoxContainer *button_hb; - ToolButton *edit_local, *edit_remote; + Button *edit_local, *edit_remote; SceneTreeEditor *scene_tree; Control *remote_tree; diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index c461bf0410..9f286bd8f6 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -432,7 +432,8 @@ EditorSettingsDialog::EditorSettingsDialog() { restart_button->connect("pressed", callable_mp(this, &EditorSettingsDialog::_editor_restart)); restart_hb->add_child(restart_button); restart_button->set_text(TTR("Save & Restart")); - restart_close_button = memnew(ToolButton); + restart_close_button = memnew(Button); + restart_close_button->set_flat(true); restart_close_button->connect("pressed", callable_mp(this, &EditorSettingsDialog::_editor_restart_close)); restart_hb->add_child(restart_close_button); restart_container->hide(); diff --git a/editor/settings_config_dialog.h b/editor/settings_config_dialog.h index 05566762fc..19fe1a7633 100644 --- a/editor/settings_config_dialog.h +++ b/editor/settings_config_dialog.h @@ -38,7 +38,6 @@ #include "scene/gui/rich_text_label.h" #include "scene/gui/tab_container.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" class EditorSettingsDialog : public AcceptDialog { GDCLASS(EditorSettingsDialog, AcceptDialog); @@ -94,7 +93,7 @@ class EditorSettingsDialog : public AcceptDialog { Label *restart_label; TextureRect *restart_icon; PanelContainer *restart_container; - ToolButton *restart_close_button; + Button *restart_close_button; void _editor_restart_request(); void _editor_restart(); diff --git a/editor/translations/af.po b/editor/translations/af.po index 1f598ef5e5..daa0737106 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -784,6 +784,11 @@ msgstr "Metode in teiken Nodus moet gespesifiseer word!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metode in teiken Nodus moet gespesifiseer word!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ar.po b/editor/translations/ar.po index a60de1a41e..ffab95cc8b 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -785,6 +785,11 @@ msgid "Method in target node must be specified." msgstr "يجب ØªØØ¯ÙŠØ¯ الدالة ÙÙŠ العقدة Ø§Ù„Ù…Ø³ØªÙ‡Ø¯ÙØ©." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "هذا الاسم ليس Ù…ÙØ¹Ø±Ùاً مميزاً ØµØ§Ù„ØØ§Ù‹:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/bg.po b/editor/translations/bg.po index f08f2b1362..c9f38d518a 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -746,6 +746,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/bn.po b/editor/translations/bn.po index 3680e4ce6c..c438934246 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -809,6 +809,11 @@ msgstr "নিরà§à¦¦à§‡à¦¶à¦¿à¦¤ নোডের মেথড নিরà§à¦¦ #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "নামটি কারà§à¦¯à¦•র সনাকà§à¦¤à¦•ারী নয়:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 1640367701..5fb91db7b4 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -765,6 +765,11 @@ msgid "Method in target node must be specified." msgstr "S'ha d'especificar el mètode al node de destinació." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "El nom no és un identificador và lid:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/cs.po b/editor/translations/cs.po index fabec77283..809bc69149 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -24,7 +24,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-06 10:15+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: ZbynÄ›k <zbynek.fiala@gmail.com>\n" "Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/" "cs/>\n" @@ -33,7 +33,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -773,6 +773,11 @@ msgid "Method in target node must be specified." msgstr "Je nutné zadat metodu v cÃlovém uzlu." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Jméno nenà platný identifikátor:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -10055,7 +10060,7 @@ msgstr "PÅ™idat akci" #: editor/project_settings_editor.cpp msgid "Button" -msgstr "TlaÄÃtko" +msgstr "Button" #: editor/project_settings_editor.cpp msgid "Left Button." diff --git a/editor/translations/da.po b/editor/translations/da.po index 8eeaaafaea..70b05c08ff 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -16,12 +16,13 @@ # Kristoffer Andersen <kjaa@google.com>, 2019. # Joe Osborne <reachjoe.o@gmail.com>, 2020. # Autowinto <happymansi@hotmail.com>, 2020. +# Mikkel Mouridsen <mikkelmouridsen@me.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-02-02 08:51+0000\n" -"Last-Translator: Autowinto <happymansi@hotmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: Mikkel Mouridsen <mikkelmouridsen@me.com>\n" "Language-Team: Danish <https://hosted.weblate.org/projects/godot-engine/" "godot/da/>\n" "Language: da\n" @@ -29,7 +30,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.11-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -443,7 +444,7 @@ msgstr "Det er ikke muligt at tilføje et nyt spor uden en rod" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" -msgstr "" +msgstr "Ugyldigt spor for Bezier (ingen passende underegenskaber)" #: editor/animation_track_editor.cpp #, fuzzy @@ -785,7 +786,7 @@ msgstr "Advarsler" #: editor/code_editor.cpp msgid "Line and column numbers." -msgstr "" +msgstr "Linje- og kolonnenumre." #: editor/connections_dialog.cpp #, fuzzy @@ -794,6 +795,11 @@ msgstr "Metode i target Node skal angives!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Navnet er ikke et gyldigt id:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1252,7 +1258,7 @@ msgstr "Udpakker Aktiver" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "The following files failed extraction from package:" -msgstr "" +msgstr "De følgende filer kunne ikke trækkes ud af pakken:" #: editor/editor_asset_installer.cpp #, fuzzy diff --git a/editor/translations/de.po b/editor/translations/de.po index b52206e56e..6fb1a29c12 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -806,6 +806,11 @@ msgid "Method in target node must be specified." msgstr "Methode des Ziel-Nodes muss angegeben werden." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Name ist kein gültiger Bezeichner:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 4dca7e4c5f..01121a8156 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -730,6 +730,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/el.po b/editor/translations/el.po index 127da8ec1f..3f04c4cf01 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -763,6 +763,11 @@ msgid "Method in target node must be specified." msgstr "Î ÏÎπει να οÏιστεί συνάÏτηση στον στοχευμÎνο κόμβο." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Το όνομα δεν είναι ÎγκυÏο αναγνωÏιστικό:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/eo.po b/editor/translations/eo.po index 3addde45ce..f98f043118 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -764,6 +764,11 @@ msgstr "Metodo en celo nodo devas esti specifita." #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metodo en celo nodo devas esti specifita." + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/es.po b/editor/translations/es.po index f8c4134d07..15efa44f3d 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -53,8 +53,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" -"Last-Translator: paco <pacosoftfree@protonmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: Javier Ocampos <xavier.ocampos@gmail.com>\n" "Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/" "godot/es/>\n" "Language: es\n" @@ -62,7 +62,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -79,7 +79,8 @@ msgstr "Se esperaba un string de longitud 1 (un carácter)." #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." msgstr "" -"No hay suficientes bytes para decodificar bytes, o el formato es invalido." +"No hay suficientes bytes para decodificar los bytes, o el formato es " +"inválido." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -96,11 +97,11 @@ msgstr "Operandos inválidos para el operador %s, %s y %s." #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" -msgstr "Indice inválido de tipo %s para tipo base %s" +msgstr "Ãndice inválido de tipo %s para el tipo base %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" -msgstr "El Ãndice de nombre «%s» no es válido para el tipo de base %s" +msgstr "El Ãndice de nombre '%s' no es válido para el tipo de base %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" @@ -806,6 +807,11 @@ msgid "Method in target node must be specified." msgstr "Se debe establecer un método en el nodo destino." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "El nombre no es un identificador válido:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -2014,7 +2020,7 @@ msgstr "Propiedades del Tema" #: editor/editor_help.cpp msgid "Enumerations" -msgstr "Enumeraciones" +msgstr "Enumerados" #: editor/editor_help.cpp msgid "Constants" @@ -3378,7 +3384,7 @@ msgstr "Página: " #: editor/editor_properties_array_dict.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Remove Item" -msgstr "Eliminar Item" +msgstr "Eliminar Ãtem" #: editor/editor_properties_array_dict.cpp msgid "New Key:" @@ -5906,15 +5912,15 @@ msgstr "Degradado Editado" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" -msgstr "Elemento %d" +msgstr "Ãtem %d" #: editor/plugins/item_list_editor_plugin.cpp msgid "Items" -msgstr "Elementos" +msgstr "Ãtems" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item List Editor" -msgstr "Editor de Lista de Items" +msgstr "Editor de Lista de Ãtems" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create Occluder Polygon" @@ -6104,7 +6110,7 @@ msgstr "Depuración del Canal UV" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Remove item %d?" -msgstr "¿Quieres borrar el elemento %d?" +msgstr "¿Eliminar el Ãtem %d?" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "" @@ -6121,11 +6127,11 @@ msgstr "LibrerÃa de Mallas" #: editor/plugins/mesh_library_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Add Item" -msgstr "Añadir Item" +msgstr "Añadir Ãtem" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Remove Selected Item" -msgstr "Borrar elemento seleccionado" +msgstr "Eliminar Ãtem Seleccionado" #: editor/plugins/mesh_library_editor_plugin.cpp msgid "Import from Scene" @@ -7935,7 +7941,7 @@ msgstr "Región de Textura" #: editor/plugins/theme_editor_plugin.cpp msgid "Add All Items" -msgstr "Añadir Todos los Elementos" +msgstr "Añadir Todos los Ãtems" #: editor/plugins/theme_editor_plugin.cpp msgid "Add All" @@ -7959,11 +7965,11 @@ msgstr "Menú de edición de tema." #: editor/plugins/theme_editor_plugin.cpp msgid "Add Class Items" -msgstr "Añadir elementos de clase" +msgstr "Añadir Clases de Ãtems" #: editor/plugins/theme_editor_plugin.cpp msgid "Remove Class Items" -msgstr "Eliminar Ãtems de Clases" +msgstr "Eliminar Clases de Ãtems" #: editor/plugins/theme_editor_plugin.cpp msgid "Create Empty Template" @@ -11146,7 +11152,7 @@ msgstr "Monitores" #: editor/script_editor_debugger.cpp msgid "Pick one or more items from the list to display the graph." -msgstr "Elige uno o más elementos de la lista para mostrar el gráfico." +msgstr "Elige uno o más Ãtems de la lista para mostrar el gráfico." #: editor/script_editor_debugger.cpp msgid "List of Video Memory Usage by Resource:" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index 46cb219e14..5cab610261 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -770,6 +770,11 @@ msgid "Method in target node must be specified." msgstr "El método en el nodo objetivo debe ser especificado." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "El nombre no es un identificador válido:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/et.po b/editor/translations/et.po index 7be6996d69..5fd61347e1 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -744,6 +744,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/eu.po b/editor/translations/eu.po index b47056d82b..e461c0f1ec 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -735,6 +735,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fa.po b/editor/translations/fa.po index 3f94d1112b..428b69062a 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -784,6 +784,11 @@ msgstr "متد در گره مقصد باید مشخص شده باشد!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "نام یک شناسه‌ی معتبر نیست:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fi.po b/editor/translations/fi.po index a95c65be41..125656ed67 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -757,6 +757,11 @@ msgid "Method in target node must be specified." msgstr "Kohdesolmun metodi täytyy määrittää." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Nimi ei ole kelvollinen tunniste:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fil.po b/editor/translations/fil.po index 920b91a30c..ceda61c802 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -743,6 +743,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/fr.po b/editor/translations/fr.po index fac3b9b84b..46d3adb070 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -834,6 +834,10 @@ msgid "Method in target node must be specified." msgstr "La méthode du nÅ“ud cible doit être spécifiée." #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "Le nom de la méthode doit être un identifiant valide." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ga.po b/editor/translations/ga.po index b9e6ba69c6..70dd5eada7 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -736,6 +736,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/he.po b/editor/translations/he.po index 56126249dc..7895ae48fe 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -777,6 +777,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 4782afecb0..e3ae2aabe5 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -756,6 +756,11 @@ msgid "Method in target node must be specified." msgstr "Method को target node में निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ कीजिà¤." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Method को target node में निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ कीजिà¤." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/hr.po b/editor/translations/hr.po index ad095145b2..5355ee1dc9 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -741,6 +741,11 @@ msgid "Method in target node must be specified." msgstr "Metoda u ciljnom Ävoru mora biti odreÄ‘ena." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metoda u ciljnom Ävoru mora biti odreÄ‘ena." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/hu.po b/editor/translations/hu.po index ef15f85977..b57028a426 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -790,6 +790,11 @@ msgstr "Nevezze meg a metódust a cél Node-ban!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Nevezze meg a metódust a cél Node-ban!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/id.po b/editor/translations/id.po index f7a86197b6..92c0c25da9 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -778,6 +778,11 @@ msgid "Method in target node must be specified." msgstr "Method dalam node target harus ditentukan." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Nama bukan sebuah pengidentifikasi yang sah:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/is.po b/editor/translations/is.po index 5a1ac9b73c..f0d93d1242 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -770,6 +770,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/it.po b/editor/translations/it.po index eeec1e05eb..bb53d26fa4 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -50,12 +50,13 @@ # J. Lavoie <j.lavoie@net-c.ca>, 2020. # Andrea Terenziani <andrea.terenziani.at@gmail.com>, 2020. # Anonymous <noreply@weblate.org>, 2020. +# riccardo boffelli <riccardo.boffelli.96@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-05-07 21:28+0000\n" -"Last-Translator: Sean Bone <seanbone@zumguy.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: riccardo boffelli <riccardo.boffelli.96@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -63,7 +64,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -802,6 +803,11 @@ msgid "Method in target node must be specified." msgstr "Il metodo del nodo designato deve essere specificato." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Il nome non è un identificatore valido:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1499,7 +1505,7 @@ msgstr "Riordina gli Autoload" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Non è possibile aggiungere l'autoload:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2463,15 +2469,16 @@ msgid "Can't reload a scene that was never saved." msgstr "Impossibile ricaricare una scena che non è mai stata salvata." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "Salva Scena" +msgstr "Ricarica scena salvata" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"La scena attuale ha dei cambiamenti non salvati.\n" +"Ricaricare comunque la scena salvata? Questa azione non può essere annullata." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -3418,11 +3425,10 @@ msgid "Did you forget the '_run' method?" msgstr "Hai dimenticato il metodo '_run'?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"Mantieni premuto Control per rilasciare un Getter. Mantieni premuto Shift " -"per rilasciare una firma generica." +"Tenere premuto il tasto Ctrl per arrotondare ai numeri interi. Tenere " +"premuto Shift per modifiche più precise." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -4022,8 +4028,10 @@ msgid "Error running post-import script:" msgstr "Errore di esecuzione dello script di post-import:" #: editor/import/resource_importer_scene.cpp +#, fuzzy msgid "Did you return a Node-derived object in the `post_import()` method?" msgstr "" +"Avete restituito un oggetto derivato da un Nodo nel metodo `post_import()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -6992,9 +7000,8 @@ msgstr "" "Manca il metodo '%s' connesso per il segnale '%s' dal nodo '%s' al nodo '%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(ignora)" +msgstr "[ignora]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7480,6 +7487,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Fare clic per passare da uno stato di visibilità all'altro.\n" +"\n" +"Apri gli occhi: Gizmo è visibile.\n" +"Occhio chiuso: Gizmo è nascosto.\n" +"Occhio semiaperto: Gizmo è visibile anche attraverso superfici opache " +"(\"raggi X\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -10579,9 +10592,8 @@ msgid "Instance Child Scene" msgstr "Istanzia Scena Figlia" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Allega Script" +msgstr "Rimuovi Script" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10747,11 +10759,15 @@ msgid "Open Documentation" msgstr "Apri la documentazione" #: editor/scene_tree_dock.cpp +#, fuzzy msgid "" "Cannot attach a script: there are no languages registered.\n" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Non è possibile allegare uno script: non ci sono linguaggi registrati.\n" +"Questo probabilmente perché questo editor è stato costruito con tutti i " +"moduli di lingua disabilitati." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10802,14 +10818,12 @@ msgstr "" "root esiste." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." -msgstr "Allega un nuovo script o uno esistente al nodo selezionato." +msgstr "Allega un nuovo script o uno già esistente al nodo selezionato." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Svuota uno script per il nodo selezionato." +msgstr "Rimuovi lo script per il nodo selezionato." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -12072,30 +12086,40 @@ msgid "Invalid package name:" msgstr "Nome del pacchetto non valido:" #: platform/android/export/export.cpp +#, fuzzy msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Modulo \"GodotPaymentV3\" non valido incluso nell'impostazione del progetto " +"\" android/moduli\" (modificato in Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "Per utilizzare i plugin \"Use Custom Build\" deve essere abilitato." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Degrees Of Freedom\" è valido solo quando \"Xr Mode\" è \"Oculus Mobile VR" +"\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" è valido solo quando \"Xr Mode\" è \"Oculus Mobile VR\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" è valida solo quando \"Xr Mode\" è \"Oculus Mobile VR\"." #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/ja.po b/editor/translations/ja.po index 7d4aed4b29..fc8444d6bc 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -786,6 +786,11 @@ msgid "Method in target node must be specified." msgstr "対象ノードã®ãƒ¡ã‚½ãƒƒãƒ‰ã‚’指定ã—ã¦ãã ã•ã„。" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "ã“ã®åå‰ã¯ç„¡åйãªè˜åˆ¥åã§ã™:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ka.po b/editor/translations/ka.po index 2435a50898..af03b1af9e 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -790,6 +790,11 @@ msgstr "სáƒáƒ›áƒ˜áƒ–ნე კვáƒáƒœáƒ«áƒ¨áƒ˜ მეთáƒáƒ“ი უნდ #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "სáƒáƒ›áƒ˜áƒ–ნე კვáƒáƒœáƒ«áƒ¨áƒ˜ მეთáƒáƒ“ი უნდრიყáƒáƒ¡ გáƒáƒœáƒ¡áƒáƒ–ღვრული!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ko.po b/editor/translations/ko.po index c568dc19b8..a895af27b6 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -768,6 +768,11 @@ msgid "Method in target node must be specified." msgstr "ëŒ€ìƒ ë…¸ë“œì— ìžˆëŠ” 메서드는 반드시 ì§€ì •í•´ì•¼ 합니다." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "ì´ë¦„ì´ ì˜¬ë°”ë¥¸ ì‹ë³„ìžê°€ 아님:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/lt.po b/editor/translations/lt.po index bbbe630d4a..fdf9ef15ae 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -773,6 +773,11 @@ msgstr "Metodas pasirinktame Node turi bÅ«ti nurodytas!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metodas pasirinktame Node turi bÅ«ti nurodytas!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/lv.po b/editor/translations/lv.po index b69ecf7eef..8417a6b650 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -757,6 +757,11 @@ msgid "Method in target node must be specified." msgstr "Metodi mÄ“rÄ·a mezglÄ nepiecieÅ¡ams specificÄ“t." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metodi mÄ“rÄ·a mezglÄ nepiecieÅ¡ams specificÄ“t." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/mi.po b/editor/translations/mi.po index fbf4bce3d6..ab68a71ee2 100644 --- a/editor/translations/mi.po +++ b/editor/translations/mi.po @@ -728,6 +728,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ml.po b/editor/translations/ml.po index 77ac327f71..db5f5638f3 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -738,6 +738,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/mr.po b/editor/translations/mr.po index 38e3ee7185..1700bcb138 100644 --- a/editor/translations/mr.po +++ b/editor/translations/mr.po @@ -735,6 +735,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ms.po b/editor/translations/ms.po index 233b5cb428..160fa6e69f 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -758,6 +758,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/nb.po b/editor/translations/nb.po index 5c80321d03..4e7ca2dce1 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-03 20:09+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" "Language-Team: Norwegian BokmÃ¥l <https://hosted.weblate.org/projects/godot-" "engine/godot/nb_NO/>\n" @@ -28,7 +28,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -796,6 +796,11 @@ msgstr "Metode i mÃ¥l-Node mÃ¥ spesifiseres!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Navn er ikke en gyldig identifikator:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -3772,12 +3777,9 @@ msgid "Favorites" msgstr "Favoritter:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "Status: Import of file failed. Please fix file and reimport manually." msgstr "" -"\n" -"Status: Import av fil feilet. Vennligst reparer filen eller reimporter " -"manuelt." +"Status: Import av fil feilet. Reparer filen eller importer igjen manuelt." #: editor/filesystem_dock.cpp #, fuzzy diff --git a/editor/translations/nl.po b/editor/translations/nl.po index 8e6c4bcfa4..3d560d3d6d 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -44,7 +44,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: Stijn Hinlopen <f.a.hinlopen@gmail.com>\n" "Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/" "nl/>\n" @@ -53,7 +53,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -790,6 +790,11 @@ msgid "Method in target node must be specified." msgstr "Methode in doelknoop moet gespecificeerd worden." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Naam is geen geldige identifier:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1987,15 +1992,15 @@ msgstr "standaard:" #: editor/editor_help.cpp msgid "Methods" -msgstr "Methodes" +msgstr "Methoden" #: editor/editor_help.cpp msgid "Theme Properties" -msgstr "Thema Eigenschappen" +msgstr "Thema-eigenschappen" #: editor/editor_help.cpp msgid "Enumerations" -msgstr "Enumeraties" +msgstr "Enumeratie" #: editor/editor_help.cpp msgid "Constants" @@ -2003,7 +2008,7 @@ msgstr "Constanten" #: editor/editor_help.cpp msgid "Property Descriptions" -msgstr "Eigenschap Beschrijvingen" +msgstr "Eigenschapbeschrijvingen" #: editor/editor_help.cpp msgid "(value)" @@ -2019,7 +2024,7 @@ msgstr "" #: editor/editor_help.cpp msgid "Method Descriptions" -msgstr "Methode Beschrijvingen" +msgstr "Methodebeschrijvingen" #: editor/editor_help.cpp msgid "" diff --git a/editor/translations/or.po b/editor/translations/or.po index afff834dee..d6678c2819 100644 --- a/editor/translations/or.po +++ b/editor/translations/or.po @@ -734,6 +734,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/pl.po b/editor/translations/pl.po index 414e66685a..558a86f1cb 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -43,7 +43,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-06 10:15+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: Tomek <kobewi4e@gmail.com>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" @@ -53,7 +53,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -791,6 +791,11 @@ msgid "Method in target node must be specified." msgstr "Metoda w węźle docelowym musi zostać podana." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Nazwa nie jest prawidÅ‚owym identyfikatorem:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1484,7 +1489,7 @@ msgstr "Przestaw Autoloady" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Nie można dodać Autoload:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -1858,11 +1863,11 @@ msgstr "Przełącz ukryte pliki" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "Ustaw jako ulubione" +msgstr "Przełącz ulubione" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "Przełącz tryby" +msgstr "Przełącz tryb" #: editor/editor_file_dialog.cpp msgid "Focus Path" @@ -1870,11 +1875,11 @@ msgstr "Przejdź do wprowadzania Å›cieżki" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" -msgstr "PrzesuÅ„ Ulubiony w górÄ™" +msgstr "PrzesuÅ„ ulubiony w górÄ™" #: editor/editor_file_dialog.cpp msgid "Move Favorite Down" -msgstr "PrzesuÅ„ Ulubiony w dół" +msgstr "PrzesuÅ„ ulubiony w dół" #: editor/editor_file_dialog.cpp msgid "Go to previous folder." @@ -2122,7 +2127,7 @@ msgstr "Wyczyść" #: editor/editor_log.cpp msgid "Clear Output" -msgstr "Wyczyść dane wyjÅ›ciowe" +msgstr "Wyczyść wyjÅ›cie" #: editor/editor_network_profiler.cpp editor/editor_node.cpp #: editor/editor_profiler.cpp @@ -2440,15 +2445,16 @@ msgid "Can't reload a scene that was never saved." msgstr "Nie można przeÅ‚adować sceny która nie zostaÅ‚a zapisana." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "Zapisz scenÄ™" +msgstr "Przywróć zapisanÄ… scenÄ™" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Aktualna scena ma niezapisane zmiany.\n" +"Przywrócić zapisanÄ… scenÄ™ tak czy inaczej? Ta akcja nie może zostać cofniÄ™ta." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -2854,8 +2860,10 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Wszelkie zmiany sceny w edytorze bÄ™dÄ… odtworzone w uruchomionej grze na " -"urzÄ…dzeniu zdalnym. Opcja ta dziaÅ‚a szybciej na sieciowych systemach plików." +"Kiedy ta opcja jest włączona, wszystkie zmiany na scenie w edytorze bÄ™dÄ… " +"powtórzone w uruchomionej grze.\n" +"Kiedy używane zdalnie na urzÄ…dzeniu, ta opcja jest wydajniejsza w sieciowym " +"systemie plików." #: editor/editor_node.cpp msgid "Sync Script Changes" @@ -2868,9 +2876,10 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Wszelkie zmiany skryptów bÄ™dÄ… synchronizowane z urzÄ…dzeniem zdalnym " -"(dziaÅ‚ajÄ…ce instancje bÄ™dÄ… zrestartowane). Opcja ta dziaÅ‚a szybciej z " -"użyciem sieciowych systemów plików." +"Kiedy ta opcja jest włączona, każdy zapisany skrypt bÄ™dzie przeÅ‚adowany w " +"uruchomionej grze.\n" +"Kiedy używane zdalnie na urzÄ…dzeniu, ta opcja jest wydajniejsza w sieciowym " +"systemie plików." #: editor/editor_node.cpp editor/script_create_dialog.cpp msgid "Editor" @@ -2894,7 +2903,7 @@ msgstr "Zrzuty ekranu sÄ… przechowywane w folderze danych/ustawieÅ„ edytora." #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "PeÅ‚ny ekran" +msgstr "Przełącz peÅ‚ny ekran" #: editor/editor_node.cpp msgid "Toggle System Console" @@ -3378,11 +3387,10 @@ msgid "Did you forget the '_run' method?" msgstr "Zapomniano metody \"_run\"?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." msgstr "" -"Przytrzymaj Ctrl, by upuÅ›cić pobieracz (Getter). Przytrzymaj Shift, by " -"upuÅ›cić generycznÄ… sygnaturÄ™." +"Przytrzyma Ctrl, by zaokrÄ…glić do liczb caÅ‚kowitych. Przytrzymaj Shift dla " +"bardziej precyzyjnych zmian." #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3983,7 +3991,7 @@ msgstr "Błąd podczas uruchamiania skryptu po imporcie:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "Czy zwracasz obiekt dziedziczÄ…cy po Node w metodzie `post_import()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -5416,7 +5424,7 @@ msgstr "Tryb przesuwania" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Mode" -msgstr "Tryb Rotacji" +msgstr "Tryb obrotu" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5556,7 +5564,7 @@ msgstr "Widok" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Always Show Grid" -msgstr "Zawsze pokaż siatkÄ™" +msgstr "Zawsze pokazuj siatkÄ™" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Helpers" @@ -6938,9 +6946,8 @@ msgstr "" "\"%s\"." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(ignoruj)" +msgstr "[Ignoruj]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -6978,7 +6985,7 @@ msgstr "Wielkie litery" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Lowercase" -msgstr "MaÅ‚e Litery" +msgstr "MaÅ‚e litery" #: editor/plugins/script_text_editor.cpp editor/plugins/text_editor.cpp msgid "Capitalize" @@ -7054,7 +7061,7 @@ msgstr "Wylicz wyrażenie" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" -msgstr "Przytnij koÅ„cowe spacje" +msgstr "Przytnij koÅ„cowe biaÅ‚e znaki" #: editor/plugins/script_text_editor.cpp msgid "Convert Indent to Spaces" @@ -7387,7 +7394,7 @@ msgstr "\"Wolny widok\" w tyÅ‚" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "\"Wolny widok\" w góre" +msgstr "\"Wolny widok\" w górÄ™" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" @@ -7425,6 +7432,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Kliknij, by przełączyć pomiÄ™dzy stanami widocznoÅ›ci.\n" +"\n" +"Otwarte oko: uchwyt jest widzialny.\n" +"ZamkniÄ™te oko: uchwyt jest ukryty.\n" +"Półotwarte oko: uchwyt jest również widoczny przez nieprzezroczyste " +"powierzchnie (\"x-ray\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7519,7 +7532,7 @@ msgstr "2 widoki" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" -msgstr "2 widoki (Alt)" +msgstr "2 widoki (alternatywnie)" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" @@ -7527,7 +7540,7 @@ msgstr "3 widoki" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" -msgstr "3 widoki (Alt)" +msgstr "3 widoki (alternatywnie)" #: editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" @@ -8807,7 +8820,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for fragment and light shader modes." -msgstr "Parametr wejÅ›ciowy \"%s\" dla dla fragmentowego i Å›wiatÅ‚owego shadera." +msgstr "Parametr wejÅ›ciowy \"%s\" dla fragmentowego i Å›wiatÅ‚owego shadera." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for fragment shader mode." @@ -9507,16 +9520,16 @@ msgid "" "Filters to export non-resource files/folders\n" "(comma-separated, e.g: *.json, *.txt, docs/*)" msgstr "" -"Filtry do eksportowania plików/folderów nie bÄ™dÄ…cych zasobami (oddzielone " -"przecinkami, np. *.json, *.txt)" +"Filtry do eksportowania plików/folderów nie bÄ™dÄ…cych zasobami\n" +"(oddzielone przecinkami, np. *.json, *.txt, docs/*)" #: editor/project_export.cpp msgid "" "Filters to exclude files/folders from project\n" "(comma-separated, e.g: *.json, *.txt, docs/*)" msgstr "" -"Filtry do wykluczenia plików/folderów z projektu (rozdzielone przecinkami, " -"np. *.json, *.txt)" +"Filtry do wykluczenia plików/folderów z projektu\n" +"(oddzielone przecinkami, np. *.json, *.txt, docs/*)" #: editor/project_export.cpp msgid "Patches" @@ -10515,9 +10528,8 @@ msgid "Instance Child Scene" msgstr "Dodaj instancjÄ™ sceny" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Dodaj skrypt" +msgstr "Odłącz skrypt" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10635,7 +10647,7 @@ msgstr "Nie można dziaÅ‚ać na wÄ™zÅ‚ach z których dziedziczy obecna scena!" #: editor/scene_tree_dock.cpp msgid "Attach Script" -msgstr "Dodaj skrypt" +msgstr "Dołącz skrypt" #: editor/scene_tree_dock.cpp msgid "Remove Node(s)" @@ -10687,6 +10699,9 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Nie można dołączyć skryptu: brak zarejestrowanych jÄ™zyków.\n" +"To prawdopodobnie przez to, że ten edytor zostaÅ‚ zbudowany z wyłączonymi " +"wszystkimi moduÅ‚ami jÄ™zyków." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10737,14 +10752,12 @@ msgstr "" "główny nie istnieje." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "Dołącz nowy lub istniejÄ…cy skrypt do zaznaczonego wÄ™zÅ‚a." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Wyczyść skrypt dla zaznaczonego wÄ™zÅ‚a." +msgstr "Odłącz skrypt z zaznaczonego wÄ™zÅ‚a." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -10783,7 +10796,7 @@ msgid "" "Node has %s connection(s) and %s group(s).\n" "Click to show signals dock." msgstr "" -"WÄ™zeÅ‚ posiada %s połączeÅ„ i %s grup.\n" +"WÄ™zeÅ‚ posiada %s połączeÅ„ i %s grup.\n" "Kliknij, aby wyÅ›wietlić panel sygnałów." #: editor/scene_tree_editor.cpp @@ -11839,15 +11852,15 @@ msgstr "Znajdź typ wÄ™zÅ‚a" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" -msgstr "Skopiuj WÄ™zeÅ‚" +msgstr "Skopiuj wÄ™zÅ‚y" #: modules/visual_script/visual_script_editor.cpp msgid "Cut Nodes" -msgstr "Wytnij WÄ™zÅ‚y" +msgstr "Wytnij wÄ™zÅ‚y" #: modules/visual_script/visual_script_editor.cpp msgid "Make Function" -msgstr "ZmieÅ„ na funkcjÄ™" +msgstr "ZamieÅ„ na funkcjÄ™" #: modules/visual_script/visual_script_editor.cpp msgid "Refresh Graph" @@ -11969,11 +11982,9 @@ msgstr "" "eksportu." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" -"Debugowy keystore nieskonfigurowany w Ustawieniach Edytora ani w profilu " -"eksportu." +"Wydaniowy keystore jest niepoprawnie skonfigurowany w profilu eksportu." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -12007,26 +12018,34 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Niepoprawny moduÅ‚ \"GodotPaymentV3\" załączony w ustawieniu projektu " +"\"android/modules\" (zmieniony w Godocie 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "\"Use Custom Build\" musi być włączone, by używać wtyczek." #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Degrees Of Freedom\" jest poprawne tylko gdy \"Xr Mode\" jest \"Oculus " +"Mobile VR\"." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" jest poprawne tylko gdy \"Xr Mode\" jest \"Oculus Mobile VR" +"\"." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" jest poprawne tylko gdy \"Xr Mode\" jest \"Oculus Mobile " +"VR\"." #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index 9d46edcbae..bfa3d0b52c 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -5,12 +5,13 @@ # Calum Knott <calum@calumk.com>, 2017. # Zion Nimchuk <zionnimchuk@gmail.com>, 2016-2017. # Allan Nordhøy <epost@anotheragency.no>, 2018. +# David Fatheree <david.fathereewcchs@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:42+0100\n" -"Last-Translator: Allan Nordhøy <epost@anotheragency.no>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: David Fatheree <david.fathereewcchs@gmail.com>\n" "Language-Team: Pirate <https://hosted.weblate.org/projects/godot-engine/" "godot/pr/>\n" "Language: pr\n" @@ -18,7 +19,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.2\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -29,7 +30,7 @@ msgstr "" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "" +msgstr "Expected a strin' o' length 1 (a character)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp @@ -39,19 +40,17 @@ msgstr "Nah enough bytes fer decodin' bytes, or ye got th' wrong ship." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "Shiver me timbers! Ye input %i (not passed) in ye expression!" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" msgstr "" #: core/math/expression.cpp -#, fuzzy msgid "Invalid operands to operator %s, %s and %s." msgstr "Yer index property name '%s' in node %s be walkin' th' plank!" #: core/math/expression.cpp -#, fuzzy msgid "Invalid index of type %s for base type %s" msgstr "Yer index property name '%s' in node %s be walkin' th' plank!" @@ -102,11 +101,11 @@ msgstr "" #: editor/animation_bezier_editor.cpp msgid "Balanced" -msgstr "" +msgstr "Smooth Sailin'" #: editor/animation_bezier_editor.cpp msgid "Mirror" -msgstr "" +msgstr "See'in Double" #: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp msgid "Time:" @@ -767,6 +766,11 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Yer name's got no valid identifier:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 199d828897..426888b3a4 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -16,7 +16,7 @@ # jonathan railarem <railarem@gmail.com>, 2017. # Lucas Silva <lucasb.hpp@gmail.com>, 2018. # Luiz G. Correia <luizgabriell2.0@gmail.com>, 2017. -# Mailson Silva Marins <mailsons335@gmail.com>, 2016. +# Mailson Silva Marins <mailsons335@gmail.com>, 2016, 2020. # MalcomRF <malcomkbk@gmail.com>, 2017. # Marcus Correia <marknokalt@live.com>, 2017-2018. # Michael Alexsander Silva Dias <michaelalexsander@protonmail.com>, 2017-2018. @@ -73,7 +73,7 @@ # Alan Tavares <alan1tavares@gmail.com>, 2019. # Rafael Silveira <res883@gmail.com>, 2019. # Luigi <luigimendeszanchett@gmail.com>, 2019. -# Nicolas Abril <nicolas.abril@protonmail.ch>, 2019. +# Nicolas Abril <nicolas.abril@protonmail.ch>, 2019, 2020. # johnnybigoode <jamarson@gmail.com>, 2019, 2020. # Zeero <igcdzeero@gmail.com>, 2019. # Gian Penna <gianfrancopen@gmail.com>, 2020. @@ -92,13 +92,13 @@ # Anonymous <noreply@weblate.org>, 2020. # André Sousa <andrelvsousa@gmail.com>, 2020. # Kleyton Luiz de Sousa Vieira <kleytonluizdesouzavieira@gmail.com>, 2020. +# Felipe Jesus Macedo <fmacedo746@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: 2016-05-30\n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" -"Last-Translator: Kleyton Luiz de Sousa Vieira " -"<kleytonluizdesouzavieira@gmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: Felipe Jesus Macedo <fmacedo746@gmail.com>\n" "Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_BR/>\n" "Language: pt_BR\n" @@ -106,7 +106,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -125,11 +125,11 @@ msgstr "Não há bytes suficientes para decodificar, ou o formato é inválido." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "Entrada inválida %i (não passou) na expressão" +msgstr "Entrada inválida %i (não passada) na expressão" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "self não pode ser usado porque a instância é nula (não passou)" +msgstr "self não pode ser usado porque a instância é nula (não passada)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." @@ -145,7 +145,7 @@ msgstr "Nome inválido de Ãndice '%s' para base tipo %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" -msgstr "Argumento inválido para construir '%s'" +msgstr "Argumentos inválidos para o construto '%s'" #: core/math/expression.cpp msgid "On call to '%s':" @@ -579,7 +579,7 @@ msgstr "" "Esta animação pertence a uma cena importada, dessa forma, mudanças das " "trilhas importadas não serão salvas.\n" "\n" -"Para ativar a possibilidade de adicionar trilhas customizadas, navegue até " +"Para ativar a possibilidade de adicionar trilhas customizadas, navegue até " "as configurações de importação da cena e defina\n" "\"Animação > Armazenamento\" para \"Arquivos\", ative \"Animação > Mantenha " "Trilhas Customizadas\", então reimporte.\n" @@ -843,6 +843,11 @@ msgid "Method in target node must be specified." msgstr "O método no nó alvo precisa ser especificado." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "O nome não é um identificador valido:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -1919,7 +1924,7 @@ msgstr "Alternar Modo" #: editor/editor_file_dialog.cpp msgid "Focus Path" -msgstr "Focar no Caminho" +msgstr "Habilitar" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" @@ -2622,8 +2627,8 @@ msgid "" "category." msgstr "" "A cena principal não foi definida, selecionar uma?\n" -"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na " -"categoria 'Application'." +"Você pode alterá-la mais tarde nas \"Configurações do Projeto\" na categoria " +"'Application'." #: editor/editor_node.cpp msgid "" @@ -2899,8 +2904,8 @@ msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." msgstr "" -"Malhas e polÃgonos de navegação serão visÃveis no jogo se esta opção estiver " -"ligada." +"Malhas e polÃgonos de navegação serão visÃveis no jogo em execução se esta " +"opção estiver ligada." #: editor/editor_node.cpp msgid "Sync Scene Changes" @@ -3121,13 +3126,13 @@ msgid "" "the \"Use Custom Build\" option should be enabled in the Android export " "preset." msgstr "" -"Isso vai configurar seu projeto para construções customizadas do Android, " -"instalando o modelo de fonte para \"res://android/build\".\n" -"Você pode então aplicar modificações e construir seu próprio APK na guia " -"Exportação (Adicionando módulos, trocando o AndroidManifest.xml, etc.).\n" -"Note que para fazer uma construção customizada, em vez de usar APKs pre-" -"construÃdos, a opção \"Usar Construção Customizada\" deve estar ativa nas " -"predefinições de exportação Android." +"Isso irá configurar o projeto para usar uma build do Android customizada " +"instalando a template raiz para \"res://android/build\".\n" +"Você poderá aplicar modificações e construir um APK customizado em exportar " +"(adicionando módulos, changing the AndroidManifest.xml, etc.).\n" +"Note que para fazer builds customizadas ao invés de usar APKs pré-" +"construÃdas, a opção \"Usar Build Customizada\" deve sestar habilitada na " +"pré-configuração de exportação Android." #: editor/editor_node.cpp msgid "" @@ -4047,7 +4052,7 @@ msgstr "Erro ao rodar script pós-importação:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "Você retornou um objeto derivado de nó no método `post import ()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -5659,7 +5664,7 @@ msgstr "Seleção de Frame" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Preview Canvas Scale" -msgstr "Visualizar Canvas Scale" +msgstr "Pré-visualização da escala do Canvas" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Translation mask for inserting keys." @@ -5667,7 +5672,7 @@ msgstr "Máscara de tradução para inserção de chaves." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation mask for inserting keys." -msgstr "Mascara de rotação para inserção de chaves." +msgstr "Máscara de rotação para inserção de chaves." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale mask for inserting keys." @@ -7005,9 +7010,8 @@ msgid "" msgstr "Falta método conectado '%s' para sinal '%s' do nó '%s' para nó '%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(ignore)" +msgstr "(Ignore)" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7438,27 +7442,27 @@ msgstr "Não disponÃvel ao usar o renderizador GLES2." #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" -msgstr "Visão Livre Esquerda" +msgstr "Visão Livre na Esquerda" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Right" -msgstr "Visão Livre Direita" +msgstr "Visão Livre na Direita" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Forward" -msgstr "Visão Livre Frente" +msgstr "Visão Livre na Frente" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Backwards" -msgstr "Visão Livre Trás" +msgstr "Visão Livre Atrás" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "Visão Livre Cima" +msgstr "Visão Livre em Cima" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" -msgstr "Visão Livre Baixo" +msgstr "Visão Livre Embaixo" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Speed Modifier" @@ -7492,6 +7496,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Clique para alternar entre estados de visibilidade.\n" +"\n" +"Olhos abertos: Gizmo está visÃvel.\n" +"Olhos fechados: Gizmo não está visÃvel.\n" +"Olhos semi-abertos: Gizmo está visÃvel através de superficies opacas (\"raio-" +"x\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7517,7 +7527,7 @@ msgstr "Usar Espaço Local" #: editor/plugins/spatial_editor_plugin.cpp msgid "Use Snap" -msgstr "Usar Snap" +msgstr "Use Snap" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" @@ -8379,9 +8389,9 @@ msgid "" "Shift+LMB: Set wildcard bit.\n" "Click on another Tile to edit it." msgstr "" -"LMB: ligar bit.\n" -"RMB: desligar bit.\n" -"Shift+LMB: Escolher bit wildcard.\n" +"LMB: Ligar bit.\n" +"RMB: Desligar bit.\n" +"Shift+LMB: Escolher bit curinga.\n" "Clique em outro Mosaico para editá-lo." #: editor/plugins/tile_set_editor_plugin.cpp @@ -8516,7 +8526,7 @@ msgstr "Nenhuma mensagem de confirmação foi fornecida" #: editor/plugins/version_control_editor_plugin.cpp msgid "No files added to stage" -msgstr "Nenhum arquivo adicionado ao palco" +msgstr "Nenhum arquivo em espera" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit" @@ -8524,11 +8534,11 @@ msgstr "Confirmação" #: editor/plugins/version_control_editor_plugin.cpp msgid "VCS Addon is not initialized" -msgstr "Extensão VCS não está inicializada" +msgstr "VCS Addon não inicializado" #: editor/plugins/version_control_editor_plugin.cpp msgid "Version Control System" -msgstr "Sistema de Controle de Versionamento" +msgstr "Sistema de Controle de Versão" #: editor/plugins/version_control_editor_plugin.cpp msgid "Initialize" @@ -8536,7 +8546,7 @@ msgstr "Inicializar" #: editor/plugins/version_control_editor_plugin.cpp msgid "Staging area" -msgstr "Ãrea Temporária" +msgstr "Ãrea de espera" #: editor/plugins/version_control_editor_plugin.cpp msgid "Detect new changes" @@ -8560,7 +8570,7 @@ msgstr "ExcluÃdo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Typechange" -msgstr "Alterar tipo" +msgstr "Alteração de tipo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Stage Selected" @@ -8572,11 +8582,11 @@ msgstr "Salvar Tudo" #: editor/plugins/version_control_editor_plugin.cpp msgid "Add a commit message" -msgstr "Adicione uma mensagem de confirmação" +msgstr "Adicione uma mensagem ao commit" #: editor/plugins/version_control_editor_plugin.cpp msgid "Commit Changes" -msgstr "Confirmar Mudanças de Script" +msgstr "Confirmar Mudanças" #: editor/plugins/version_control_editor_plugin.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp @@ -8774,7 +8784,7 @@ msgstr "Cor constante." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Color uniform." -msgstr "Cor uniforme." +msgstr "Uniformidade de cor." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the boolean result of the %s comparison between two parameters." @@ -8890,7 +8900,7 @@ msgstr "Parâmetro de entrada '%s' para o modo de sombra do vértice." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "'%s' input parameter for vertex and fragment shader mode." msgstr "" -"Parâmetro de entrada '%s' para os modos de sombra de vértice e fragmentada." +"Parâmetro de entrada '%s' para os modo de sombra fragmentada e vértice." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Scalar function." @@ -9144,7 +9154,7 @@ msgstr "Execute a pesquisa de textura cúbica." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Perform the texture lookup." -msgstr "Faz uma busca de texturas." +msgstr "Faz uma busca por texturas." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Cubic texture uniform lookup." @@ -9160,7 +9170,7 @@ msgstr "Consulta de textura 2D uniforme com triplanar." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Transform function." -msgstr "Função Transform." +msgstr "Função Transformação..." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9182,7 +9192,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Composes transform from four vectors." -msgstr "Compõe transformação a partir de quatro vetores." +msgstr "Compõe a transformação de quatro vetores." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Decomposes transform to four vectors." @@ -9190,19 +9200,19 @@ msgstr "Decompõe transformação em quatro vetores." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the determinant of a transform." -msgstr "Calcula o determinante de uma transformada." +msgstr "Calcula o determinante de uma transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the inverse of a transform." -msgstr "Calcula a inversa de uma transformada." +msgstr "Calcula a inversa de uma transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the transpose of a transform." -msgstr "Calcula a transposta de uma transformada." +msgstr "Calcula a transposta de uma transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Multiplies transform by transform." -msgstr "Multiplica a transformação por transformação." +msgstr "Multiplica transformação por transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Multiplies vector by transform." @@ -9210,11 +9220,11 @@ msgstr "Multiplica vetor por transformação." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Transform constant." -msgstr "Constante de transformação." +msgstr "Transformar constante." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Transform uniform." -msgstr "Uniforme de transformação." +msgstr "Transformação uniforme." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector function." @@ -9363,11 +9373,11 @@ msgstr "Subtrai vetor de vetor." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector constant." -msgstr "Vetor constante." +msgstr "Constante vetorial." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector uniform." -msgstr "Vector uniforme." +msgstr "Uniformidade vetorial." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9381,12 +9391,13 @@ msgstr "" "declarações de função internas." #: editor/plugins/visual_shader_editor_plugin.cpp +#, fuzzy msgid "" "Returns falloff based on the dot product of surface normal and view " "direction of camera (pass associated inputs to it)." msgstr "" -"Retorna falloff baseado no produto escalar do normal da superfÃcie e da " -"direção de visualização da câmera (passe entradas associadas a ela)." +"Retorna falloff com base no produto dos pontos da superfÃcie normal e na " +"direção de visualização da câmera (passa as entradas associadas a ela)." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9413,7 +9424,7 @@ msgid "" "(Fragment/Light mode only) (Vector) Derivative in 'x' using local " "differencing." msgstr "" -"(Apenas modo Fragmento/Luz) (Vetor) Derivada em 'x' usando diferenciação " +"(Apenas modo Fragmento/Luz) (Vetor) Derivativo em 'x' usando diferenciação " "local." #: editor/plugins/visual_shader_editor_plugin.cpp @@ -9832,7 +9843,7 @@ msgstr "Projeto ausente" #: editor/project_manager.cpp msgid "Error: Project is missing on the filesystem." -msgstr "Erro: O Projeto está ausente no sistema de arquivos." +msgstr "Erro: Projeto não encontrado no sistema de arquivos." #: editor/project_manager.cpp msgid "Can't open project at '%s'." @@ -9854,14 +9865,15 @@ msgid "" "Warning: You won't be able to open the project with previous versions of the " "engine anymore." msgstr "" -"O seguinte arquivo de configurações do projeto não especifica com qual " -"versão do Godot ele foi criado.\n" +"O seguinte arquivo de configurações do projeto não especifica a versão do " +"Godot pelo qual ele foi criado.\n" "\n" "%s\n" "\n" -"Se escolher abrÃ-lo, será convertido para o formato atual de arquivo de " -"configuração do Godot\n" -"Aviso: Você não poderá mais abrir o projeto com versões anteriores do Godot." +"Se você o abrir, ele será convertido para o formato de arquivo da " +"configuração atual do Godot.\n" +"Atenção: Você não será mais capaz de abrir o projeto com versões anteriores " +"da engine." #: editor/project_manager.cpp msgid "" @@ -9981,7 +9993,7 @@ msgstr "Novo Projeto" #: editor/project_manager.cpp msgid "Remove Missing" -msgstr "Remover Ausentes" +msgstr "Remover Ausente" #: editor/project_manager.cpp msgid "Templates" @@ -10144,7 +10156,7 @@ msgstr "Botão Direito." #: editor/project_settings_editor.cpp msgid "Middle Button." -msgstr "Botão do Meio." +msgstr "Botão do Meio." #: editor/project_settings_editor.cpp msgid "Wheel Up." @@ -10572,16 +10584,15 @@ msgstr "Instanciar Cena(s)" #: editor/scene_tree_dock.cpp msgid "Replace with Branch Scene" -msgstr "Substituir com Ramo como Cena" +msgstr "Substituir por cena ramo" #: editor/scene_tree_dock.cpp msgid "Instance Child Scene" msgstr "Instânciar Cena Filha" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Adicionar Script" +msgstr "Remover Script" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10751,6 +10762,9 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Não pode associar um script: Não existem linguagens registradas.\n" +"É provável que o editor tenha sido construido com todos os módulos de " +"linguagem desabilitados." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10801,14 +10815,12 @@ msgstr "" "existir um nó raiz." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." -msgstr "Adicionar um script novo ou existente para o nó selecionado." +msgstr "Adicionar um novo script, ou um já existente, para o nó selecionado." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Remove um script do nó selecionado." +msgstr "Remove o script do nó selecionado." #: editor/scene_tree_dock.cpp msgid "Remote" @@ -10920,7 +10932,7 @@ msgstr "Selecione um Nó" #: editor/script_create_dialog.cpp msgid "Path is empty." -msgstr "O caminho está vazio." +msgstr "Caminho vazio." #: editor/script_create_dialog.cpp msgid "Filename is empty." @@ -11328,7 +11340,7 @@ msgstr "Singleton GDNative ativado" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Disabled GDNative Singleton" -msgstr "Singleton GDNative Desabilitado" +msgstr "GDNative Singleton desativado" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Library" @@ -11589,8 +11601,8 @@ msgid "" "Node yielded, but did not return a function state in the first working " "memory." msgstr "" -"Nó entrou em yield, mas não retornou um estado de função na primeira memória " -"de trabalho." +"O nó cedeu, mas não retornou um estado de função na primeira memória de " +"trabalho." #: modules/visual_script/visual_script.cpp msgid "" @@ -12041,20 +12053,20 @@ msgstr "" #, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" -"Porta-chaves de depuração não configurado nas Configurações do Editor e nem " -"na predefinição." +"Keystore de liberação icorretamente configurada na predefinição de " +"exportação." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." msgstr "" -"A compilação personalizada requer um caminho SDK do Android válido nas " +"Build personalizada precisa de um caminho Android SDK válido em " "Configurações do Editor." #: platform/android/export/export.cpp msgid "Invalid Android SDK path for custom build in Editor Settings." msgstr "" -"Caminho SDK do Android inválido para a compilação personalizada nas " -"Configurações do Editor." +"Caminho do Android SDK inválido para o build personalizado em Configurações " +"do Editor." #: platform/android/export/export.cpp msgid "" @@ -12066,7 +12078,7 @@ msgstr "" #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." -msgstr "Chave pública inválida para expansão de APK." +msgstr "Chave pública inválida para expansão do APK." #: platform/android/export/export.cpp msgid "Invalid package name:" @@ -12077,34 +12089,45 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"Módulo inválido \"GodotPaymentV3\" incluido na configuração de projeto " +"\"android/modules\" (changed in Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." msgstr "" +"\"Use Custom Build\" precisa estar ativo para ser possÃvel utilizar plugins." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"\"Degrees Of Freedom\" só é válido quando o \"Oculus Mobile VR\" está no " +"\"Mode Xr\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" só é válido quando o\"Oculus Mobile VR\" está no \"Xr Mode" +"\"." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" só é válido quando o \"Oculus Mobile VR\" está no \"Xr " +"Mode\"." #: platform/android/export/export.cpp msgid "" "Trying to build from a custom built template, but no version info for it " "exists. Please reinstall from the 'Project' menu." msgstr "" -"Tentando compilar a partir de um modelo compilado personalizado, mas nenhuma " -"informação de versão para ele existe. Por favor, reinstale pelo menu " +"Tentando construir a partir de um modelo compilado personalizado, mas " +"nenhuma informação de versão para ele existe. Por favor, reinstale pelo menu " "'Projeto'." #: platform/android/export/export.cpp @@ -12114,7 +12137,7 @@ msgid "" " Godot Version: %s\n" "Please reinstall Android build template from 'Project' menu." msgstr "" -"Diferença de versão da compilação do Android:\n" +"Diferença na versão da build do Android:\n" " Modelo instalado: %s\n" " Versão do Godot: %s\n" "Por favor reinstale o modelo de compilação do Android pelo menu 'Projeto'." @@ -12128,13 +12151,13 @@ msgid "" "Building of Android project failed, check output for the error.\n" "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" -"A compilação do projeto Android falhou, verifique a saÃda pelo erro.\n" +"A construção do projeto Android falhou, verifique a saÃda para detalhes.\n" "Alternativamente, visite docs.godotengine.org para ver a documentação de " "compilação do Android." #: platform/android/export/export.cpp msgid "No build apk generated at: " -msgstr "Nenhuma compilação apk gerada em: " +msgstr "Nenhuma construção apk gerada em: " #: platform/iphone/export/export.cpp msgid "Identifier is missing." @@ -12545,7 +12568,8 @@ msgstr "" #: scene/3d/collision_shape.cpp msgid "" "ConcavePolygonShape doesn't support RigidBody in another mode than static." -msgstr "Lol." +msgstr "" +"ConcavePolygonShape não suporta um RigidBody em outro modo além do estático." #: scene/3d/cpu_particles.cpp msgid "Nothing is visible because no mesh has been assigned." @@ -12718,7 +12742,7 @@ msgstr "Nada está ligado à entrada '%s' do nó '%s'." #: scene/animation/animation_tree.cpp msgid "No root AnimationNode for the graph is set." -msgstr "Um AnimationNode raiz para o gráfico não está definido." +msgstr "Nenhuma raiz AnimationNode para o gráfico está definida." #: scene/animation/animation_tree.cpp msgid "Path to an AnimationPlayer node containing animations is not set." @@ -12784,9 +12808,9 @@ msgid "" "The Hint Tooltip won't be displayed as the control's Mouse Filter is set to " "\"Ignore\". To solve this, set the Mouse Filter to \"Stop\" or \"Pass\"." msgstr "" -"A Dica não será exibida quando o controle de Filtro do Mouse estiver " -"definido como \"Ignorar\". Para resolver, defina o Filtro do Mouse como " -"\"Parar\" ou \"Continuar\"." +"A sugestão de dica não será exibida quando o Filtro do Mouse do controle " +"estiver definido como \"Ignorar\". Para resolver isto, defina o Filtro do " +"Mouse como \"Parar\" ou \"Passar\"." #: scene/gui/dialogs.cpp msgid "Alert!" @@ -12831,7 +12855,7 @@ msgid "" "Environment -> Default Environment) could not be loaded." msgstr "" "O Ambiente Padrão especificado nas Configurações de Projeto (Rendering -> " -"Environment -> Default Environment) não pôde ser carregado." +"Environment -> Default Environment) não pôde ser carregado." #: scene/main/viewport.cpp msgid "" diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index 40a83eaa87..54accb0d6f 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -768,6 +768,11 @@ msgid "Method in target node must be specified." msgstr "Método no nó alvo deve ser especificado." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "O nome não é um identificador válido:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 5e362de330..cbf6a8f0a0 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -749,6 +749,11 @@ msgid "Method in target node must be specified." msgstr "Metoda din nodul È›intă trebuie specificată." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metoda din nodul È›intă trebuie specificată." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 8bae9207d0..a2e562446d 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -27,7 +27,7 @@ # Yan <uvokinuvokines@gmail.com>, 2018. # V. <Unit68189@gmail.com>, 2018, 2019. # Victor Butorin <mrwebsterchannel@gmail.com>, 2018. -# ÐлекÑандр <ol-vin@mail.ru>, 2018, 2019. +# ÐлекÑандр <ol-vin@mail.ru>, 2018, 2019, 2020. # Ðнатолий Горбунов <afgorbunov@gmail.com>, 2018, 2019. # Vadim Vergasov <vadim.vergasov2003@gmail.com>, 2018, 2019. # ÐÑлан Снупов <aslan170505@gmail.com>, 2018. @@ -76,12 +76,14 @@ # Nikita <Kulacnikita@ya.ru>, 2020. # Alexander <ramzi7208@gmail.com>, 2020. # Alex Tern <ternvein@gmail.com>, 2020. +# Varion Drakon Neonovich <variondrakon@gmail.com>, 2020. +# d2cyb <dmitrydpb@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 12:01+0000\n" -"Last-Translator: Alex Tern <ternvein@gmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: ÐлекÑандр <ol-vin@mail.ru>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -90,7 +92,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.1\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -99,13 +101,13 @@ msgstr "Ðеверный тип аргумента Ð´Ð»Ñ convert(), иÑÐ¿Ð¾Ð»Ñ #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "ОжидалаÑÑŒ Ñтрока длиной 1 (Ñимвол)." +msgstr "ОжидалаÑÑŒ Ñтрока длиной 1 (Ñ‚.е. Ñимвол)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Not enough bytes for decoding bytes, or invalid format." -msgstr "ÐедоÑтаточно байтов Ð´Ð»Ñ Ð´ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ неверный формат." +msgstr "ÐедоÑтаточно байтов Ð´Ð»Ñ Ð´ÐµÐºÐ¾Ð´Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð¹Ñ‚Ð¾Ð² или неверный формат." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -134,7 +136,7 @@ msgstr "ÐедопуÑтимые аргументы Ð´Ð»Ñ Ð¿Ð¾ÑÑ‚Ñ€Ð¾ÐµÐ½Ð¸Ñ #: core/math/expression.cpp msgid "On call to '%s':" -msgstr "Ðа вызове '%s':" +msgstr "При вызове '%s':" #: core/ustring.cpp msgid "B" @@ -190,11 +192,11 @@ msgstr "Ð’Ñтавить ключ здеÑÑŒ" #: editor/animation_bezier_editor.cpp msgid "Duplicate Selected Key(s)" -msgstr "Дублировать выделенные ключ(и)" +msgstr "Дублировать выделенные ключи" #: editor/animation_bezier_editor.cpp msgid "Delete Selected Key(s)" -msgstr "Удалить выделенные ключ(и)" +msgstr "Удалить выделенные ключи" #: editor/animation_bezier_editor.cpp msgid "Add Bezier Point" @@ -242,7 +244,7 @@ msgstr "Многократное изменение перехода" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Transform" -msgstr "Ðнимационное многократное изменение положениÑ" +msgstr "Ðнимационное многоÑменное преобразование" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Keyframe Value" @@ -250,7 +252,7 @@ msgstr "Изменить значение ключевого кадра" #: editor/animation_track_editor.cpp msgid "Anim Multi Change Call" -msgstr "Ðнимационный многократный вызов изменениÑ" +msgstr "Изменить вызов анимации" #: editor/animation_track_editor.cpp msgid "Change Animation Length" @@ -320,7 +322,7 @@ msgstr "Изменить Путь СледованиÑ" #: editor/animation_track_editor.cpp msgid "Toggle this track on/off." -msgstr "Переключить Ñтот трек вкл/выкл." +msgstr "Включить/выключить Ñтот трек." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" @@ -328,16 +330,15 @@ msgstr "Режим ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ (Как Ñто ÑвойÑтво уÑта #: editor/animation_track_editor.cpp msgid "Interpolation Mode" -msgstr "Режим Перехода" +msgstr "Режим интерполÑции" #: editor/animation_track_editor.cpp msgid "Loop Wrap Mode (Interpolate end with beginning on loop)" -msgstr "" -"Режим Обработки Ð—Ð°Ñ†Ð¸ÐºÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ (Переход заканчиваетÑÑ Ñ Ð½Ð°Ñ‡Ð°Ð»Ð¾Ð¼ нового цикла)" +msgstr "Режим Ð·Ð°Ñ†Ð¸ÐºÐ»Ð¸Ð²Ð°Ð½Ð¸Ñ (интерполировать начало и конец при зацикливании)" #: editor/animation_track_editor.cpp msgid "Remove this track." -msgstr "Удалить Ñтот трек." +msgstr "Удалить Ñту дорожку." #: editor/animation_track_editor.cpp msgid "Time (s): " @@ -403,7 +404,7 @@ msgstr "Изменить режим Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ð¸" #: editor/animation_track_editor.cpp msgid "Change Animation Interpolation Mode" -msgstr "Изменить режим интерполÑции анимации" +msgstr "Изменить ÑпоÑоб интерполÑции анимации" #: editor/animation_track_editor.cpp msgid "Change Animation Loop Mode" @@ -463,7 +464,8 @@ msgstr "ПереÑтавить дорожки" #: editor/animation_track_editor.cpp msgid "Transform tracks only apply to Spatial-based nodes." -msgstr "Трек транÑформации применÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ к оÑнованным на Spatial узлам." +msgstr "" +"Дорожка Ð¿Ñ€ÐµÐ¾Ð±Ñ€Ð°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÑетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ к оÑнованным на Spatial узлам." #: editor/animation_track_editor.cpp msgid "" @@ -472,14 +474,14 @@ msgid "" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" msgstr "" -"Aудио треки могут указывать только на узлы типа:\n" +"Ðудио дорожки могут указывать только на узлы типа:\n" "-AudioStreamPlayer\n" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" #: editor/animation_track_editor.cpp msgid "Animation tracks can only point to AnimationPlayer nodes." -msgstr "Треки Ðнимации могут указывать только на узлы типа AnimationPlayer." +msgstr "Дорожки анимации могут указывать только на узлы типа AnimationPlayer." #: editor/animation_track_editor.cpp msgid "An animation player can't animate itself, only other players." @@ -487,11 +489,11 @@ msgstr "Проигрыватель анимации не может анимир #: editor/animation_track_editor.cpp msgid "Not possible to add a new track without a root" -msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ новый трек без корневого узла" +msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ новую дорожку без корневого узла" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" -msgstr "Ðеверный трек Ð´Ð»Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹ Безье (нет подходÑщих подÑвойÑтв)" +msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð´Ð¾Ñ€Ð¾Ð¶ÐºÐ° Ð´Ð»Ñ ÐºÑ€Ð¸Ð²Ð¾Ð¹ Безье (нет подходÑщих подÑвойÑтв)" #: editor/animation_track_editor.cpp msgid "Add Bezier Track" @@ -499,11 +501,11 @@ msgstr "Добавить дорожку Безье" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a key." -msgstr "Путь трека некорректен, потому Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ключ." +msgstr "Путь к дорожке некорректен, потому Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ключ." #: editor/animation_track_editor.cpp msgid "Track is not of type Spatial, can't insert key" -msgstr "Трек не имеет тип Spatial, Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ключ" +msgstr "Дорожка не имеет тип Spatial, Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ключ" #: editor/animation_track_editor.cpp msgid "Add Transform Track Key" @@ -515,11 +517,11 @@ msgstr "Добавить ключ дорожки" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a method key." -msgstr "Путь трека некорректен, потому Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ключ метода." +msgstr "Путь к дорожке некорректен, потому Ð½ÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ ключ метода." #: editor/animation_track_editor.cpp msgid "Add Method Track Key" -msgstr "Добавить ключ отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð°" +msgstr "Добавить ключ дорожки Ð´Ð»Ñ Ð¼ÐµÑ‚Ð¾Ð´Ð°" #: editor/animation_track_editor.cpp msgid "Method not found in object: " @@ -546,7 +548,7 @@ msgid "" "This option does not work for Bezier editing, as it's only a single track." msgstr "" "Ðта Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ðµ работает Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÑ€Ð¸Ð²Ñ‹Ð¼Ð¸ Безье, так как Ñто только " -"один трек." +"одна дорожка." #: editor/animation_track_editor.cpp msgid "" @@ -561,14 +563,14 @@ msgid "" "files." msgstr "" "Ð”Ð°Ð½Ð½Ð°Ñ Ð°Ð½Ð¸Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ‚ импортированной Ñцене, поÑтому изменениÑ, " -"внеÑенные в импортированные треки, не будут Ñохранены.\n" +"внеÑенные в импортированные дорожки, не будут Ñохранены.\n" "\n" -"Чтобы активировать возможноÑть Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких треков, перейдите " -"к наÑтройкам импорта Ñцены и уÑтановите\n" +"Чтобы активировать возможноÑть Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑких дорожек, " +"перейдите к наÑтройкам импорта Ñцены и уÑтановите\n" "\"ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ > Хранилище\" в значение \"Файлы\", а также включите пункт " -"\"ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ > СохранÑть пользовательÑкие треки\", и заново импортируйте " +"\"ÐÐ½Ð¸Ð¼Ð°Ñ†Ð¸Ñ > СохранÑть пользовательÑкие дорожки\", и заново импортируйте " "Ñцену.\n" -"Ð’ качеÑтве альтернативы иÑпользуйте преÑет импорта, который импортирует " +"Ð’ качеÑтве альтернативы иÑпользуйте шаблон импорта, который импортирует " "анимации в отдельные файлы." #: editor/animation_track_editor.cpp @@ -581,11 +583,11 @@ msgstr "Выберите узел AnimationPlayer Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ рР#: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." -msgstr "Показывать треки только выделенных в дереве узлов." +msgstr "Показывать дорожки только выделенных в дереве узлов." #: editor/animation_track_editor.cpp msgid "Group tracks by node or display them as plain list." -msgstr "Группировать треки по узлам или показывать их как проÑтой ÑпиÑок." +msgstr "Группировать дорожки по узлам или показывать их как проÑтой ÑпиÑок." #: editor/animation_track_editor.cpp msgid "Snap:" @@ -619,7 +621,7 @@ msgstr "СвойÑтва анимации." #: editor/animation_track_editor.cpp msgid "Copy Tracks" -msgstr "Копировать треки" +msgstr "Копировать дорожки" #: editor/animation_track_editor.cpp msgid "Scale Selection" @@ -635,7 +637,7 @@ msgstr "Дублировать выделенное" #: editor/animation_track_editor.cpp msgid "Duplicate Transposed" -msgstr "Дублировать и перемеÑтить" +msgstr "Дублировать и транÑпонировать" #: editor/animation_track_editor.cpp msgid "Delete Selection" @@ -825,7 +827,12 @@ msgstr "Ðомера Ñтрок и Ñтолбцов." #: editor/connections_dialog.cpp msgid "Method in target node must be specified." -msgstr "Метод должен быть указан в целевом узле." +msgstr "Метод в целевом узле должен быть указан." + +#: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Ð˜Ð¼Ñ Ð½Ðµ ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым идентификатором:" #: editor/connections_dialog.cpp msgid "" @@ -837,7 +844,7 @@ msgstr "" #: editor/connections_dialog.cpp msgid "Connect to Node:" -msgstr "ПриÑоединить к узлу:" +msgstr "ПриÑоединить к Узлу:" #: editor/connections_dialog.cpp msgid "Connect to Script:" @@ -849,7 +856,7 @@ msgstr "От Ñигнала:" #: editor/connections_dialog.cpp msgid "Scene does not contain any script." -msgstr "Узел не Ñодержит Ñкрипт." +msgstr "Сцена не Ñодержит каких-либо Ñкриптов." #: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp #: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp @@ -870,7 +877,7 @@ msgstr "Удалить" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" -msgstr "Добавить дополнительный параметр вызова:" +msgstr "Добавить дополнительный аргумент вызова:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" @@ -956,7 +963,7 @@ msgstr "Подключить Ñигнал к методу" #: editor/connections_dialog.cpp msgid "Edit Connection:" -msgstr "Редактировать подключение:" +msgstr "Редактировать Ñоединение:" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" @@ -1093,7 +1100,7 @@ msgstr "Владельцы:" #: editor/dependency_editor.cpp msgid "Remove selected files from the project? (Can't be restored)" -msgstr "Удалить выбранные файлы из проекта? (ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ!)" +msgstr "Удалить выбранные файлы из проекта? (ÐÐµÐ»ÑŒÐ·Ñ Ð²Ð¾ÑÑтановить)" #: editor/dependency_editor.cpp msgid "" @@ -1522,7 +1529,7 @@ msgstr "ПереÑтановка автозагрузок" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð²Ð°Ð¸Ñ‚ÑŒ автозагрузку:" +msgstr "Ðе удаётÑÑ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ автозагрузку:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -2482,7 +2489,7 @@ msgstr "Ðе возможно загрузить Ñцену, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ #: editor/editor_node.cpp msgid "Reload Saved Scene" -msgstr "Перезагрузить Ñохранённую Ñцену" +msgstr "Перезагрузить Ñохраненную Ñцену" #: editor/editor_node.cpp msgid "" @@ -2768,12 +2775,12 @@ msgstr "Ðабор тайлов..." #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Undo" -msgstr "Отменить" +msgstr "Отменить (Undo)" #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Redo" -msgstr "Повторить" +msgstr "Повторить (Redo)" #: editor/editor_node.cpp msgid "Miscellaneous project or scene-wide tools." @@ -2930,7 +2937,7 @@ msgstr "Макет редактора" #: editor/editor_node.cpp msgid "Take Screenshot" -msgstr "Сделать Ñнимок Ñкрана" +msgstr "Сделать Ñкриншот" #: editor/editor_node.cpp msgid "Screenshots are stored in the Editor Data/Settings Folder." @@ -3000,7 +3007,7 @@ msgstr "СообщеÑтво" #: editor/editor_node.cpp msgid "About" -msgstr "О движке" +msgstr "О Godot Engine" #: editor/editor_node.cpp msgid "Play the project." @@ -3181,7 +3188,7 @@ msgstr "Открыть предыдущий редактор" #: editor/editor_node.h msgid "Warning!" -msgstr "Внимание!" +msgstr "Предупреждение!" #: editor/editor_path.cpp msgid "No sub-resources found." @@ -3290,7 +3297,7 @@ msgstr "[ПуÑто]" #: editor/editor_properties.cpp editor/plugins/root_motion_editor_plugin.cpp msgid "Assign..." -msgstr "ÐазначаетÑÑ..." +msgstr "УÑтанавливать.." #: editor/editor_properties.cpp msgid "Invalid RID" @@ -4025,7 +4032,7 @@ msgstr "Ошибка запуÑка поÑÑ‚-импорт Ñкрипта:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "Ð’Ñ‹ вернули производный от Node объект в методе `post_import ()`?" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -4243,7 +4250,7 @@ msgstr "Загрузка..." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Move Node Point" -msgstr "Передвинуть узел" +msgstr "Передвинуть точку узла" #: editor/plugins/animation_blend_space_1d_editor.cpp msgid "Change BlendSpace1D Limits" @@ -4698,7 +4705,7 @@ msgstr "ПеремеÑтить узел" #: editor/plugins/animation_state_machine_editor.cpp msgid "Transition exists!" -msgstr "Переход уже ÑущеÑтвует!" +msgstr "Переход ÑущеÑтвует!" #: editor/plugins/animation_state_machine_editor.cpp msgid "Add Transition" @@ -5632,7 +5639,7 @@ msgstr "МаÑштаб при проÑмотре холÑта" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Translation mask for inserting keys." -msgstr "МаÑка Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»Ñемых ключей." +msgstr "МаÑка транÑформации Ð´Ð»Ñ Ð²Ñтавки ключей." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation mask for inserting keys." @@ -5665,7 +5672,7 @@ msgstr "ÐвтовÑтавка ключа" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Animation Key and Pose Options" -msgstr "ÐаÑтройки ключевых кадров и поз" +msgstr "Опции анимационных ключей и поз" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key (Existing Tracks)" @@ -5777,7 +5784,7 @@ msgstr "МаÑка излучениÑ" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Solid Pixels" -msgstr "Сплошные пикÑели" +msgstr "Залитые пикÑели" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp @@ -5923,16 +5930,15 @@ msgstr "Ðто не работает на корне Ñцены!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Shape" -msgstr "Создать треугольную Ñетку ÑтатичеÑкой формы" +msgstr "Создать Ñетку ÑтатичеÑкой формы" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Can't create a single convex collision shape for the scene root." -msgstr "" -"Ðе удаетÑÑ Ñоздать единÑтвенную выпуклую форму ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð½Ñ Ñцены." +msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ñоздать единую выпуклую форму ÑÑ‚Ð¾Ð»ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ Ð´Ð»Ñ ÐºÐ¾Ñ€Ð½Ñ Ñцены." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Couldn't create a single convex collision shape." -msgstr "Ðе удалоÑÑŒ Ñоздать одну выпуклую форму Ñтолкновений." +msgstr "Ðе удалоÑÑŒ Ñоздать ни одной выпуклой формы ÑтолкновениÑ." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Single Convex Shape" @@ -5945,11 +5951,11 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Couldn't create any collision shapes." -msgstr "Ðе удалоÑÑŒ Ñоздать ни одной форму ÑтолкновениÑ." +msgstr "Ðе удалоÑÑŒ Ñоздать ни одну форму ÑтолкновениÑ." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Multiple Convex Shapes" -msgstr "Создать неÑколько выпуклых форм" +msgstr "Создать неÑкольких выпуклых фигур" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Navigation Mesh" @@ -6035,7 +6041,7 @@ msgstr "" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Multiple Convex Collision Siblings" -msgstr "Создать неÑколько ÑоÑедних выпуклых форм ÑтолкновениÑ" +msgstr "Создать выпуклую облаÑть ÑтолкновениÑ" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "" @@ -6056,10 +6062,10 @@ msgid "" "This can be used instead of the SpatialMaterial Grow property when using " "that property isn't possible." msgstr "" -"Создаёт Ñтатичную обводочную полиÑетку. Её нормали переворачиваютÑÑ " -"автоматичеÑки.\n" -"Она может быть иÑпользована в Ñлучае, еÑли иÑпользовать ÑвойÑтво Grow " -"материала SpatialMaterial не предÑтавлÑетÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹Ð¼." +"Создать Ñтатичную контурную полиÑетку. ÐšÐ¾Ð½Ñ‚ÑƒÑ€Ð½Ð°Ñ Ð¿Ð¾Ð»Ð¸Ñетка будет иметь Ñвои " +"нормали, перевернутые автоматичеÑки.\n" +"Можно иÑпользовать вмеÑто ÑвойÑтва Grow в SpatialMaterial, в Ñлучае когда " +"оно не применимо." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "View UV1" @@ -6974,7 +6980,6 @@ msgstr "" "'%s'." #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" msgstr "(игнорировать)" @@ -7335,7 +7340,7 @@ msgstr "ВыравнÑть преобразование Ñ Ð¾Ð±Ð»Ð°Ñтью пр #: editor/plugins/spatial_editor_plugin.cpp msgid "Align Rotation with View" -msgstr "ВыравнÑть поворот Ñ Ð¾Ð±Ð»Ð°Ñтью проÑмотра" +msgstr "СовмеÑтить поворот Ñ Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ взглÑда" #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "No parent to instance a child at." @@ -7462,6 +7467,12 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Ðажмите Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ ÑоÑтоÑниÑми видимоÑти.\n" +"\n" +"Открытый глаз: Гизмо видно.\n" +"Закрытый глаз: Гизмо Ñкрыто.\n" +"Полуоткрытый глаз: Гизмо также видно Ñквозь непрозрачные поверхноÑти " +"(«рентген»)." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7694,7 +7705,7 @@ msgstr "" #: editor/plugins/sprite_editor_plugin.cpp msgid "Invalid geometry, can't replace by mesh." -msgstr "ÐÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð°Ñ Ð³ÐµÐ¾Ð¼ÐµÑ‚Ñ€Ð¸Ñ, не может быть заменена Ñеткой." +msgstr "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ð³ÐµÐ¾Ð¼ÐµÑ‚Ñ€Ð¸Ñ, не может быть заменена полиÑеткой." #: editor/plugins/sprite_editor_plugin.cpp msgid "Convert to Mesh2D" @@ -8597,7 +8608,7 @@ msgstr "Добавить входной порт" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add output port" -msgstr "Добавить выходной порт" +msgstr "Добавить иÑходÑщий порт" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Change input port type" @@ -8678,7 +8689,7 @@ msgstr "Показать полученный код шейдера." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Create Shader Node" -msgstr "Создать узел шейдера" +msgstr "Создать Шейдерный узел" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Color function." @@ -8722,7 +8733,7 @@ msgstr "Оператор выцветаниÑ." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "HardLight operator." -msgstr "Оператор HardLight." +msgstr "Оператор жёÑткого Ñвета." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Lighten operator." @@ -9239,7 +9250,7 @@ msgstr "Ð›Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑÑ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ð´Ð²ÑƒÐ¼Ñ Ð²ÐµÐºÑ‚ #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Linear interpolation between two vectors using scalar." -msgstr "Ð›Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑÑ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ð´Ð²ÑƒÐ¼Ñ Ð²ÐµÐºÑ‚Ð¾Ñ€Ð°Ð¼Ð¸ Ñ Ð¸Ñпользованием ÑкалÑра." +msgstr "Ð›Ð¸Ð½ÐµÐ¹Ð½Ð°Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»ÑÑ†Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ð´Ð²ÑƒÐ¼Ñ Ð²ÐµÐºÑ‚Ð¾Ñ€Ð°Ð¼Ð¸ иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ ÑкалÑÑ€." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the normalize product of vector." @@ -10166,7 +10177,7 @@ msgstr "ÐаÑтройки Ñохранены нормально." #: editor/project_settings_editor.cpp msgid "Moved Input Action Event" -msgstr "Событие ввода дейÑÑ‚Ð²Ð¸Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¾" +msgstr "ПеренеÑите Ñобытие ввода дейÑтвиÑ" #: editor/project_settings_editor.cpp msgid "Override for Feature" @@ -10551,7 +10562,6 @@ msgid "Instance Child Scene" msgstr "Добавить дочернюю Ñцену" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" msgstr "Прикрепить Ñкрипт" @@ -10724,6 +10734,9 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Ðевозможно прикрепить Ñкрипт: нет зарегиÑтрированных Ñзыков.\n" +"ВероÑтно, Ñто ÑвÑзано Ñ Ñ‚ÐµÐ¼, что Ñтот редактор был поÑтроен Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ‹Ð¼Ð¸ " +"вÑеми Ñзыковыми модулÑми." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10774,12 +10787,10 @@ msgstr "" "не ÑущеÑтвует." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "Прикрепить новый или ÑущеÑтвующий Ñкрипт к выбранному узлу." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." msgstr "Убрать Ñкрипт у выбранного узла." @@ -11387,7 +11398,7 @@ msgstr "Залить выделенную GridMap" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "GridMap Paste Selection" -msgstr "Ð’Ñтавить выделенную Ñетку" +msgstr "Ð’Ñтавка выделенной Ñетки" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "GridMap Paint" @@ -12008,7 +12019,6 @@ msgstr "" "предуÑтановках." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." msgstr "" "ÐžÑ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ ÐºÐ»Ð°Ð²Ð¸Ð°Ñ‚ÑƒÑ€Ð° не наÑтроена ни в наÑтройках редактора, ни в " @@ -12046,26 +12056,34 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"ÐедопуÑтимый модуль «GodotPaymentV3», включенный в наÑтройку проекта " +"«android/modules» (изменен в Godot 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "«Use Custom Build» должен быть включен Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð»Ð°Ð³Ð¸Ð½Ð¾Ð²." #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." msgstr "" +"«Степени Ñвободы» дейÑтвительны только тогда, когда «Xr Mode» - Ñто «Oculus " +"Mobile VR»." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"«ОтÑлеживание рук» дейÑтвует только тогда, когда «Xr Mode» - Ñто «Oculus " +"Mobile VR»." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"«ОÑведомленноÑть о фокуÑе» дейÑтвительна только в том Ñлучае, еÑли «Режим " +"Xr» - Ñто «Oculus Mobile VR»." #: platform/android/export/export.cpp msgid "" @@ -12298,7 +12316,7 @@ msgstr "" #: scene/2d/light_occluder_2d.cpp msgid "The occluder polygon for this occluder is empty. Please draw a polygon." msgstr "" -"ЗаÑлонÑющий полигон Ð´Ð»Ñ Ñтого окклюдера пуÑÑ‚. ПожалуйÑта, нариÑуйте полигон." +"ЗаÑлонÑющий полигон Ð´Ð»Ñ Ñтого окклюдера пуÑÑ‚. ПожалуйÑта, добавьте полигон." #: scene/2d/navigation_polygon.cpp msgid "" diff --git a/editor/translations/si.po b/editor/translations/si.po index 4d252a53d6..141696c00a 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -756,6 +756,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sk.po b/editor/translations/sk.po index a341552d1c..0920487af3 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -756,6 +756,11 @@ msgid "Method in target node must be specified." msgstr "Metóda v target node-e musà byÅ¥ Å¡pecifikovaná." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metóda v target node-e musà byÅ¥ Å¡pecifikovaná." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sl.po b/editor/translations/sl.po index faec304f67..114dce1e63 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -799,6 +799,11 @@ msgstr "Metoda v ciljnem gradniku mora biti navedena!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Ime ni pravilen identifikator:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sq.po b/editor/translations/sq.po index 5bcf15eb82..32d08c7bc9 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -744,6 +744,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index 4e7064f00c..01d8c4ca91 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -841,6 +841,11 @@ msgstr "Метода у циљаном чвору мора бити наведе #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Име није важећи идентификатор:" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index e62d152c45..fe13877f42 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -765,6 +765,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/sv.po b/editor/translations/sv.po index e316c74160..ddd0188d5d 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -772,6 +772,11 @@ msgstr "Metod i MÃ¥l-Node mÃ¥ste specificeras!" #: editor/connections_dialog.cpp #, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Metod i MÃ¥l-Node mÃ¥ste specificeras!" + +#: editor/connections_dialog.cpp +#, fuzzy msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ta.po b/editor/translations/ta.po index b8ea8d3538..8f161acfc9 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -757,6 +757,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/te.po b/editor/translations/te.po index 589064278d..87fb947dd0 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -736,6 +736,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/th.po b/editor/translations/th.po index db7fd6adea..3af6fde5a0 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -744,6 +744,11 @@ msgid "Method in target node must be specified." msgstr "ต้à¸à¸‡à¸£à¸°à¸šà¸¸à¹€à¸¡à¸˜à¸à¸”ในโหนดเป้าหมาย" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "ไม่สามารถใช้ชื่à¸à¸™à¸µà¹‰à¹„ด้:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/tr.po b/editor/translations/tr.po index 277cc2c807..27886e1d4d 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -798,6 +798,11 @@ msgid "Method in target node must be specified." msgstr "Hedef düğümdeki metod tanımlanmalı." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Ad doÄŸru bir belirleyici deÄŸil:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/uk.po b/editor/translations/uk.po index 75cce04e0e..66d7caab34 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -773,6 +773,11 @@ msgid "Method in target node must be specified." msgstr "Має бути вказано метод у цільовому вузлі." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Ðазва не Ñ” коректним ідентифікатором:" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index 10558ad98e..6985cbdc39 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -746,6 +746,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/vi.po b/editor/translations/vi.po index fe846d5e08..ff214a7091 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -763,6 +763,11 @@ msgid "Method in target node must be specified." msgstr "Phương thức trong nút Ä‘Ãch phải được chỉ định." #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "Phương thức trong nút Ä‘Ãch phải được chỉ định." + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index 5dc2b5948f..4acf70b8ae 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -64,12 +64,14 @@ # binotaliu <binota@protonmail.ch>, 2020. # BinotaLIU <binota@protonmail.ch>, 2020. # Tim Bao <honiebao@gmail.com>, 2020. +# UnluckyNinja <unluckyninja1994@gmail.com>, 2020. +# æ— åŒæµ <1257678024@qq.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Chinese (Simplified) (Godot Engine)\n" "POT-Creation-Date: 2018-01-20 12:15+0200\n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" -"Last-Translator: Tim Bao <honiebao@gmail.com>\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" +"Last-Translator: æ— åŒæµ <1257678024@qq.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hans/>\n" "Language: zh_CN\n" @@ -77,7 +79,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -806,6 +808,11 @@ msgid "Method in target node must be specified." msgstr "å¿…é¡»æŒ‡å®šç›®æ ‡èŠ‚ç‚¹çš„æ–¹æ³•ã€‚" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "åç§°ä¸æ˜¯æœ‰æ•ˆçš„æ ‡è¯†ç¬¦ï¼š" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -2438,6 +2445,8 @@ msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"当å‰åœºæ™¯æœ‰æœªä¿å˜çš„æ›´æ”¹ã€‚\n" +"是å¦é‡æ–°åŠ è½½ä¿å˜çš„场景? æ¤æ“ä½œæ— æ³•æ’¤æ¶ˆã€‚" #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -2655,7 +2664,7 @@ msgstr "ä¸‹ä¸€ä¸ªæ ‡ç¾é¡µ" #: editor/editor_node.cpp msgid "Previous tab" -msgstr "ä¸Šä¸€ä¸ªæ ‡ç¾é¡µ" +msgstr "ä¸Šä¸€ä¸ªæ ‡ç¾" #: editor/editor_node.cpp msgid "Filter Files..." @@ -2855,7 +2864,7 @@ msgstr "编辑器布局" #: editor/editor_node.cpp msgid "Take Screenshot" -msgstr "截å–å±å¹•" +msgstr "截å±" #: editor/editor_node.cpp msgid "Screenshots are stored in the Editor Data/Settings Folder." @@ -3339,9 +3348,8 @@ msgid "Did you forget the '_run' method?" msgstr "您是å¦é—æ¼äº†_run()方法?" #: editor/editor_spin_slider.cpp -#, fuzzy msgid "Hold Ctrl to round to integers. Hold Shift for more precise changes." -msgstr "按ä½Ctrl键放置一个Getter节点。按ä½Shift键放置一个通用ç¾å。" +msgstr "按ä½Ctrlé”®æ¥å››èˆäº”入至整数。 按ä½Shifté”®èŽ·å–æ›´ç²¾ç¡®çš„å˜åŒ–。" #: editor/editor_sub_scene.cpp msgid "Select Node(s) to Import" @@ -3932,7 +3940,7 @@ msgstr "åŽå¤„ç†è„šæœ¬è¿è¡Œå‘生错误:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" -msgstr "" +msgstr "ä½ æ˜¯å¦åœ¨ `post_import()` 方法ä¸è¿”回了 Node è¡ç”Ÿå¯¹è±¡ï¼Ÿ" #: editor/import/resource_importer_scene.cpp msgid "Saving..." @@ -6844,9 +6852,8 @@ msgid "" msgstr "未找到方法“%sâ€ï¼ˆè¿žæŽ¥äºŽä¿¡å·â€œ%sâ€ã€æ¥è‡ªèŠ‚ç‚¹â€œ%sâ€ã€ç›®æ ‡èŠ‚ç‚¹â€œ%sâ€ï¼‰ã€‚" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "[Ignore]" -msgstr "(忽略)" +msgstr "[忽略]" #: editor/plugins/script_text_editor.cpp msgid "Line" @@ -7276,27 +7283,27 @@ msgstr "使用GLES2渲染器时ä¸å¯ç”¨ã€‚" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Left" -msgstr "自由视图 å·¦" +msgstr "自由观看å‘å·¦" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Right" -msgstr "自由视图 å³" +msgstr "自由观看å‘å³" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Forward" -msgstr "自由视图 å‰" +msgstr "自由观看å‘å‰" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Backwards" -msgstr "自由视图 åŽ" +msgstr "自由观看å‘åŽ" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Up" -msgstr "自由视图 上" +msgstr "自由观看å‘上" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Down" -msgstr "自由视图 下" +msgstr "自由观看å‘下" #: editor/plugins/spatial_editor_plugin.cpp msgid "Freelook Speed Modifier" @@ -7330,6 +7337,11 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"点击以切æ¢å¯è§çжæ€ã€‚\n" +"\n" +"ççœ¼ï¼šæ ‡å¿—å¯è§ã€‚\n" +"é—çœ¼ï¼šæ ‡å¿—éšè—。\n" +"åŠççœ¼ï¼šæ ‡å¿—ä¹Ÿå¯ç©¿è¿‡ä¸é€æ˜Žçš„表é¢å¯è§ï¼ˆâ€œXå…‰â€ï¼‰ã€‚" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7359,11 +7371,11 @@ msgstr "使用å¸é™„" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" -msgstr "底视图" +msgstr "仰视图。" #: editor/plugins/spatial_editor_plugin.cpp msgid "Top View" -msgstr "顶视图" +msgstr "俯视" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rear View" @@ -7371,7 +7383,7 @@ msgstr "åŽè§†å›¾" #: editor/plugins/spatial_editor_plugin.cpp msgid "Front View" -msgstr "å‰è§†å›¾" +msgstr "æ£è§†å›¾" #: editor/plugins/spatial_editor_plugin.cpp msgid "Left View" @@ -7383,7 +7395,7 @@ msgstr "å³è§†å›¾" #: editor/plugins/spatial_editor_plugin.cpp msgid "Switch Perspective/Orthogonal View" -msgstr "åˆ‡æ¢æŠ•å½±/æ£äº¤è§†å›¾" +msgstr "切æ¢é€è§†å›¾/æ£äº¤è§†å›¾" #: editor/plugins/spatial_editor_plugin.cpp msgid "Insert Animation Key" @@ -7399,7 +7411,7 @@ msgstr "èšç„¦é€‰ä¸é¡¹" #: editor/plugins/spatial_editor_plugin.cpp msgid "Toggle Freelook" -msgstr "切æ¢è‡ªç”±è§‚察模å¼" +msgstr "切æ¢è‡ªç”±è§‚看" #: editor/plugins/spatial_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp @@ -7408,7 +7420,7 @@ msgstr "å˜æ¢" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Object to Floor" -msgstr "将对象å¸é™„到地æ¿" +msgstr "å¸é™„物体到地é¢" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." @@ -10354,9 +10366,8 @@ msgid "Instance Child Scene" msgstr "实例化å场景" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "æ·»åŠ è„šæœ¬" +msgstr "分离脚本" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10519,6 +10530,8 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"æ— æ³•é™„åŠ è„šæœ¬ï¼šæ²¡æœ‰è¯è¨€è¢«æ³¨å†Œã€‚\n" +"è¿™å¯èƒ½æ˜¯å› 为这个编辑器是在所有è¯è¨€æ¨¡å—被关é—的状æ€ä¸‹è¢«æž„建的。" #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10567,14 +10580,12 @@ msgid "" msgstr "å®žä¾‹åŒ–åœºæ™¯æ–‡ä»¶ä¸ºä¸€ä¸ªèŠ‚ç‚¹ï¼Œå¦‚æžœæ²¡æœ‰æ ¹èŠ‚ç‚¹åˆ™åˆ›å»ºä¸€ä¸ªç»§æ‰¿è‡ªè¯¥æ–‡ä»¶çš„åœºæ™¯ã€‚" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." msgstr "为选ä¸èŠ‚ç‚¹åˆ›å»ºæˆ–è®¾ç½®è„šæœ¬ã€‚" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "清除选ä¸èŠ‚ç‚¹çš„è„šæœ¬ã€‚" +msgstr "从选ä¸èŠ‚ç‚¹åˆ†ç¦»è„šæœ¬ã€‚" #: editor/scene_tree_dock.cpp msgid "Remote" @@ -11780,9 +11791,8 @@ msgid "Debug keystore not configured in the Editor Settings nor in the preset." msgstr "未在编辑器设置或预设ä¸é…置调试密钥库。" #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." -msgstr "未在编辑器设置或预设ä¸é…置调试密钥库。" +msgstr "用于å‘布的密钥å˜å‚¨åœ¨å¯¼å‡ºé¢„è®¾ä¸æœªè¢«æ£ç¡®è®¾ç½®ã€‚" #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -11811,26 +11821,28 @@ msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"“android/modulesâ€é¡¹ç›®è®¾ç½®ï¼ˆå˜æ›´äºŽGodot 3.2.2)ä¸åŒ…å«äº†æ— 效模" +"组“GodotPaymentV3â€.\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "å¿…é¡»å¯ç”¨â€œä½¿ç”¨è‡ªå®šä¹‰æž„å»ºâ€æ‰èƒ½ä½¿ç”¨æ’件。" #: platform/android/export/export.cpp msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." -msgstr "" +msgstr "“自由度â€åªæœ‰åœ¨å½““Xr Modeâ€æ˜¯â€œOculus Mobile VRâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." -msgstr "" +msgstr "“手部追踪â€åªæœ‰åœ¨å½““Xr Modeâ€æ˜¯â€œOculus Mobile VRâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." -msgstr "" +msgstr "“焦点感知â€åªæœ‰åœ¨å½““Xr Modeâ€æ˜¯â€œOculus Mobile VRâ€æ—¶æ‰æœ‰æ•ˆã€‚" #: platform/android/export/export.cpp msgid "" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index 4832307ce5..90c85892f6 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -793,6 +793,10 @@ msgid "Method in target node must be specified." msgstr "" #: editor/connections_dialog.cpp +msgid "Method name must be a valid identifier." +msgstr "" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 22051058ad..129a3fdad4 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -28,7 +28,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-15 01:48+0000\n" +"PO-Revision-Date: 2020-06-22 06:40+0000\n" "Last-Translator: BinotaLIU <me@binota.org>\n" "Language-Team: Chinese (Traditional) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hant/>\n" @@ -37,7 +37,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.1-dev\n" +"X-Generator: Weblate 4.2-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -766,6 +766,11 @@ msgid "Method in target node must be specified." msgstr "å¿…é ˆæŒ‡å®šç›®æ¨™ç¯€é»žçš„æ–¹æ³•ã€‚" #: editor/connections_dialog.cpp +#, fuzzy +msgid "Method name must be a valid identifier." +msgstr "åç¨±ä¸æ˜¯ä¸€å€‹æœ‰æ•ˆçš„è˜åˆ¥ç¬¦ï¼š" + +#: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." @@ -9880,7 +9885,7 @@ msgstr "新增事件" #: editor/project_settings_editor.cpp msgid "Button" -msgstr "Button(按鈕)" +msgstr "Button (按鈕)" #: editor/project_settings_editor.cpp msgid "Left Button." diff --git a/main/main.cpp b/main/main.cpp index 610a6ed672..00760b39b0 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -930,6 +930,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph #endif } + // Initialize user data dir. + OS::get_singleton()->ensure_user_data_dir(); + GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60); ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/multithreaded_server/rid_pool_prealloc", PropertyInfo(Variant::INT, "memory/limits/multithreaded_server/rid_pool_prealloc", PROPERTY_HINT_RANGE, "0,500,1")); // No negative and limit to 500 due to crashes GLOBAL_DEF("network/limits/debugger/max_chars_per_second", 32768); @@ -948,7 +951,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph packed_data->set_disabled(true); globals->set_disable_feature_overrides(true); } - #endif GLOBAL_DEF("logging/file_logging/enable_file_logging", false); @@ -1266,10 +1268,6 @@ Error Main::setup2(Thread::ID p_main_tid_override) { Thread::_main_thread_id = p_main_tid_override; } - /* Initialize user data dir */ - - OS::get_singleton()->ensure_user_data_dir(); - /* Initialize Input */ input = memnew(Input); @@ -1312,6 +1310,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { } rendering_server->init(); + rendering_server->set_render_loop_enabled(!disable_render_loop); OS::get_singleton()->initialize_joypads(); @@ -1634,6 +1633,8 @@ bool Main::start() { GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd"); GLOBAL_DEF("mono/profiler/enabled", false); GLOBAL_DEF("mono/unhandled_exception_policy", 0); + // From editor/csharp_project.cpp. + GLOBAL_DEF("mono/project/auto_update_project", true); #endif DocData doc; @@ -1919,7 +1920,14 @@ bool Main::start() { sml->set_quit_on_go_back(GLOBAL_DEF("application/config/quit_on_go_back", true)); String appname = ProjectSettings::get_singleton()->get("application/config/name"); appname = TranslationServer::get_singleton()->translate(appname); +#ifdef DEBUG_ENABLED + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + DisplayServer::get_singleton()->window_set_title(vformat("%s (DEBUG)", appname)); +#else DisplayServer::get_singleton()->window_set_title(appname); +#endif int shadow_atlas_size = GLOBAL_GET("rendering/quality/shadow_atlas/size"); int shadow_atlas_q0_subdiv = GLOBAL_GET("rendering/quality/shadow_atlas/quadrant_0_subdiv"); @@ -2203,7 +2211,7 @@ bool Main::iteration() { RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames. - if (DisplayServer::get_singleton()->can_any_window_draw() && !disable_render_loop) { + if (DisplayServer::get_singleton()->can_any_window_draw() && RenderingServer::get_singleton()->is_render_loop_enabled()) { if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { if (RenderingServer::get_singleton()->has_changed()) { RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands @@ -2325,8 +2333,8 @@ void Main::cleanup() { ResourceLoader::remove_custom_loaders(); ResourceSaver::remove_custom_savers(); + // Flush before uninitializing the scene, but delete the MessageQueue as late as possible. message_queue->flush(); - memdelete(message_queue); OS::get_singleton()->delete_main_loop(); @@ -2412,6 +2420,10 @@ void Main::cleanup() { OS::get_singleton()->set_restart_on_exit(false, List<String>()); //clear list (uses memory) } + // Now should be safe to delete MessageQueue (famous last words). + message_queue->flush(); + memdelete(message_queue); + unregister_core_driver_types(); unregister_core_types(); diff --git a/main/tests/test_basis.cpp b/main/tests/test_basis.cpp new file mode 100644 index 0000000000..ac25151fd8 --- /dev/null +++ b/main/tests/test_basis.cpp @@ -0,0 +1,325 @@ +/*************************************************************************/ +/* test_fbx.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "test_basis.h" + +#include "core/math/random_number_generator.h" +#include "core/os/os.h" +#include "core/ustring.h" + +namespace TestBasis { + +enum RotOrder { + EulerXYZ, + EulerXZY, + EulerYZX, + EulerYXZ, + EulerZXY, + EulerZYX +}; + +Vector3 deg2rad(const Vector3 &p_rotation) { + return p_rotation / 180.0 * Math_PI; +} + +Vector3 rad2deg(const Vector3 &p_rotation) { + return p_rotation / Math_PI * 180.0; +} + +Basis EulerToBasis(RotOrder mode, const Vector3 &p_rotation) { + Basis ret; + switch (mode) { + case EulerXYZ: + ret.set_euler_xyz(p_rotation); + break; + + case EulerXZY: + ret.set_euler_xzy(p_rotation); + break; + + case EulerYZX: + ret.set_euler_yzx(p_rotation); + break; + + case EulerYXZ: + ret.set_euler_yxz(p_rotation); + break; + + case EulerZXY: + ret.set_euler_zxy(p_rotation); + break; + + case EulerZYX: + ret.set_euler_zyx(p_rotation); + break; + + default: + // If you land here, Please integrate all rotation orders. + CRASH_NOW_MSG("This is not unreachable."); + } + + return ret; +} + +Vector3 BasisToEuler(RotOrder mode, const Basis &p_rotation) { + switch (mode) { + case EulerXYZ: + return p_rotation.get_euler_xyz(); + + case EulerXZY: + return p_rotation.get_euler_xzy(); + + case EulerYZX: + return p_rotation.get_euler_yzx(); + + case EulerYXZ: + return p_rotation.get_euler_yxz(); + + case EulerZXY: + return p_rotation.get_euler_zxy(); + + case EulerZYX: + return p_rotation.get_euler_zyx(); + + default: + // If you land here, Please integrate all rotation orders. + CRASH_NOW_MSG("This is not unreachable."); + return Vector3(); + } +} + +String get_rot_order_name(RotOrder ro) { + switch (ro) { + case EulerXYZ: + return "XYZ"; + case EulerXZY: + return "XZY"; + case EulerYZX: + return "YZX"; + case EulerYXZ: + return "YXZ"; + case EulerZXY: + return "ZXY"; + case EulerZYX: + return "ZYX"; + default: + return "[Not supported]"; + } +} + +bool test_rotation(Vector3 deg_original_euler, RotOrder rot_order) { + // This test: + // 1. Converts the rotation vector from deg to rad. + // 2. Converts euler to basis. + // 3. Converts the above basis back into euler. + // 4. Converts the above euler into basis again. + // 5. Compares the basis obtained in step 2 with the basis of step 4 + // + // The conversion "basis to euler", done in the step 3, may be different from + // the original euler, even if the final rotation are the same. + // This happens because there are more ways to represents the same rotation, + // both valid, using eulers. + // For this reason is necessary to convert that euler back to basis and finally + // compares it. + // + // In this way we can assert that both functions: basis to euler / euler to basis + // are correct. + + bool pass = true; + + // Euler to rotation + const Vector3 original_euler = deg2rad(deg_original_euler); + const Basis to_rotation = EulerToBasis(rot_order, original_euler); + + // Euler from rotation + const Vector3 euler_from_rotation = BasisToEuler(rot_order, to_rotation); + const Basis rotation_from_computed_euler = EulerToBasis(rot_order, euler_from_rotation); + + Basis res = to_rotation.inverse() * rotation_from_computed_euler; + + if ((res.get_axis(0) - Vector3(1.0, 0.0, 0.0)).length() > 0.1) { + OS::get_singleton()->print("Fail due to X %ls\n", String(res.get_axis(0)).c_str()); + pass = false; + } + if ((res.get_axis(1) - Vector3(0.0, 1.0, 0.0)).length() > 0.1) { + OS::get_singleton()->print("Fail due to Y %ls\n", String(res.get_axis(1)).c_str()); + pass = false; + } + if ((res.get_axis(2) - Vector3(0.0, 0.0, 1.0)).length() > 0.1) { + OS::get_singleton()->print("Fail due to Z %ls\n", String(res.get_axis(2)).c_str()); + pass = false; + } + + if (pass) { + // Double check `to_rotation` decomposing with XYZ rotation order. + const Vector3 euler_xyz_from_rotation = to_rotation.get_euler_xyz(); + Basis rotation_from_xyz_computed_euler; + rotation_from_xyz_computed_euler.set_euler_xyz(euler_xyz_from_rotation); + + res = to_rotation.inverse() * rotation_from_xyz_computed_euler; + + if ((res.get_axis(0) - Vector3(1.0, 0.0, 0.0)).length() > 0.1) { + OS::get_singleton()->print("Double check with XYZ rot order failed, due to X %ls\n", String(res.get_axis(0)).c_str()); + pass = false; + } + if ((res.get_axis(1) - Vector3(0.0, 1.0, 0.0)).length() > 0.1) { + OS::get_singleton()->print("Double check with XYZ rot order failed, due to Y %ls\n", String(res.get_axis(1)).c_str()); + pass = false; + } + if ((res.get_axis(2) - Vector3(0.0, 0.0, 1.0)).length() > 0.1) { + OS::get_singleton()->print("Double check with XYZ rot order failed, due to Z %ls\n", String(res.get_axis(2)).c_str()); + pass = false; + } + } + + if (pass == false) { + // Print phase only if not pass. + OS *os = OS::get_singleton(); + os->print("Rotation order: %ls\n.", get_rot_order_name(rot_order).c_str()); + os->print("Original Rotation: %ls\n", String(deg_original_euler).c_str()); + os->print("Quaternion to rotation order: %ls\n", String(rad2deg(euler_from_rotation)).c_str()); + } + + return pass; +} + +void test_euler_conversion() { + Vector<RotOrder> rotorder_to_test; + rotorder_to_test.push_back(EulerXYZ); + rotorder_to_test.push_back(EulerXZY); + rotorder_to_test.push_back(EulerYZX); + rotorder_to_test.push_back(EulerYXZ); + rotorder_to_test.push_back(EulerZXY); + rotorder_to_test.push_back(EulerZYX); + + Vector<Vector3> vectors_to_test; + + // Test the special cases. + vectors_to_test.push_back(Vector3(0.0, 0.0, 0.0)); + vectors_to_test.push_back(Vector3(0.5, 0.5, 0.5)); + vectors_to_test.push_back(Vector3(-0.5, -0.5, -0.5)); + vectors_to_test.push_back(Vector3(40.0, 40.0, 40.0)); + vectors_to_test.push_back(Vector3(-40.0, -40.0, -40.0)); + vectors_to_test.push_back(Vector3(0.0, 0.0, -90.0)); + vectors_to_test.push_back(Vector3(0.0, -90.0, 0.0)); + vectors_to_test.push_back(Vector3(-90.0, 0.0, 0.0)); + vectors_to_test.push_back(Vector3(0.0, 0.0, 90.0)); + vectors_to_test.push_back(Vector3(0.0, 90.0, 0.0)); + vectors_to_test.push_back(Vector3(90.0, 0.0, 0.0)); + vectors_to_test.push_back(Vector3(0.0, 0.0, -30.0)); + vectors_to_test.push_back(Vector3(0.0, -30.0, 0.0)); + vectors_to_test.push_back(Vector3(-30.0, 0.0, 0.0)); + vectors_to_test.push_back(Vector3(0.0, 0.0, 30.0)); + vectors_to_test.push_back(Vector3(0.0, 30.0, 0.0)); + vectors_to_test.push_back(Vector3(30.0, 0.0, 0.0)); + vectors_to_test.push_back(Vector3(0.5, 50.0, 20.0)); + vectors_to_test.push_back(Vector3(-0.5, -50.0, -20.0)); + vectors_to_test.push_back(Vector3(0.5, 0.0, 90.0)); + vectors_to_test.push_back(Vector3(0.5, 0.0, -90.0)); + vectors_to_test.push_back(Vector3(360.0, 360.0, 360.0)); + vectors_to_test.push_back(Vector3(-360.0, -360.0, -360.0)); + vectors_to_test.push_back(Vector3(-90.0, 60.0, -90.0)); + vectors_to_test.push_back(Vector3(90.0, 60.0, -90.0)); + vectors_to_test.push_back(Vector3(90.0, -60.0, -90.0)); + vectors_to_test.push_back(Vector3(-90.0, -60.0, -90.0)); + vectors_to_test.push_back(Vector3(-90.0, 60.0, 90.0)); + vectors_to_test.push_back(Vector3(90.0, 60.0, 90.0)); + vectors_to_test.push_back(Vector3(90.0, -60.0, 90.0)); + vectors_to_test.push_back(Vector3(-90.0, -60.0, 90.0)); + vectors_to_test.push_back(Vector3(60.0, 90.0, -40.0)); + vectors_to_test.push_back(Vector3(60.0, -90.0, -40.0)); + vectors_to_test.push_back(Vector3(-60.0, -90.0, -40.0)); + vectors_to_test.push_back(Vector3(-60.0, 90.0, 40.0)); + vectors_to_test.push_back(Vector3(60.0, 90.0, 40.0)); + vectors_to_test.push_back(Vector3(60.0, -90.0, 40.0)); + vectors_to_test.push_back(Vector3(-60.0, -90.0, 40.0)); + vectors_to_test.push_back(Vector3(-90.0, 90.0, -90.0)); + vectors_to_test.push_back(Vector3(90.0, 90.0, -90.0)); + vectors_to_test.push_back(Vector3(90.0, -90.0, -90.0)); + vectors_to_test.push_back(Vector3(-90.0, -90.0, -90.0)); + vectors_to_test.push_back(Vector3(-90.0, 90.0, 90.0)); + vectors_to_test.push_back(Vector3(90.0, 90.0, 90.0)); + vectors_to_test.push_back(Vector3(90.0, -90.0, 90.0)); + vectors_to_test.push_back(Vector3(20.0, 150.0, 30.0)); + vectors_to_test.push_back(Vector3(20.0, -150.0, 30.0)); + vectors_to_test.push_back(Vector3(-120.0, -150.0, 30.0)); + vectors_to_test.push_back(Vector3(-120.0, -150.0, -130.0)); + vectors_to_test.push_back(Vector3(120.0, -150.0, -130.0)); + vectors_to_test.push_back(Vector3(120.0, 150.0, -130.0)); + vectors_to_test.push_back(Vector3(120.0, 150.0, 130.0)); + + // Add 1000 random vectors with weirds numbers. + RandomNumberGenerator rng; + for (int _ = 0; _ < 1000; _ += 1) { + vectors_to_test.push_back(Vector3( + rng.randf_range(-1800, 1800), + rng.randf_range(-1800, 1800), + rng.randf_range(-1800, 1800))); + } + + bool success = true; + for (int h = 0; h < rotorder_to_test.size(); h += 1) { + int passed = 0; + int failed = 0; + for (int i = 0; i < vectors_to_test.size(); i += 1) { + if (test_rotation(vectors_to_test[i], rotorder_to_test[h])) { + //OS::get_singleton()->print("Success. \n\n"); + passed += 1; + } else { + OS::get_singleton()->print("FAILED FAILED FAILED. \n\n"); + OS::get_singleton()->print("------------>\n"); + OS::get_singleton()->print("------------>\n"); + failed += 1; + success = false; + } + } + + if (failed == 0) { + OS::get_singleton()->print("%i passed tests for rotation order: %ls.\n", passed, get_rot_order_name(rotorder_to_test[h]).c_str()); + } else { + OS::get_singleton()->print("%i FAILED tests for rotation order: %ls.\n", failed, get_rot_order_name(rotorder_to_test[h]).c_str()); + } + } + + if (success) { + OS::get_singleton()->print("Euler conversion checks passed.\n"); + } else { + OS::get_singleton()->print("Euler conversion checks FAILED.\n"); + } +} + +MainLoop *test() { + OS::get_singleton()->print("Start euler conversion checks.\n"); + test_euler_conversion(); + + return NULL; +} + +} // namespace TestBasis diff --git a/scene/gui/tool_button.cpp b/main/tests/test_basis.h index c9f87f0015..67c9db8877 100644 --- a/scene/gui/tool_button.cpp +++ b/main/tests/test_basis.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* tool_button.cpp */ +/* test_fbx.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "tool_button.h" +#ifndef TEST_BASIS_H +#define TEST_BASIS_H -ToolButton::ToolButton() { - set_flat(true); +#include "core/os/main_loop.h" + +namespace TestBasis { +MainLoop *test(); } + +#endif diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp index 0bb8367240..5ebdaf1741 100644 --- a/main/tests/test_main.cpp +++ b/main/tests/test_main.cpp @@ -35,6 +35,7 @@ #ifdef DEBUG_ENABLED #include "test_astar.h" +#include "test_basis.h" #include "test_class_db.h" #include "test_gdscript.h" #include "test_gui.h" @@ -51,6 +52,7 @@ const char **tests_get_names() { static const char *test_names[] = { "string", "math", + "basis", "physics_2d", "physics_3d", "render", @@ -79,6 +81,10 @@ MainLoop *test_main(String p_test, const List<String> &p_args) { return TestMath::test(); } + if (p_test == "basis") { + return TestBasis::test(); + } + if (p_test == "physics_2d") { return TestPhysics2D::test(); } diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 4b2870b67a..2ae3564faf 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -8,58 +8,22 @@ /* Begin PBXBuildFile section */ 1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; }; - 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */; }; - 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926951FBBF7C400F53A6F /* Security.framework */; }; - 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */; }; - 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */; }; - 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926921FBBF7A000F53A6F /* GameController.framework */; }; - 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926911FBBF79500F53A6F /* CoreMotion.framework */; }; - 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */; }; - 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */; }; - 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */; }; - E360193721F32F38009258C1 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E360193621F32F37009258C1 /* CoreVideo.framework */; }; DEADBEEF2F582BE20003B888 /* $binary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DEADBEEF1F582BE20003B888 /* $binary.a */; }; $modules_buildfile 1FF8DBB11FBA9DE1009DE660 /* dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */; }; - 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; }; - 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1861F584E5600A41E41 /* StoreKit.framework */; }; - 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1881F584E7600A41E41 /* StoreKit.framework */; }; D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D07CD44D1C5D589C00B7FB28 /* Images.xcassets */; }; - D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */; }; - D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */; }; - D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */; }; - D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */; }; - D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; }; D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; }; D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = "<group>"; }; - 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; - 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; - 1FE926911FBBF79500F53A6F /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; }; - 1FE926921FBBF7A000F53A6F /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; }; - 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; - 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 1FE926951FBBF7C400F53A6F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; DEADBEEF1F582BE20003B888 /* $binary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot; path = "$binary.a"; sourceTree = "<group>"; }; $modules_fileref - 1FF4C1841F584E3F00A41E41 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; - 1FF4C1861F584E5600A41E41 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; }; - 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "$binary.entitlements"; sourceTree = "<group>"; }; 1FF8DBB01FBA9DE1009DE660 /* dummy.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = "<group>"; }; D07CD44D1C5D589C00B7FB28 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; }; D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "$binary.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - E360193621F32F37009258C1 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; - D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; - D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; }; D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = "$binary.pck"; sourceTree = "<group>"; }; @@ -72,24 +36,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */, - E360193721F32F38009258C1 /* CoreVideo.framework in Frameworks */, - 1FE926991FBBF85400F53A6F /* SystemConfiguration.framework in Frameworks */, - 1FE9269A1FBBF85F00F53A6F /* Security.framework in Frameworks */, - 1FE9269B1FBBF86200F53A6F /* QuartzCore.framework in Frameworks */, - 1FE9269C1FBBF86500F53A6F /* MediaPlayer.framework in Frameworks */, - 1FE9269D1FBBF86600F53A6F /* GameController.framework in Frameworks */, - 1FE9269E1FBBF86900F53A6F /* CoreMotion.framework in Frameworks */, - 1FE9269F1FBBF86B00F53A6F /* CoreMedia.framework in Frameworks */, - 1FE926A11FBBF86D00F53A6F /* CoreAudio.framework in Frameworks */, - 1FE926A01FBBF86D00F53A6F /* AudioToolbox.framework in Frameworks */, - D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */, - 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */, - 1FF4C1871F584E7600A41E41 /* AVFoundation.framework in Frameworks */, - D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */, - 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */, - D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */, - D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */, DEADBEEF2F582BE20003B888 /* $binary.a */, $modules_buildphase $additional_pbx_frameworks_build @@ -122,24 +68,6 @@ D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = { isa = PBXGroup; children = ( - 1FE926961FBBF7D400F53A6F /* SystemConfiguration.framework */, - 1FE926951FBBF7C400F53A6F /* Security.framework */, - 1FE926941FBBF7BD00F53A6F /* QuartzCore.framework */, - 1FE926931FBBF7AD00F53A6F /* MediaPlayer.framework */, - 1FE926921FBBF7A000F53A6F /* GameController.framework */, - 1FE926911FBBF79500F53A6F /* CoreMotion.framework */, - 1FE926901FBBF78E00F53A6F /* CoreMedia.framework */, - 1FE9268F1FBBF77F00F53A6F /* CoreAudio.framework */, - E360193621F32F37009258C1 /* CoreVideo.framework */, - 1FE9268E1FBBF77300F53A6F /* AudioToolbox.framework */, - 1FF4C1861F584E5600A41E41 /* StoreKit.framework */, - 1FF4C1841F584E3F00A41E41 /* GameKit.framework */, - 1FF4C1881F584E7600A41E41 /* AVFoundation.framework */, - D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */, - D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */, - D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */, - D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */, - D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */, DEADBEEF1F582BE20003B888 /* $binary.a */, $modules_buildgrp $additional_pbx_frameworks_refs @@ -433,7 +361,7 @@ "$(inherited)", "$(PROJECT_DIR)", ); - PRODUCT_BUNDLE_IDENTIFIER = $identifier; + PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -459,7 +387,7 @@ "$(inherited)", "$(PROJECT_DIR)", ); - PRODUCT_BUNDLE_IDENTIFIER = $identifier; + PRODUCT_BUNDLE_IDENTIFIER = $bundle_identifier; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "$provisioning_profile_uuid_release"; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/misc/dist/ios_xcode/godot_ios/export_options.plist b/misc/dist/ios_xcode/godot_ios/export_options.plist index 3878a4dbe6..71073d9a07 100644 --- a/misc/dist/ios_xcode/godot_ios/export_options.plist +++ b/misc/dist/ios_xcode/godot_ios/export_options.plist @@ -10,11 +10,11 @@ <key>provisioningProfiles</key> <dict> - <key>$identifier</key> + <key>$bundle_identifier</key> <string>$provisioning_profile_uuid</string> </dict> <key>compileBitcode</key> <false/> </dict> -</plist>
\ No newline at end of file +</plist> diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements b/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements index 903def2af5..c9b58a85cf 100644 --- a/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements +++ b/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements @@ -2,7 +2,6 @@ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> - <key>aps-environment</key> - <string>development</string> +$entitlements_push_notifications </dict> </plist> diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist index 3b765e6bb8..aaee42aa5f 100755 --- a/misc/dist/osx_template.app/Contents/Info.plist +++ b/misc/dist/osx_template.app/Contents/Info.plist @@ -13,7 +13,7 @@ <key>CFBundleIconFile</key> <string>icon.icns</string> <key>CFBundleIdentifier</key> - <string>$identifier</string> + <string>$bundle_identifier</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> diff --git a/modules/arkit/SCsub b/modules/arkit/SCsub index 61c0a8248c..7e103d6565 100644 --- a/modules/arkit/SCsub +++ b/modules/arkit/SCsub @@ -5,6 +5,9 @@ Import("env_modules") env_arkit = env_modules.Clone() +# (iOS) Enable module support +env_arkit.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + # (iOS) Build as separate static library modules_sources = [] env_arkit.add_source_files(modules_sources, "*.cpp") diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub index b853ebfc63..21bdcca18e 100644 --- a/modules/bullet/SCsub +++ b/modules/bullet/SCsub @@ -201,8 +201,8 @@ if env["builtin_bullet"]: env_bullet.Append(CPPFLAGS=["-isystem", Dir(thirdparty_dir).path]) else: env_bullet.Prepend(CPPPATH=[thirdparty_dir]) - # if env['target'] == "debug" or env['target'] == "release_debug": - # env_bullet.Append(CPPDEFINES=['BT_DEBUG']) + if env["target"] == "debug" or env["target"] == "release_debug": + env_bullet.Append(CPPDEFINES=["DEBUG"]) env_bullet.Append(CPPDEFINES=["BT_USE_OLD_DAMPING_METHOD"]) diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 99f58e7059..cfe8cd5322 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -123,6 +123,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra } ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { @@ -152,7 +153,17 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra } bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { + r_closest_safe = 0.0f; + r_closest_unsafe = 0.0f; + btVector3 bt_motion; + G_TO_B(p_motion, bt_motion); + + if (bt_motion.fuzzyZero()) { + return false; + } + ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin); if (!btShape->isConvex()) { @@ -162,9 +173,6 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf } btConvexShape *bt_convex_shape = static_cast<btConvexShape *>(btShape); - btVector3 bt_motion; - G_TO_B(p_motion, bt_motion); - btTransform bt_xform_from; G_TO_B(p_xform, bt_xform_from); UNSCALE_BT_BASIS(bt_xform_from); @@ -178,9 +186,6 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, space->dynamicsWorld->getDispatchInfo().m_allowedCcdPenetration); - r_closest_unsafe = 1.0; - r_closest_safe = 1.0; - if (btResult.hasHit()) { const btScalar l = bt_motion.length(); r_closest_unsafe = btResult.m_closestHitFraction; @@ -196,6 +201,9 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf r_info->collider_id = collision_object->get_instance_id(); r_info->shape = btResult.m_shapeId; } + } else { + r_closest_safe = 1.0f; + r_closest_unsafe = 1.0f; } bulletdelete(bt_convex_shape); @@ -209,6 +217,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & } ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { @@ -240,6 +249,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale_abs(), p_margin); if (!btShape->isConvex()) { diff --git a/modules/camera/SCsub b/modules/camera/SCsub index 63c4e9fbab..631a65bde2 100644 --- a/modules/camera/SCsub +++ b/modules/camera/SCsub @@ -6,6 +6,9 @@ Import("env_modules") env_camera = env_modules.Clone() if env["platform"] == "iphone": + # (iOS) Enable module support + env_camera.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + # (iOS) Build as separate static library modules_sources = [] env_camera.add_source_files(modules_sources, "register_types.cpp") diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index ded0b970dc..d0c9bf5d38 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -904,8 +904,12 @@ void CSGBrushOperation::Build2DFaces::_merge_faces(const Vector<int> &p_segment_ vertices[p_segment_indices[closest_idx]].point }; if (are_segements_parallel(edge1, edge2, vertex_snap2)) { - degenerate_points.push_back(outer_edge_idx[0]); - degenerate_points.push_back(outer_edge_idx[1]); + if (!degenerate_points.find(outer_edge_idx[0])) { + degenerate_points.push_back(outer_edge_idx[0]); + } + if (!degenerate_points.find(outer_edge_idx[1])) { + degenerate_points.push_back(outer_edge_idx[1]); + } continue; } diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index ba425371a8..2f4f7d7a4c 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -29,14 +29,15 @@ /*************************************************************************/ #include "texture_loader_dds.h" + #include "core/os/file_access.h" #define PF_FOURCC(s) ((uint32_t)(((s)[3] << 24U) | ((s)[2] << 16U) | ((s)[1] << 8U) | ((s)[0]))) +// Reference: https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dds-header + enum { DDS_MAGIC = 0x20534444, - DDSD_CAPS = 0x00000001, - DDSD_PIXELFORMAT = 0x00001000, DDSD_PITCH = 0x00000008, DDSD_LINEARSIZE = 0x00080000, DDSD_MIPMAPCOUNT = 0x00020000, @@ -47,7 +48,6 @@ enum { }; enum DDSFormat { - DDS_DXT1, DDS_DXT3, DDS_DXT5, @@ -128,7 +128,9 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, //validate - if (magic != DDS_MAGIC || hsize != 124 || !(flags & DDSD_PIXELFORMAT) || !(flags & DDSD_CAPS)) { + // We don't check DDSD_CAPS or DDSD_PIXELFORMAT, as they're mandatory when writing, + // but non-mandatory when reading (as some writers don't set them)... + if (magic != DDS_MAGIC || hsize != 124) { ERR_FAIL_V_MSG(RES(), "Invalid or unsupported DDS texture file '" + p_path + "'."); } diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py index 4b997e4bfe..7603e7d69d 100644 --- a/modules/gdnative/config.py +++ b/modules/gdnative/config.py @@ -8,7 +8,6 @@ def configure(env): def get_doc_classes(): return [ - "@NativeScript", "XRInterfaceGDNative", "GDNative", "GDNativeLibrary", diff --git a/modules/gdnative/doc_classes/@NativeScript.xml b/modules/gdnative/doc_classes/@NativeScript.xml deleted file mode 100644 index 809b225e21..0000000000 --- a/modules/gdnative/doc_classes/@NativeScript.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="@NativeScript" version="4.0"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp index 2a9836329e..5896da4640 100644 --- a/modules/gdnative/gdnative_library_editor_plugin.cpp +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -283,7 +283,7 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { platforms["Haiku"] = platform_haiku; NativePlatformConfig platform_uwp; - platform_uwp.name = "Windows Universal"; + platform_uwp.name = "UWP"; platform_uwp.entries.push_back("arm"); platform_uwp.entries.push_back("32"); platform_uwp.entries.push_back("64"); diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp index 5fe1060aae..648f4f7cdd 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp @@ -95,13 +95,15 @@ void NavigationMeshEditor::_bind_methods() { NavigationMeshEditor::NavigationMeshEditor() { bake_hbox = memnew(HBoxContainer); - button_bake = memnew(ToolButton); + button_bake = memnew(Button); + button_bake->set_flat(true); bake_hbox->add_child(button_bake); button_bake->set_toggle_mode(true); button_bake->set_text(TTR("Bake NavMesh")); button_bake->connect("pressed", callable_mp(this, &NavigationMeshEditor::_bake_pressed)); - button_reset = memnew(ToolButton); + button_reset = memnew(Button); + button_reset->set_flat(true); bake_hbox->add_child(button_reset); // No button text, we only use a revert icon which is set when entering the tree. button_reset->set_tooltip(TTR("Clear the navigation mesh.")); diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.h b/modules/gdnavigation/navigation_mesh_editor_plugin.h index da3a981f8c..728f958eaa 100644 --- a/modules/gdnavigation/navigation_mesh_editor_plugin.h +++ b/modules/gdnavigation/navigation_mesh_editor_plugin.h @@ -46,8 +46,8 @@ class NavigationMeshEditor : public Control { AcceptDialog *err_dialog; HBoxContainer *bake_hbox; - ToolButton *button_bake; - ToolButton *button_reset; + Button *button_bake; + Button *button_reset; Label *bake_info; NavigationRegion3D *node; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index bc095ae1f9..5bc9003c29 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -1422,6 +1422,10 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo codegen.opcodes.push_back(0); codegen.opcodes.write[else_addr] = codegen.opcodes.size(); + codegen.opcodes.push_back(GDScriptFunction::OPCODE_LINE); + codegen.opcodes.push_back(cf->body_else->line); + codegen.current_line = cf->body_else->line; + Error err2 = _parse_block(codegen, cf->body_else, p_stack_level, p_break_addr, p_continue_addr); if (err2) { return err2; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 50d8289fd1..3a5db3687b 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -3093,6 +3093,14 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co return OK; } } + + for (int i = 0; i < base_type.class_type->subclasses.size(); i++) { + if (base_type.class_type->subclasses[i]->name == p_symbol) { + r_result.type = ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION; + r_result.location = base_type.class_type->subclasses[i]->line; + return OK; + } + } } base_type = base_type.class_type->base_type; } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index a06ecb1ea8..ca452bf008 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2821,6 +2821,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { #ifdef DEBUG_ENABLED + pending_newline = -1; // reset for the new block + NewLineNode *nl = alloc_node<NewLineNode>(); nl->line = tokenizer->get_token_line(); @@ -3178,6 +3180,13 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { IdentifierNode *id = alloc_node<IdentifierNode>(); id->name = tokenizer->get_token_identifier(); +#ifdef DEBUG_ENABLED + for (int j = 0; j < current_class->variables.size(); j++) { + if (current_class->variables[j].identifier == id->name) { + _add_warning(GDScriptWarning::SHADOWED_VARIABLE, id->line, id->name, itos(current_class->variables[j].line)); + } + } +#endif // DEBUG_ENABLED BlockNode *check_block = p_block; while (check_block) { diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 3b0e78546d..1b7ce98721 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -1241,14 +1241,16 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { search_box->connect("text_changed", callable_mp(this, &GridMapEditor::_text_changed)); search_box->connect("gui_input", callable_mp(this, &GridMapEditor::_sbox_input)); - mode_thumbnail = memnew(ToolButton); + mode_thumbnail = memnew(Button); + mode_thumbnail->set_flat(true); mode_thumbnail->set_toggle_mode(true); mode_thumbnail->set_pressed(true); mode_thumbnail->set_icon(p_editor->get_gui_base()->get_theme_icon("FileThumbnail", "EditorIcons")); hb->add_child(mode_thumbnail); mode_thumbnail->connect("pressed", callable_mp(this, &GridMapEditor::_set_display_mode), varray(DISPLAY_THUMBNAIL)); - mode_list = memnew(ToolButton); + mode_list = memnew(Button); + mode_list->set_flat(true); mode_list->set_toggle_mode(true); mode_list->set_pressed(false); mode_list->set_icon(p_editor->get_gui_base()->get_theme_icon("FileList", "EditorIcons")); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 19eea18965..0ae9b27833 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -74,8 +74,8 @@ class GridMapEditor : public VBoxContainer { MenuButton *options; SpinBox *floor; double accumulated_floor_delta; - ToolButton *mode_thumbnail; - ToolButton *mode_list; + Button *mode_thumbnail; + Button *mode_list; LineEdit *search_box; HSlider *size_slider; HBoxContainer *spatial_editor_hb; diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp index 1f9d8c2aa3..501bfff075 100644 --- a/modules/mbedtls/crypto_mbedtls.cpp +++ b/modules/mbedtls/crypto_mbedtls.cpp @@ -50,7 +50,7 @@ CryptoKey *CryptoKeyMbedTLS::create() { return memnew(CryptoKeyMbedTLS); } -Error CryptoKeyMbedTLS::load(String p_path) { +Error CryptoKeyMbedTLS::load(String p_path, bool p_public_only) { ERR_FAIL_COND_V_MSG(locks, ERR_ALREADY_IN_USE, "Key is in use"); PackedByteArray out; @@ -59,42 +59,81 @@ Error CryptoKeyMbedTLS::load(String p_path) { int flen = f->get_len(); out.resize(flen + 1); - { - uint8_t *w = out.ptrw(); - f->get_buffer(w, flen); - w[flen] = 0; //end f string - } + f->get_buffer(out.ptrw(), flen); + out.write[flen] = 0; // string terminator memdelete(f); - int ret = mbedtls_pk_parse_key(&pkey, out.ptr(), out.size(), nullptr, 0); + int ret = 0; + if (p_public_only) { + ret = mbedtls_pk_parse_public_key(&pkey, out.ptr(), out.size()); + } else { + ret = mbedtls_pk_parse_key(&pkey, out.ptr(), out.size(), nullptr, 0); + } // We MUST zeroize the memory for safety! mbedtls_platform_zeroize(out.ptrw(), out.size()); - ERR_FAIL_COND_V_MSG(ret, FAILED, "Error parsing private key '" + itos(ret) + "'."); + ERR_FAIL_COND_V_MSG(ret, FAILED, "Error parsing key '" + itos(ret) + "'."); + public_only = p_public_only; return OK; } -Error CryptoKeyMbedTLS::save(String p_path) { +Error CryptoKeyMbedTLS::save(String p_path, bool p_public_only) { FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE); ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot save CryptoKeyMbedTLS file '" + p_path + "'."); unsigned char w[16000]; memset(w, 0, sizeof(w)); - int ret = mbedtls_pk_write_key_pem(&pkey, w, sizeof(w)); + int ret = 0; + if (p_public_only) { + ret = mbedtls_pk_write_pubkey_pem(&pkey, w, sizeof(w)); + } else { + ret = mbedtls_pk_write_key_pem(&pkey, w, sizeof(w)); + } if (ret != 0) { memdelete(f); - memset(w, 0, sizeof(w)); // Zeroize anything we might have written. + mbedtls_platform_zeroize(w, sizeof(w)); // Zeroize anything we might have written. ERR_FAIL_V_MSG(FAILED, "Error writing key '" + itos(ret) + "'."); } size_t len = strlen((char *)w); f->store_buffer(w, len); memdelete(f); - memset(w, 0, sizeof(w)); // Zeroize temporary buffer. + mbedtls_platform_zeroize(w, sizeof(w)); // Zeroize temporary buffer. return OK; } +Error CryptoKeyMbedTLS::load_from_string(String p_string_key, bool p_public_only) { + int ret = 0; + if (p_public_only) { + ret = mbedtls_pk_parse_public_key(&pkey, (unsigned char *)p_string_key.utf8().get_data(), p_string_key.utf8().size()); + } else { + ret = mbedtls_pk_parse_key(&pkey, (unsigned char *)p_string_key.utf8().get_data(), p_string_key.utf8().size(), nullptr, 0); + } + ERR_FAIL_COND_V_MSG(ret, FAILED, "Error parsing key '" + itos(ret) + "'."); + + public_only = p_public_only; + return OK; +} + +String CryptoKeyMbedTLS::save_to_string(bool p_public_only) { + unsigned char w[16000]; + memset(w, 0, sizeof(w)); + + int ret = 0; + if (p_public_only) { + ret = mbedtls_pk_write_pubkey_pem(&pkey, w, sizeof(w)); + } else { + ret = mbedtls_pk_write_key_pem(&pkey, w, sizeof(w)); + } + if (ret != 0) { + mbedtls_platform_zeroize(w, sizeof(w)); + ERR_FAIL_V_MSG("", "Error saving key '" + itos(ret) + "'."); + } + String s = String::utf8((char *)w); + return s; +} + X509Certificate *X509CertificateMbedTLS::create() { return memnew(X509CertificateMbedTLS); } @@ -108,11 +147,8 @@ Error X509CertificateMbedTLS::load(String p_path) { int flen = f->get_len(); out.resize(flen + 1); - { - uint8_t *w = out.ptrw(); - f->get_buffer(w, flen); - w[flen] = 0; //end f string - } + f->get_buffer(out.ptrw(), flen); + out.write[flen] = 0; // string terminator memdelete(f); int ret = mbedtls_x509_crt_parse(&cert, out.ptr(), out.size()); @@ -211,9 +247,8 @@ void CryptoMbedTLS::load_default_certificates(String p_path) { // Use builtin certs only if user did not override it in project settings. PackedByteArray out; out.resize(_certs_uncompressed_size + 1); - uint8_t *w = out.ptrw(); - Compression::decompress(w, _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE); - w[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator + Compression::decompress(out.ptrw(), _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE); + out.write[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator #ifdef DEBUG_ENABLED print_verbose("Loaded builtin certs"); #endif @@ -228,6 +263,7 @@ Ref<CryptoKey> CryptoMbedTLS::generate_rsa(int p_bytes) { int ret = mbedtls_pk_setup(&(out->pkey), mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); ERR_FAIL_COND_V(ret != 0, nullptr); ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(out->pkey), mbedtls_ctr_drbg_random, &ctr_drbg, p_bytes, 65537); + out->public_only = false; ERR_FAIL_COND_V(ret != 0, nullptr); return out; } @@ -281,3 +317,75 @@ PackedByteArray CryptoMbedTLS::generate_random_bytes(int p_bytes) { mbedtls_ctr_drbg_random(&ctr_drbg, out.ptrw(), p_bytes); return out; } + +mbedtls_md_type_t CryptoMbedTLS::_md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size) { + switch (p_hash_type) { + case HashingContext::HASH_MD5: + r_size = 16; + return MBEDTLS_MD_MD5; + case HashingContext::HASH_SHA1: + r_size = 20; + return MBEDTLS_MD_SHA1; + case HashingContext::HASH_SHA256: + r_size = 32; + return MBEDTLS_MD_SHA256; + default: + r_size = 0; + ERR_FAIL_V_MSG(MBEDTLS_MD_NONE, "Invalid hash type."); + } +} + +Vector<uint8_t> CryptoMbedTLS::sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key) { + int size; + mbedtls_md_type_t type = _md_type_from_hashtype(p_hash_type, size); + ERR_FAIL_COND_V_MSG(type == MBEDTLS_MD_NONE, Vector<uint8_t>(), "Invalid hash type."); + ERR_FAIL_COND_V_MSG(p_hash.size() != size, Vector<uint8_t>(), "Invalid hash provided. Size must be " + itos(size)); + Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key); + ERR_FAIL_COND_V_MSG(!key.is_valid(), Vector<uint8_t>(), "Invalid key provided."); + ERR_FAIL_COND_V_MSG(key->is_public_only(), Vector<uint8_t>(), "Invalid key provided. Cannot sign with public_only keys."); + size_t sig_size = 0; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + Vector<uint8_t> out; + int ret = mbedtls_pk_sign(&(key->pkey), type, p_hash.ptr(), size, buf, &sig_size, mbedtls_ctr_drbg_random, &ctr_drbg); + ERR_FAIL_COND_V_MSG(ret, out, "Error while signing: " + itos(ret)); + out.resize(sig_size); + copymem(out.ptrw(), buf, sig_size); + return out; +} + +bool CryptoMbedTLS::verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key) { + int size; + mbedtls_md_type_t type = _md_type_from_hashtype(p_hash_type, size); + ERR_FAIL_COND_V_MSG(type == MBEDTLS_MD_NONE, false, "Invalid hash type."); + ERR_FAIL_COND_V_MSG(p_hash.size() != size, false, "Invalid hash provided. Size must be " + itos(size)); + Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key); + ERR_FAIL_COND_V_MSG(!key.is_valid(), false, "Invalid key provided."); + return mbedtls_pk_verify(&(key->pkey), type, p_hash.ptr(), size, p_signature.ptr(), p_signature.size()) == 0; +} + +Vector<uint8_t> CryptoMbedTLS::encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext) { + Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key); + ERR_FAIL_COND_V_MSG(!key.is_valid(), Vector<uint8_t>(), "Invalid key provided."); + uint8_t buf[1024]; + size_t size; + Vector<uint8_t> out; + int ret = mbedtls_pk_encrypt(&(key->pkey), p_plaintext.ptr(), p_plaintext.size(), buf, &size, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg); + ERR_FAIL_COND_V_MSG(ret, out, "Error while encrypting: " + itos(ret)); + out.resize(size); + copymem(out.ptrw(), buf, size); + return out; +} + +Vector<uint8_t> CryptoMbedTLS::decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext) { + Ref<CryptoKeyMbedTLS> key = static_cast<Ref<CryptoKeyMbedTLS>>(p_key); + ERR_FAIL_COND_V_MSG(!key.is_valid(), Vector<uint8_t>(), "Invalid key provided."); + ERR_FAIL_COND_V_MSG(key->is_public_only(), Vector<uint8_t>(), "Invalid key provided. Cannot decrypt using a public_only key."); + uint8_t buf[2048]; + size_t size; + Vector<uint8_t> out; + int ret = mbedtls_pk_decrypt(&(key->pkey), p_ciphertext.ptr(), p_ciphertext.size(), buf, &size, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg); + ERR_FAIL_COND_V_MSG(ret, out, "Error while decrypting: " + itos(ret)); + out.resize(size); + copymem(out.ptrw(), buf, size); + return out; +} diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h index 48855d082a..2a446f9d48 100644 --- a/modules/mbedtls/crypto_mbedtls.h +++ b/modules/mbedtls/crypto_mbedtls.h @@ -43,15 +43,19 @@ class SSLContextMbedTLS; class CryptoKeyMbedTLS : public CryptoKey { private: mbedtls_pk_context pkey; - int locks; + int locks = 0; + bool public_only = true; public: static CryptoKey *create(); static void make_default() { CryptoKey::_create = create; } static void finalize() { CryptoKey::_create = nullptr; } - virtual Error load(String p_path); - virtual Error save(String p_path); + virtual Error load(String p_path, bool p_public_only); + virtual Error save(String p_path, bool p_public_only); + virtual String save_to_string(bool p_public_only); + virtual Error load_from_string(String p_string_key, bool p_public_only); + virtual bool is_public_only() const { return public_only; }; CryptoKeyMbedTLS() { mbedtls_pk_init(&pkey); @@ -102,6 +106,7 @@ private: mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; static X509CertificateMbedTLS *default_certs; + mbedtls_md_type_t _md_type_from_hashtype(HashingContext::HashType p_hash_type, int &r_size); public: static Crypto *create(); @@ -113,6 +118,10 @@ public: virtual PackedByteArray generate_random_bytes(int p_bytes); virtual Ref<CryptoKey> generate_rsa(int p_bytes); virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after); + virtual Vector<uint8_t> sign(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Ref<CryptoKey> p_key); + virtual bool verify(HashingContext::HashType p_hash_type, Vector<uint8_t> p_hash, Vector<uint8_t> p_signature, Ref<CryptoKey> p_key); + virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext); + virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext); CryptoMbedTLS(); ~CryptoMbedTLS(); diff --git a/modules/mono/build_scripts/godot_tools_build.py b/modules/mono/build_scripts/godot_tools_build.py index 7391e8790d..3bbbf29d3b 100644 --- a/modules/mono/build_scripts/godot_tools_build.py +++ b/modules/mono/build_scripts/godot_tools_build.py @@ -15,7 +15,9 @@ def build_godot_tools(source, target, env): from .solution_builder import build_solution - build_solution(env, solution_path, build_config) + extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]] + + build_solution(env, solution_path, build_config, extra_msbuild_args) # No need to copy targets. The GodotTools csproj takes care of copying them. diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 23f01b3cca..80e3b59325 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -191,17 +191,16 @@ def configure(env, env_mono): env.Append(LIBS=["psapi"]) env.Append(LIBS=["version"]) else: - mono_lib_name = find_name_in_dir_files( - mono_lib_path, mono_lib_names, prefixes=["", "lib"], extensions=lib_suffixes - ) + mono_lib_file = find_file_in_dir(mono_lib_path, mono_lib_names, extensions=lib_suffixes) - if not mono_lib_name: + if not mono_lib_file: raise RuntimeError("Could not find mono library in: " + mono_lib_path) if env.msvc: - env.Append(LINKFLAGS=mono_lib_name + ".lib") + env.Append(LINKFLAGS=mono_lib_file) else: - env.Append(LIBS=[mono_lib_name]) + mono_lib_file_path = os.path.join(mono_lib_path, mono_lib_file) + env.Append(LINKFLAGS=mono_lib_file_path) mono_bin_path = os.path.join(mono_root, "bin") diff --git a/modules/mono/config.py b/modules/mono/config.py index 7980a86cb3..cd659057ef 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -57,7 +57,6 @@ def configure(env): def get_doc_classes(): return [ - "@C#", "CSharpScript", "GodotSharp", ] diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml deleted file mode 100644 index 83a7fbf02c..0000000000 --- a/modules/mono/doc_classes/@C#.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="@C#" version="4.0"> - <brief_description> - </brief_description> - <description> - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml index 1eb3404f9e..e1e9d1381f 100644 --- a/modules/mono/doc_classes/CSharpScript.xml +++ b/modules/mono/doc_classes/CSharpScript.xml @@ -1,16 +1,21 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="CSharpScript" inherits="Script" version="4.0"> <brief_description> + A script implemented in the C# programming language (Mono-enabled builds only). </brief_description> <description> + This class represents a C# script. It is the C# equivalent of the [GDScript] class and is only available in Mono-enabled Godot builds. + See also [GodotSharp]. </description> <tutorials> + <link>https://docs.godotengine.org/en/latest/getting_started/scripting/c_sharp/index.html</link> </tutorials> <methods> <method name="new" qualifiers="vararg"> <return type="Variant"> </return> <description> + Returns a new instance of the script. </description> </method> </methods> diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml index 19a08d2036..417f8ac704 100644 --- a/modules/mono/doc_classes/GodotSharp.xml +++ b/modules/mono/doc_classes/GodotSharp.xml @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GodotSharp" inherits="Object" version="4.0"> <brief_description> + Bridge between Godot and the Mono runtime (Mono-enabled builds only). </brief_description> <description> + This class is a bridge between Godot and the Mono runtime. It exposes several low-level operations and is only available in Mono-enabled Godot builds. + See also [CSharpScript]. </description> <tutorials> </tutorials> @@ -11,26 +14,30 @@ <return type="void"> </return> <description> - Attaches the current thread to the mono runtime. + Attaches the current thread to the Mono runtime. </description> </method> <method name="detach_thread"> <return type="void"> </return> <description> - Detaches the current thread from the mono runtime. + Detaches the current thread from the Mono runtime. </description> </method> <method name="get_domain_id"> <return type="int"> </return> <description> + Returns the current MonoDomain ID. + [b]Note:[/b] The Mono runtime must be initialized for this method to work (use [method is_runtime_initialized] to check). If the Mono runtime isn't initialized at the time this method is called, the engine will crash. </description> </method> <method name="get_scripts_domain_id"> <return type="int"> </return> <description> + Returns the scripts MonoDomain's ID. This will be the same MonoDomain ID as [method get_domain_id], unless the scripts domain isn't loaded. + [b]Note:[/b] The Mono runtime must be initialized for this method to work (use [method is_runtime_initialized] to check). If the Mono runtime isn't initialized at the time this method is called, the engine will crash. </description> </method> <method name="is_domain_finalizing_for_unload"> @@ -39,26 +46,28 @@ <argument index="0" name="domain_id" type="int"> </argument> <description> - Returns whether the domain is being finalized. + Returns [code]true[/code] if the domain is being finalized, [code]false[/code] otherwise. </description> </method> <method name="is_runtime_initialized"> <return type="bool"> </return> <description> + Returns [code]true[/code] if the Mono runtime is initialized, [code]false[/code] otherwise. </description> </method> <method name="is_runtime_shutting_down"> <return type="bool"> </return> <description> + Returns [code]true[/code] if the Mono runtime is shutting down, [code]false[/code] otherwise. </description> </method> <method name="is_scripts_domain_loaded"> <return type="bool"> </return> <description> - Returns whether the scripts domain is loaded. + Returns [code]true[/code] if the scripts domain is loaded, [code]false[/code] otherwise. </description> </method> </methods> diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs index 7ab5c5fc59..012b69032e 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs @@ -25,8 +25,9 @@ namespace GodotTools.Core bool rooted = path.IsAbsolutePath(); path = path.Replace('\\', '/'); + path = path[path.Length - 1] == '/' ? path.Substring(0, path.Length - 1) : path; - string[] parts = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + string[] parts = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries); path = string.Join(Path.DirectorySeparatorChar.ToString(), parts).Trim(); diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs index d069651dd3..572c541412 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Client.cs @@ -19,9 +19,12 @@ namespace GodotTools.IdeMessaging private readonly string identity; private string MetaFilePath { get; } + private DateTime? metaFileModifiedTime; private GodotIdeMetadata godotIdeMetadata; private readonly FileSystemWatcher fsWatcher; + public string GodotEditorExecutablePath => godotIdeMetadata.EditorExecutablePath; + private readonly IMessageHandler messageHandler; private Peer peer; @@ -123,7 +126,7 @@ namespace GodotTools.IdeMessaging MetaFilePath = Path.Combine(projectMetadataDir, GodotIdeMetadata.DefaultFileName); // FileSystemWatcher requires an existing directory - if (!File.Exists(projectMetadataDir)) + if (!Directory.Exists(projectMetadataDir)) Directory.CreateDirectory(projectMetadataDir); fsWatcher = new FileSystemWatcher(projectMetadataDir, GodotIdeMetadata.DefaultFileName); @@ -142,6 +145,13 @@ namespace GodotTools.IdeMessaging if (!File.Exists(MetaFilePath)) return; + var lastWriteTime = File.GetLastWriteTime(MetaFilePath); + + if (lastWriteTime == metaFileModifiedTime) + return; + + metaFileModifiedTime = lastWriteTime; + var metadata = ReadMetadataFile(); if (metadata != null && metadata != godotIdeMetadata) @@ -173,6 +183,13 @@ namespace GodotTools.IdeMessaging if (IsConnected || !File.Exists(MetaFilePath)) return; + var lastWriteTime = File.GetLastWriteTime(MetaFilePath); + + if (lastWriteTime == metaFileModifiedTime) + return; + + metaFileModifiedTime = lastWriteTime; + var metadata = ReadMetadataFile(); if (metadata != null) @@ -185,7 +202,8 @@ namespace GodotTools.IdeMessaging private GodotIdeMetadata? ReadMetadataFile() { - using (var reader = File.OpenText(MetaFilePath)) + using (var fileStream = new FileStream(MetaFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + using (var reader = new StreamReader(fileStream)) { string portStr = reader.ReadLine(); @@ -272,6 +290,7 @@ namespace GodotTools.IdeMessaging // ReSharper disable once UnusedMember.Global public async void Start() { + fsWatcher.Created += OnMetaFileChanged; fsWatcher.Changed += OnMetaFileChanged; fsWatcher.Deleted += OnMetaFileDeleted; fsWatcher.EnableRaisingEvents = true; diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj index 67815959a6..dad6b9ae7a 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj @@ -4,7 +4,7 @@ <TargetFramework>netstandard2.0</TargetFramework> <LangVersion>7.2</LangVersion> <PackageId>GodotTools.IdeMessaging</PackageId> - <Version>1.1.0</Version> + <Version>1.1.1</Version> <AssemblyVersion>$(Version)</AssemblyVersion> <Authors>Godot Engine contributors</Authors> <Company /> diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs index a4e86d6177..10d7e1898e 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Peer.cs @@ -105,49 +105,45 @@ namespace GodotTools.IdeMessaging try { - try + if (msg.Kind == MessageKind.Request) { - if (msg.Kind == MessageKind.Request) - { - var responseContent = await messageHandler.HandleRequest(this, msg.Id, msg.Content, Logger); - await WriteMessage(new Message(MessageKind.Response, msg.Id, responseContent)); - } - else if (msg.Kind == MessageKind.Response) - { - ResponseAwaiter responseAwaiter; + var responseContent = await messageHandler.HandleRequest(this, msg.Id, msg.Content, Logger); + await WriteMessage(new Message(MessageKind.Response, msg.Id, responseContent)); + } + else if (msg.Kind == MessageKind.Response) + { + ResponseAwaiter responseAwaiter; - using (await requestsSem.UseAsync()) + using (await requestsSem.UseAsync()) + { + if (!requestAwaiterQueues.TryGetValue(msg.Id, out var queue) || queue.Count <= 0) { - if (!requestAwaiterQueues.TryGetValue(msg.Id, out var queue) || queue.Count <= 0) - { - Logger.LogError($"Received unexpected response: {msg.Id}"); - return; - } - - responseAwaiter = queue.Dequeue(); + Logger.LogError($"Received unexpected response: {msg.Id}"); + return; } - responseAwaiter.SetResult(msg.Content); - } - else - { - throw new IndexOutOfRangeException($"Invalid message kind {msg.Kind}"); + responseAwaiter = queue.Dequeue(); } + + responseAwaiter.SetResult(msg.Content); } - catch (Exception e) + else { - Logger.LogError($"Message handler for '{msg}' failed with exception", e); + throw new IndexOutOfRangeException($"Invalid message kind {msg.Kind}"); } } catch (Exception e) { - Logger.LogError($"Exception thrown from message handler. Message: {msg}", e); + Logger.LogError($"Message handler for '{msg}' failed with exception", e); } } } catch (Exception e) { - Logger.LogError("Unhandled exception in the peer loop", e); + if (!IsDisposed || !(e is SocketException || e.InnerException is SocketException)) + { + Logger.LogError("Unhandled exception in the peer loop", e); + } } } diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs index 1dd4f852e5..e93db9377b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/Requests/Requests.cs @@ -67,6 +67,19 @@ namespace GodotTools.IdeMessaging.Requests { } + public sealed class StopPlayRequest : Request + { + public new const string Id = "StopPlay"; + + public StopPlayRequest() : base(Id) + { + } + } + + public sealed class StopPlayResponse : Response + { + } + public sealed class DebugPlayRequest : Request { public string DebuggerHost { get; set; } diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj new file mode 100644 index 0000000000..5b3ed0b1b7 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid> + <OutputType>Exe</OutputType> + <TargetFramework>net472</TargetFramework> + <LangVersion>7.2</LangVersion> + </PropertyGroup> + <ItemGroup> + <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> + <PackageReference Include="EnvDTE" Version="8.0.2" /> + </ItemGroup> +</Project> diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs new file mode 100644 index 0000000000..affb2a47e7 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/Program.cs @@ -0,0 +1,270 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Text.RegularExpressions; +using EnvDTE; + +namespace GodotTools.OpenVisualStudio +{ + internal static class Program + { + [DllImport("ole32.dll")] + private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable pprot); + + [DllImport("ole32.dll")] + private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc); + + [DllImport("user32.dll")] + private static extern bool SetForegroundWindow(IntPtr hWnd); + + private static void ShowHelp() + { + Console.WriteLine("Opens the file(s) in a Visual Studio instance that is editing the specified solution."); + Console.WriteLine("If an existing instance for the solution is not found, a new one is created."); + Console.WriteLine(); + Console.WriteLine("Usage:"); + Console.WriteLine(@" GodotTools.OpenVisualStudio.exe solution [file[;line[;col]]...]"); + Console.WriteLine(); + Console.WriteLine("Lines and columns begin at one. Zero or lower will result in an error."); + Console.WriteLine("If a line is specified but a column is not, the line is selected in the text editor."); + } + + // STAThread needed, otherwise CoRegisterMessageFilter may return CO_E_NOT_SUPPORTED. + [STAThread] + private static int Main(string[] args) + { + if (args.Length == 0 || args[0] == "--help" || args[0] == "-h") + { + ShowHelp(); + return 0; + } + + string solutionFile = NormalizePath(args[0]); + + var dte = FindInstanceEditingSolution(solutionFile); + + if (dte == null) + { + // Open a new instance + + var visualStudioDteType = Type.GetTypeFromProgID("VisualStudio.DTE.16.0", throwOnError: true); + dte = (DTE)Activator.CreateInstance(visualStudioDteType); + + dte.UserControl = true; + + try + { + dte.Solution.Open(solutionFile); + } + catch (ArgumentException) + { + Console.Error.WriteLine("Solution.Open: Invalid path or file not found"); + return 1; + } + + dte.MainWindow.Visible = true; + } + + MessageFilter.Register(); + + try + { + // Open files + + for (int i = 1; i < args.Length; i++) + { + // Both the line number and the column begin at one + + string[] fileArgumentParts = args[i].Split(';'); + + string filePath = NormalizePath(fileArgumentParts[0]); + + try + { + dte.ItemOperations.OpenFile(filePath); + } + catch (ArgumentException) + { + Console.Error.WriteLine("ItemOperations.OpenFile: Invalid path or file not found"); + return 1; + } + + if (fileArgumentParts.Length > 1) + { + if (int.TryParse(fileArgumentParts[1], out int line)) + { + var textSelection = (TextSelection)dte.ActiveDocument.Selection; + + if (fileArgumentParts.Length > 2) + { + if (int.TryParse(fileArgumentParts[2], out int column)) + { + textSelection.MoveToLineAndOffset(line, column); + } + else + { + Console.Error.WriteLine("The column part of the argument must be a valid integer"); + return 1; + } + } + else + { + textSelection.GotoLine(line, Select: true); + } + } + else + { + Console.Error.WriteLine("The line part of the argument must be a valid integer"); + return 1; + } + } + } + } + finally + { + var mainWindow = dte.MainWindow; + mainWindow.Activate(); + SetForegroundWindow(new IntPtr(mainWindow.HWnd)); + + MessageFilter.Revoke(); + } + + return 0; + } + + private static DTE FindInstanceEditingSolution(string solutionPath) + { + if (GetRunningObjectTable(0, out IRunningObjectTable pprot) != 0) + return null; + + try + { + pprot.EnumRunning(out IEnumMoniker ppenumMoniker); + ppenumMoniker.Reset(); + + var moniker = new IMoniker[1]; + + while (ppenumMoniker.Next(1, moniker, IntPtr.Zero) == 0) + { + string ppszDisplayName; + + CreateBindCtx(0, out IBindCtx ppbc); + + try + { + moniker[0].GetDisplayName(ppbc, null, out ppszDisplayName); + } + finally + { + Marshal.ReleaseComObject(ppbc); + } + + if (ppszDisplayName == null) + continue; + + // The digits after the colon are the process ID + if (!Regex.IsMatch(ppszDisplayName, "!VisualStudio.DTE.16.0:[0-9]")) + continue; + + if (pprot.GetObject(moniker[0], out object ppunkObject) == 0) + { + if (ppunkObject is DTE dte && dte.Solution.FullName.Length > 0) + { + if (NormalizePath(dte.Solution.FullName) == solutionPath) + return dte; + } + } + } + } + finally + { + Marshal.ReleaseComObject(pprot); + } + + return null; + } + + static string NormalizePath(string path) + { + return new Uri(Path.GetFullPath(path)).LocalPath + .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + .ToUpperInvariant(); + } + + #region MessageFilter. See: http: //msdn.microsoft.com/en-us/library/ms228772.aspx + + private class MessageFilter : IOleMessageFilter + { + // Class containing the IOleMessageFilter + // thread error-handling functions + + private static IOleMessageFilter _oldFilter; + + // Start the filter + public static void Register() + { + IOleMessageFilter newFilter = new MessageFilter(); + int ret = CoRegisterMessageFilter(newFilter, out _oldFilter); + if (ret != 0) + Console.Error.WriteLine($"CoRegisterMessageFilter failed with error code: {ret}"); + } + + // Done with the filter, close it + public static void Revoke() + { + int ret = CoRegisterMessageFilter(_oldFilter, out _); + if (ret != 0) + Console.Error.WriteLine($"CoRegisterMessageFilter failed with error code: {ret}"); + } + + // + // IOleMessageFilter functions + // Handle incoming thread requests + int IOleMessageFilter.HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo) + { + // Return the flag SERVERCALL_ISHANDLED + return 0; + } + + // Thread call was rejected, so try again. + int IOleMessageFilter.RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType) + { + if (dwRejectType == 2) + // flag = SERVERCALL_RETRYLATER + { + // Retry the thread call immediately if return >= 0 & < 100 + return 99; + } + + // Too busy; cancel call + return -1; + } + + int IOleMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType) + { + // Return the flag PENDINGMSG_WAITDEFPROCESS + return 2; + } + + // Implement the IOleMessageFilter interface + [DllImport("ole32.dll")] + private static extern int CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter); + } + + [ComImport(), Guid("00000016-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + private interface IOleMessageFilter + { + [PreserveSig] + int HandleInComingCall(int dwCallType, IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo); + + [PreserveSig] + int RetryRejectedCall(IntPtr hTaskCallee, int dwTickCount, int dwRejectType); + + [PreserveSig] + int MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType); + } + + #endregion + } +} diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs index fb2beb6995..679d5bb444 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectGenerator.cs @@ -12,6 +12,11 @@ namespace GodotTools.ProjectEditor private const string CoreApiProjectName = "GodotSharp"; private const string EditorApiProjectName = "GodotSharpEditor"; + public const string CSharpProjectTypeGuid = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; + public const string GodotProjectTypeGuid = "{8F3E2DF0-C35C-4265-82FC-BEA011F4A7ED}"; + + public static readonly string GodotDefaultProjectTypeGuids = $"{GodotProjectTypeGuid};{CSharpProjectTypeGuid}"; + public static string GenGameProject(string dir, string name, IEnumerable<string> compileItems) { string path = Path.Combine(dir, name + ".csproj"); @@ -19,6 +24,7 @@ namespace GodotTools.ProjectEditor ProjectPropertyGroupElement mainGroup; var root = CreateLibraryProject(name, "Debug", out mainGroup); + mainGroup.SetProperty("ProjectTypeGuids", GodotDefaultProjectTypeGuids); mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)")); mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj")); mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)")); diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs index 069a1edaa3..8774b4ee31 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs @@ -165,6 +165,21 @@ namespace GodotTools.ProjectEditor return result.ToArray(); } + public static void EnsureHasProjectTypeGuids(MSBuildProject project) + { + var root = project.Root; + + bool found = root.PropertyGroups.Any(pg => + string.IsNullOrEmpty(pg.Condition) && pg.Properties.Any(p => p.Name == "ProjectTypeGuids")); + + if (found) + return; + + root.AddProperty("ProjectTypeGuids", ProjectGenerator.GodotDefaultProjectTypeGuids); + + project.HasUnsavedChanges = true; + } + /// Simple function to make sure the Api assembly references are configured correctly public static void FixApiHintPath(MSBuildProject project) { diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln index f6147eb5bb..ba5379e562 100644 --- a/modules/mono/editor/GodotTools/GodotTools.sln +++ b/modules/mono/editor/GodotTools/GodotTools.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.BuildLogger", "G EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.IdeMessaging", "GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj", "{92600954-25F0-4291-8E11-1FEE9FC4BE20}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.OpenVisualStudio", "GodotTools.OpenVisualStudio\GodotTools.OpenVisualStudio.csproj", "{EAFFF236-FA96-4A4D-BD23-0E51EF988277}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -37,5 +39,9 @@ Global {92600954-25F0-4291-8E11-1FEE9FC4BE20}.Debug|Any CPU.Build.0 = Debug|Any CPU {92600954-25F0-4291-8E11-1FEE9FC4BE20}.Release|Any CPU.ActiveCfg = Release|Any CPU {92600954-25F0-4291-8E11-1FEE9FC4BE20}.Release|Any CPU.Build.0 = Release|Any CPU + {EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EAFFF236-FA96-4A4D-BD23-0E51EF988277}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs index 3cf495f025..3de3d8d318 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs @@ -20,8 +20,8 @@ namespace GodotTools private ItemList buildTabsList; private TabContainer buildTabs; - private ToolButton warningsBtn; - private ToolButton errorsBtn; + private Button warningsBtn; + private Button errorsBtn; private Button viewLogBtn; private void _UpdateBuildTabsList() @@ -285,7 +285,7 @@ namespace GodotTools toolBarHBox.AddSpacer(begin: false); - warningsBtn = new ToolButton + warningsBtn = new Button { Text = "Warnings".TTR(), ToggleMode = true, @@ -296,7 +296,7 @@ namespace GodotTools warningsBtn.Toggled += _WarningsToggled; toolBarHBox.AddChild(warningsBtn); - errorsBtn = new ToolButton + errorsBtn = new Button { Text = "Errors".TTR(), ToggleMode = true, diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs index a1a69334e3..837c8adddb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildTool.cs @@ -1,6 +1,6 @@ namespace GodotTools.Build { - public enum BuildTool + public enum BuildTool : long { MsBuildMono, MsBuildVs, diff --git a/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs b/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs index bb218c2f19..90d6eb960e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs +++ b/modules/mono/editor/GodotTools/GodotTools/ExternalEditorId.cs @@ -1,6 +1,6 @@ namespace GodotTools { - public enum ExternalEditorId + public enum ExternalEditorId : long { None, VisualStudio, // TODO (Windows-only) diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index c874025be0..f330f9ed2c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Linq; using GodotTools.Ides; using GodotTools.Ides.Rider; using GodotTools.Internals; @@ -29,7 +30,7 @@ namespace GodotTools private AcceptDialog aboutDialog; private CheckBox aboutDialogCheckBox; - private ToolButton bottomPanelBtn; + private Button bottomPanelBtn; public GodotIdeManager GodotIdeManager { get; private set; } @@ -238,7 +239,31 @@ namespace GodotTools // Not an error. Tells the caller to fallback to the global external editor settings or the built-in editor. return Error.Unavailable; case ExternalEditorId.VisualStudio: - throw new NotSupportedException(); + { + string scriptPath = ProjectSettings.GlobalizePath(script.ResourcePath); + + var args = new List<string> + { + GodotSharpDirs.ProjectSlnPath, + line >= 0 ? $"{scriptPath};{line + 1};{col + 1}" : scriptPath + }; + + string command = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "GodotTools.OpenVisualStudio.exe"); + + try + { + if (Godot.OS.IsStdoutVerbose()) + Console.WriteLine($"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}"); + + OS.RunProcess(command, args); + } + catch (Exception e) + { + GD.PushError($"Error when trying to run code editor: VisualStudio. Exception message: '{e.Message}'"); + } + + break; + } case ExternalEditorId.VisualStudioForMac: goto case ExternalEditorId.MonoDevelop; case ExternalEditorId.Rider: @@ -458,6 +483,9 @@ namespace GodotTools // Apply the other fixes only after configurations have been migrated + // Make sure the existing project has the ProjectTypeGuids property (for VisualStudio) + ProjectUtils.EnsureHasProjectTypeGuids(msbuildProject); + // Make sure the existing project has Api assembly references configured correctly ProjectUtils.FixApiHintPath(msbuildProject); @@ -485,7 +513,7 @@ namespace GodotTools menuPopup.IdPressed += _MenuOptionPressed; - var buildButton = new ToolButton + var buildButton = new Button { Text = "Build", HintTooltip = "Build solution", @@ -501,7 +529,8 @@ namespace GodotTools if (OS.IsWindows) { - settingsHintStr += $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + + settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudio}" + + $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" + $",Visual Studio Code:{(int)ExternalEditorId.VsCode}" + $",JetBrains Rider:{(int)ExternalEditorId.Rider}"; } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj index ba527ca3b5..3f14629b11 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj +++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj @@ -33,5 +33,7 @@ <ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" /> <ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj" /> <ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" /> + <!-- Include it if this is an SCons build targeting Windows, or if it's not an SCons build but we're on Windows --> + <ProjectReference Include="..\GodotTools.OpenVisualStudio\GodotTools.OpenVisualStudio.csproj" Condition=" '$(GodotPlatform)' == 'windows' Or ( '$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT' ) " /> </ItemGroup> </Project> diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs index 32f264d100..17f3339560 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MessagingServer.cs @@ -12,6 +12,7 @@ using GodotTools.IdeMessaging; using GodotTools.IdeMessaging.Requests; using GodotTools.IdeMessaging.Utils; using GodotTools.Internals; +using GodotTools.Utils; using Newtonsoft.Json; using Directory = System.IO.Directory; using File = System.IO.File; @@ -307,6 +308,11 @@ namespace GodotTools.Ides var request = JsonConvert.DeserializeObject<DebugPlayRequest>(content.Body); return await HandleDebugPlay(request); }, + [StopPlayRequest.Id] = async (peer, content) => + { + var request = JsonConvert.DeserializeObject<StopPlayRequest>(content.Body); + return await HandleStopPlay(request); + }, [ReloadScriptsRequest.Id] = async (peer, content) => { _ = JsonConvert.DeserializeObject<ReloadScriptsRequest>(content.Body); @@ -343,6 +349,12 @@ namespace GodotTools.Ides return Task.FromResult<Response>(new DebugPlayResponse()); } + private static Task<Response> HandleStopPlay(StopPlayRequest request) + { + DispatchToMainThread(Internal.EditorRunStop); + return Task.FromResult<Response>(new StopPlayResponse()); + } + private static Task<Response> HandleReloadScripts() { DispatchToMainThread(Internal.ScriptEditorDebugger_ReloadScripts); @@ -351,8 +363,13 @@ namespace GodotTools.Ides private static async Task<Response> HandleCodeCompletionRequest(CodeCompletionRequest request) { + // This is needed if the "resource path" part of the path is case insensitive. + // However, it doesn't fix resource loading if the rest of the path is also case insensitive. + string scriptFileLocalized = FsPathUtils.LocalizePathWithCaseChecked(request.ScriptFile); + var response = new CodeCompletionResponse {Kind = request.Kind, ScriptFile = request.ScriptFile}; - response.Suggestions = await Task.Run(() => Internal.CodeCompletionRequest(response.Kind, response.ScriptFile)); + response.Suggestions = await Task.Run(() => + Internal.CodeCompletionRequest(response.Kind, scriptFileLocalized ?? request.ScriptFile)); return response; } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs index 7fb087467f..569f27649f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs @@ -13,9 +13,9 @@ namespace GodotTools.Internals public string Name { get; } public string Namespace { get; } public bool Nested { get; } - public int BaseCount { get; } + public long BaseCount { get; } - public ClassDecl(string name, string @namespace, bool nested, int baseCount) + public ClassDecl(string name, string @namespace, bool nested, long baseCount) { Name = name; Namespace = @namespace; @@ -45,7 +45,7 @@ namespace GodotTools.Internals (string)classDeclDict["name"], (string)classDeclDict["namespace"], (bool)classDeclDict["nested"], - (int)classDeclDict["base_count"] + (long)classDeclDict["base_count"] )); } diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs new file mode 100644 index 0000000000..c6724ccaf7 --- /dev/null +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/FsPathUtils.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using Godot; +using GodotTools.Core; +using JetBrains.Annotations; + +namespace GodotTools.Utils +{ + public static class FsPathUtils + { + private static readonly string ResourcePath = ProjectSettings.GlobalizePath("res://"); + + private static bool PathStartsWithAlreadyNorm(this string childPath, string parentPath) + { + // This won't work for Linux/macOS case insensitive file systems, but it's enough for our current problems + bool caseSensitive = !OS.IsWindows; + + string parentPathNorm = parentPath.NormalizePath() + Path.DirectorySeparatorChar; + string childPathNorm = childPath.NormalizePath() + Path.DirectorySeparatorChar; + + return childPathNorm.StartsWith(parentPathNorm, + caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); + } + + public static bool PathStartsWith(this string childPath, string parentPath) + { + string childPathNorm = childPath.NormalizePath() + Path.DirectorySeparatorChar; + string parentPathNorm = parentPath.NormalizePath() + Path.DirectorySeparatorChar; + + return childPathNorm.PathStartsWithAlreadyNorm(parentPathNorm); + } + + [CanBeNull] + public static string LocalizePathWithCaseChecked(string path) + { + string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar; + string resourcePathNorm = ResourcePath.NormalizePath() + Path.DirectorySeparatorChar; + + if (!pathNorm.PathStartsWithAlreadyNorm(resourcePathNorm)) + return null; + + string result = "res://" + pathNorm.Substring(resourcePathNorm.Length); + + // Remove the last separator we added + return result.Substring(0, result.Length - 1); + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs new file mode 100644 index 0000000000..20b11a48dd --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/SceneTreeExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Runtime.CompilerServices; +using Godot.Collections; + +namespace Godot +{ + public partial class SceneTree + { + public Array<T> GetNodesInGroup<T>(StringName group) where T : class + { + return new Array<T>(godot_icall_SceneTree_get_nodes_in_group_Generic(Object.GetPtr(this), StringName.GetPtr(group), typeof(T))); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType); + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index b5ac124c9a..06ec2483c8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -53,6 +53,7 @@ <Compile Include="Core\Extensions\NodeExtensions.cs" /> <Compile Include="Core\Extensions\ObjectExtensions.cs" /> <Compile Include="Core\Extensions\ResourceLoaderExtensions.cs" /> + <Compile Include="Core\Extensions\SceneTreeExtensions.cs" /> <Compile Include="Core\GD.cs" /> <Compile Include="Core\GodotSynchronizationContext.cs" /> <Compile Include="Core\GodotTaskScheduler.cs" /> diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index ee99a300b9..f6999d01fb 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -35,6 +35,7 @@ #include "gd_glue.h" #include "nodepath_glue.h" #include "rid_glue.h" +#include "scene_tree_glue.h" #include "string_glue.h" #include "string_name_glue.h" @@ -50,6 +51,7 @@ void godot_register_glue_header_icalls() { godot_register_object_icalls(); godot_register_rid_icalls(); godot_register_string_icalls(); + godot_register_scene_tree_icalls(); } // Used by the generated glue diff --git a/platform/haiku/context_gl_haiku.cpp b/modules/mono/glue/scene_tree_glue.cpp index 3c4d43ff71..bea9544b08 100644 --- a/platform/haiku/context_gl_haiku.cpp +++ b/modules/mono/glue/scene_tree_glue.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* context_gl_haiku.cpp */ +/* scene_tree_glue.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,56 +28,55 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "context_gl_haiku.h" - -#if defined(OPENGL_ENABLED) - -ContextGL_Haiku::ContextGL_Haiku(HaikuDirectWindow *p_window) { - window = p_window; - - uint32 type = BGL_RGB | BGL_DOUBLE | BGL_DEPTH; - view = new HaikuGLView(window->Bounds(), type); - - use_vsync = false; -} - -ContextGL_Haiku::~ContextGL_Haiku() { - delete view; -} - -Error ContextGL_Haiku::initialize() { - window->AddChild(view); - window->SetHaikuGLView(view); - - return OK; -} - -void ContextGL_Haiku::release_current() { - view->UnlockGL(); -} - -void ContextGL_Haiku::make_current() { - view->LockGL(); -} - -void ContextGL_Haiku::swap_buffers() { - view->SwapBuffers(use_vsync); -} - -int ContextGL_Haiku::get_window_width() { - return window->Bounds().IntegerWidth(); -} - -int ContextGL_Haiku::get_window_height() { - return window->Bounds().IntegerHeight(); -} - -void ContextGL_Haiku::set_use_vsync(bool p_use) { - use_vsync = p_use; +#include "scene_tree_glue.h" + +#ifdef MONO_GLUE_ENABLED + +#include "core/class_db.h" +#include "modules/mono/csharp_script.h" +#include "modules/mono/mono_gd/gd_mono_utils.h" +#include "scene/main/node.h" + +Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringName *group, MonoReflectionType *refltype) { + List<Node *> nodes; + Array ret; + + // Retrieve all the nodes in the group + ptr->get_nodes_in_group(*group, &nodes); + + // No need to bother if the group is empty + if (!nodes.empty()) { + MonoType *elem_type = mono_reflection_type_get_type(refltype); + MonoClass *mono_class = mono_class_from_mono_type(elem_type); + GDMonoClass *klass = GDMono::get_singleton()->get_class(mono_class); + + if (klass == GDMonoUtils::get_class_native_base(klass)) { + // If we're trying to get native objects, just check the inheritance list + StringName native_class_name = GDMonoUtils::get_native_godot_class_name(klass); + for (int i = 0; i < nodes.size(); ++i) { + if (ClassDB::is_parent_class(nodes[i]->get_class(), native_class_name)) + ret.push_back(nodes[i]); + } + } else { + // If we're trying to get csharpscript instances, get the mono object and compare the classes + for (int i = 0; i < nodes.size(); ++i) { + CSharpInstance *si = CAST_CSHARP_INSTANCE(nodes[i]->get_script_instance()); + + if (si != nullptr) { + MonoObject *obj = si->get_mono_object(); + if (obj != nullptr && mono_object_get_class(obj) == mono_class) { + ret.push_back(nodes[i]); + } + } + } + } + } + + return memnew(Array(ret)); } -bool ContextGL_Haiku::is_using_vsync() const { - return use_vsync; +void godot_register_scene_tree_icalls() { + mono_add_internal_call("Godot.SceneTree::godot_icall_SceneTree_get_nodes_in_group_Generic", (void *)godot_icall_SceneTree_get_nodes_in_group_Generic); } -#endif +#endif // MONO_GLUE_ENABLED diff --git a/platform/haiku/godot_haiku.cpp b/modules/mono/glue/scene_tree_glue.h index 0657f4c052..e9af35a30b 100644 --- a/platform/haiku/godot_haiku.cpp +++ b/modules/mono/glue/scene_tree_glue.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* godot_haiku.cpp */ +/* scene_tree_glue.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,22 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "main/main.h" -#include "os_haiku.h" +#ifndef SCENE_TREE_GLUE_H +#define SCENE_TREE_GLUE_H -int main(int argc, char *argv[]) { - OS_Haiku os; +#ifdef MONO_GLUE_ENABLED - Error error = Main::setup(argv[0], argc - 1, &argv[1]); - if (error != OK) { - return 255; - } +#include "core/array.h" +#include "core/string_name.h" +#include "scene/main/scene_tree.h" - if (Main::start()) { - os.run(); - } +#include "../mono_gd/gd_mono_marshal.h" - Main::cleanup(); +Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringName *group, MonoReflectionType *refltype); - return os.get_exit_code(); -} +// Register internal calls + +void godot_register_scene_tree_icalls(); + +#endif // MONO_GLUE_ENABLED + +#endif // SCENE_TREE_GLUE_H diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 085062261d..158742846b 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -624,8 +624,8 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty return BOX_BOOLEAN(val); } case Variant::INT: { - int32_t val = p_var->operator signed int(); - return BOX_INT32(val); + int64_t val = p_var->operator int64_t(); + return BOX_INT64(val); } case Variant::FLOAT: { #ifdef REAL_T_IS_DOUBLE diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp index 1b4fe68582..e0cf916a01 100644 --- a/modules/mono/utils/mono_reg_utils.cpp +++ b/modules/mono/utils/mono_reg_utils.cpp @@ -75,7 +75,6 @@ LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value) if (res == ERROR_MORE_DATA) { // dwBufferSize now contains the actual size - Vector<WCHAR> buffer; buffer.resize(dwBufferSize); res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); } diff --git a/modules/visual_script/config.py b/modules/visual_script/config.py index bd459ca344..b15479797c 100644 --- a/modules/visual_script/config.py +++ b/modules/visual_script/config.py @@ -8,7 +8,6 @@ def configure(env): def get_doc_classes(): return [ - "@VisualScript", "VisualScriptBasicTypeConstant", "VisualScriptBuiltinFunc", "VisualScriptClassConstant", diff --git a/modules/visual_script/doc_classes/@VisualScript.xml b/modules/visual_script/doc_classes/@VisualScript.xml deleted file mode 100644 index a2b966bfbb..0000000000 --- a/modules/visual_script/doc_classes/@VisualScript.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<class name="@VisualScript" version="4.0"> - <brief_description> - Built-in visual script functions. - </brief_description> - <description> - A list of built-in visual script functions, see [VisualScriptBuiltinFunc] and [VisualScript]. - </description> - <tutorials> - </tutorials> - <methods> - </methods> - <constants> - </constants> -</class> diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index 80c6be0fae..821a4dc584 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -97,13 +97,6 @@ task copyReleaseAARToAppModule(type: Copy) { include('godot-lib.release.aar') } -task copyGodotPaymentPluginToAppModule(type: Copy) { - dependsOn ':plugins:godotpayment:assembleRelease' - from('plugins/godotpayment/build/outputs/aar') - into('app/libs/plugins') - include('GodotPayment.release.aar') -} - /** * Copy the Godot android library archive release file into the root bin directory. * Depends on the library build task to ensure the AAR file is generated prior to copying. @@ -161,7 +154,6 @@ task generateGodotTemplates(type: GradleBuild) { } } - dependsOn 'copyGodotPaymentPluginToAppModule' finalizedBy 'zipCustomBuild' } diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 8ba9b0400f..fcbbc86100 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -262,7 +262,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe // Include the returned non-null views in the Godot view hierarchy. for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { - View pluginView = plugin.onMainCreateView(this); + View pluginView = plugin.onMainCreate(this); if (pluginView != null) { layout.addView(pluginView); } diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java index 431bd4f5f9..ce85880fa3 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java @@ -35,6 +35,7 @@ import org.godotengine.godot.Godot; import android.app.Activity; import android.content.Intent; +import android.os.Bundle; import android.util.Log; import android.view.Surface; import android.view.View; @@ -93,6 +94,14 @@ public abstract class GodotPlugin { } /** + * Provides access to the underlying {@link Activity}. + */ + @Nullable + protected Activity getActivity() { + return godot; + } + + /** * Register the plugin with Godot native code. * * This method is invoked on the render thread. @@ -145,13 +154,14 @@ public abstract class GodotPlugin { * Invoked once during the Godot Android initialization process after creation of the * {@link org.godotengine.godot.GodotView} view. * <p> - * This method should be overridden by descendants of this class that would like to add - * their view/layout to the Godot view hierarchy. + * The plugin can return a non-null {@link View} layout in order to add it to the Godot view + * hierarchy. * - * @return the view to be included; null if no views should be included. + * @see Activity#onCreate(Bundle) + * @return the plugin's view to be included; null if no views should be included. */ @Nullable - public View onMainCreateView(Activity activity) { + public View onMainCreate(Activity activity) { return null; } diff --git a/platform/android/java/plugins/godotpayment/build.gradle b/platform/android/java/plugins/godotpayment/build.gradle deleted file mode 100644 index fb3aa8bba2..0000000000 --- a/platform/android/java/plugins/godotpayment/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - - defaultConfig { - minSdkVersion versions.minSdk - targetSdkVersion versions.targetSdk - } - - libraryVariants.all { variant -> - variant.outputs.all { output -> - output.outputFileName = "GodotPayment.${variant.name}.aar" - } - } - -} - -dependencies { - implementation libraries.supportCoreUtils - implementation libraries.v4Support - implementation 'com.android.billingclient:billing:2.2.1' - - if (rootProject.findProject(":lib")) { - compileOnly project(":lib") - } else if (rootProject.findProject(":godot:lib")) { - compileOnly project(":godot:lib") - } else { - compileOnly fileTree(dir: 'libs', include: ['godot-lib*.aar']) - } -} diff --git a/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml b/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml deleted file mode 100644 index 61afa03799..0000000000 --- a/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml +++ /dev/null @@ -1,11 +0,0 @@ -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="org.godotengine.godot.plugin.payment"> - - <application> - - <meta-data - android:name="org.godotengine.plugin.v1.GodotPayment" - android:value="org.godotengine.godot.plugin.payment.GodotPayment" /> - - </application> -</manifest> diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java deleted file mode 100644 index 6447a9ec3f..0000000000 --- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java +++ /dev/null @@ -1,239 +0,0 @@ -/*************************************************************************/ -/* GodotPayment.java */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -package org.godotengine.godot.plugin.payment; - -import org.godotengine.godot.Dictionary; -import org.godotengine.godot.Godot; -import org.godotengine.godot.plugin.GodotPlugin; -import org.godotengine.godot.plugin.SignalInfo; -import org.godotengine.godot.plugin.payment.utils.GodotPaymentUtils; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.collection.ArraySet; - -import com.android.billingclient.api.AcknowledgePurchaseParams; -import com.android.billingclient.api.AcknowledgePurchaseResponseListener; -import com.android.billingclient.api.BillingClient; -import com.android.billingclient.api.BillingClientStateListener; -import com.android.billingclient.api.BillingFlowParams; -import com.android.billingclient.api.BillingResult; -import com.android.billingclient.api.ConsumeParams; -import com.android.billingclient.api.ConsumeResponseListener; -import com.android.billingclient.api.Purchase; -import com.android.billingclient.api.PurchasesUpdatedListener; -import com.android.billingclient.api.SkuDetails; -import com.android.billingclient.api.SkuDetailsParams; -import com.android.billingclient.api.SkuDetailsResponseListener; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Set; - -public class GodotPayment extends GodotPlugin implements PurchasesUpdatedListener, BillingClientStateListener { - private final BillingClient billingClient; - private final HashMap<String, SkuDetails> skuDetailsCache = new HashMap<>(); // sku → SkuDetails - - public GodotPayment(Godot godot) { - super(godot); - - billingClient = BillingClient - .newBuilder(getGodot()) - .enablePendingPurchases() - .setListener(this) - .build(); - } - - public void startConnection() { - billingClient.startConnection(this); - } - - public void endConnection() { - billingClient.endConnection(); - } - - public boolean isReady() { - return this.billingClient.isReady(); - } - - public Dictionary queryPurchases(String type) { - Purchase.PurchasesResult result = billingClient.queryPurchases(type); - - Dictionary returnValue = new Dictionary(); - if (result.getBillingResult().getResponseCode() == BillingClient.BillingResponseCode.OK) { - returnValue.put("status", 0); // OK = 0 - returnValue.put("purchases", GodotPaymentUtils.convertPurchaseListToDictionaryObjectArray(result.getPurchasesList())); - } else { - returnValue.put("status", 1); // FAILED = 1 - returnValue.put("response_code", result.getBillingResult().getResponseCode()); - returnValue.put("debug_message", result.getBillingResult().getDebugMessage()); - } - - return returnValue; - } - - public void querySkuDetails(final String[] list, String type) { - List<String> skuList = Arrays.asList(list); - - SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder() - .setSkusList(skuList) - .setType(type); - - billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { - @Override - public void onSkuDetailsResponse(BillingResult billingResult, - List<SkuDetails> skuDetailsList) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - for (SkuDetails skuDetails : skuDetailsList) { - skuDetailsCache.put(skuDetails.getSku(), skuDetails); - } - emitSignal("sku_details_query_completed", (Object)GodotPaymentUtils.convertSkuDetailsListToDictionaryObjectArray(skuDetailsList)); - } else { - emitSignal("sku_details_query_error", billingResult.getResponseCode(), billingResult.getDebugMessage(), list); - } - } - }); - } - - public void acknowledgePurchase(final String purchaseToken) { - AcknowledgePurchaseParams acknowledgePurchaseParams = - AcknowledgePurchaseParams.newBuilder() - .setPurchaseToken(purchaseToken) - .build(); - billingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() { - @Override - public void onAcknowledgePurchaseResponse(BillingResult billingResult) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - emitSignal("purchase_acknowledged", purchaseToken); - } else { - emitSignal("purchase_acknowledgement_error", billingResult.getResponseCode(), billingResult.getDebugMessage(), purchaseToken); - } - } - }); - } - - public void consumePurchase(String purchaseToken) { - ConsumeParams consumeParams = ConsumeParams.newBuilder() - .setPurchaseToken(purchaseToken) - .build(); - - billingClient.consumeAsync(consumeParams, new ConsumeResponseListener() { - @Override - public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - emitSignal("purchase_consumed", purchaseToken); - } else { - emitSignal("purchase_consumption_error", billingResult.getResponseCode(), billingResult.getDebugMessage(), purchaseToken); - } - } - }); - } - - @Override - public void onBillingSetupFinished(BillingResult billingResult) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - emitSignal("connected"); - } else { - emitSignal("connect_error", billingResult.getResponseCode(), billingResult.getDebugMessage()); - } - } - - @Override - public void onBillingServiceDisconnected() { - emitSignal("disconnected"); - } - - public Dictionary purchase(String sku) { - if (!skuDetailsCache.containsKey(sku)) { - emitSignal("purchase_error", null, "You must query the sku details and wait for the result before purchasing!"); - } - - SkuDetails skuDetails = skuDetailsCache.get(sku); - BillingFlowParams purchaseParams = BillingFlowParams.newBuilder() - .setSkuDetails(skuDetails) - .build(); - - BillingResult result = billingClient.launchBillingFlow(getGodot(), purchaseParams); - - Dictionary returnValue = new Dictionary(); - if (result.getResponseCode() == BillingClient.BillingResponseCode.OK) { - returnValue.put("status", 0); // OK = 0 - } else { - returnValue.put("status", 1); // FAILED = 1 - returnValue.put("response_code", result.getResponseCode()); - returnValue.put("debug_message", result.getDebugMessage()); - } - - return returnValue; - } - - @Override - public void onPurchasesUpdated(final BillingResult billingResult, @Nullable final List<Purchase> list) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) { - emitSignal("purchases_updated", (Object)GodotPaymentUtils.convertPurchaseListToDictionaryObjectArray(list)); - } else { - emitSignal("purchase_error", billingResult.getResponseCode(), billingResult.getDebugMessage()); - } - } - - @NonNull - @Override - public String getPluginName() { - return "GodotPayment"; - } - - @NonNull - @Override - public List<String> getPluginMethods() { - return Arrays.asList("startConnection", "endConnection", "purchase", "querySkuDetails", "isReady", "queryPurchases", "acknowledgePurchase", "consumePurchase"); - } - - @NonNull - @Override - public Set<SignalInfo> getPluginSignals() { - Set<SignalInfo> signals = new ArraySet<>(); - - signals.add(new SignalInfo("connected")); - signals.add(new SignalInfo("disconnected")); - signals.add(new SignalInfo("connect_error", Integer.class, String.class)); - signals.add(new SignalInfo("purchases_updated", Object[].class)); - signals.add(new SignalInfo("purchase_error", Integer.class, String.class)); - signals.add(new SignalInfo("sku_details_query_completed", Object[].class)); - signals.add(new SignalInfo("sku_details_query_error", Integer.class, String.class, String[].class)); - signals.add(new SignalInfo("purchase_acknowledged", String.class)); - signals.add(new SignalInfo("purchase_acknowledgement_error", Integer.class, String.class, String.class)); - signals.add(new SignalInfo("purchase_consumed", String.class)); - signals.add(new SignalInfo("purchase_consumption_error", Integer.class, String.class, String.class)); - - return signals; - } -} diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/GodotPaymentUtils.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/GodotPaymentUtils.java deleted file mode 100644 index f569c1b8bf..0000000000 --- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/GodotPaymentUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.godotengine.godot.plugin.payment.utils; - -import org.godotengine.godot.Dictionary; - -import com.android.billingclient.api.Purchase; -import com.android.billingclient.api.SkuDetails; - -import java.util.List; - -public class GodotPaymentUtils { - public static Dictionary convertPurchaseToDictionary(Purchase purchase) { - Dictionary dictionary = new Dictionary(); - dictionary.put("order_id", purchase.getOrderId()); - dictionary.put("package_name", purchase.getPackageName()); - dictionary.put("purchase_state", Integer.valueOf(purchase.getPurchaseState())); - dictionary.put("purchase_time", Long.valueOf(purchase.getPurchaseTime())); - dictionary.put("purchase_token", purchase.getPurchaseToken()); - dictionary.put("signature", purchase.getSignature()); - dictionary.put("sku", purchase.getSku()); - dictionary.put("is_acknowledged", Boolean.valueOf(purchase.isAcknowledged())); - dictionary.put("is_auto_renewing", Boolean.valueOf(purchase.isAutoRenewing())); - return dictionary; - } - - public static Dictionary convertSkuDetailsToDictionary(SkuDetails details) { - Dictionary dictionary = new Dictionary(); - dictionary.put("sku", details.getSku()); - dictionary.put("title", details.getTitle()); - dictionary.put("description", details.getDescription()); - dictionary.put("price", details.getPrice()); - dictionary.put("price_currency_code", details.getPriceCurrencyCode()); - dictionary.put("price_amount_micros", Long.valueOf(details.getPriceAmountMicros())); - dictionary.put("free_trial_period", details.getFreeTrialPeriod()); - dictionary.put("icon_url", details.getIconUrl()); - dictionary.put("introductory_price", details.getIntroductoryPrice()); - dictionary.put("introductory_price_amount_micros", Long.valueOf(details.getIntroductoryPriceAmountMicros())); - dictionary.put("introductory_price_cycles", details.getIntroductoryPriceCycles()); - dictionary.put("introductory_price_period", details.getIntroductoryPricePeriod()); - dictionary.put("original_price", details.getOriginalPrice()); - dictionary.put("original_price_amount_micros", Long.valueOf(details.getOriginalPriceAmountMicros())); - dictionary.put("subscription_period", details.getSubscriptionPeriod()); - dictionary.put("type", details.getType()); - dictionary.put("is_rewarded", Boolean.valueOf(details.isRewarded())); - return dictionary; - } - - public static Object[] convertPurchaseListToDictionaryObjectArray(List<Purchase> purchases) { - Object[] purchaseDictionaries = new Object[purchases.size()]; - - for (int i = 0; i < purchases.size(); i++) { - purchaseDictionaries[i] = GodotPaymentUtils.convertPurchaseToDictionary(purchases.get(i)); - } - - return purchaseDictionaries; - } - - public static Object[] convertSkuDetailsListToDictionaryObjectArray(List<SkuDetails> skuDetails) { - Object[] skuDetailsDictionaries = new Object[skuDetails.size()]; - - for (int i = 0; i < skuDetails.size(); i++) { - skuDetailsDictionaries[i] = GodotPaymentUtils.convertSkuDetailsToDictionary(skuDetails.get(i)); - } - - return skuDetailsDictionaries; - } -} diff --git a/platform/android/java/settings.gradle b/platform/android/java/settings.gradle index 9536d3de6d..f6921c70aa 100644 --- a/platform/android/java/settings.gradle +++ b/platform/android/java/settings.gradle @@ -3,4 +3,3 @@ rootProject.name = "Godot" include ':app' include ':lib' -include ':plugins:godotpayment' diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 1f61c4a805..8667727b1d 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -435,6 +435,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv * env->DeleteLocalRef(obj); }; + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); obj->call_deferred(str_method, args[0], args[1], args[2], args[3], args[4]); // something env->PopLocalFrame(nullptr); diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h index 5bc0fc3a58..ea3c7b4f55 100644 --- a/platform/android/plugin/godot_plugin_config.h +++ b/platform/android/plugin/godot_plugin_config.h @@ -86,17 +86,18 @@ struct PluginConfig { /* * Set of prebuilt plugins. + * Currently unused, this is just for future reference: */ -static const PluginConfig GODOT_PAYMENT = { - /*.valid_config =*/true, - /*.last_updated =*/0, - /*.name =*/"GodotPayment", - /*.binary_type =*/"local", - /*.binary =*/"res://android/build/libs/plugins/GodotPayment.release.aar", - /*.local_dependencies =*/{}, - /*.remote_dependencies =*/String("com.android.billingclient:billing:2.2.1").split("|"), - /*.custom_maven_repos =*/{} -}; +// static const PluginConfig MY_PREBUILT_PLUGIN = { +// /*.valid_config =*/true, +// /*.last_updated =*/0, +// /*.name =*/"GodotPayment", +// /*.binary_type =*/"local", +// /*.binary =*/"res://android/build/libs/plugins/GodotPayment.release.aar", +// /*.local_dependencies =*/{}, +// /*.remote_dependencies =*/String("com.android.billingclient:billing:2.2.1").split("|"), +// /*.custom_maven_repos =*/{} +// }; static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { String absolute_path; @@ -125,7 +126,7 @@ static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin, static inline Vector<PluginConfig> get_prebuilt_plugins(String plugins_base_dir) { Vector<PluginConfig> prebuilt_plugins; - prebuilt_plugins.push_back(resolve_prebuilt_plugin(GODOT_PAYMENT, plugins_base_dir)); + // prebuilt_plugins.push_back(resolve_prebuilt_plugin(MY_PREBUILT_PLUGIN, plugins_base_dir)); return prebuilt_plugins; } diff --git a/platform/haiku/SCsub b/platform/haiku/SCsub deleted file mode 100644 index dbff6c5ae9..0000000000 --- a/platform/haiku/SCsub +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -common_haiku = [ - "os_haiku.cpp", - "context_gl_haiku.cpp", - "haiku_application.cpp", - "haiku_direct_window.cpp", - "haiku_gl_view.cpp", - "key_mapping_haiku.cpp", - "audio_driver_media_kit.cpp", -] - -target = env.add_program("#bin/godot", ["godot_haiku.cpp"] + common_haiku) - -command = env.Command("#bin/godot.rsrc", "#platform/haiku/godot.rdef", ["rc -o $TARGET $SOURCE"]) - - -def addResourcesAction(target=None, source=None, env=None): - return env.Execute("xres -o " + File(target)[0].path + " bin/godot.rsrc") - - -env.AddPostAction(target, addResourcesAction) -env.Depends(target, command) diff --git a/platform/haiku/audio_driver_media_kit.cpp b/platform/haiku/audio_driver_media_kit.cpp deleted file mode 100644 index 2fbbeeb176..0000000000 --- a/platform/haiku/audio_driver_media_kit.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/*************************************************************************/ -/* audio_driver_media_kit.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "audio_driver_media_kit.h" - -#ifdef MEDIA_KIT_ENABLED - -#include "core/project_settings.h" - -int32_t *AudioDriverMediaKit::samples_in = nullptr; - -Error AudioDriverMediaKit::init() { - active = false; - - mix_rate = GLOBAL_GET("audio/mix_rate"); - speaker_mode = SPEAKER_MODE_STEREO; - channels = 2; - - int latency = GLOBAL_GET("audio/output_latency"); - buffer_size = next_power_of_2(latency * mix_rate / 1000); - samples_in = memnew_arr(int32_t, buffer_size * channels); - - media_raw_audio_format format; - format = media_raw_audio_format::wildcard; - format.frame_rate = mix_rate; - format.channel_count = channels; - format.format = media_raw_audio_format::B_AUDIO_INT; - format.byte_order = B_MEDIA_LITTLE_ENDIAN; - format.buffer_size = buffer_size * sizeof(int32_t) * channels; - - player = new BSoundPlayer( - &format, - "godot_sound_server", - AudioDriverMediaKit::PlayBuffer, - nullptr, - this); - - if (player->InitCheck() != B_OK) { - fprintf(stderr, "MediaKit ERR: can not create a BSoundPlayer instance\n"); - ERR_FAIL_COND_V(player == nullptr, ERR_CANT_OPEN); - } - - player->Start(); - - return OK; -} - -void AudioDriverMediaKit::PlayBuffer(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format) { - AudioDriverMediaKit *ad = (AudioDriverMediaKit *)cookie; - int32_t *buf = (int32_t *)buffer; - - if (!ad->active) { - for (unsigned int i = 0; i < ad->buffer_size * ad->channels; i++) { - AudioDriverMediaKit::samples_in[i] = 0; - } - } else { - ad->lock(); - ad->audio_server_process(ad->buffer_size, AudioDriverMediaKit::samples_in); - ad->unlock(); - } - - for (unsigned int i = 0; i < ad->buffer_size * ad->channels; i++) { - buf[i] = AudioDriverMediaKit::samples_in[i]; - } -} - -void AudioDriverMediaKit::start() { - active = true; -} - -int AudioDriverMediaKit::get_mix_rate() const { - return mix_rate; -} - -AudioDriverMediaKit::SpeakerMode AudioDriverMediaKit::get_speaker_mode() const { - return speaker_mode; -} - -void AudioDriverMediaKit::lock() { - if (!mutex) - return; - - mutex.lock(); -} - -void AudioDriverMediaKit::unlock() { - if (!mutex) - return; - - mutex.unlock(); -} - -void AudioDriverMediaKit::finish() { - delete player; - - if (samples_in) { - memdelete_arr(samples_in); - }; -} - -AudioDriverMediaKit::AudioDriverMediaKit() { - player = nullptr; -} - -AudioDriverMediaKit::~AudioDriverMediaKit() { -} - -#endif diff --git a/platform/haiku/audio_driver_media_kit.h b/platform/haiku/audio_driver_media_kit.h deleted file mode 100644 index 8272780fa7..0000000000 --- a/platform/haiku/audio_driver_media_kit.h +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************/ -/* audio_driver_media_kit.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "servers/audio_server.h" - -#ifdef MEDIA_KIT_ENABLED - -#include "core/os/mutex.h" -#include "core/os/thread.h" - -#include <kernel/image.h> // needed for image_id - -#include <SoundPlayer.h> - -class AudioDriverMediaKit : public AudioDriver { - Mutex mutex; - - BSoundPlayer *player; - static int32_t *samples_in; - - static void PlayBuffer(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format); - - unsigned int mix_rate; - SpeakerMode speaker_mode; - unsigned int buffer_size; - int channels; - - bool active; - -public: - const char *get_name() const { - return "MediaKit"; - }; - - virtual Error init(); - virtual void start(); - virtual int get_mix_rate() const; - virtual SpeakerMode get_speaker_mode() const; - virtual void lock(); - virtual void unlock(); - virtual void finish(); - - AudioDriverMediaKit(); - ~AudioDriverMediaKit(); -}; - -#endif diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py deleted file mode 100644 index 0b84df8f9b..0000000000 --- a/platform/haiku/detect.py +++ /dev/null @@ -1,158 +0,0 @@ -import os -import sys - - -def is_active(): - return True - - -def get_name(): - return "Haiku" - - -def can_build(): - - if os.name != "posix" or sys.platform == "darwin": - return False - - return True - - -def get_opts(): - from SCons.Variables import EnumVariable - - return [ - EnumVariable("debug_symbols", "Add debugging symbols to release builds", "yes", ("yes", "no", "full")), - ] - - -def get_flags(): - - return [] - - -def configure(env): - - ## Build type - - if env["target"] == "release": - env.Prepend(CCFLAGS=["-O3"]) - if env["debug_symbols"] == "yes": - env.Prepend(CCFLAGS=["-g1"]) - if env["debug_symbols"] == "full": - env.Prepend(CCFLAGS=["-g2"]) - - elif env["target"] == "release_debug": - env.Prepend(CCFLAGS=["-O2", "-DDEBUG_ENABLED"]) - if env["debug_symbols"] == "yes": - env.Prepend(CCFLAGS=["-g1"]) - if env["debug_symbols"] == "full": - env.Prepend(CCFLAGS=["-g2"]) - - elif env["target"] == "debug": - env.Prepend(CCFLAGS=["-g3", "-DDEBUG_ENABLED", "-DDEBUG_MEMORY_ENABLED"]) - - ## Architecture - - is64 = sys.maxsize > 2 ** 32 - if env["bits"] == "default": - env["bits"] = "64" if is64 else "32" - - ## Compiler configuration - - env["CC"] = "gcc-x86" - env["CXX"] = "g++-x86" - - ## Dependencies - - if not env["builtin_libwebp"]: - env.ParseConfig("pkg-config libwebp --cflags --libs") - - # freetype depends on libpng and zlib, so bundling one of them while keeping others - # as shared libraries leads to weird issues - if env["builtin_freetype"] or env["builtin_libpng"] or env["builtin_zlib"]: - env["builtin_freetype"] = True - env["builtin_libpng"] = True - env["builtin_zlib"] = True - - if not env["builtin_freetype"]: - env.ParseConfig("pkg-config freetype2 --cflags --libs") - - if not env["builtin_libpng"]: - env.ParseConfig("pkg-config libpng16 --cflags --libs") - - if not env["builtin_bullet"]: - # We need at least version 2.88 - import subprocess - - bullet_version = subprocess.check_output(["pkg-config", "bullet", "--modversion"]).strip() - if bullet_version < "2.88": - # Abort as system bullet was requested but too old - print( - "Bullet: System version {0} does not match minimal requirements ({1}). Aborting.".format( - bullet_version, "2.88" - ) - ) - sys.exit(255) - env.ParseConfig("pkg-config bullet --cflags --libs") - - if not env["builtin_enet"]: - env.ParseConfig("pkg-config libenet --cflags --libs") - - if not env["builtin_squish"]: - env.ParseConfig("pkg-config libsquish --cflags --libs") - - if not env["builtin_zstd"]: - env.ParseConfig("pkg-config libzstd --cflags --libs") - - # Sound and video libraries - # Keep the order as it triggers chained dependencies (ogg needed by others, etc.) - - if not env["builtin_libtheora"]: - env["builtin_libogg"] = False # Needed to link against system libtheora - env["builtin_libvorbis"] = False # Needed to link against system libtheora - env.ParseConfig("pkg-config theora theoradec --cflags --libs") - - if not env["builtin_libvpx"]: - env.ParseConfig("pkg-config vpx --cflags --libs") - - if not env["builtin_libvorbis"]: - env["builtin_libogg"] = False # Needed to link against system libvorbis - env.ParseConfig("pkg-config vorbis vorbisfile --cflags --libs") - - if not env["builtin_opus"]: - env["builtin_libogg"] = False # Needed to link against system opus - env.ParseConfig("pkg-config opus opusfile --cflags --libs") - - if not env["builtin_libogg"]: - env.ParseConfig("pkg-config ogg --cflags --libs") - - if env["builtin_libtheora"]: - list_of_x86 = ["x86_64", "x86", "i386", "i586"] - if any(platform.machine() in s for s in list_of_x86): - env["x86_libtheora_opt_gcc"] = True - - if not env["builtin_wslay"]: - env.ParseConfig("pkg-config libwslay --cflags --libs") - - if not env["builtin_mbedtls"]: - # mbedTLS does not provide a pkgconfig config yet. See https://github.com/ARMmbed/mbedtls/issues/228 - env.Append(LIBS=["mbedtls", "mbedcrypto", "mbedx509"]) - - if not env["builtin_miniupnpc"]: - # No pkgconfig file so far, hardcode default paths. - env.Prepend(CPPPATH=["/system/develop/headers/x86/miniupnpc"]) - env.Append(LIBS=["miniupnpc"]) - - # On Linux wchar_t should be 32-bits - # 16-bit library shouldn't be required due to compiler optimisations - if not env["builtin_pcre2"]: - env.ParseConfig("pkg-config libpcre2-32 --cflags --libs") - - ## Flags - - env.Prepend(CPPPATH=["#platform/haiku"]) - env.Append(CPPDEFINES=["UNIX_ENABLED", "OPENGL_ENABLED", "GLES_ENABLED"]) - env.Append(CPPDEFINES=["MEDIA_KIT_ENABLED"]) - env.Append(CPPDEFINES=["PTHREAD_NO_RENAME"]) # TODO: enable when we have pthread_setname_np - env.Append(LIBS=["be", "game", "media", "network", "bnetapi", "z", "GL"]) diff --git a/platform/haiku/godot.rdef b/platform/haiku/godot.rdef deleted file mode 100644 index a55cddbf0d..0000000000 --- a/platform/haiku/godot.rdef +++ /dev/null @@ -1,60 +0,0 @@ -resource app_version { - major = 2, - middle = 0, - minor = 0, - - variety = B_APPV_FINAL, - internal = 0, - - short_info = "Godot Game Engine", - long_info = "An advanced, feature packed, multi-platform 2D and 3D game engine." -}; - -resource app_signature "application/x-vnd.godot"; - -resource vector_icon { - $"6E6369660403A39F9F05FF03478CBF03414042090A04B37FB379CC26B379CC26" - $"CC20B37FCC200A09B5E9C41B2AC240B8E1BDFBBFA1BDA4C6A7BDFFCA1AC45CC9" - $"7AC607C01CC75BB6F4C65A062AFE9FFF9F69FE7FFEDFCF0FC95FC3D7C95FC51E" - $"C95FC51EC95FC53EC92BC565C94AC55BC92BC565C728C60BC728C60BC712C612" - $"C6E6C600C6F9C60EC6D3C5F2C6C7C5C4C6C7C5DCC6C7C5C4C460C4E5C4BCC4E5" - $"C626C4E5C626C4E5C64BC4A5C670C4CAC66BC4A5C670C1EDC6CFC1EDC6CFC1E9" - $"C6CFC1E2C6D0C1E6C6D0C1D1C6D0C1B2C6BEC1BFC6C9C1A2C6AFC19851C198C6" - $"9BC19851C505C031C507C507C016C507BFFCC507C507BE94C505BE9451BE9451" - $"BE94C69BBE7BC6BEBE8BC6AFBE6DC6C9BE4AC6D0BE5CC6D0BE47C6D0BE40C6CF" - $"BE44C6CFBE40C6CFBB87C670BB87C670BB63C66BBB47C626BB47C64BBB47C626" - $"C4BCB965C460B965C5C4B965C5C4B965C5DCB947C600B95AC5F2B934C60EB904" - $"C60BB91BC612B904C60BB701C565B701C565B6E3C55BB6CEC51EB6CEC53EB6CE" - $"C51EC3D7B590C36CB590C36CB581C3B0B578C43AB578C3F5B578C78FBFF8CA27" - $"BA2ACA22BFF8CA27BFFABFFCCA27BFFCCA27C5CACA22CA7CC43ACA7CC78FCA7C" - $"C3FBCA67C37ECA754ACA67C37E0639F6F97FFEF8E7FFF9F6FFFFFFFFFF03B67D" - $"BDEEC31FB730C35CB730C35CB74EC3662BC3A22BC3822BC3A2C4E8B8D1C55EB8" - $"D1C406B8D1C406B8D1C3F0B8ECC3CDB8DBC3DBB8FDC3BFB929C3BDB913C3B9B9" - $"29C3BDBB9FC436BB9FC436BBC2C43CBBDCC47EBBDCC45BBBDCC47EC5E6BE00C6" - $"31BE00C4BBBE00C4BBBE00C4A7BE16C486BE08C494BE24C479BE4AC471BE37C4" - $"71BE4AC471BE4BC016C473C1E2C471C1E2C471C1F6C471C217C486C209C479C2" - $"25C494C22DC4BBC22DC4A7C22DC4BBC631C451C5E6C451C47EC451C47EC451C4" - $"5BC48DC436C46AC43CC48DC436C704C3BDC704C3BDC719C3B9C741C3CDC730C3" - $"BF53C3DBC75CC406C75CC3F0C75CC406C55EC8CAC4E8C8CAC3A2C8CAC3A2C8CA" - $"C382C8FDC35CC8DFC366C8FDC35CC977C333BDEEC97ABDEEC97ABDEEC9F1BD56" - $"CAC9BC0BCA60BCB6CA3DBB1CC8D9B981C991BA47C82FB9D7C6EDBAA0C789BA38" - $"C69FBA52C5F0B9D0C647BA12C59BB98BC4E0B91FC53BB959C4FBB855C50EB6C0" - $"C509B78FC424B64AC22DB5C4C32AB5FCC1C8B66DC11BB7D9C16BB725C0BCB7C9" - $"BFFCB7C2C05CB7C3BFFCB7C2BFFCB7C2BFFCB7C2BFFBB7C2BFFAB7C2BFFAB7C2" - $"BFF9B7C2BFF8B7C2BFF9B7C2BFF8B7C2BFF8B7C2BFF8B7C2BF98B7C3BED9B7D9" - $"BF38B7C9BE88B725BDC7B5C4BE2CB66DBCCAB5FCBAE6B6C0BBD0B64ABAEBB78F" - $"BB13B91F34B855BAB8B959BA04B9D0BA59B98BB9ADBA12B907BAA0B955BA52B8" - $"6ABA38B71AB981B7C5B9D7B663BA47B52BBC0BB5B7BB1CB594BCB6B679BDEEB6" - $"02BD56B679BDEE0005BD3EC06CBD3EC06CBD3EC197BB2147BC4C47B9F647B904" - $"C06CB904C197B904BF41BB21BE4FB9F6BE4FBC4CBE4FBD3EC06CBD3EBF41BD3E" - $"C06C0005BCBC42BCBC42BCBCC153BB55C1F3BC1BC1F3BA8EC1F3B9ED42B9EDC1" - $"53B9EDBFC6BB55BF25BA8EBF25BC1BBF25BCBC42BCBCBFC6BCBC420007C01BC2" - $"BBC01BC2BBBFBAC2BBBF6CC21CBF6CC274BF6CC21CBF6CC02ABF6CC02ABF6CBF" - $"D3C01BBF8CBFBABF8CC07BBF8CC0C9C02AC0C9BFD3C0C9C02AC0C9C21CC0C9C2" - $"1CC0C9C274C01BC2BBC07BC2BBC01BC2BB0005C2F7C06CC2F7C06CC2F7C197C5" - $"1547C3E947C64047C732C06CC732C197C732BF41C515BE4FC640BE4FC3E9BE4F" - $"C2F7C06CC2F7BF41C2F7C06C0005C37942C37942C379C153C4E1C1F3C41AC1F3" - $"C5A7C1F3C64842C648C153C648BFC6C4E1BF25C5A7BF25C41ABF25C37942C379" - $"BFC6C37942090A0000000A010101000A020102000A020103000A010104000A03" - $"0105000A010106000A010107000A03010800" -}; diff --git a/platform/haiku/haiku_application.cpp b/platform/haiku/haiku_application.cpp deleted file mode 100644 index 82d9c093e1..0000000000 --- a/platform/haiku/haiku_application.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************/ -/* haiku_application.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "haiku_application.h" - -HaikuApplication::HaikuApplication() : - BApplication("application/x-vnd.godot") { -} diff --git a/platform/haiku/haiku_application.h b/platform/haiku/haiku_application.h deleted file mode 100644 index 2e04d921bf..0000000000 --- a/platform/haiku/haiku_application.h +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************/ -/* haiku_application.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef HAIKU_APPLICATION_H -#define HAIKU_APPLICATION_H - -#include <kernel/image.h> // needed for image_id - -#include <Application.h> - -class HaikuApplication : public BApplication { -public: - HaikuApplication(); -}; - -#endif diff --git a/platform/haiku/haiku_direct_window.cpp b/platform/haiku/haiku_direct_window.cpp deleted file mode 100644 index 0a40f847f4..0000000000 --- a/platform/haiku/haiku_direct_window.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/*************************************************************************/ -/* haiku_direct_window.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include <UnicodeChar.h> - -#include "core/os/keyboard.h" -#include "haiku_direct_window.h" -#include "key_mapping_haiku.h" -#include "main/main.h" - -HaikuDirectWindow::HaikuDirectWindow(BRect p_frame) : - BDirectWindow(p_frame, "Godot", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) { - last_mouse_pos_valid = false; - last_buttons_state = 0; - last_button_mask = 0; - last_key_modifier_state = 0; - - view = nullptr; - update_runner = nullptr; - input = nullptr; - main_loop = nullptr; -} - -HaikuDirectWindow::~HaikuDirectWindow() { -} - -void HaikuDirectWindow::SetHaikuGLView(HaikuGLView *p_view) { - view = p_view; -} - -void HaikuDirectWindow::StartMessageRunner() { - update_runner = new BMessageRunner(BMessenger(this), - new BMessage(REDRAW_MSG), 1000000 / 60 /* 60 fps */); -} - -void HaikuDirectWindow::StopMessageRunner() { - delete update_runner; -} - -void HaikuDirectWindow::SetInput(InputDefault *p_input) { - input = p_input; -} - -void HaikuDirectWindow::SetMainLoop(MainLoop *p_main_loop) { - main_loop = p_main_loop; -} - -bool HaikuDirectWindow::QuitRequested() { - StopMessageRunner(); - main_loop->notification(NOTIFICATION_WM_CLOSE_REQUEST); - return false; -} - -void HaikuDirectWindow::DirectConnected(direct_buffer_info *info) { - view->DirectConnected(info); - view->EnableDirectMode(true); -} - -void HaikuDirectWindow::MessageReceived(BMessage *message) { - switch (message->what) { - case REDRAW_MSG: - if (Main::iteration()) { - view->EnableDirectMode(false); - Quit(); - } - break; - - default: - BDirectWindow::MessageReceived(message); - } -} - -void HaikuDirectWindow::DispatchMessage(BMessage *message, BHandler *handler) { - switch (message->what) { - case B_MOUSE_DOWN: - case B_MOUSE_UP: - HandleMouseButton(message); - break; - - case B_MOUSE_MOVED: - HandleMouseMoved(message); - break; - - case B_MOUSE_WHEEL_CHANGED: - HandleMouseWheelChanged(message); - break; - - case B_KEY_DOWN: - case B_KEY_UP: - HandleKeyboardEvent(message); - break; - - case B_MODIFIERS_CHANGED: - HandleKeyboardModifierEvent(message); - break; - - case B_WINDOW_RESIZED: - HandleWindowResized(message); - break; - - case LOCKGL_MSG: - view->LockGL(); - break; - - case UNLOCKGL_MSG: - view->UnlockGL(); - break; - - default: - BDirectWindow::DispatchMessage(message, handler); - } -} - -void HaikuDirectWindow::HandleMouseButton(BMessage *message) { - BPoint where; - if (message->FindPoint("where", &where) != B_OK) { - return; - } - - uint32 modifiers = message->FindInt32("modifiers"); - uint32 buttons = message->FindInt32("buttons"); - uint32 button = buttons ^ last_buttons_state; - last_buttons_state = buttons; - - // TODO: implement the mouse_mode checks - /* - if (mouse_mode == MOUSE_MODE_CAPTURED) { - event.xbutton.x=last_mouse_pos.x; - event.xbutton.y=last_mouse_pos.y; - } - */ - - Ref<InputEventMouseButton> mouse_event; - mouse_event.instance(); - - mouse_event->set_button_mask(GetMouseButtonState(buttons)); - mouse_event->set_position({ where.x, where.y }); - mouse_event->set_global_position({ where.x, where.y }); - GetKeyModifierState(mouse_event, modifiers); - - switch (button) { - default: - case B_PRIMARY_MOUSE_BUTTON: - mouse_event->set_button_index(1); - break; - - case B_SECONDARY_MOUSE_BUTTON: - mouse_event->set_button_index(2); - break; - - case B_TERTIARY_MOUSE_BUTTON: - mouse_event->set_button_index(3); - break; - } - - mouse_event->set_pressed(message->what == B_MOUSE_DOWN); - - if (message->what == B_MOUSE_DOWN && mouse_event->get_button_index() == 1) { - int32 clicks = message->FindInt32("clicks"); - - if (clicks > 1) { - mouse_event->set_doubleclick(true); - } - } - - input->parse_input_event(mouse_event); -} - -void HaikuDirectWindow::HandleMouseMoved(BMessage *message) { - BPoint where; - if (message->FindPoint("where", &where) != B_OK) { - return; - } - - Point2i pos(where.x, where.y); - uint32 modifiers = message->FindInt32("modifiers"); - uint32 buttons = message->FindInt32("buttons"); - - if (!last_mouse_pos_valid) { - last_mouse_position = pos; - last_mouse_pos_valid = true; - } - - Point2i rel = pos - last_mouse_position; - - Ref<InputEventMouseMotion> motion_event; - motion_event.instance(); - GetKeyModifierState(motion_event, modifiers); - - motion_event->set_button_mask(GetMouseButtonState(buttons)); - motion_event->set_position({ pos.x, pos.y }); - input->set_mouse_position(pos); - motion_event->set_global_position({ pos.x, pos.y }); - motion_event->set_speed({ input->get_last_mouse_speed().x, - input->get_last_mouse_speed().y }); - - motion_event->set_relative({ rel.x, rel.y }); - - last_mouse_position = pos; - - input->parse_input_event(motion_event); -} - -void HaikuDirectWindow::HandleMouseWheelChanged(BMessage *message) { - float wheel_delta_y = 0; - if (message->FindFloat("be:wheel_delta_y", &wheel_delta_y) != B_OK) { - return; - } - - Ref<InputEventMouseButton> mouse_event; - mouse_event.instance(); - //GetKeyModifierState(mouse_event, modifiers); - - mouse_event->set_button_index(wheel_delta_y < 0 ? 4 : 5); - mouse_event->set_button_mask(last_button_mask); - mouse_event->set_position({ last_mouse_position.x, - last_mouse_position.y }); - mouse_event->set_global_position({ last_mouse_position.x, - last_mouse_position.y }); - - mouse_event->set_pressed(true); - input->parse_input_event(mouse_event); - - mouse_event->set_pressed(false); - input->parse_input_event(mouse_event); -} - -void HaikuDirectWindow::HandleKeyboardEvent(BMessage *message) { - int32 raw_char = 0; - int32 key = 0; - int32 modifiers = 0; - - if (message->FindInt32("raw_char", &raw_char) != B_OK) { - return; - } - - if (message->FindInt32("key", &key) != B_OK) { - return; - } - - if (message->FindInt32("modifiers", &modifiers) != B_OK) { - return; - } - - Ref<InputEventKey> event; - event.instance(); - GetKeyModifierState(event, modifiers); - event->set_pressed(message->what == B_KEY_DOWN); - event->set_keycode(KeyMappingHaiku::get_keysym(raw_char, key)); - event->set_physical_keycode(KeyMappingHaiku::get_keysym(raw_char, key)); - event->set_echo(message->HasInt32("be:key_repeat")); - event->set_unicode(0); - - const char *bytes = nullptr; - if (message->FindString("bytes", &bytes) == B_OK) { - event->set_unicode(BUnicodeChar::FromUTF8(&bytes)); - } - - //make it consistent across platforms. - if (event->get_keycode() == KEY_BACKTAB) { - event->set_keycode(KEY_TAB); - event->set_physical_keycode(KEY_TAB); - event->set_shift(true); - } - - input->parse_input_event(event); -} - -void HaikuDirectWindow::HandleKeyboardModifierEvent(BMessage *message) { - int32 old_modifiers = 0; - int32 modifiers = 0; - - if (message->FindInt32("be:old_modifiers", &old_modifiers) != B_OK) { - return; - } - - if (message->FindInt32("modifiers", &modifiers) != B_OK) { - return; - } - - int32 key = old_modifiers ^ modifiers; - - Ref<InputEventWithModifiers> event; - event.instance(); - GetKeyModifierState(event, modifiers); - - event->set_shift(key & B_SHIFT_KEY); - event->set_alt(key & B_OPTION_KEY); - event->set_control(key & B_CONTROL_KEY); - event->set_command(key & B_COMMAND_KEY); - - input->parse_input_event(event); -} - -void HaikuDirectWindow::HandleWindowResized(BMessage *message) { - int32 width = 0; - int32 height = 0; - - if ((message->FindInt32("width", &width) != B_OK) || (message->FindInt32("height", &height) != B_OK)) { - return; - } - - current_video_mode->width = width; - current_video_mode->height = height; -} - -inline void HaikuDirectWindow::GetKeyModifierState(Ref<InputEventWithModifiers> event, uint32 p_state) { - last_key_modifier_state = p_state; - - event->set_shift(p_state & B_SHIFT_KEY); - event->set_control(p_state & B_CONTROL_KEY); - event->set_alt(p_state & B_OPTION_KEY); - event->set_metakey(p_state & B_COMMAND_KEY); - - return state; -} - -inline int HaikuDirectWindow::GetMouseButtonState(uint32 p_state) { - int state = 0; - - if (p_state & B_PRIMARY_MOUSE_BUTTON) { - state |= 1 << 0; - } - - if (p_state & B_SECONDARY_MOUSE_BUTTON) { - state |= 1 << 1; - } - - if (p_state & B_TERTIARY_MOUSE_BUTTON) { - state |= 1 << 2; - } - - last_button_mask = state; - - return state; -} diff --git a/platform/haiku/haiku_direct_window.h b/platform/haiku/haiku_direct_window.h deleted file mode 100644 index 4817abbb7a..0000000000 --- a/platform/haiku/haiku_direct_window.h +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************/ -/* haiku_direct_window.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef HAIKU_DIRECT_WINDOW_H -#define HAIKU_DIRECT_WINDOW_H - -#include <kernel/image.h> // needed for image_id - -#include <DirectWindow.h> - -#include "core/input/input.h" -#include "core/os/os.h" - -#include "haiku_gl_view.h" - -#define REDRAW_MSG 'rdrw' -#define LOCKGL_MSG 'glck' -#define UNLOCKGL_MSG 'ulck' - -class HaikuDirectWindow : public BDirectWindow { -private: - Point2i last_mouse_position; - bool last_mouse_pos_valid; - uint32 last_buttons_state; - uint32 last_key_modifier_state; - int last_button_mask; - OS::VideoMode *current_video_mode; - - MainLoop *main_loop; - InputDefault *input; - HaikuGLView *view; - BMessageRunner *update_runner; - - void HandleMouseButton(BMessage *message); - void HandleMouseMoved(BMessage *message); - void HandleMouseWheelChanged(BMessage *message); - void HandleWindowResized(BMessage *message); - void HandleKeyboardEvent(BMessage *message); - void HandleKeyboardModifierEvent(BMessage *message); - inline void GetKeyModifierState(Ref<InputEventWithModifiers> event, uint32 p_state); - inline int GetMouseButtonState(uint32 p_state); - -public: - HaikuDirectWindow(BRect p_frame); - ~HaikuDirectWindow(); - - void SetHaikuGLView(HaikuGLView *p_view); - void StartMessageRunner(); - void StopMessageRunner(); - void SetInput(InputDefault *p_input); - void SetMainLoop(MainLoop *p_main_loop); - inline void SetVideoMode(OS::VideoMode *video_mode) { current_video_mode = video_mode; }; - virtual bool QuitRequested(); - virtual void DirectConnected(direct_buffer_info *info); - virtual void MessageReceived(BMessage *message); - virtual void DispatchMessage(BMessage *message, BHandler *handler); - - inline Point2i GetLastMousePosition() { return last_mouse_position; }; - inline int GetLastButtonMask() { return last_button_mask; }; -}; - -#endif diff --git a/platform/haiku/haiku_gl_view.cpp b/platform/haiku/haiku_gl_view.cpp deleted file mode 100644 index 970a1276fd..0000000000 --- a/platform/haiku/haiku_gl_view.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************/ -/* haiku_gl_view.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "haiku_gl_view.h" -#include "main/main.h" - -HaikuGLView::HaikuGLView(BRect frame, uint32 type) : - BGLView(frame, "GodotGLView", B_FOLLOW_ALL_SIDES, 0, type) { -} - -void HaikuGLView::AttachedToWindow(void) { - LockGL(); - BGLView::AttachedToWindow(); - UnlockGL(); - MakeFocus(); -} - -void HaikuGLView::Draw(BRect updateRect) { - Main::force_redraw(); -} diff --git a/platform/haiku/haiku_gl_view.h b/platform/haiku/haiku_gl_view.h deleted file mode 100644 index 59e02d2367..0000000000 --- a/platform/haiku/haiku_gl_view.h +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************/ -/* haiku_gl_view.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef HAIKU_GL_VIEW_H -#define HAIKU_GL_VIEW_H - -#include <kernel/image.h> // needed for image_id - -#include <GLView.h> - -class HaikuGLView : public BGLView { -public: - HaikuGLView(BRect frame, uint32 type); - virtual void AttachedToWindow(void); - virtual void Draw(BRect updateRect); -}; - -#endif diff --git a/platform/haiku/key_mapping_haiku.cpp b/platform/haiku/key_mapping_haiku.cpp deleted file mode 100644 index 692a1e5a78..0000000000 --- a/platform/haiku/key_mapping_haiku.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/*************************************************************************/ -/* key_mapping_haiku.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include <InterfaceDefs.h> - -#include "core/os/keyboard.h" -#include "key_mapping_haiku.h" - -struct _HaikuTranslatePair { - unsigned int keysym; - int32 keycode; -}; - -static _HaikuTranslatePair _mod_to_keycode[] = { - { KEY_SHIFT, B_SHIFT_KEY }, - { KEY_ALT, B_COMMAND_KEY }, - { KEY_CONTROL, B_CONTROL_KEY }, - { KEY_CAPSLOCK, B_CAPS_LOCK }, - { KEY_SCROLLLOCK, B_SCROLL_LOCK }, - { KEY_NUMLOCK, B_NUM_LOCK }, - { KEY_SUPER_L, B_OPTION_KEY }, - { KEY_MENU, B_MENU_KEY }, - { KEY_SHIFT, B_LEFT_SHIFT_KEY }, - { KEY_SHIFT, B_RIGHT_SHIFT_KEY }, - { KEY_ALT, B_LEFT_COMMAND_KEY }, - { KEY_ALT, B_RIGHT_COMMAND_KEY }, - { KEY_CONTROL, B_LEFT_CONTROL_KEY }, - { KEY_CONTROL, B_RIGHT_CONTROL_KEY }, - { KEY_SUPER_L, B_LEFT_OPTION_KEY }, - { KEY_SUPER_R, B_RIGHT_OPTION_KEY }, - { KEY_UNKNOWN, 0 } -}; - -static _HaikuTranslatePair _fn_to_keycode[] = { - { KEY_F1, B_F1_KEY }, - { KEY_F2, B_F2_KEY }, - { KEY_F3, B_F3_KEY }, - { KEY_F4, B_F4_KEY }, - { KEY_F5, B_F5_KEY }, - { KEY_F6, B_F6_KEY }, - { KEY_F7, B_F7_KEY }, - { KEY_F8, B_F8_KEY }, - { KEY_F9, B_F9_KEY }, - { KEY_F10, B_F10_KEY }, - { KEY_F11, B_F11_KEY }, - { KEY_F12, B_F12_KEY }, - //{ KEY_F13, ? }, - //{ KEY_F14, ? }, - //{ KEY_F15, ? }, - //{ KEY_F16, ? }, - { KEY_PRINT, B_PRINT_KEY }, - { KEY_SCROLLLOCK, B_SCROLL_KEY }, - { KEY_PAUSE, B_PAUSE_KEY }, - { KEY_UNKNOWN, 0 } -}; - -static _HaikuTranslatePair _hb_to_keycode[] = { - { KEY_BACKSPACE, B_BACKSPACE }, - { KEY_TAB, B_TAB }, - { KEY_ENTER, B_RETURN }, - { KEY_CAPSLOCK, B_CAPS_LOCK }, - { KEY_ESCAPE, B_ESCAPE }, - { KEY_SPACE, B_SPACE }, - { KEY_PAGEUP, B_PAGE_UP }, - { KEY_PAGEDOWN, B_PAGE_DOWN }, - { KEY_END, B_END }, - { KEY_HOME, B_HOME }, - { KEY_LEFT, B_LEFT_ARROW }, - { KEY_UP, B_UP_ARROW }, - { KEY_RIGHT, B_RIGHT_ARROW }, - { KEY_DOWN, B_DOWN_ARROW }, - { KEY_PRINT, B_PRINT_KEY }, - { KEY_INSERT, B_INSERT }, - { KEY_DELETE, B_DELETE }, - // { KEY_HELP, ??? }, - - { KEY_0, (0x30) }, - { KEY_1, (0x31) }, - { KEY_2, (0x32) }, - { KEY_3, (0x33) }, - { KEY_4, (0x34) }, - { KEY_5, (0x35) }, - { KEY_6, (0x36) }, - { KEY_7, (0x37) }, - { KEY_8, (0x38) }, - { KEY_9, (0x39) }, - { KEY_A, (0x61) }, - { KEY_B, (0x62) }, - { KEY_C, (0x63) }, - { KEY_D, (0x64) }, - { KEY_E, (0x65) }, - { KEY_F, (0x66) }, - { KEY_G, (0x67) }, - { KEY_H, (0x68) }, - { KEY_I, (0x69) }, - { KEY_J, (0x6A) }, - { KEY_K, (0x6B) }, - { KEY_L, (0x6C) }, - { KEY_M, (0x6D) }, - { KEY_N, (0x6E) }, - { KEY_O, (0x6F) }, - { KEY_P, (0x70) }, - { KEY_Q, (0x71) }, - { KEY_R, (0x72) }, - { KEY_S, (0x73) }, - { KEY_T, (0x74) }, - { KEY_U, (0x75) }, - { KEY_V, (0x76) }, - { KEY_W, (0x77) }, - { KEY_X, (0x78) }, - { KEY_Y, (0x79) }, - { KEY_Z, (0x7A) }, - - /* -{ KEY_PLAY, VK_PLAY},// (0xFA) -{ KEY_STANDBY,VK_SLEEP },//(0x5F) -{ KEY_BACK,VK_BROWSER_BACK},// (0xA6) -{ KEY_FORWARD,VK_BROWSER_FORWARD},// (0xA7) -{ KEY_REFRESH,VK_BROWSER_REFRESH},// (0xA8) -{ KEY_STOP,VK_BROWSER_STOP},// (0xA9) -{ KEY_SEARCH,VK_BROWSER_SEARCH},// (0xAA) -{ KEY_FAVORITES, VK_BROWSER_FAVORITES},// (0xAB) -{ KEY_HOMEPAGE,VK_BROWSER_HOME},// (0xAC) -{ KEY_VOLUMEMUTE,VK_VOLUME_MUTE},// (0xAD) -{ KEY_VOLUMEDOWN,VK_VOLUME_DOWN},// (0xAE) -{ KEY_VOLUMEUP,VK_VOLUME_UP},// (0xAF) -{ KEY_MEDIANEXT,VK_MEDIA_NEXT_TRACK},// (0xB0) -{ KEY_MEDIAPREVIOUS,VK_MEDIA_PREV_TRACK},// (0xB1) -{ KEY_MEDIASTOP,VK_MEDIA_STOP},// (0xB2) -{ KEY_LAUNCHMAIL, VK_LAUNCH_MAIL},// (0xB4) -{ KEY_LAUNCHMEDIA,VK_LAUNCH_MEDIA_SELECT},// (0xB5) -{ KEY_LAUNCH0,VK_LAUNCH_APP1},// (0xB6) -{ KEY_LAUNCH1,VK_LAUNCH_APP2},// (0xB7) -*/ - - { KEY_SEMICOLON, 0x3B }, - { KEY_EQUAL, 0x3D }, - { KEY_COLON, 0x2C }, - { KEY_MINUS, 0x2D }, - { KEY_PERIOD, 0x2E }, - { KEY_SLASH, 0x2F }, - { KEY_KP_MULTIPLY, 0x2A }, - { KEY_KP_ADD, 0x2B }, - - { KEY_QUOTELEFT, 0x60 }, - { KEY_BRACKETLEFT, 0x5B }, - { KEY_BACKSLASH, 0x5C }, - { KEY_BRACKETRIGHT, 0x5D }, - { KEY_APOSTROPHE, 0x27 }, - - { KEY_UNKNOWN, 0 } -}; - -unsigned int KeyMappingHaiku::get_keysym(int32 raw_char, int32 key) { - if (raw_char == B_INSERT && key == 0x64) { - return KEY_KP_0; - } - if (raw_char == B_END && key == 0x58) { - return KEY_KP_1; - } - if (raw_char == B_DOWN_ARROW && key == 0x59) { - return KEY_KP_2; - } - if (raw_char == B_PAGE_DOWN && key == 0x5A) { - return KEY_KP_3; - } - if (raw_char == B_LEFT_ARROW && key == 0x48) { - return KEY_KP_4; - } - if (raw_char == 0x35 && key == 0x49) { - return KEY_KP_5; - } - if (raw_char == B_RIGHT_ARROW && key == 0x4A) { - return KEY_KP_6; - } - if (raw_char == B_HOME && key == 0x37) { - return KEY_KP_7; - } - if (raw_char == B_UP_ARROW && key == 0x38) { - return KEY_KP_8; - } - if (raw_char == B_PAGE_UP && key == 0x39) { - return KEY_KP_9; - } - if (raw_char == 0x2F && key == 0x23) { - return KEY_KP_DIVIDE; - } - if (raw_char == 0x2D && key == 0x25) { - return KEY_KP_SUBTRACT; - } - if (raw_char == B_DELETE && key == 0x65) { - return KEY_KP_PERIOD; - } - - if (raw_char == 0x10) { - for (int i = 0; _fn_to_keycode[i].keysym != KEY_UNKNOWN; i++) { - if (_fn_to_keycode[i].keycode == key) { - return _fn_to_keycode[i].keysym; - } - } - - return KEY_UNKNOWN; - } - - for (int i = 0; _hb_to_keycode[i].keysym != KEY_UNKNOWN; i++) { - if (_hb_to_keycode[i].keycode == raw_char) { - return _hb_to_keycode[i].keysym; - } - } - - return KEY_UNKNOWN; -} - -unsigned int KeyMappingHaiku::get_modifier_keysym(int32 key) { - for (int i = 0; _mod_to_keycode[i].keysym != KEY_UNKNOWN; i++) { - if ((_mod_to_keycode[i].keycode & key) != 0) { - return _mod_to_keycode[i].keysym; - } - } - - return KEY_UNKNOWN; -} diff --git a/platform/haiku/key_mapping_haiku.h b/platform/haiku/key_mapping_haiku.h deleted file mode 100644 index e735108e44..0000000000 --- a/platform/haiku/key_mapping_haiku.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************/ -/* key_mapping_haiku.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef KEY_MAPPING_HAIKU_H -#define KEY_MAPPING_HAIKU_H - -class KeyMappingHaiku { - KeyMappingHaiku() {} - -public: - static unsigned int get_keysym(int32 raw_char, int32 key); - static unsigned int get_modifier_keysym(int32 key); -}; - -#endif diff --git a/platform/haiku/logo.png b/platform/haiku/logo.png Binary files differdeleted file mode 100644 index a2d8e242a6..0000000000 --- a/platform/haiku/logo.png +++ /dev/null diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp deleted file mode 100644 index 7a2591784f..0000000000 --- a/platform/haiku/os_haiku.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/*************************************************************************/ -/* os_haiku.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "os_haiku.h" - -#include "drivers/gles2/rasterizer_gles2.h" -#include "main/main.h" -#include "servers/physics_3d/physics_server_3d_sw.h" -#include "servers/rendering/rendering_server_raster.h" -#include "servers/rendering/rendering_server_wrap_mt.h" - -#include <Screen.h> - -OS_Haiku::OS_Haiku() { -#ifdef MEDIA_KIT_ENABLED - AudioDriverManager::add_driver(&driver_media_kit); -#endif -}; - -void OS_Haiku::run() { - if (!main_loop) { - return; - } - - main_loop->init(); - context_gl->release_current(); - - // TODO: clean up - BMessenger *bms = new BMessenger(window); - BMessage *msg = new BMessage(); - bms->SendMessage(LOCKGL_MSG, msg); - - window->StartMessageRunner(); - app->Run(); - window->StopMessageRunner(); - - delete app; - - delete bms; - delete msg; - main_loop->finish(); -} - -String OS_Haiku::get_name() const { - return "Haiku"; -} - -int OS_Haiku::get_video_driver_count() const { - return 1; -} - -const char *OS_Haiku::get_video_driver_name(int p_driver) const { - return "GLES2"; -} - -int OS_Haiku::get_current_video_driver() const { - return video_driver_index; -} - -Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { - main_loop = nullptr; - current_video_mode = p_desired; - - app = new HaikuApplication(); - - BRect frame; - frame.Set(50, 50, 50 + current_video_mode.width - 1, 50 + current_video_mode.height - 1); - - window = new HaikuDirectWindow(frame); - window->SetVideoMode(¤t_video_mode); - - if (current_video_mode.fullscreen) { - window->SetFullScreen(true); - } - - if (!current_video_mode.resizable) { - uint32 flags = window->Flags(); - flags |= B_NOT_RESIZABLE; - window->SetFlags(flags); - } - -#if defined(OPENGL_ENABLED) - context_gl = memnew(ContextGL_Haiku(window)); - context_gl->initialize(); - context_gl->make_current(); - context_gl->set_use_vsync(current_video_mode.use_vsync); - // FIXME: That's not how the rasterizer setup should happen. - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); -#endif - - rendering_server = memnew(RenderingServerRaster); - // FIXME: Reimplement threaded rendering - if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - rendering_server = memnew(RenderingServerWrapMT(rendering_server, false)); - } - - ERR_FAIL_COND_V(!rendering_server, ERR_UNAVAILABLE); - - video_driver_index = p_video_driver; - - input = memnew(InputDefault); - window->SetInput(input); - - window->Show(); - rendering_server->init(); - - AudioDriverManager::initialize(p_audio_driver); - - return OK; -} - -void OS_Haiku::finalize() { - if (main_loop) { - memdelete(main_loop); - } - - main_loop = nullptr; - - rendering_server->finish(); - memdelete(rendering_server); - - memdelete(input); - -#if defined(OPENGL_ENABLED) - memdelete(context_gl); -#endif -} - -void OS_Haiku::set_main_loop(MainLoop *p_main_loop) { - main_loop = p_main_loop; - input->set_main_loop(p_main_loop); - window->SetMainLoop(p_main_loop); -} - -MainLoop *OS_Haiku::get_main_loop() const { - return main_loop; -} - -void OS_Haiku::delete_main_loop() { - if (main_loop) { - memdelete(main_loop); - } - - main_loop = nullptr; - window->SetMainLoop(nullptr); -} - -void OS_Haiku::release_rendering_thread() { - context_gl->release_current(); -} - -void OS_Haiku::make_rendering_thread() { - context_gl->make_current(); -} - -bool OS_Haiku::can_draw() const { - // TODO: implement - return true; -} - -void OS_Haiku::swap_buffers() { - context_gl->swap_buffers(); -} - -Point2 OS_Haiku::get_mouse_position() const { - return window->GetLastMousePosition(); -} - -int OS_Haiku::get_mouse_button_state() const { - return window->GetLastButtonMask(); -} - -void OS_Haiku::set_cursor_shape(CursorShape p_shape) { - //ERR_PRINT("set_cursor_shape() NOT IMPLEMENTED"); -} - -OS::CursorShape OS_Haiku::get_cursor_shape() const { - // TODO: implement get_cursor_shape -} - -void OS_Haiku::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) { - // TODO -} - -int OS_Haiku::get_screen_count() const { - // TODO: implement get_screen_count() - return 1; -} - -int OS_Haiku::get_current_screen() const { - // TODO: implement get_current_screen() - return 0; -} - -void OS_Haiku::set_current_screen(int p_screen) { - // TODO: implement set_current_screen() -} - -Point2 OS_Haiku::get_screen_position(int p_screen) const { - // TODO: make this work with the p_screen parameter - BScreen *screen = new BScreen(window); - BRect frame = screen->Frame(); - delete screen; - return Point2i(frame.left, frame.top); -} - -Size2 OS_Haiku::get_screen_size(int p_screen) const { - // TODO: make this work with the p_screen parameter - BScreen *screen = new BScreen(window); - BRect frame = screen->Frame(); - delete screen; - return Size2i(frame.IntegerWidth() + 1, frame.IntegerHeight() + 1); -} - -void OS_Haiku::set_window_title(const String &p_title) { - window->SetTitle(p_title.utf8().get_data()); -} - -Size2 OS_Haiku::get_window_size() const { - BSize size = window->Size(); - return Size2i(size.IntegerWidth() + 1, size.IntegerHeight() + 1); -} - -void OS_Haiku::set_window_size(const Size2 p_size) { - // TODO: why does it stop redrawing after this is called? - window->ResizeTo(p_size.x, p_size.y); -} - -Point2 OS_Haiku::get_window_position() const { - BPoint point(0, 0); - window->ConvertToScreen(&point); - return Point2i(point.x, point.y); -} - -void OS_Haiku::set_window_position(const Point2 &p_position) { - window->MoveTo(p_position.x, p_position.y); -} - -void OS_Haiku::set_window_fullscreen(bool p_enabled) { - window->SetFullScreen(p_enabled); - current_video_mode.fullscreen = p_enabled; - rendering_server->init(); -} - -bool OS_Haiku::is_window_fullscreen() const { - return current_video_mode.fullscreen; -} - -void OS_Haiku::set_window_resizable(bool p_enabled) { - uint32 flags = window->Flags(); - - if (p_enabled) { - flags &= ~(B_NOT_RESIZABLE); - } else { - flags |= B_NOT_RESIZABLE; - } - - window->SetFlags(flags); - current_video_mode.resizable = p_enabled; -} - -bool OS_Haiku::is_window_resizable() const { - return current_video_mode.resizable; -} - -void OS_Haiku::set_window_minimized(bool p_enabled) { - window->Minimize(p_enabled); -} - -bool OS_Haiku::is_window_minimized() const { - return window->IsMinimized(); -} - -void OS_Haiku::set_window_maximized(bool p_enabled) { - window->Minimize(!p_enabled); -} - -bool OS_Haiku::is_window_maximized() const { - return !window->IsMinimized(); -} - -void OS_Haiku::set_video_mode(const VideoMode &p_video_mode, int p_screen) { - ERR_PRINT("set_video_mode() NOT IMPLEMENTED"); -} - -OS::VideoMode OS_Haiku::get_video_mode(int p_screen) const { - return current_video_mode; -} - -void OS_Haiku::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const { - ERR_PRINT("get_fullscreen_mode_list() NOT IMPLEMENTED"); -} - -String OS_Haiku::get_executable_path() const { - return OS::get_executable_path(); -} - -bool OS_Haiku::_check_internal_feature_support(const String &p_feature) { - return p_feature == "pc"; -} - -String OS_Haiku::get_config_path() const { - if (has_environment("XDG_CONFIG_HOME")) { - return get_environment("XDG_CONFIG_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file("config/settings"); - } else { - return "."; - } -} - -String OS_Haiku::get_data_path() const { - if (has_environment("XDG_DATA_HOME")) { - return get_environment("XDG_DATA_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file("config/data"); - } else { - return get_config_path(); - } -} - -String OS_Haiku::get_cache_path() const { - if (has_environment("XDG_CACHE_HOME")) { - return get_environment("XDG_CACHE_HOME"); - } else if (has_environment("HOME")) { - return get_environment("HOME").plus_file("config/cache"); - } else { - return get_config_path(); - } -} diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h deleted file mode 100644 index d3ef9400d4..0000000000 --- a/platform/haiku/os_haiku.h +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************/ -/* os_haiku.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef OS_HAIKU_H -#define OS_HAIKU_H - -#include "audio_driver_media_kit.h" -#include "context_gl_haiku.h" -#include "core/input/input.h" -#include "drivers/unix/os_unix.h" -#include "haiku_application.h" -#include "haiku_direct_window.h" -#include "servers/audio_server.h" -#include "servers/rendering_server.h" - -class OS_Haiku : public OS_Unix { -private: - HaikuApplication *app; - HaikuDirectWindow *window; - MainLoop *main_loop; - InputDefault *input; - RenderingServer *rendering_server; - VideoMode current_video_mode; - int video_driver_index; - -#ifdef MEDIA_KIT_ENABLED - AudioDriverMediaKit driver_media_kit; -#endif - -#if defined(OPENGL_ENABLED) - ContextGL_Haiku *context_gl; -#endif - - virtual void delete_main_loop(); - -protected: - virtual int get_video_driver_count() const; - virtual const char *get_video_driver_name(int p_driver) const; - virtual int get_current_video_driver() const; - - virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); - virtual void finalize(); - - virtual void set_main_loop(MainLoop *p_main_loop); - -public: - OS_Haiku(); - void run(); - - virtual String get_name() const; - - virtual MainLoop *get_main_loop() const; - - virtual bool can_draw() const; - virtual void release_rendering_thread(); - virtual void make_rendering_thread(); - virtual void swap_buffers(); - - virtual Point2 get_mouse_position() const; - virtual int get_mouse_button_state() const; - virtual void set_cursor_shape(CursorShape p_shape); - virtual CursorShape get_cursor_shape() const; - virtual void set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot); - - virtual int get_screen_count() const; - virtual int get_current_screen() const; - virtual void set_current_screen(int p_screen); - virtual Point2 get_screen_position(int p_screen = -1) const; - virtual Size2 get_screen_size(int p_screen = -1) const; - virtual void set_window_title(const String &p_title); - virtual Size2 get_window_size() const; - virtual void set_window_size(const Size2 p_size); - virtual Point2 get_window_position() const; - virtual void set_window_position(const Point2 &p_position); - virtual void set_window_fullscreen(bool p_enabled); - virtual bool is_window_fullscreen() const; - virtual void set_window_resizable(bool p_enabled); - virtual bool is_window_resizable() const; - virtual void set_window_minimized(bool p_enabled); - virtual bool is_window_minimized() const; - virtual void set_window_maximized(bool p_enabled); - virtual bool is_window_maximized() const; - - virtual void set_video_mode(const VideoMode &p_video_mode, int p_screen = 0); - virtual VideoMode get_video_mode(int p_screen = 0) const; - virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const; - virtual String get_executable_path() const; - - virtual bool _check_internal_feature_support(const String &p_feature); - - virtual String get_config_path() const; - virtual String get_data_path() const; - virtual String get_cache_path() const; -}; - -#endif diff --git a/platform/haiku/platform_config.h b/platform/haiku/platform_config.h deleted file mode 100644 index f2d5418adf..0000000000 --- a/platform/haiku/platform_config.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* platform_config.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include <alloca.h> - -// for ifaddrs.h needed in drivers/unix/ip_unix.cpp -#define _BSD_SOURCE 1 - -#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h" diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub index a48629f720..b72d29149c 100644 --- a/platform/iphone/SCsub +++ b/platform/iphone/SCsub @@ -20,6 +20,9 @@ iphone_lib = [ env_ios = env.Clone() ios_lib = env_ios.add_library("iphone", iphone_lib) +# (iOS) Enable module support +env_ios.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) + def combine_libs(target=None, source=None, env=None): lib_path = target[0].srcnode().abspath diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 63c3cb8c23..194e71c9de 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -217,7 +217,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); @@ -293,8 +293,8 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$name", p_config.pkg_name) + "\n"; } else if (lines[i].find("$info") != -1) { strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n"; - } else if (lines[i].find("$identifier") != -1) { - strnew += lines[i].replace("$identifier", p_preset->get("application/identifier")) + "\n"; + } else if (lines[i].find("$bundle_identifier") != -1) { + strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n"; } else if (lines[i].find("$short_version") != -1) { strnew += lines[i].replace("$short_version", p_preset->get("application/short_version")) + "\n"; } else if (lines[i].find("$version") != -1) { @@ -343,6 +343,9 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ } else if (lines[i].find("$push_notifications") != -1) { bool is_on = p_preset->get("capabilities/push_notifications"); strnew += lines[i].replace("$push_notifications", is_on ? "1" : "0") + "\n"; + } else if (lines[i].find("$entitlements_push_notifications") != -1) { + bool is_on = p_preset->get("capabilities/push_notifications"); + strnew += lines[i].replace("$entitlements_push_notifications", is_on ? "<key>aps-environment</key><string>development</string>" : "") + "\n"; } else if (lines[i].find("$required_device_capabilities") != -1) { String capabilities; @@ -1066,6 +1069,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p files_to_parse.insert("godot_ios/dummy.cpp"); files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata"); files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme"); + files_to_parse.insert("godot_ios/godot_ios.entitlements"); IOSConfigData config_data = { pkg_name, @@ -1346,7 +1350,7 @@ bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset valid = false; } - String identifier = p_preset->get("application/identifier"); + String identifier = p_preset->get("application/bundle_identifier"); String pn_err; if (!is_package_name_valid(identifier, &pn_err)) { err += TTR("Invalid Identifier:") + " " + pn_err + "\n"; diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index a2efd6691b..548dcc549d 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -207,7 +207,7 @@ Error InAppStore::restore_purchases() { NSString *receipt_to_send = nil; if (receipt != nil) { - receipt_to_send = [receipt description]; + receipt_to_send = [receipt base64EncodedStringWithOptions:0]; } Dictionary receipt_ret; receipt_ret["receipt"] = String::utf8(receipt_to_send != nil ? [receipt_to_send UTF8String] : ""); diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 4a94e09c1c..920fd24c4a 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -1937,10 +1937,14 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { // Apple Docs state that the display parameter is not used. // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." // https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html - CGDisplayHideCursor(kCGDirectMainDisplay); + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + CGDisplayHideCursor(kCGDirectMainDisplay); + } CGAssociateMouseAndMouseCursorPosition(false); } else if (p_mode == MOUSE_MODE_HIDDEN) { - CGDisplayHideCursor(kCGDirectMainDisplay); + if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) { + CGDisplayHideCursor(kCGDirectMainDisplay); + } CGAssociateMouseAndMouseCursorPosition(true); } else { CGDisplayShowCursor(kCGDirectMainDisplay); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index c9b01ebbb4..9af7c02351 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -145,7 +145,7 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0")); @@ -354,8 +354,8 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset strnew += lines[i].replace("$name", p_binary) + "\n"; } else if (lines[i].find("$info") != -1) { strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n"; - } else if (lines[i].find("$identifier") != -1) { - strnew += lines[i].replace("$identifier", p_preset->get("application/identifier")) + "\n"; + } else if (lines[i].find("$bundle_identifier") != -1) { + strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n"; } else if (lines[i].find("$short_version") != -1) { strnew += lines[i].replace("$short_version", p_preset->get("application/short_version")) + "\n"; } else if (lines[i].find("$version") != -1) { @@ -399,7 +399,7 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset args.push_back("--notarize-app"); args.push_back("--primary-bundle-id"); - args.push_back(p_preset->get("application/identifier")); + args.push_back(p_preset->get("application/bundle_identifier")); args.push_back("--username"); args.push_back(p_preset->get("notarization/apple_id_name")); @@ -829,7 +829,10 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String zipfi.tmz_date.tm_sec = time.sec; zipfi.tmz_date.tm_year = date.year; zipfi.dosDate = 0; - zipfi.external_fa = (is_executable ? 0755 : 0644) << 16L; + // 0100000: regular file type + // 0000755: permissions rwxr-xr-x + // 0000644: permissions rw-r--r-- + zipfi.external_fa = (is_executable ? 0100755 : 0100644) << 16L; zipfi.internal_fa = 0; zipOpenNewFileInZip4(p_zip, @@ -885,7 +888,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset valid = dvalid || rvalid; r_missing_templates = !valid; - String identifier = p_preset->get("application/identifier"); + String identifier = p_preset->get("application/bundle_identifier"); String pn_err; if (!is_package_name_valid(identifier, &pn_err)) { err += TTR("Invalid bundle identifier:") + " " + pn_err + "\n"; diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index cb4716bd65..0fd017f96e 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -970,7 +970,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform { public: virtual String get_name() const { - return "Windows Universal"; + return "UWP"; } virtual String get_os_name() const { return "UWP"; @@ -1180,7 +1180,7 @@ public: virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) { String src_appx; - EditorProgress ep("export", "Exporting for Windows Universal", 7, true); + EditorProgress ep("export", "Exporting for UWP", 7, true); if (p_debug) { src_appx = p_preset->get("custom_template/debug"); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 0b7130db74..f47afcc4e5 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -103,7 +103,11 @@ void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { } if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) { - hCursor = SetCursor(nullptr); + if (hCursor == nullptr) { + hCursor = SetCursor(nullptr); + } else { + SetCursor(nullptr); + } } else { CursorShape c = cursor_shape; cursor_shape = CURSOR_MAX; @@ -117,9 +121,9 @@ void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) { if (mouse_mode == p_mode) return; - _set_mouse_mode_impl(p_mode); - mouse_mode = p_mode; + + _set_mouse_mode_impl(p_mode); } DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode() const { @@ -2565,9 +2569,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA case WM_KEYUP: case WM_KEYDOWN: { if (wParam == VK_SHIFT) - shift_mem = uMsg == WM_KEYDOWN; + shift_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); if (wParam == VK_CONTROL) - control_mem = uMsg == WM_KEYDOWN; + control_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); if (wParam == VK_MENU) { alt_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); if (lParam & (1 << 24)) @@ -2654,10 +2658,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA if (LOWORD(lParam) == HTCLIENT) { if (windows[window_id].window_has_focus && (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED)) { //Hide the cursor - if (hCursor == nullptr) + if (hCursor == nullptr) { hCursor = SetCursor(nullptr); - else + } else { SetCursor(nullptr); + } } else { if (hCursor != nullptr) { CursorShape c = cursor_shape; diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index 271a4e41bc..65caee3035 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -172,6 +172,7 @@ bool JoypadWindows::setup_dinput_joypad(const DIDEVICEINSTANCE *instance) { sprintf_s(uid, "%04x%04x%04x%04x%04x%04x%04x%04x", type, 0, vendor, 0, product, 0, version, 0); id_to_change = joypad_count; + slider_count = 0; joy->di_joy->SetDataFormat(&c_dfDIJoystick2); joy->di_joy->SetCooperativeLevel(*hWnd, DISCL_FOREGROUND); @@ -206,9 +207,14 @@ void JoypadWindows::setup_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_ ofs = DIJOFS_RY; else if (ob->guidType == GUID_RzAxis) ofs = DIJOFS_RZ; - else if (ob->guidType == GUID_Slider) - ofs = DIJOFS_SLIDER(0); - else + else if (ob->guidType == GUID_Slider) { + if (slider_count < 2) { + ofs = DIJOFS_SLIDER(slider_count); + slider_count++; + } else { + return; + } + } else return; prop_range.diph.dwSize = sizeof(DIPROPRANGE); prop_range.diph.dwHeaderSize = sizeof(DIPROPHEADER); @@ -388,9 +394,9 @@ void JoypadWindows::process_joypads() { } // on mingw, these constants are not constants - int count = 6; - unsigned int axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ }; - int values[] = { js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz }; + int count = 8; + unsigned int axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1) }; + int values[] = { js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz, js.rglSlider[0], js.rglSlider[1] }; for (int j = 0; j < joy->joy_axis.size(); j++) { for (int k = 0; k < count; k++) { diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h index 6c06b3f6f0..c961abf0a5 100644 --- a/platform/windows/joypad_windows.h +++ b/platform/windows/joypad_windows.h @@ -118,6 +118,7 @@ private: Input *input; int id_to_change; + int slider_count; int joypad_count; bool attached_joypads[JOYPADS_MAX]; dinput_gamepad d_joypads[JOYPADS_MAX]; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 29eabfdde8..5b15896b0c 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -208,6 +208,13 @@ void OS_Windows::initialize() { process_map = memnew((Map<ProcessID, ProcessInfo>)); + // Add current Godot PID to the list of known PIDs + ProcessInfo current_pi = {}; + PROCESS_INFORMATION current_pi_pi = {}; + current_pi.pi = current_pi_pi; + current_pi.pi.hProcess = GetCurrentProcess(); + process_map->insert(GetCurrentProcessId(), current_pi); + IP_Unix::make_default(); main_loop = nullptr; } @@ -343,55 +350,21 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { return ret; } -uint64_t OS_Windows::get_unix_time() const { - FILETIME ft; - SYSTEMTIME st; - GetSystemTime(&st); - SystemTimeToFileTime(&st, &ft); - - SYSTEMTIME ep; - ep.wYear = 1970; - ep.wMonth = 1; - ep.wDayOfWeek = 4; - ep.wDay = 1; - ep.wHour = 0; - ep.wMinute = 0; - ep.wSecond = 0; - ep.wMilliseconds = 0; - FILETIME fep; - SystemTimeToFileTime(&ep, &fep); - - // Type punning through unions (rather than pointer cast) as per: - // https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime#remarks - ULARGE_INTEGER ft_punning; - ft_punning.LowPart = ft.dwLowDateTime; - ft_punning.HighPart = ft.dwHighDateTime; - - ULARGE_INTEGER fep_punning; - fep_punning.LowPart = fep.dwLowDateTime; - fep_punning.HighPart = fep.dwHighDateTime; - - return (ft_punning.QuadPart - fep_punning.QuadPart) / 10000000; -}; - -uint64_t OS_Windows::get_system_time_secs() const { - return get_system_time_msecs() / 1000; -} - -uint64_t OS_Windows::get_system_time_msecs() const { - const uint64_t WINDOWS_TICK = 10000; - const uint64_t MSEC_TO_UNIX_EPOCH = 11644473600000LL; +double OS_Windows::get_unix_time() const { + // 1 Windows tick is 100ns + const uint64_t WINDOWS_TICKS_PER_SECOND = 10000000; + const uint64_t TICKS_TO_UNIX_EPOCH = 116444736000000000LL; SYSTEMTIME st; GetSystemTime(&st); FILETIME ft; SystemTimeToFileTime(&st, &ft); - uint64_t ret; - ret = ft.dwHighDateTime; - ret <<= 32; - ret |= ft.dwLowDateTime; + uint64_t ticks_time; + ticks_time = ft.dwHighDateTime; + ticks_time <<= 32; + ticks_time |= ft.dwLowDateTime; - return (uint64_t)(ret / WINDOWS_TICK - MSEC_TO_UNIX_EPOCH); + return (double)(ticks_time - TICKS_TO_UNIX_EPOCH) / WINDOWS_TICKS_PER_SECOND; } void OS_Windows::delay_usec(uint32_t p_usec) const { diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 11e3533bfd..910a83539a 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -129,9 +129,7 @@ public: virtual Date get_date(bool utc) const; virtual Time get_time(bool utc) const; virtual TimeZoneInfo get_time_zone_info() const; - virtual uint64_t get_unix_time() const; - virtual uint64_t get_system_time_secs() const; - virtual uint64_t get_system_time_msecs() const; + virtual double get_unix_time() const; virtual Error set_cwd(const String &p_cwd); diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index 8f69676da4..68e99445d8 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -343,7 +343,9 @@ void Camera2D::_notification(int p_what) { void Camera2D::set_offset(const Vector2 &p_offset) { offset = p_offset; + Point2 old_smoothed_camera_pos = smoothed_camera_pos; _update_scroll(); + smoothed_camera_pos = old_smoothed_camera_pos; } Vector2 Camera2D::get_offset() const { @@ -361,7 +363,9 @@ Camera2D::AnchorMode Camera2D::get_anchor_mode() const { void Camera2D::set_rotating(bool p_rotating) { rotating = p_rotating; + Point2 old_smoothed_camera_pos = smoothed_camera_pos; _update_scroll(); + smoothed_camera_pos = old_smoothed_camera_pos; } bool Camera2D::is_rotating() const { @@ -522,7 +526,9 @@ bool Camera2D::is_v_drag_enabled() const { void Camera2D::set_v_offset(float p_offset) { v_ofs = p_offset; v_offset_changed = true; + Point2 old_smoothed_camera_pos = smoothed_camera_pos; _update_scroll(); + smoothed_camera_pos = old_smoothed_camera_pos; } float Camera2D::get_v_offset() const { @@ -532,7 +538,9 @@ float Camera2D::get_v_offset() const { void Camera2D::set_h_offset(float p_offset) { h_ofs = p_offset; h_offset_changed = true; + Point2 old_smoothed_camera_pos = smoothed_camera_pos; _update_scroll(); + smoothed_camera_pos = old_smoothed_camera_pos; } float Camera2D::get_h_offset() const { diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index ae448129bc..84560b843b 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -997,6 +997,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector2 body_velocity = p_linear_velocity; Vector2 body_velocity_normal = body_velocity.normalized(); + Vector2 up_direction = p_up_direction.normalized(); Vector2 current_floor_velocity = floor_velocity; if (on_floor && on_floor_body.is_valid()) { @@ -1043,11 +1044,11 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const colliders.push_back(collision); motion = collision.remainder; - if (p_up_direction == Vector2()) { + if (up_direction == Vector2()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; floor_normal = collision.normal; @@ -1055,14 +1056,14 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform2D gt = get_global_transform(); - gt.elements[2] -= collision.travel.slide(p_up_direction); + gt.elements[2] -= collision.travel.slide(up_direction); set_global_transform(gt); return Vector2(); } } - } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -1085,9 +1086,10 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const } Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { + Vector2 up_direction = p_up_direction.normalized(); bool was_on_floor = on_floor; - Vector2 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector2 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector2()) { return ret; } @@ -1097,8 +1099,8 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_up_direction != Vector2()) { - if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (up_direction != Vector2()) { + if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { on_floor = true; floor_normal = col.normal; on_floor_body = col.collider_rid; @@ -1106,7 +1108,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = p_up_direction * p_up_direction.dot(col.travel); + col.travel = up_direction * up_direction.dot(col.travel); } } else { diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 8dc5cd4aba..7ffca4bd9e 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -754,9 +754,9 @@ void ClippedCamera3D::_notification(int p_what) { xf.origin = ray_from; xf.orthonormalize(); - float csafe, cunsafe; - if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, csafe, cunsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) { - clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * csafe); + float closest_safe = 1.0f, closest_unsafe = 1.0f; + if (dspace->cast_motion(pyramid_shape, xf, cam_pos - ray_from, margin, closest_safe, closest_unsafe, exclude, collision_mask, clip_to_bodies, clip_to_areas)) { + clip_offset = cam_pos.distance_to(ray_from + (cam_pos - ray_from) * closest_safe); } _update_camera(); diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index ef24676d69..9270b548b7 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -424,9 +424,11 @@ DirectionalLight3D::DirectionalLight3D() : Light3D(RenderingServer::LIGHT_DIRECTIONAL) { set_param(PARAM_SHADOW_MAX_DISTANCE, 100); set_param(PARAM_SHADOW_FADE_START, 0.8); + // Increase the default shadow bias to better suit most scenes. + // Leave normal bias untouched as it doesn't benefit DirectionalLight3D as much as OmniLight3D. + set_param(PARAM_SHADOW_BIAS, 0.05); set_shadow_mode(SHADOW_PARALLEL_4_SPLITS); set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE); - blend_splits = false; } @@ -468,6 +470,9 @@ void OmniLight3D::_bind_methods() { OmniLight3D::OmniLight3D() : Light3D(RenderingServer::LIGHT_OMNI) { set_shadow_mode(SHADOW_CUBE); + // Increase the default shadow biases to better suit most scenes. + set_param(PARAM_SHADOW_BIAS, 0.1); + set_param(PARAM_SHADOW_NORMAL_BIAS, 2.0); } String SpotLight3D::get_configuration_warning() const { diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index de8f1eea2e..6320af21eb 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -945,6 +945,7 @@ bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector3 body_velocity = p_linear_velocity; Vector3 body_velocity_normal = body_velocity.normalized(); + Vector3 up_direction = p_up_direction.normalized(); for (int i = 0; i < 3; i++) { if (locked_axis & (1 << i)) { @@ -988,11 +989,11 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const colliders.push_back(collision); motion = collision.remainder; - if (p_up_direction == Vector3()) { + if (up_direction == Vector3()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; floor_normal = collision.normal; @@ -1000,14 +1001,14 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform gt = get_global_transform(); - gt.origin -= collision.travel.slide(p_up_direction); + gt.origin -= collision.travel.slide(up_direction); set_global_transform(gt); return Vector3(); } } - } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -1036,9 +1037,10 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const } Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { + Vector3 up_direction = p_up_direction.normalized(); bool was_on_floor = on_floor; - Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector3 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector3()) { return ret; } @@ -1048,8 +1050,8 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_up_direction != Vector3()) { - if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (up_direction != Vector3()) { + if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { on_floor = true; floor_normal = col.normal; on_floor_body = col.collider_rid; @@ -1057,7 +1059,7 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = col.travel.project(p_up_direction); + col.travel = col.travel.project(up_direction); } } else { apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index a09424fa17..6723ca04b9 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -67,6 +67,8 @@ SkinReference::~SkinReference() { RS::get_singleton()->free(skeleton); } +/////////////////////////////////////// + bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) { String path = p_path; @@ -853,6 +855,15 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) { return skin_ref; } +// helper functions +Transform Skeleton3D::bone_transform_to_world_transform(Transform p_bone_transform) { + return get_global_transform() * p_bone_transform; +} + +Transform Skeleton3D::world_transform_to_bone_transform(Transform p_world_transform) { + return get_global_transform().affine_inverse() * p_world_transform; +} + void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_process_orders"), &Skeleton3D::get_bone_process_orders); ClassDB::bind_method(D_METHOD("add_bone", "name"), &Skeleton3D::add_bone); @@ -892,6 +903,9 @@ void Skeleton3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_bone_custom_pose", "bone_idx"), &Skeleton3D::get_bone_custom_pose); ClassDB::bind_method(D_METHOD("set_bone_custom_pose", "bone_idx", "custom_pose"), &Skeleton3D::set_bone_custom_pose); + ClassDB::bind_method(D_METHOD("bone_transform_to_world_transform", "bone_transform"), &Skeleton3D::bone_transform_to_world_transform); + ClassDB::bind_method(D_METHOD("world_transform_to_bone_transform", "world_transform"), &Skeleton3D::world_transform_to_bone_transform); + #ifndef _3D_DISABLED ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton3D::set_animate_physical_bones); diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 66706a9450..a21891a32e 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -71,10 +71,6 @@ class Skeleton3D : public Node3D { private: friend class SkinReference; - Set<SkinReference *> skin_bindings; - - void _skin_changed(); - struct Bone { String name; @@ -116,6 +112,10 @@ private: } }; + Set<SkinReference *> skin_bindings; + + void _skin_changed(); + bool animate_physical_bones; Vector<Bone> bones; Vector<int> process_order; @@ -200,6 +200,10 @@ public: Ref<SkinReference> register_skin(const Ref<Skin> &p_skin); + // Helper functions + Transform bone_transform_to_world_transform(Transform p_transform); + Transform world_transform_to_bone_transform(Transform p_transform); + #ifndef _3D_DISABLED // Physical bone API @@ -213,7 +217,7 @@ public: PhysicalBone3D *get_physical_bone_parent(int p_bone); private: - /// This is a slow API os it's cached + /// This is a slow API, so it's cached PhysicalBone3D *_get_physical_bone_parent(int p_bone); void _rebuild_physical_bones_cache(); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 84170a65d1..fafbb298b7 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -758,7 +758,8 @@ ColorPicker::ColorPicker() : sample->set_h_size_flags(SIZE_EXPAND_FILL); sample->connect("draw", callable_mp(this, &ColorPicker::_sample_draw)); - btn_pick = memnew(ToolButton); + btn_pick = memnew(Button); + btn_pick->set_flat(true); hb_smpl->add_child(btn_pick); btn_pick->set_toggle_mode(true); btn_pick->set_tooltip(TTR("Pick a color from the editor window.")); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 31ae92f4e4..b2e8263e7f 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -41,7 +41,6 @@ #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" class ColorPicker : public BoxContainer { GDCLASS(ColorPicker, BoxContainer); @@ -57,7 +56,7 @@ private: HSeparator *preset_separator; Button *bt_add_preset; List<Color> presets; - ToolButton *btn_pick; + Button *btn_pick; CheckButton *btn_hsv; CheckButton *btn_raw; HSlider *scroll[4]; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 630f3c8ff6..41ca6458af 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -45,9 +45,9 @@ VBoxContainer *FileDialog::get_vbox() { } void FileDialog::_theme_changed() { - Color font_color = vbox->get_theme_color("font_color", "ToolButton"); - Color font_color_hover = vbox->get_theme_color("font_color_hover", "ToolButton"); - Color font_color_pressed = vbox->get_theme_color("font_color_pressed", "ToolButton"); + Color font_color = vbox->get_theme_color("font_color", "Button"); + Color font_color_hover = vbox->get_theme_color("font_color_hover", "Button"); + Color font_color_pressed = vbox->get_theme_color("font_color_pressed", "Button"); dir_up->add_theme_color_override("icon_color_normal", font_color); dir_up->add_theme_color_override("icon_color_hover", font_color_hover); @@ -859,7 +859,8 @@ FileDialog::FileDialog() { HBoxContainer *hbc = memnew(HBoxContainer); - dir_up = memnew(ToolButton); + dir_up = memnew(Button); + dir_up->set_flat(true); dir_up->set_tooltip(RTR("Go to parent folder.")); hbc->add_child(dir_up); dir_up->connect("pressed", callable_mp(this, &FileDialog::_go_up)); @@ -877,12 +878,14 @@ FileDialog::FileDialog() { hbc->add_child(dir); dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); - refresh = memnew(ToolButton); + refresh = memnew(Button); + refresh->set_flat(true); refresh->set_tooltip(RTR("Refresh files.")); refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list)); hbc->add_child(refresh); - show_hidden = memnew(ToolButton); + show_hidden = memnew(Button); + show_hidden->set_flat(true); show_hidden->set_toggle_mode(true); show_hidden->set_pressed(is_showing_hidden_files()); show_hidden->set_tooltip(RTR("Toggle the visibility of hidden files.")); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 8bc536d576..44050a2376 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -36,7 +36,6 @@ #include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" class FileDialog : public ConfirmationDialog { @@ -87,10 +86,10 @@ private: DirAccess *dir_access; ConfirmationDialog *confirm_save; - ToolButton *dir_up; + Button *dir_up; - ToolButton *refresh; - ToolButton *show_hidden; + Button *refresh; + Button *show_hidden; Vector<String> filters; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 5080ba74e2..2b0e084db4 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -33,6 +33,7 @@ #include "core/input/input.h" #include "core/os/keyboard.h" #include "scene/gui/box_container.h" +#include "scene/gui/button.h" #ifdef TOOLS_ENABLED #include "editor/editor_scale.h" @@ -1310,25 +1311,29 @@ GraphEdit::GraphEdit() { top_layer->add_child(zoom_hb); zoom_hb->set_position(Vector2(10, 10)); - zoom_minus = memnew(ToolButton); + zoom_minus = memnew(Button); + zoom_minus->set_flat(true); zoom_hb->add_child(zoom_minus); zoom_minus->set_tooltip(RTR("Zoom Out")); zoom_minus->connect("pressed", callable_mp(this, &GraphEdit::_zoom_minus)); zoom_minus->set_focus_mode(FOCUS_NONE); - zoom_reset = memnew(ToolButton); + zoom_reset = memnew(Button); + zoom_reset->set_flat(true); zoom_hb->add_child(zoom_reset); zoom_reset->set_tooltip(RTR("Zoom Reset")); zoom_reset->connect("pressed", callable_mp(this, &GraphEdit::_zoom_reset)); zoom_reset->set_focus_mode(FOCUS_NONE); - zoom_plus = memnew(ToolButton); + zoom_plus = memnew(Button); + zoom_plus->set_flat(true); zoom_hb->add_child(zoom_plus); zoom_plus->set_tooltip(RTR("Zoom In")); zoom_plus->connect("pressed", callable_mp(this, &GraphEdit::_zoom_plus)); zoom_plus->set_focus_mode(FOCUS_NONE); - snap_button = memnew(ToolButton); + snap_button = memnew(Button); + snap_button->set_flat(true); snap_button->set_toggle_mode(true); snap_button->set_tooltip(RTR("Enable snap and show grid.")); snap_button->connect("pressed", callable_mp(this, &GraphEdit::_snap_toggled)); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index c632490855..a627a8eec8 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -32,12 +32,12 @@ #define GRAPH_EDIT_H #include "scene/gui/box_container.h" +#include "scene/gui/button.h" #include "scene/gui/graph_node.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" class GraphEdit; @@ -65,11 +65,11 @@ public: }; private: - ToolButton *zoom_minus; - ToolButton *zoom_reset; - ToolButton *zoom_plus; + Button *zoom_minus; + Button *zoom_reset; + Button *zoom_plus; - ToolButton *snap_button; + Button *snap_button; SpinBox *snap_amount; void _zoom_minus(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ee6783167a..ba55927980 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -274,6 +274,22 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { set_cursor_position(text.length()); shift_selection_check_post(k->get_shift()); } break; + case (KEY_BACKSPACE): { + if (!editable) + break; + + // If selected, delete the selection + if (selection.enabled) { + selection_delete(); + break; + } + + // Otherwise delete from cursor to beginning of text edit + int current_pos = get_cursor_position(); + if (current_pos != 0) { + delete_text(0, current_pos); + } + } break; #endif default: { handled = false; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 92508f7fd2..5ae27081ea 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1570,6 +1570,10 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { } updating_scroll = false; + + if (fit_content_height) { + minimum_size_changed(); + } } void RichTextLabel::_invalidate_current_line(ItemFrame *p_frame) { @@ -1989,6 +1993,17 @@ int RichTextLabel::get_tab_size() const { return tab_size; } +void RichTextLabel::set_fit_content_height(bool p_enabled) { + if (p_enabled != fit_content_height) { + fit_content_height = p_enabled; + minimum_size_changed(); + } +} + +bool RichTextLabel::is_fit_content_height_enabled() const { + return fit_content_height; +} + void RichTextLabel::set_meta_underline(bool p_underline) { underline_meta = p_underline; update(); @@ -2646,7 +2661,7 @@ void RichTextLabel::install_effect(const Variant effect) { } } -int RichTextLabel::get_content_height() { +int RichTextLabel::get_content_height() const { int total_height = 0; if (main->lines.size()) { total_height = main->lines[main->lines.size() - 1].height_accum_cache + get_theme_stylebox("normal")->get_minimum_size().height; @@ -2701,6 +2716,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("set_tab_size", "spaces"), &RichTextLabel::set_tab_size); ClassDB::bind_method(D_METHOD("get_tab_size"), &RichTextLabel::get_tab_size); + ClassDB::bind_method(D_METHOD("set_fit_content_height", "enabled"), &RichTextLabel::set_fit_content_height); + ClassDB::bind_method(D_METHOD("is_fit_content_height_enabled"), &RichTextLabel::is_fit_content_height_enabled); + ClassDB::bind_method(D_METHOD("set_selection_enabled", "enabled"), &RichTextLabel::set_selection_enabled); ClassDB::bind_method(D_METHOD("is_selection_enabled"), &RichTextLabel::is_selection_enabled); @@ -2743,6 +2761,8 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_size", PROPERTY_HINT_RANGE, "0,24,1"), "set_tab_size", "get_tab_size"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fit_content_height"), "set_fit_content_height", "is_fit_content_height_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_active"), "set_scroll_active", "is_scroll_active"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_following"), "set_scroll_follow", "is_scroll_following"); @@ -2809,12 +2829,17 @@ void RichTextLabel::set_fixed_size_to_width(int p_width) { } Size2 RichTextLabel::get_minimum_size() const { + Size2 size(0, 0); if (fixed_width != -1) { + size.x = fixed_width; + } + + if (fixed_width != -1 || fit_content_height) { const_cast<RichTextLabel *>(this)->_validate_line_caches(main); - return Size2(fixed_width, const_cast<RichTextLabel *>(this)->get_content_height()); + size.y = get_content_height(); } - return Size2(); + return size; } Ref<RichTextEffect> RichTextLabel::_get_custom_effect_by_code(String p_bbcode_identifier) { @@ -2934,6 +2959,8 @@ RichTextLabel::RichTextLabel() { visible_line_count = 0; fixed_width = -1; + fit_content_height = false; + set_clip_contents(true); } diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 4cec435568..7eeb071cb5 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -403,6 +403,8 @@ private: int fixed_width; + bool fit_content_height; + protected: void _notification(int p_what); @@ -456,13 +458,16 @@ public: void set_tab_size(int p_spaces); int get_tab_size() const; + void set_fit_content_height(bool p_enabled); + bool is_fit_content_height_enabled() const; + bool search(const String &p_string, bool p_from_selection = false, bool p_search_previous = false); void scroll_to_line(int p_line); int get_line_count() const; int get_visible_line_count() const; - int get_content_height(); + int get_content_height() const; VScrollBar *get_v_scroll() { return vscroll; } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 0d48fde642..41b8fad49d 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -71,6 +71,8 @@ int TabContainer::_get_top_margin() const { void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; + Popup *popup = get_popup(); + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { Point2 pos(mb->get_position().x, mb->get_position().y); Size2 size = get_size(); @@ -82,6 +84,7 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) { // Handle menu button. Ref<Texture2D> menu = get_theme_icon("menu"); + if (popup && pos.x > size.width - menu->get_width()) { emit_signal("pre_popup_pressed"); @@ -223,6 +226,7 @@ void TabContainer::_notification(int p_what) { int header_width = get_size().width - side_margin * 2; // Find the width of the header area. + Popup *popup = get_popup(); if (popup) { header_width -= menu->get_width(); } @@ -284,6 +288,7 @@ void TabContainer::_notification(int p_what) { int header_x = side_margin; int header_width = size.width - side_margin * 2; int header_height = _get_top_margin(); + Popup *popup = get_popup(); if (popup) { header_width -= menu->get_width(); } @@ -749,6 +754,7 @@ int TabContainer::get_tab_idx_at_point(const Point2 &p_point) const { Size2 size = get_size(); int right_ofs = 0; + Popup *popup = get_popup(); if (popup) { Ref<Texture2D> menu = get_theme_icon("menu"); right_ofs += menu->get_width(); @@ -948,12 +954,24 @@ Size2 TabContainer::get_minimum_size() const { void TabContainer::set_popup(Node *p_popup) { ERR_FAIL_NULL(p_popup); - popup = Object::cast_to<Popup>(p_popup); + Popup *popup = Object::cast_to<Popup>(p_popup); + popup_obj_id = popup ? popup->get_instance_id() : ObjectID(); update(); } Popup *TabContainer::get_popup() const { - return popup; + if (popup_obj_id.is_valid()) { + Popup *popup = Object::cast_to<Popup>(ObjectDB::get_instance(popup_obj_id)); + if (popup) { + return popup; + } else { +#ifdef DEBUG_ENABLED + ERR_PRINT("Popup assigned to TabContainer is gone!"); +#endif + popup_obj_id = ObjectID(); + } + } + return nullptr; } void TabContainer::set_drag_to_rearrange_enabled(bool p_enabled) { @@ -1037,7 +1055,6 @@ TabContainer::TabContainer() { previous = 0; align = ALIGN_CENTER; tabs_visible = true; - popup = nullptr; drag_to_rearrange_enabled = false; tabs_rearrange_group = -1; use_hidden_tabs_for_min_size = false; diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 55a5d35b30..6ee72a379a 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -57,7 +57,7 @@ private: TabAlign align; Control *_get_tab(int p_idx) const; int _get_top_margin() const; - Popup *popup; + mutable ObjectID popup_obj_id; bool drag_to_rearrange_enabled; bool use_hidden_tabs_for_min_size; int tabs_rearrange_group; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index e050b3f174..c7fc8dbe43 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -366,26 +366,9 @@ void TextEdit::_update_scrollbars() { total_width += cache.minimap_width; } - bool use_hscroll = true; - bool use_vscroll = true; - - // Thanks yessopie for this clever bit of logic. - if (total_rows <= visible_rows && total_width <= visible_width) { - use_hscroll = false; - use_vscroll = false; - } else { - if (total_rows > visible_rows && total_width <= visible_width) { - use_hscroll = false; - } - - if (total_rows <= visible_rows && total_width > visible_width) { - use_vscroll = false; - } - } - updating_scrolls = true; - if (use_vscroll) { + if (total_rows > visible_rows) { v_scroll->show(); v_scroll->set_max(total_rows + get_visible_rows_offset()); v_scroll->set_page(visible_rows + get_visible_rows_offset()); @@ -403,7 +386,7 @@ void TextEdit::_update_scrollbars() { v_scroll->hide(); } - if (use_hscroll && !is_wrap_enabled()) { + if (total_width > visible_width && !is_wrap_enabled()) { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); @@ -2274,14 +2257,14 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { if (mb->get_shift()) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); - } else { + } else if (v_scroll->is_visible()) { _scroll_up(3 * mb->get_factor()); } } if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { if (mb->get_shift()) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); - } else { + } else if (v_scroll->is_visible()) { _scroll_down(3 * mb->get_factor()); } } diff --git a/scene/gui/tool_button.h b/scene/gui/tool_button.h deleted file mode 100644 index 9848b21381..0000000000 --- a/scene/gui/tool_button.h +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************/ -/* tool_button.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef TOOL_BUTTON_H -#define TOOL_BUTTON_H - -#include "scene/gui/button.h" - -class ToolButton : public Button { - GDCLASS(ToolButton, Button); - -public: - ToolButton(); -}; - -#endif // TOOL_BUTTON_H diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 524ff346d1..721f573f39 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1222,8 +1222,8 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask"); ADD_GROUP("Texture", "texture_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "ParentNode,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "ParentNode,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Inherit,Nearest,Linear,MipmapNearest,MipmapLinear,MipmapNearestAniso,MipmapLinearAniso"), "set_texture_filter", "get_texture_filter"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_repeat", PROPERTY_HINT_ENUM, "Inherit,Disabled,Enabled,Mirror"), "set_texture_repeat", "get_texture_repeat"); ADD_GROUP("Material", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material"); diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index a0e10f30c0..3c3c7533a3 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -170,6 +170,7 @@ void SceneTree::_flush_ugc() { v[i] = E->get()[i]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4]); unique_group_calls.erase(E); @@ -907,6 +908,7 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Cal v[i] = *p_args[i + 3]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4]); return Variant(); } @@ -926,6 +928,7 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable: v[i] = *p_args[i + 2]; } + static_assert(VARIANT_ARG_MAX == 5, "This code needs to be updated if VARIANT_ARG_MAX != 5"); call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4]); return Variant(); } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 2d0e2daf41..54112ef2bd 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -117,7 +117,6 @@ #include "scene/gui/texture_button.h" #include "scene/gui/texture_progress.h" #include "scene/gui/texture_rect.h" -#include "scene/gui/tool_button.h" #include "scene/gui/tree.h" #include "scene/gui/video_player.h" #include "scene/main/canvas_item.h" @@ -306,7 +305,6 @@ void register_scene_types() { ClassDB::register_class<MenuButton>(); ClassDB::register_class<CheckBox>(); ClassDB::register_class<CheckButton>(); - ClassDB::register_class<ToolButton>(); ClassDB::register_class<LinkButton>(); ClassDB::register_class<Panel>(); ClassDB::register_virtual_class<Range>(); @@ -541,6 +539,8 @@ void register_scene_types() { ClassDB::register_class<VisualShaderNodeVectorDecompose>(); ClassDB::register_class<VisualShaderNodeTransformDecompose>(); ClassDB::register_class<VisualShaderNodeTexture>(); + ClassDB::register_virtual_class<VisualShaderNodeSample3D>(); + ClassDB::register_class<VisualShaderNodeTexture2DArray>(); ClassDB::register_class<VisualShaderNodeCubemap>(); ClassDB::register_virtual_class<VisualShaderNodeUniform>(); ClassDB::register_class<VisualShaderNodeFloatUniform>(); @@ -551,6 +551,7 @@ void register_scene_types() { ClassDB::register_class<VisualShaderNodeTransformUniform>(); ClassDB::register_class<VisualShaderNodeTextureUniform>(); ClassDB::register_class<VisualShaderNodeTextureUniformTriplanar>(); + ClassDB::register_class<VisualShaderNodeTexture2DArrayUniform>(); ClassDB::register_class<VisualShaderNodeCubemapUniform>(); ClassDB::register_class<VisualShaderNodeIf>(); ClassDB::register_class<VisualShaderNodeSwitch>(); @@ -764,6 +765,7 @@ void register_scene_types() { #ifndef DISABLE_DEPRECATED // Dropped in 4.0, near approximation. ClassDB::add_compatibility_class("AnimationTreePlayer", "AnimationTree"); + ClassDB::add_compatibility_class("ToolButton", "Button"); // Renamed in 4.0. // Keep alphabetical ordering to easily locate classes and avoid duplicates. diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index fd5c861eb5..83d4db7bae 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -219,22 +219,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("hseparation", "ColorPickerButton", 2 * scale); - // ToolButton - - theme->set_stylebox("normal", "ToolButton", make_empty_stylebox(6, 4, 6, 4)); - theme->set_stylebox("pressed", "ToolButton", make_stylebox(button_pressed_png, 4, 4, 4, 4, 6, 4, 6, 4)); - theme->set_stylebox("hover", "ToolButton", make_stylebox(button_normal_png, 4, 4, 4, 4, 6, 4, 6, 4)); - theme->set_stylebox("disabled", "ToolButton", make_empty_stylebox(6, 4, 6, 4)); - theme->set_stylebox("focus", "ToolButton", focus); - theme->set_font("font", "ToolButton", default_font); - - theme->set_color("font_color", "ToolButton", control_font_color); - theme->set_color("font_color_pressed", "ToolButton", control_font_color_pressed); - theme->set_color("font_color_hover", "ToolButton", control_font_color_hover); - theme->set_color("font_color_disabled", "ToolButton", Color(0.9, 0.95, 1, 0.3)); - - theme->set_constant("hseparation", "ToolButton", 3); - // OptionButton Ref<StyleBox> sb_optbutton_normal = sb_expand(make_stylebox(option_button_normal_png, 4, 4, 21, 4, 6, 3, 9, 3), 2, 2, 2, 2); diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 99e8020e34..94cecc76eb 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -100,6 +100,7 @@ void Shape2D::_bind_methods() { ClassDB::bind_method(D_METHOD("collide_with_motion", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion); ClassDB::bind_method(D_METHOD("collide_and_get_contacts", "local_xform", "with_shape", "shape_xform"), &Shape2D::collide_and_get_contacts); ClassDB::bind_method(D_METHOD("collide_with_motion_and_get_contacts", "local_xform", "local_motion", "with_shape", "shape_xform", "shape_motion"), &Shape2D::collide_with_motion_and_get_contacts); + ClassDB::bind_method(D_METHOD("draw", "canvas_item", "color"), &Shape2D::draw); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "custom_solver_bias", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_custom_solver_bias", "get_custom_solver_bias"); } diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 77d4dee21e..8236f9a9e3 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1268,7 +1268,7 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui String class_name = vsnode->get_class_name(); if (class_name == "VisualShaderNodeCustom") { - class_name = vsnode->get_script_instance()->get_script()->get_language()->get_global_class_name(vsnode->get_script_instance()->get_script()->get_path()); + class_name = vsnode->get_script_instance()->get_script()->get_path(); } if (!r_classes.has(class_name)) { global_code_per_node += vsnode->generate_global_per_node(get_mode(), type, node); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 87720cf110..5c6b13a527 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -781,6 +781,183 @@ VisualShaderNodeTexture::VisualShaderNodeTexture() { source = SOURCE_TEXTURE; } +////////////// Sample3D + +int VisualShaderNodeSample3D::get_input_port_count() const { + return 3; +} + +VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR; + case 1: + return PORT_TYPE_SCALAR; + case 2: + return PORT_TYPE_SAMPLER; + default: + return PORT_TYPE_SCALAR; + } +} + +String VisualShaderNodeSample3D::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "uvw"; + case 1: + return "lod"; + default: + return ""; + } +} + +int VisualShaderNodeSample3D::get_output_port_count() const { + return 2; +} + +VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_output_port_type(int p_port) const { + return p_port == 0 ? PORT_TYPE_VECTOR : PORT_TYPE_SCALAR; +} + +String VisualShaderNodeSample3D::get_output_port_name(int p_port) const { + return p_port == 0 ? "rgb" : "alpha"; +} + +String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const { + if (p_port == 0) { + return "vec3(UV.xy, 0.0)"; + } + return ""; +} + +String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + if (source == SOURCE_TEXTURE || source == SOURCE_PORT) { + String id; + code += "\t{\n"; + if (source == SOURCE_TEXTURE) { + id = make_unique_id(p_type, p_id, "tex3d"); + } else { + id = p_input_vars[2]; + } + if (id != String()) { + if (p_input_vars[0] == String()) { // Use UV by default. + if (p_input_vars[1] == String()) { + code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", vec3(UV.xy, 0.0));\n"; + } else { + code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", vec3(UV.xy, 0.0), " + p_input_vars[1] + ");\n"; + } + } else if (p_input_vars[1] == String()) { + //no lod + code += "\t\tvec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n"; + } else { + code += "\t\tvec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; + } + } else { + code += "\t\tvec4 " + id + "_tex_read = vec4(0.0);\n"; + } + + code += "\t\t" + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n"; + code += "\t\t" + p_output_vars[1] + " = " + id + "_tex_read.a;\n"; + code += "\t}\n"; + return code; + } + code += "\t" + p_output_vars[0] + " = vec3(0.0);\n"; + code += "\t" + p_output_vars[1] + " = 1.0;\n"; + return code; +} + +void VisualShaderNodeSample3D::set_source(Source p_source) { + source = p_source; + emit_changed(); + emit_signal("editor_refresh_request"); +} + +VisualShaderNodeSample3D::Source VisualShaderNodeSample3D::get_source() const { + return source; +} + +void VisualShaderNodeSample3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_source", "value"), &VisualShaderNodeSample3D::set_source); + ClassDB::bind_method(D_METHOD("get_source"), &VisualShaderNodeSample3D::get_source); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "source", PROPERTY_HINT_ENUM, "Texture,SamplerPort"), "set_source", "get_source"); + + BIND_ENUM_CONSTANT(SOURCE_TEXTURE); + BIND_ENUM_CONSTANT(SOURCE_PORT); +} + +String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const { + if (source == SOURCE_TEXTURE) { + return String(); // all good + } + if (source == SOURCE_PORT) { + return String(); // all good + } + return TTR("Invalid source for shader."); +} + +VisualShaderNodeSample3D::VisualShaderNodeSample3D() { + source = SOURCE_TEXTURE; + simple_decl = false; +} + +////////////// Texture2DArray + +String VisualShaderNodeTexture2DArray::get_caption() const { + return "Texture2DArray"; +} + +String VisualShaderNodeTexture2DArray::get_input_port_name(int p_port) const { + if (p_port == 2) { + return "sampler2DArray"; + } + return VisualShaderNodeSample3D::get_input_port_name(p_port); +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture2DArray::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { + VisualShader::DefaultTextureParam dtp; + dtp.name = make_unique_id(p_type, p_id, "tex3d"); + dtp.param = texture; + Vector<VisualShader::DefaultTextureParam> ret; + ret.push_back(dtp); + return ret; +} + +String VisualShaderNodeTexture2DArray::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (source == SOURCE_TEXTURE) { + return "uniform sampler2DArray " + make_unique_id(p_type, p_id, "tex3d") + ";\n"; + } + return String(); +} + +void VisualShaderNodeTexture2DArray::set_texture_array(Ref<Texture2DArray> p_value) { + texture = p_value; + emit_changed(); +} + +Ref<Texture2DArray> VisualShaderNodeTexture2DArray::get_texture_array() const { + return texture; +} + +Vector<StringName> VisualShaderNodeTexture2DArray::get_editable_properties() const { + Vector<StringName> props; + props.push_back("source"); + if (source == SOURCE_TEXTURE) { + props.push_back("texture_array"); + } + return props; +} + +void VisualShaderNodeTexture2DArray::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture_array", "value"), &VisualShaderNodeTexture2DArray::set_texture_array); + ClassDB::bind_method(D_METHOD("get_texture_array"), &VisualShaderNodeTexture2DArray::get_texture_array); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_array", PROPERTY_HINT_RESOURCE_TYPE, "Texture2DArray"), "set_texture_array", "get_texture_array"); +} + +VisualShaderNodeTexture2DArray::VisualShaderNodeTexture2DArray() { +} ////////////// Cubemap String VisualShaderNodeCubemap::get_caption() const { @@ -3926,6 +4103,74 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_default_hint(int VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() { } +////////////// Texture2DArray Uniform + +String VisualShaderNodeTexture2DArrayUniform::get_caption() const { + return "Texture2DArrayUniform"; +} + +int VisualShaderNodeTexture2DArrayUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SAMPLER; +} + +String VisualShaderNodeTexture2DArrayUniform::get_output_port_name(int p_port) const { + return "sampler2DArray"; +} + +int VisualShaderNodeTexture2DArrayUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture2DArrayUniform::get_input_port_default_hint(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler2DArray " + get_uniform_name(); + + switch (texture_type) { + case TYPE_DATA: + if (color_default == COLOR_DEFAULT_BLACK) + code += " : hint_black;\n"; + else + code += ";\n"; + break; + case TYPE_COLOR: + if (color_default == COLOR_DEFAULT_BLACK) + code += " : hint_black_albedo;\n"; + else + code += " : hint_albedo;\n"; + break; + case TYPE_NORMALMAP: + code += " : hint_normal;\n"; + break; + case TYPE_ANISO: + code += " : hint_aniso;\n"; + break; + } + + return code; +} + +String VisualShaderNodeTexture2DArrayUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + return String(); +} + +VisualShaderNodeTexture2DArrayUniform::VisualShaderNodeTexture2DArrayUniform() { +} + ////////////// Cubemap Uniform String VisualShaderNodeCubemapUniform::get_caption() const { diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 69f42f621a..28a9de6819 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -236,7 +236,7 @@ public: enum TextureType { TYPE_DATA, TYPE_COLOR, - TYPE_NORMALMAP + TYPE_NORMALMAP, }; private: @@ -284,6 +284,68 @@ VARIANT_ENUM_CAST(VisualShaderNodeTexture::Source) /////////////////////////////////////// +class VisualShaderNodeSample3D : public VisualShaderNode { + GDCLASS(VisualShaderNodeSample3D, VisualShaderNode); + +public: + enum Source { + SOURCE_TEXTURE, + SOURCE_PORT, + }; + +protected: + Source source; + + static void _bind_methods(); + +public: + virtual String get_caption() const = 0; + + virtual int get_input_port_count() const; + virtual PortType get_input_port_type(int p_port) const; + virtual String get_input_port_name(int p_port) const; + virtual String get_input_port_default_hint(int p_port) const; + + virtual int get_output_port_count() const; + virtual PortType get_output_port_type(int p_port) const; + virtual String get_output_port_name(int p_port) const; + + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const = 0; + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + void set_source(Source p_source); + Source get_source() const; + + virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const; + + VisualShaderNodeSample3D(); +}; + +VARIANT_ENUM_CAST(VisualShaderNodeSample3D::Source) + +class VisualShaderNodeTexture2DArray : public VisualShaderNodeSample3D { + GDCLASS(VisualShaderNodeTexture2DArray, VisualShaderNodeSample3D); + Ref<Texture2DArray> texture; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const; + + virtual String get_input_port_name(int p_port) const; + + virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; + + void set_texture_array(Ref<Texture2DArray> p_value); + Ref<Texture2DArray> get_texture_array() const; + + virtual Vector<StringName> get_editable_properties() const; + + VisualShaderNodeTexture2DArray(); +}; + class VisualShaderNodeCubemap : public VisualShaderNode { GDCLASS(VisualShaderNodeCubemap, VisualShaderNode); Ref<Cubemap> cube_map; @@ -1695,6 +1757,29 @@ public: /////////////////////////////////////// +class VisualShaderNodeTexture2DArrayUniform : public VisualShaderNodeTextureUniform { + GDCLASS(VisualShaderNodeTexture2DArrayUniform, VisualShaderNodeTextureUniform); + +public: + virtual String get_caption() const; + + virtual int get_input_port_count() const; + virtual PortType get_input_port_type(int p_port) const; + virtual String get_input_port_name(int p_port) const; + + virtual int get_output_port_count() const; + virtual PortType get_output_port_type(int p_port) const; + virtual String get_output_port_name(int p_port) const; + + virtual String get_input_port_default_hint(int p_port) const; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const; + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const; //if no output is connected, the output var passed will be empty. if no input is connected and input is NIL, the input var passed will be empty + + VisualShaderNodeTexture2DArrayUniform(); +}; + +/////////////////////////////////////// + class VisualShaderNodeCubemapUniform : public VisualShaderNodeTextureUniform { GDCLASS(VisualShaderNodeCubemapUniform, VisualShaderNodeTextureUniform); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 2dd8ea3edb..9668358710 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -295,7 +295,7 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion) { ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - float closest_safe, closest_unsafe; + float closest_safe = 1.0f, closest_unsafe = 1.0f; bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); if (!res) { return Array(); diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp index 32321164a1..79bb990649 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -711,6 +711,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge gcode += _typestr(cnode.type); } gcode += " " + _mkid(String(cnode.name)); + if (cnode.array_size > 0) { + gcode += "["; + gcode += itos(cnode.array_size); + gcode += "]"; + } gcode += "="; gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); gcode += ";\n"; @@ -988,7 +993,29 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge } break; case SL::Node::TYPE_CONSTANT: { SL::ConstantNode *cnode = (SL::ConstantNode *)p_node; - return get_constant_text(cnode->datatype, cnode->values); + + if (cnode->array_size == 0) { + return get_constant_text(cnode->datatype, cnode->values); + } else { + if (cnode->get_datatype() == SL::TYPE_STRUCT) { + code += _mkid(cnode->struct_name); + } else { + code += _typestr(cnode->datatype); + } + code += "["; + code += itos(cnode->array_size); + code += "]"; + code += "("; + for (int i = 0; i < cnode->array_size; i++) { + if (i > 0) { + code += ","; + } else { + code += ""; + } + code += _dump_node_code(cnode->array_declarations[0].initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + code += ")"; + } } break; case SL::Node::TYPE_OPERATOR: { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 2ec65b7ea8..a3fef10cc0 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -1014,6 +1014,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea if (r_data_type) { *r_data_type = shader->constants[p_identifier].type; } + if (r_array_size) { + *r_array_size = shader->constants[p_identifier].array_size; + } if (r_type) { *r_type = IDENTIFIER_CONSTANT; } @@ -3064,7 +3067,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI } else if (p_node->type == Node::TYPE_ARRAY) { ArrayNode *arr = static_cast<ArrayNode *>(p_node); - if (arr->is_const) { + if (shader->constants.has(arr->name) || arr->is_const) { if (r_message) { *r_message = RTR("Constants cannot be modified."); } @@ -4976,7 +4979,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } DataType type2; - String struct_name2 = ""; + StringName struct_name2 = ""; if (shader->structs.has(tk.text)) { type2 = TYPE_STRUCT; @@ -6445,38 +6448,253 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct constant.type_str = struct_name; constant.precision = precision; constant.initializer = nullptr; + constant.array_size = 0; - if (tk.type == TK_OP_ASSIGN) { - if (!is_constant) { - _set_error("Expected 'const' keyword before constant definition"); + bool unknown_size = false; + + if (tk.type == TK_BRACKET_OPEN) { + if (RenderingServer::get_singleton()->is_low_end()) { + _set_error("Global const arrays are supported only on high-end platform!"); return ERR_PARSE_ERROR; } - //variable created with assignment! must parse an expression - Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>()); - if (!expr) { + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + unknown_size = true; + tk = _get_token(); + } else if (tk.type == TK_INT_CONSTANT && ((int)tk.constant) > 0) { + constant.array_size = (int)tk.constant; + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } else { + _set_error("Expected integer constant > 0 or ']'"); return ERR_PARSE_ERROR; } - if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { - _set_error("Expected constant expression after '='"); + } + + if (tk.type == TK_OP_ASSIGN) { + if (!is_constant) { + _set_error("Expected 'const' keyword before constant definition"); return ERR_PARSE_ERROR; } - constant.initializer = static_cast<ConstantNode *>(expr); + if (constant.array_size > 0 || unknown_size) { + bool full_def = false; + + ArrayDeclarationNode::Declaration decl; + decl.name = name; + decl.size = constant.array_size; - if (is_struct) { - if (expr->get_datatype_name() != struct_name) { - _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + struct_name + "'"); + tk = _get_token(); + + if (tk.type != TK_CURLY_BRACKET_OPEN) { + if (unknown_size) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + + full_def = true; + + DataPrecision precision2 = PRECISION_DEFAULT; + if (is_token_precision(tk.type)) { + precision2 = get_token_precision(tk.type); + tk = _get_token(); + if (!is_token_nonvoid_datatype(tk.type)) { + _set_error("Expected datatype after precision"); + return ERR_PARSE_ERROR; + } + } + + StringName struct_name2; + DataType type2; + + if (shader->structs.has(tk.text)) { + type2 = TYPE_STRUCT; + struct_name2 = tk.text; + } else { + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for array"); + return ERR_PARSE_ERROR; + } + type2 = get_token_datatype(tk.type); + } + + int array_size2 = 0; + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + TkPos pos2 = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + array_size2 = constant.array_size; + tk = _get_token(); + } else { + _set_tkpos(pos2); + + Node *n = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + ConstantNode *cnode = (ConstantNode *)n; + if (cnode->values.size() == 1) { + array_size2 = cnode->values[0].sint; + if (array_size2 <= 0) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']"); + return ERR_PARSE_ERROR; + } else { + tk = _get_token(); + } + } + } else { + _set_error("Expected '["); + return ERR_PARSE_ERROR; + } + + if (constant.precision != precision2 || constant.type != type2 || struct_name != struct_name2 || constant.array_size != array_size2) { + String error_str = "Cannot convert from '"; + if (type2 == TYPE_STRUCT) { + error_str += struct_name2; + } else { + if (precision2 != PRECISION_DEFAULT) { + error_str += get_precision_name(precision2); + error_str += " "; + } + error_str += get_datatype_name(type2); + } + error_str += "["; + error_str += itos(array_size2); + error_str += "]'"; + error_str += " to '"; + if (type == TYPE_STRUCT) { + error_str += struct_name; + } else { + if (precision != PRECISION_DEFAULT) { + error_str += get_precision_name(precision); + error_str += " "; + } + error_str += get_datatype_name(type); + } + error_str += "["; + error_str += itos(constant.array_size); + error_str += "]'"; + _set_error(error_str); + return ERR_PARSE_ERROR; + } + } + + bool curly = tk.type == TK_CURLY_BRACKET_OPEN; + + if (unknown_size) { + if (!curly) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + } else { + if (full_def) { + if (curly) { + _set_error("Expected '('"); + return ERR_PARSE_ERROR; + } + } + } + + if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization + while (true) { + Node *n = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + if (!n) { + return ERR_PARSE_ERROR; + } + + if (n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + _set_error("Expected constant expression"); + return ERR_PARSE_ERROR; + } + + if (constant.type != n->get_datatype() || n->get_datatype_name() != struct_name) { + _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(constant.type)) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type == TK_COMMA) { + decl.initializer.push_back(n); + continue; + } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) { + decl.initializer.push_back(n); + break; + } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) { + decl.initializer.push_back(n); + break; + } else { + if (curly) + _set_error("Expected '}' or ','"); + else + _set_error("Expected ')' or ','"); + return ERR_PARSE_ERROR; + } + } + if (unknown_size) { + decl.size = decl.initializer.size(); + constant.array_size = decl.initializer.size(); + } else if (decl.initializer.size() != constant.array_size) { + _set_error("Array size mismatch"); + return ERR_PARSE_ERROR; + } + } + + ConstantNode *expr = memnew(ConstantNode); + + expr->datatype = constant.type; + + expr->struct_name = constant.type_str; + + expr->array_size = constant.array_size; + + expr->array_declarations.push_back(decl); + + constant.initializer = static_cast<ConstantNode *>(expr); + } else { + //variable created with assignment! must parse an expression + Node *expr = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } + + constant.initializer = static_cast<ConstantNode *>(expr); + + if (type != expr->get_datatype() || expr->get_datatype_name() != struct_name) { + _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + (is_struct ? String(struct_name) : get_datatype_name(type)) + "'"); return ERR_PARSE_ERROR; } - } else if (type != expr->get_datatype()) { - _set_error("Invalid assignment of '" + get_datatype_name(expr->get_datatype()) + "' to '" + get_datatype_name(type) + "'"); - return ERR_PARSE_ERROR; } tk = _get_token(); } else { - _set_error("Expected initialization of constant"); - return ERR_PARSE_ERROR; + if (constant.array_size > 0 || unknown_size) { + _set_error("Expected array initialization"); + return ERR_PARSE_ERROR; + } else { + _set_error("Expected initialization of constant"); + return ERR_PARSE_ERROR; + } } shader->constants[name] = constant; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 020a5e3e6f..bc8f03774a 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -453,6 +453,8 @@ public: struct ConstantNode : public Node { DataType datatype = TYPE_VOID; + String struct_name = ""; + int array_size = 0; union Value { bool boolean; @@ -462,7 +464,9 @@ public: }; Vector<Value> values; + Vector<ArrayDeclarationNode::Declaration> array_declarations; virtual DataType get_datatype() const { return datatype; } + virtual String get_datatype_name() const { return struct_name; } ConstantNode() : Node(TYPE_CONSTANT) {} @@ -573,6 +577,7 @@ public: StringName type_str; DataPrecision precision; ConstantNode *initializer; + int array_size; }; struct Function { diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 4f12ec5b02..7edab1418d 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1895,6 +1895,10 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &RenderingServer::has_os_feature); ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &RenderingServer::set_debug_generate_wireframes); + ClassDB::bind_method(D_METHOD("is_render_loop_enabled"), &RenderingServer::is_render_loop_enabled); + ClassDB::bind_method(D_METHOD("set_render_loop_enabled", "enabled"), &RenderingServer::set_render_loop_enabled); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_loop_enabled"), "set_render_loop_enabled", "is_render_loop_enabled"); + BIND_CONSTANT(NO_INDEX_ARRAY); BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); BIND_CONSTANT(CANVAS_ITEM_Z_MIN); @@ -2286,6 +2290,14 @@ RID RenderingServer::instance_create2(RID p_base, RID p_scenario) { return instance; } +bool RenderingServer::is_render_loop_enabled() const { + return render_loop_enabled; +} + +void RenderingServer::set_render_loop_enabled(bool p_enabled) { + render_loop_enabled = p_enabled; +} + RenderingServer::RenderingServer() { //ERR_FAIL_COND(singleton); singleton = this; diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 3ce63585a8..56a8325630 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -47,6 +47,7 @@ class RenderingServer : public Object { static RenderingServer *singleton; int mm_policy; + bool render_loop_enabled = true; void _camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); void _canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector<float> &p_margins, const Color &p_modulate = Color(1, 1, 1)); @@ -1229,6 +1230,9 @@ public: virtual bool is_low_end() const = 0; + bool is_render_loop_enabled() const; + void set_render_loop_enabled(bool p_enabled); + RenderingServer(); virtual ~RenderingServer(); }; |