diff options
571 files changed, 17463 insertions, 7914 deletions
diff --git a/.gitignore b/.gitignore index 6af581040c..8d1aad947d 100644 --- a/.gitignore +++ b/.gitignore @@ -383,3 +383,6 @@ ruby.png snow.png updown.png gcov.css + +# https://clangd.llvm.org/ cache folder +.clangd/ diff --git a/.lgtm.yml b/.lgtm.yml new file mode 100644 index 0000000000..e4841eaff4 --- /dev/null +++ b/.lgtm.yml @@ -0,0 +1,7 @@ +extraction: + cpp: + after_prepare: + - pip3 install scons + - PATH="/opt/work/.local/bin:$PATH" + index: + build_command: scons -j2 @@ -24,6 +24,7 @@ dankan1890 <mewuidev2@gmail.com> Daniel J. Ramirez <djrmuv@gmail.com> Dominik 'dreamsComeTrue' JasiÅ„ski <dominikjasinski@o2.pl> Emmanuel Barroga <emmanuelbarroga@gmail.com> +Eric M <itsjusteza@gmail.com> Erik Selecký <35656626+rxlecky@users.noreply.github.com> Erik Selecký <35656626+rxlecky@users.noreply.github.com> <35656626+SeleckyErik@users.noreply.github.com> Fabian <supagu@gmail.com> diff --git a/AUTHORS.md b/AUTHORS.md index 40aa50f8b6..8ae19cfdf7 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -66,6 +66,7 @@ name is available. Emmanuel Leblond (touilleMan) Eoin O'Neill (Eoin-ONeill-Yokai) Eric Lasota (elasota) + Eric M (EricEzaM) Eric Rybicki (ericrybick) Erik Selecký (rxlecky) est31 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f8f8bd676..88c9e1a8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -384,6 +384,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Ogg samples now have an icon in the editor, like WAV samples. - Camera2D drag margins are now disabled by default. - If porting a project from Godot 3.1 where drag margins were used, these must be enabled manually again. +- The Camera2D Offset property now ignores the Limit property. + - To get the old behavior back, move the camera itself instead of changing the offset. - `Camera.project_position()` now requires a second `depth` argument to determine the distance of the point from the camera. - To get the old behavior back, pass the Camera's `near` property value as the second argument. - `Skeleton.set_bone_global_pose()` was replaced by `Skeleton.set_bone_global_pose_override()`. diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt index 8ccdecd307..757913f0bd 100644 --- a/COPYRIGHT.txt +++ b/COPYRIGHT.txt @@ -338,7 +338,7 @@ License: Expat Files: ./thirdparty/tinyexr/ Comment: TinyEXR -Copyright: 2014-2019, Syoyo Fujita +Copyright: 2014-2020, Syoyo Fujita 2002, Industrial Light & Magic, a division of Lucas Digital Ltd. LLC License: BSD-3-clause @@ -14,7 +14,6 @@ generous deed immortalized in the next stable release of Godot Engine. Gamblify <https://www.gamblify.com> Heroic Labs <https://heroiclabs.com> - Interblock <http://interblockgaming.com> ## Gold sponsors @@ -27,16 +26,17 @@ generous deed immortalized in the next stable release of Godot Engine. ## Bronze sponsors Brandon Lamb + Garry Newman ## Mini sponsors AD Ford - Alan Beauchamp albinaask Alejandro Saucedo alex brown Andrew Dunai Christian Baune + Christoffer Sundbom Christopher Montesano Darkhan Baimyrza Darrin Massena @@ -46,7 +46,6 @@ generous deed immortalized in the next stable release of Godot Engine. Edward Flick Gamechuck GameDev.net - Grady Hein-Pieter van Braam Jacob McKenney Jasper Brooks @@ -78,7 +77,6 @@ generous deed immortalized in the next stable release of Godot Engine. Asher Glick Austen McRae Bernhard Werner - beVR Carlo Cabanilla Chris Goddard Christopher Case @@ -93,8 +91,11 @@ generous deed immortalized in the next stable release of Godot Engine. Florian Rämisch Forge Gamejunkey + Grady Jakub Grzesik Javier Roman + Jeff Nyte + Joan Fons Jon Woodward Karl Werf Klavdij Voncina @@ -103,7 +104,9 @@ generous deed immortalized in the next stable release of Godot Engine. Maciej Pendolski Manuele Finocchiaro Markus Wiesner + Mason Bially Matthew Hillier + m kaersten Mohamed Ikbel Boulabiar Monster Vial Officine Pixel S.n.c. @@ -114,10 +117,9 @@ generous deed immortalized in the next stable release of Godot Engine. Rob Messick Roland Fredenhagen Ronan Zeegers - Ryan Badour Sandro Jenny Sarksus - Scott Wadden + Sean Sergey Sofox Spicylewd @@ -133,13 +135,16 @@ generous deed immortalized in the next stable release of Godot Engine. Adam Nakonieczny Adam Neumann Alexander J Maynard + Alex de la Mare Alexey Dyadchenko Alex Khayrullin alice gambrell Andreas Funke André Frélicot Andrew Harris + Antoni Batchelli aoshiwik + Arisaka Mayuki Barugon Can Eris Carlos de Sousa Marques @@ -148,7 +153,6 @@ generous deed immortalized in the next stable release of Godot Engine. Chelsea Hash Chris Petrich Chris Serino - Christian Alexander Bjørklund Bøhler Christian Leth Jeppesen Cody Parker Conrad Curry @@ -164,19 +168,20 @@ generous deed immortalized in the next stable release of Godot Engine. Felix Brückner flesk F S + Gabrielius VaiÅ¡kÅ«nas Gary Hulst gavlig GGGames.org GiulianoB + Green Fox Guilherme Felipe de C. G. da Silva Heath Hayes Hoai Nam Tran Horváth Péter Hu Hund + James Couzens Jared Jared White - Jeff Nyte - Joan Fons Joel Fivat Joel Höglund John G Gentzel @@ -186,26 +191,31 @@ generous deed immortalized in the next stable release of Godot Engine. Joshua Flores Joshua Lesperance Juan Velandia + Judd Julian Todd Juraj Móza + JUSTIN CARROLL Justo Delgado Baudà Kelteseth kickmaniac kinfox + kuku Lachie Lain Ballard Leo Fidel R Liban luca duran + Luc-Frédéric Langis MadScientistCarl Marcelo Dornbusch Lopes Marisa Clardy Markus Fehr Martin Eigel + Martin Kotz + Martin Soucek Matt Eunson Michael Michael Dürwald Mikado069 - m kaersten MuffinManKen Nick Abousselam Oliver Dick @@ -221,13 +231,13 @@ generous deed immortalized in the next stable release of Godot Engine. pl Ranoller Raymond Harris + razmie Ricardo Alcantara Rob Robert Willes Rob McInroy Rocknight Studios Ronnie Ashlock - Ryan Ryan Wilson Samuel Judd Scott Pilet @@ -235,9 +245,9 @@ generous deed immortalized in the next stable release of Godot Engine. Sean Robertson Sébastien Serban Serafimescu + Sergey Minakov Shishir Tandale SKison - SleepCircle spilldata Steven Landow Stoned Xander @@ -245,13 +255,14 @@ generous deed immortalized in the next stable release of Godot Engine. TheLevelOfDetail . Thomas Bjarnelöf Thomas Kurz + Tim Howard Timothy Pulliam Tobias Bocanegra Trent Fehl Valryia VikFro - Vincent Henderson VojtÄ›ch + voxelv William Foster Wojciech Chojnacki Xavier PATRICELLI @@ -264,6 +275,7 @@ generous deed immortalized in the next stable release of Godot Engine. 1D_Inc Aaron + Aaron Passchier Abraham Haskins Acheron Adam @@ -275,9 +287,11 @@ generous deed immortalized in the next stable release of Godot Engine. Adam Smeltzer Adam SzymaÅ„ski Adisibio + Agar3s - Giovanny Beltrán Agustinus Arya Aidan O'Flannagain Aki Mimoto + Alan Beauchamp Albin Jonasson Svärdsby Alder Stefano AleMax @@ -290,6 +304,7 @@ generous deed immortalized in the next stable release of Godot Engine. Allen Schade Andreas Krampitz André Simões + Andre Stackhouse andrew james morris Andrew Mansuetti Andrew Rosenwinkel @@ -298,16 +313,18 @@ generous deed immortalized in the next stable release of Godot Engine. Anthony Avina AP Condomines Arda Erol - Arisaka Mayuki Armin Preiml Arseniy M Arthur S. Muszynski Ashley Claymore Ashton Scott Snapp + Astier Mickael Aubrey Falconer B A Balázs Batári + Balázs Kondákor Bartosz Bielecki + Bekhoucha Danyl Benedikt Ben Vercammen Bernd Jänichen @@ -315,6 +332,7 @@ generous deed immortalized in the next stable release of Godot Engine. Black Block Blair Allen Bobby CC Wong + Borkzilla Bram brian Brian mc gowan @@ -322,6 +340,7 @@ generous deed immortalized in the next stable release of Godot Engine. Burney Waring Caleb Gartner Cameron Meyer + Carlos Cejudo Carl van der Geest Carwyn Edwards Cas Brugman @@ -329,14 +348,15 @@ generous deed immortalized in the next stable release of Godot Engine. Chad Steadman Chris Brown Chris Chapin + Chris Jagusch + Christian Clavet Christian Winter Christoffer Dahlblom - Christoffer Sundbom Christophe Gagnier Christopher Schmitt - Christoph Woinke Clay Heaton Cole Johnson + Conall O Curt King CzechBlueBear Daniel De Macedo @@ -344,8 +364,10 @@ generous deed immortalized in the next stable release of Godot Engine. DanielMaximiano Daniel Szarfman Daniel Tebbutt + Danny Welch Daren Scot Wilson Dave Walker + David Bôle David May David Woodard David Zanetti @@ -377,7 +399,6 @@ generous deed immortalized in the next stable release of Godot Engine. Fekinox Felix Bohmann Flaredown - Florian Richer Forty Doubleu Frank FuDiggity @@ -385,6 +406,7 @@ generous deed immortalized in the next stable release of Godot Engine. gamedev by Celio Gary Thomas George Marques + Greg Lincoln Greg Olson GREGORY C FEIN Greyson Richey @@ -394,9 +416,11 @@ generous deed immortalized in the next stable release of Godot Engine. Guldoman Gustavo Loureiro dos Reis Hal A + helija Heribert Hirth Hunter Jones Hylpher + Ian Williams Iiari iKlem IndustrialRobot @@ -406,9 +430,11 @@ generous deed immortalized in the next stable release of Godot Engine. Jaguar Jaiden Gerig Jaime Ruiz-Borau Vizárraga + Jake Huxell Jako Danar James James A F Manley + James Thomas Jamiee H Jamie Massey Janders @@ -429,6 +455,7 @@ generous deed immortalized in the next stable release of Godot Engine. Jonatan R Jonathan G Jon Bonazza + Jon Oakes Jon Sully Jordy Goodridge Jorge Antunes @@ -437,12 +464,12 @@ generous deed immortalized in the next stable release of Godot Engine. Josh Mitchell Joshua Southerland Juanfran - Judd Julian Murgia June Little JungleRobba Justin Calleja Justin Hamilton + Justin Oaksford Justin Spedding KaDokta Karel NÄ›mec @@ -454,11 +481,13 @@ generous deed immortalized in the next stable release of Godot Engine. Kevin McPhillips Kiri Jolly Kjetil Haugland + Kristian Nygaard Jensen KsyTek Games Kuan Cheang kycho Kyle Appelgate Kyuppin + Laurent CHEA Laurent Tréguier LEMMiNO Leonardo Dimano @@ -496,9 +525,10 @@ generous deed immortalized in the next stable release of Godot Engine. Mikayla Mike Birkhead Mike Cunningham + Mitchell J. Wagner Molinghu + Molly Jameson MoM - Mored4u Nathan Fish Natrim nee @@ -520,25 +550,25 @@ generous deed immortalized in the next stable release of Godot Engine. Oleg Reva Olivier Omar Delarosa + Orinxlm Oscar Domingo Oscar Norlander - Pan Ip Parinya Teerakasemsuk Patrick Dully Patrick Nafarrete Paul Gieske Paul Mason PaweÅ‚ Kowal + PaweÅ‚ Åyczkowski Pedro Assuncao Penguin - Peter Philip Cohoe Pierre-Nicolas Tollitte Piotr Góral Point08 Preethi Vaidyanathan + Price Comstock pwab - Rad Cat Rafa Laguna Remi Rampin Rémi Verschelde @@ -547,6 +577,7 @@ generous deed immortalized in the next stable release of Godot Engine. Richard Ivánek Robert Farr (Larington) Robert Larnach + Rob Ruana Roger Smith Roland RzÄ…sa Roman Tinkov @@ -558,6 +589,7 @@ generous deed immortalized in the next stable release of Godot Engine. Sam Caulfield Sam Edson Samuele Zolfanelli + sayaks Scott D. Yelich Scott Longley ScottMakesGames @@ -574,6 +606,7 @@ generous deed immortalized in the next stable release of Godot Engine. Simon Schoenenberger Simon Wenner Sintinium + Skalli smbe19 smo1704 soft circles @@ -581,9 +614,11 @@ generous deed immortalized in the next stable release of Godot Engine. Stefano Caronia Steve Cloete Svenne Krap + tadashi endo Tannen Helmers Terry tezuvholovdr + Theodore Lindsey TheVoiceInMyHead thomas Thomas Bechtold @@ -591,6 +626,7 @@ generous deed immortalized in the next stable release of Godot Engine. Thomas Kelly Tim Drumheller Tim Erskine + Tim Gleason Timothy B. MacDonald Tobbun Tobias Bradtke @@ -622,10 +658,16 @@ generous deed immortalized in the next stable release of Godot Engine. werner mendizabal Wiley Thompson Will + William Edwards + William F Siqueira + William Hogben + Windvis Wyatt Goodin + x1212 Yegor Smirnov YiYin Gu Yuri Sizov + Zak Stephens Zgegnesh Hemomancer ΒΑΣΙΛΗΣ ΓΕΩΡΓΑΚΟΠΟΥΛΟΣ éƒæ™¨ç…œ diff --git a/SConstruct b/SConstruct index 64a4c48eff..b7b0321039 100644 --- a/SConstruct +++ b/SConstruct @@ -13,8 +13,6 @@ from collections import OrderedDict # Local import methods import glsl_builders -import version -from platform_methods import run_in_subprocess # Scan possible build platforms diff --git a/core/SCsub b/core/SCsub index 40ee78d3ea..16ee49d003 100644 --- a/core/SCsub +++ b/core/SCsub @@ -4,7 +4,6 @@ Import("env") import core_builders import make_binders -from platform_methods import run_in_subprocess env.core_sources = [] diff --git a/core/color.cpp b/core/color.cpp index c85cd9100d..c61ee0e64a 100644 --- a/core/color.cpp +++ b/core/color.cpp @@ -390,7 +390,7 @@ String _to_hex(float p_val) { String ret; for (int i = 0; i < 2; i++) { - CharType c[2] = { 0, 0 }; + char32_t c[2] = { 0, 0 }; int lv = v & 0xF; if (lv < 10) { c[0] = '0' + lv; @@ -399,7 +399,7 @@ String _to_hex(float p_val) { } v >>= 4; - String cs = (const CharType *)c; + String cs = (const char32_t *)c; ret = cs + ret; } diff --git a/core/cowdata.h b/core/cowdata.h index 82daefb5bd..79676e6d80 100644 --- a/core/cowdata.h +++ b/core/cowdata.h @@ -40,6 +40,7 @@ template <class T> class Vector; class String; +class Char16String; class CharString; template <class T, class V> class VMap; @@ -49,6 +50,7 @@ class CowData { template <class TV> friend class Vector; friend class String; + friend class Char16String; friend class CharString; template <class TV, class VV> friend class VMap; diff --git a/core/crypto/crypto_core.cpp b/core/crypto/crypto_core.cpp index b0dc47e655..117e47d538 100644 --- a/core/crypto/crypto_core.cpp +++ b/core/crypto/crypto_core.cpp @@ -140,13 +140,19 @@ Error CryptoCore::AESContext::encrypt_ecb(const uint8_t p_src[16], uint8_t r_dst return ret ? FAILED : OK; } -Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) { - int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_src, r_dst); +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::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); +Error CryptoCore::AESContext::encrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst) { + size_t iv_off = 0; // Ignore and assume 16-byte alignment. + int ret = mbedtls_aes_crypt_cfb128((mbedtls_aes_context *)ctx, MBEDTLS_AES_ENCRYPT, p_length, &iv_off, p_iv, p_src, r_dst); + return ret ? FAILED : OK; +} + +Error CryptoCore::AESContext::decrypt_ecb(const uint8_t p_src[16], uint8_t r_dst[16]) { + int ret = mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_src, r_dst); return ret ? FAILED : OK; } @@ -155,6 +161,12 @@ Error CryptoCore::AESContext::decrypt_cbc(size_t p_length, uint8_t r_iv[16], con return ret ? FAILED : OK; } +Error CryptoCore::AESContext::decrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst) { + size_t iv_off = 0; // Ignore and assume 16-byte alignment. + int ret = mbedtls_aes_crypt_cfb128((mbedtls_aes_context *)ctx, MBEDTLS_AES_DECRYPT, p_length, &iv_off, p_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 82df9c23a8..9ab2871caa 100644 --- a/core/crypto/crypto_core.h +++ b/core/crypto/crypto_core.h @@ -88,6 +88,8 @@ public: 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); + Error encrypt_cfb(size_t p_length, uint8_t p_iv[16], const uint8_t *p_src, uint8_t *r_dst); + Error decrypt_cfb(size_t p_length, uint8_t p_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/hashfuncs.h b/core/hashfuncs.h index d984f6c524..f4048843fc 100644 --- a/core/hashfuncs.h +++ b/core/hashfuncs.h @@ -146,6 +146,8 @@ struct HashMapHasherDefault { static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return p_int; } static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return (uint32_t)p_int; } static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return (uint32_t)p_wchar; } + static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return (uint32_t)p_uchar; } + static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return (uint32_t)p_uchar; } static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); } static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } diff --git a/core/image.cpp b/core/image.cpp index e2f353698f..b8a443eed2 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -363,6 +363,82 @@ void Image::get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int r_size = ofs2 - ofs; } +Image::Image3DValidateError Image::validate_3d_image(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_images) { + int w = p_width; + int h = p_height; + int d = p_depth; + + int arr_ofs = 0; + + while (true) { + for (int i = 0; i < d; i++) { + int idx = i + arr_ofs; + if (idx >= p_images.size()) { + return VALIDATE_3D_ERR_MISSING_IMAGES; + } + if (p_images[idx].is_null() || p_images[idx]->empty()) { + return VALIDATE_3D_ERR_IMAGE_EMPTY; + } + if (p_images[idx]->get_format() != p_format) { + return VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH; + } + if (p_images[idx]->get_width() != w || p_images[idx]->get_height() != h) { + return VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH; + } + if (p_images[idx]->has_mipmaps()) { + return VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS; + } + } + + arr_ofs += d; + + if (!p_mipmaps) { + break; + } + + if (w == 1 && h == 1 && d == 1) { + break; + } + + w = MAX(1, w >> 1); + h = MAX(1, h >> 1); + d = MAX(1, d >> 1); + } + + if (arr_ofs != p_images.size()) { + return VALIDATE_3D_ERR_EXTRA_IMAGES; + } + + return VALIDATE_3D_OK; +} + +String Image::get_3d_image_validation_error_text(Image3DValidateError p_error) { + switch (p_error) { + case VALIDATE_3D_OK: { + return TTR("Ok"); + } break; + case VALIDATE_3D_ERR_IMAGE_EMPTY: { + return TTR("Empty Image found"); + } break; + case VALIDATE_3D_ERR_MISSING_IMAGES: { + return TTR("Missing Images"); + } break; + case VALIDATE_3D_ERR_EXTRA_IMAGES: { + return TTR("Too many Images"); + } break; + case VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH: { + return TTR("Image size mismatch"); + } break; + case VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH: { + return TTR("Image format mismatch"); + } break; + case VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS: { + return TTR("Image has included mipmaps"); + } break; + } + return String(); +} + int Image::get_width() const { return width; } diff --git a/core/image.h b/core/image.h index d2572b072e..06794c7fed 100644 --- a/core/image.h +++ b/core/image.h @@ -230,6 +230,19 @@ public: void get_mipmap_offset_and_size(int p_mipmap, int &r_ofs, int &r_size) const; //get where the mipmap begins in data void get_mipmap_offset_size_and_dimensions(int p_mipmap, int &r_ofs, int &r_size, int &w, int &h) const; //get where the mipmap begins in data + enum Image3DValidateError { + VALIDATE_3D_OK, + VALIDATE_3D_ERR_IMAGE_EMPTY, + VALIDATE_3D_ERR_MISSING_IMAGES, + VALIDATE_3D_ERR_EXTRA_IMAGES, + VALIDATE_3D_ERR_IMAGE_SIZE_MISMATCH, + VALIDATE_3D_ERR_IMAGE_FORMAT_MISMATCH, + VALIDATE_3D_ERR_IMAGE_HAS_MIPMAPS, + }; + + static Image3DValidateError validate_3d_image(Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_images); + static String get_3d_image_validation_error_text(Image3DValidateError p_error); + /** * Resize the image, using the preferred interpolation method. */ diff --git a/core/input/SCsub b/core/input/SCsub index f40978911b..740398b266 100644 --- a/core/input/SCsub +++ b/core/input/SCsub @@ -2,7 +2,6 @@ Import("env") -from platform_methods import run_in_subprocess import input_builders diff --git a/core/io/compression.cpp b/core/io/compression.cpp index 99ca8107e4..7480262835 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -180,8 +180,95 @@ int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p ERR_FAIL_V(-1); } +/** + This will handle both Gzip and Deflat streams. It will automatically allocate the output buffer into the provided p_dst_vect Vector. + This is required for compressed data who's final uncompressed size is unknown, as is the case for HTTP response bodies. + This is much slower however than using Compression::decompress because it may result in multiple full copies of the output buffer. +*/ +int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode) { + int ret; + uint8_t *dst = nullptr; + int out_mark = 0; + z_stream strm; + + ERR_FAIL_COND_V(p_src_size <= 0, Z_DATA_ERROR); + + // This function only supports GZip and Deflate + int window_bits = p_mode == MODE_DEFLATE ? 15 : 15 + 16; + ERR_FAIL_COND_V(p_mode != MODE_DEFLATE && p_mode != MODE_GZIP, Z_ERRNO); + + // Initialize the stream + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + + int err = inflateInit2(&strm, window_bits); + ERR_FAIL_COND_V(err != Z_OK, -1); + + // Setup the stream inputs + strm.next_in = (Bytef *)p_src; + strm.avail_in = p_src_size; + + // Ensure the destination buffer is empty + p_dst_vect->resize(0); + + // decompress until deflate stream ends or end of file + do { + // Add another chunk size to the output buffer + // This forces a copy of the whole buffer + p_dst_vect->resize(p_dst_vect->size() + gzip_chunk); + // Get pointer to the actual output buffer + dst = p_dst_vect->ptrw(); + + // Set the stream to the new output stream + // Since it was copied, we need to reset the stream to the new buffer + strm.next_out = &(dst[out_mark]); + strm.avail_out = gzip_chunk; + + // run inflate() on input until output buffer is full and needs to be resized + // or input runs out + do { + ret = inflate(&strm, Z_SYNC_FLUSH); + + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + [[fallthrough]]; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + case Z_STREAM_ERROR: + WARN_PRINT(strm.msg); + (void)inflateEnd(&strm); + p_dst_vect->resize(0); + return ret; + } + } while (strm.avail_out > 0 && strm.avail_in > 0); + + out_mark += gzip_chunk; + + // Encorce max output size + if (p_max_dst_size > -1 && strm.total_out > (uint64_t)p_max_dst_size) { + (void)inflateEnd(&strm); + p_dst_vect->resize(0); + return Z_BUF_ERROR; + } + } while (ret != Z_STREAM_END); + + // If all done successfully, resize the output if it's larger than the actual output + if (ret == Z_STREAM_END && (unsigned long)p_dst_vect->size() > strm.total_out) { + p_dst_vect->resize(strm.total_out); + } + + // clean up and return + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + int Compression::zlib_level = Z_DEFAULT_COMPRESSION; int Compression::gzip_level = Z_DEFAULT_COMPRESSION; int Compression::zstd_level = 3; bool Compression::zstd_long_distance_matching = false; int Compression::zstd_window_log_size = 27; // ZSTD_WINDOWLOG_LIMIT_DEFAULT +int Compression::gzip_chunk = 16384; diff --git a/core/io/compression.h b/core/io/compression.h index f195f96ba5..c103fa8eae 100644 --- a/core/io/compression.h +++ b/core/io/compression.h @@ -32,6 +32,7 @@ #define COMPRESSION_H #include "core/typedefs.h" +#include "core/vector.h" class Compression { public: @@ -40,6 +41,7 @@ public: static int zstd_level; static bool zstd_long_distance_matching; static int zstd_window_log_size; + static int gzip_chunk; enum Mode { MODE_FASTLZ, @@ -51,6 +53,7 @@ public: static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD); static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD); static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD); + static int decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode); Compression() {} }; diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 5938914cb0..eb684f457e 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -37,52 +37,54 @@ #include <stdio.h> -#define COMP_MAGIC 0x43454447 - -Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode) { +Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) { ERR_FAIL_COND_V_MSG(file != nullptr, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open."); ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER); pos = 0; eofed = false; + use_magic = p_with_magic; if (p_mode == MODE_WRITE_AES256) { data.clear(); writing = true; file = p_base; - mode = p_mode; key = p_key; } else if (p_mode == MODE_READ) { writing = false; key = p_key; - uint32_t magic = p_base->get_32(); - ERR_FAIL_COND_V(magic != COMP_MAGIC, ERR_FILE_UNRECOGNIZED); - mode = Mode(p_base->get_32()); - ERR_FAIL_INDEX_V(mode, MODE_MAX, ERR_FILE_CORRUPT); - ERR_FAIL_COND_V(mode == 0, ERR_FILE_CORRUPT); + if (use_magic) { + uint32_t magic = p_base->get_32(); + ERR_FAIL_COND_V(magic != ENCRYPTED_HEADER_MAGIC, ERR_FILE_UNRECOGNIZED); + } unsigned char md5d[16]; p_base->get_buffer(md5d, 16); length = p_base->get_64(); + + unsigned char iv[16]; + for (int i = 0; i < 16; i++) { + iv[i] = p_base->get_8(); + } + base = p_base->get_position(); ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT); uint32_t ds = length; if (ds % 16) { ds += 16 - (ds % 16); } - data.resize(ds); uint32_t blen = p_base->get_buffer(data.ptrw(), ds); ERR_FAIL_COND_V(blen != ds, ERR_FILE_CORRUPT); - CryptoCore::AESContext ctx; - ctx.set_decode_key(key.ptrw(), 256); + { + CryptoCore::AESContext ctx; - for (size_t i = 0; i < ds; i += 16) { - ctx.decrypt_ecb(&data.write[i], &data.write[i]); + ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption! + ctx.decrypt_cfb(ds, iv, data.ptrw(), data.ptrw()); } data.resize(length); @@ -119,6 +121,25 @@ void FileAccessEncrypted::close() { return; } + _release(); + + file->close(); + memdelete(file); + + file = nullptr; +} + +void FileAccessEncrypted::release() { + if (!file) { + return; + } + + _release(); + + file = nullptr; +} + +void FileAccessEncrypted::_release() { if (writing) { Vector<uint8_t> compressed; size_t len = data.size(); @@ -138,27 +159,23 @@ void FileAccessEncrypted::close() { CryptoCore::AESContext ctx; ctx.set_encode_key(key.ptrw(), 256); - for (size_t i = 0; i < len; i += 16) { - ctx.encrypt_ecb(&compressed.write[i], &compressed.write[i]); + if (use_magic) { + file->store_32(ENCRYPTED_HEADER_MAGIC); } - file->store_32(COMP_MAGIC); - file->store_32(mode); - file->store_buffer(hash, 16); file->store_64(data.size()); - file->store_buffer(compressed.ptr(), compressed.size()); - file->close(); - memdelete(file); - file = nullptr; - data.clear(); + unsigned char iv[16]; + for (int i = 0; i < 16; i++) { + iv[i] = Math::rand() % 256; + file->store_8(iv[i]); + } - } else { - file->close(); - memdelete(file); + ctx.encrypt_cfb(len, iv, compressed.ptrw(), compressed.ptrw()); + + file->store_buffer(compressed.ptr(), compressed.size()); data.clear(); - file = nullptr; } } diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index e269c1e30c..fddc6842f3 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -33,6 +33,8 @@ #include "core/os/file_access.h" +#define ENCRYPTED_HEADER_MAGIC 0x43454447 + class FileAccessEncrypted : public FileAccess { public: enum Mode { @@ -42,7 +44,6 @@ public: }; private: - Mode mode = MODE_MAX; Vector<uint8_t> key; bool writing = false; FileAccess *file = nullptr; @@ -51,13 +52,17 @@ private: Vector<uint8_t> data; mutable int pos = 0; mutable bool eofed = false; + bool use_magic = true; + + void _release(); public: - Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode); + Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true); Error open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode); virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file virtual void close(); ///< close a file + virtual void release(); ///< finish and keep base file open virtual bool is_open() const; ///< true when file is open virtual String get_path() const; /// returns the path for the current open file diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 024ec3b2b5..8fdbb650d4 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -30,6 +30,8 @@ #include "file_access_pack.h" +#include "core/io/file_access_encrypted.h" +#include "core/script_language.h" #include "core/version.h" #include <stdio.h> @@ -44,13 +46,14 @@ Error PackedData::add_pack(const String &p_path, bool p_replace_files, size_t p_ return ERR_FILE_UNRECOGNIZED; } -void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files) { +void PackedData::add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted) { PathMD5 pmd5(path.md5_buffer()); - //printf("adding path %ls, %lli, %lli\n", path.c_str(), pmd5.a, pmd5.b); + //printf("adding path %s, %lli, %lli\n", path.utf8().get_data(), pmd5.a, pmd5.b); bool exists = files.has(pmd5); PackedFile pf; + pf.encrypted = p_encrypted; pf.pack = pkg_path; pf.offset = ofs; pf.size = size; @@ -179,6 +182,11 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, ERR_FAIL_V_MSG(false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + "."); } + uint32_t pack_flags = f->get_32(); + uint64_t file_base = f->get_64(); + + bool enc_directory = (pack_flags & PACK_DIR_ENCRYPTED); + for (int i = 0; i < 16; i++) { //reserved f->get_32(); @@ -186,6 +194,30 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, int file_count = f->get_32(); + if (enc_directory) { + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); + if (!fae) { + f->close(); + memdelete(f); + ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory."); + } + + Vector<uint8_t> key; + key.resize(32); + for (int i = 0; i < key.size(); i++) { + key.write[i] = script_encryption_key[i]; + } + + Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false); + if (err) { + f->close(); + memdelete(f); + memdelete(fae); + ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory."); + } + f = fae; + } + for (int i = 0; i < file_count; i++) { uint32_t sl = f->get_32(); CharString cs; @@ -196,11 +228,13 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, String path; path.parse_utf8(cs.ptr()); - uint64_t ofs = f->get_64(); + uint64_t ofs = file_base + f->get_64(); uint64_t size = f->get_64(); uint8_t md5[16]; f->get_buffer(md5, 16); - PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files); + uint32_t flags = f->get_32(); + + PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED)); } f->close(); @@ -234,7 +268,7 @@ void FileAccessPack::seek(size_t p_position) { eof = false; } - f->seek(pf.offset + p_position); + f->seek(off + p_position); pos = p_position; } @@ -319,12 +353,35 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'."); f->seek(pf.offset); + off = pf.offset; + + if (pf.encrypted) { + FileAccessEncrypted *fae = memnew(FileAccessEncrypted); + if (!fae) { + ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'."); + } + + Vector<uint8_t> key; + key.resize(32); + for (int i = 0; i < key.size(); i++) { + key.write[i] = script_encryption_key[i]; + } + + Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false); + if (err) { + memdelete(fae); + ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'."); + } + f = fae; + off = 0; + } pos = 0; eof = false; } FileAccessPack::~FileAccessPack() { if (f) { + f->close(); memdelete(f); } } diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 6e316119cb..d934b0deb5 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -40,7 +40,15 @@ // Godot's packed file magic header ("GDPC" in ASCII). #define PACK_HEADER_MAGIC 0x43504447 // The current packed file format version number. -#define PACK_FORMAT_VERSION 1 +#define PACK_FORMAT_VERSION 2 + +enum PackFlags { + PACK_DIR_ENCRYPTED = 1 << 0 +}; + +enum PackFileFlags { + PACK_FILE_ENCRYPTED = 1 << 0 +}; class PackSource; @@ -56,6 +64,7 @@ public: uint64_t size; uint8_t md5[16]; PackSource *src; + bool encrypted; }; private: @@ -102,7 +111,7 @@ private: public: void add_pack_source(PackSource *p_source); - void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files); // for PackSource + void add_path(const String &pkg_path, const String &path, uint64_t ofs, uint64_t size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource void set_disabled(bool p_disabled) { disabled = p_disabled; } _FORCE_INLINE_ bool is_disabled() const { return disabled; } @@ -135,6 +144,7 @@ class FileAccessPack : public FileAccess { mutable size_t pos; mutable bool eof; + uint64_t off; FileAccess *f; virtual Error _open(const String &p_path, int p_mode_flags); diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index 974bb65a18..ce402fe8ed 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -148,7 +148,7 @@ unzFile ZipArchive::get_file_handle(String p_file) const { } bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, size_t p_offset = 0) { - //printf("opening zip pack %ls, %i, %i\n", p_name.c_str(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); + //printf("opening zip pack %s, %i, %i\n", p_name.utf8().get_data(), p_name.extension().nocasecmp_to("zip"), p_name.extension().nocasecmp_to("pcz")); // load with offset feature only supported for PCK files ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Invalid PCK data. Note that loading files with a non-zero offset isn't supported with ZIP archives."); @@ -200,8 +200,8 @@ bool ZipArchive::try_open_pack(const String &p_path, bool p_replace_files, size_ files[fname] = f; uint8_t md5[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this, p_replace_files); - //printf("packed data add path %ls, %ls\n", p_name.c_str(), fname.c_str()); + PackedData::get_singleton()->add_path(p_path, fname, 1, 0, md5, this, p_replace_files, false); + //printf("packed data add path %s, %s\n", p_name.utf8().get_data(), fname.utf8().get_data()); if ((i + 1) < gi.number_entry) { unzGoToNextFile(zfile); diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index ec51a9e4fb..2cce24e878 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef MINIZIP_ENABLED - #ifndef FILE_ACCESS_ZIP_H #define FILE_ACCESS_ZIP_H +#ifdef MINIZIP_ENABLED + #include "core/io/file_access_pack.h" #include "core/map.h" @@ -113,6 +113,6 @@ public: ~FileAccessZip(); }; -#endif // FILE_ACCESS_ZIP_H - #endif // MINIZIP_ENABLED + +#endif // FILE_ACCESS_ZIP_H diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index c7a0ae5605..d0fb63b958 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -71,7 +71,7 @@ static void _parse_hex(const String &p_string, int p_start, uint8_t *p_dst) { } int n = 0; - CharType c = p_string[i]; + char32_t c = p_string[i]; if (c >= '0' && c <= '9') { n = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -101,7 +101,7 @@ void IP_Address::_parse_ipv6(const String &p_string) { int parts_idx = 0; for (int i = 0; i < p_string.length(); i++) { - CharType c = p_string[i]; + char32_t c = p_string[i]; if (c == ':') { if (i == 0) { continue; // next must be a ":" diff --git a/core/io/json.cpp b/core/io/json.cpp index 8bdd6385cb..1b89d966fd 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -125,7 +125,7 @@ String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_key return _print_var(p_var, p_indent, 0, p_sort_keys); } -Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) { +Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) { while (p_len > 0) { switch (p_str[index]) { case '\n': { @@ -180,12 +180,12 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to } else if (p_str[index] == '\\') { //escaped characters... index++; - CharType next = p_str[index]; + char32_t next = p_str[index]; if (next == 0) { r_err_str = "Unterminated String"; return ERR_PARSE_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -206,7 +206,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to case 'u': { // hex number for (int j = 0; j < 4; j++) { - CharType c = p_str[index + j + 1]; + char32_t c = p_str[index + j + 1]; if (c == 0) { r_err_str = "Unterminated String"; return ERR_PARSE_ERROR; @@ -215,7 +215,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to r_err_str = "Malformed hex constant in string"; return ERR_PARSE_ERROR; } - CharType v; + char32_t v; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -264,7 +264,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to if (p_str[index] == '-' || (p_str[index] >= '0' && p_str[index] <= '9')) { //a number - const CharType *rptr; + const char32_t *rptr; double number = String::to_float(&p_str[index], &rptr); index += (rptr - &p_str[index]); r_token.type = TK_NUMBER; @@ -293,7 +293,7 @@ Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_to return ERR_PARSE_ERROR; } -Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { +Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { if (token.type == TK_CURLY_BRACKET_OPEN) { Dictionary d; Error err = _parse_object(d, p_str, index, p_len, line, r_err_str); @@ -337,7 +337,7 @@ Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, in } } -Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { +Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { Token token; bool need_comma = false; @@ -375,7 +375,7 @@ Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_ return ERR_PARSE_ERROR; } -Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { +Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { bool at_key = true; String key; Token token; @@ -439,7 +439,7 @@ Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, } Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) { - const CharType *str = p_json.ptr(); + const char32_t *str = p_json.ptr(); int idx = 0; int len = p_json.length(); Token token; diff --git a/core/io/json.h b/core/io/json.h index 4fc5630a93..9122228163 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -65,10 +65,10 @@ class JSON { static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys); - static Error _get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str); - static Error _parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str); - static Error _parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str); - static Error _parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str); + static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str); + static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); + static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); + static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); public: static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true); diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 374b2a5e07..5480d3c535 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -30,36 +30,58 @@ #include "pck_packer.h" +#include "core/crypto/crypto_core.h" +#include "core/io/file_access_encrypted.h" #include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION #include "core/os/file_access.h" #include "core/version.h" -static uint64_t _align(uint64_t p_n, int p_alignment) { - if (p_alignment == 0) { - return p_n; +static int _get_pad(int p_alignment, int p_n) { + int rest = p_n % p_alignment; + int pad = 0; + if (rest > 0) { + pad = p_alignment - rest; } - uint64_t rest = p_n % p_alignment; - if (rest == 0) { - return p_n; - } else { - return p_n + (p_alignment - rest); - } -} - -static void _pad(FileAccess *p_file, int p_bytes) { - for (int i = 0; i < p_bytes; i++) { - p_file->store_8(0); - } + return pad; } void PCKPacker::_bind_methods() { - ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment"), &PCKPacker::pck_start, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path"), &PCKPacker::add_file); + ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(0), DEFVAL(String()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false)); ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false)); } -Error PCKPacker::pck_start(const String &p_file, int p_alignment) { +Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) { + ERR_FAIL_COND_V_MSG((p_key.empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long)."); + + String _key = p_key.to_lower(); + key.resize(32); + for (int i = 0; i < 32; i++) { + int v = 0; + if (i * 2 < _key.length()) { + char32_t ct = _key[i * 2]; + if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = 10 + ct - 'a'; + } + v |= ct << 4; + } + + if (i * 2 + 1 < _key.length()) { + char32_t ct = _key[i * 2 + 1]; + if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = 10 + ct - 'a'; + } + v |= ct; + } + key.write[i] = v; + } + enc_dir = p_encrypt_directory; + if (file != nullptr) { memdelete(file); } @@ -76,16 +98,19 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment) { file->store_32(VERSION_MINOR); file->store_32(VERSION_PATCH); - for (int i = 0; i < 16; i++) { - file->store_32(0); // reserved + uint32_t pack_flags = 0; + if (enc_dir) { + pack_flags |= PACK_DIR_ENCRYPTED; } + file->store_32(pack_flags); // flags files.clear(); + ofs = 0; return OK; } -Error PCKPacker::add_file(const String &p_file, const String &p_src) { +Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) { FileAccess *f = FileAccess::open(p_src, FileAccess::READ); if (!f) { return ERR_FILE_CANT_OPEN; @@ -94,8 +119,32 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src) { File pf; pf.path = p_file; pf.src_path = p_src; + pf.ofs = ofs; pf.size = f->get_len(); - pf.offset_offset = 0; + + Vector<uint8_t> data = FileAccess::get_file_as_array(p_src); + { + unsigned char hash[16]; + CryptoCore::md5(data.ptr(), data.size(), hash); + pf.md5.resize(16); + for (int i = 0; i < 16; i++) { + pf.md5.write[i] = hash[i]; + } + } + pf.encrypted = p_encrypt; + + uint64_t _size = pf.size; + if (p_encrypt) { // Add encryption overhead. + if (_size % 16) { // Pad to encryption block size. + _size += 16 - (_size % 16); + } + _size += 16; // hash + _size += 8; // data size + _size += 16; // iv + } + + int pad = _get_pad(alignment, ofs + _size); + ofs = ofs + _size + pad; files.push_back(pf); @@ -108,27 +157,64 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src) { Error PCKPacker::flush(bool p_verbose) { ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use."); - // write the index + int64_t file_base_ofs = file->get_position(); + file->store_64(0); // files base + for (int i = 0; i < 16; i++) { + file->store_32(0); // reserved + } + + // write the index file->store_32(files.size()); + FileAccessEncrypted *fae = nullptr; + FileAccess *fhead = file; + + if (enc_dir) { + fae = memnew(FileAccessEncrypted); + ERR_FAIL_COND_V(!fae, ERR_CANT_CREATE); + + Error err = fae->open_and_parse(file, key, FileAccessEncrypted::MODE_WRITE_AES256, false); + ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); + + fhead = fae; + } + for (int i = 0; i < files.size(); i++) { - file->store_pascal_string(files[i].path); - files.write[i].offset_offset = file->get_position(); - file->store_64(0); // offset - file->store_64(files[i].size); // size - - // # empty md5 - file->store_32(0); - file->store_32(0); - file->store_32(0); - file->store_32(0); + int string_len = files[i].path.utf8().length(); + int pad = _get_pad(4, string_len); + + fhead->store_32(string_len + pad); + fhead->store_buffer((const uint8_t *)files[i].path.utf8().get_data(), string_len); + for (int j = 0; j < pad; j++) { + fhead->store_8(0); + } + + fhead->store_64(files[i].ofs); + fhead->store_64(files[i].size); // pay attention here, this is where file is + fhead->store_buffer(files[i].md5.ptr(), 16); //also save md5 for file + + uint32_t flags = 0; + if (files[i].encrypted) { + flags |= PACK_FILE_ENCRYPTED; + } + fhead->store_32(flags); + } + + if (fae) { + fae->release(); + memdelete(fae); } - uint64_t ofs = file->get_position(); - ofs = _align(ofs, alignment); + int header_padding = _get_pad(alignment, file->get_position()); + for (int i = 0; i < header_padding; i++) { + file->store_8(Math::rand() % 256); + } - _pad(file, ofs - file->get_position()); + int64_t file_base = file->get_position(); + file->seek(file_base_ofs); + file->store_64(file_base); // update files base + file->seek(file_base); const uint32_t buf_max = 65536; uint8_t *buf = memnew_arr(uint8_t, buf_max); @@ -137,26 +223,41 @@ Error PCKPacker::flush(bool p_verbose) { for (int i = 0; i < files.size(); i++) { FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ); uint64_t to_write = files[i].size; + + fae = nullptr; + FileAccess *ftmp = file; + if (files[i].encrypted) { + fae = memnew(FileAccessEncrypted); + ERR_FAIL_COND_V(!fae, ERR_CANT_CREATE); + + Error err = fae->open_and_parse(file, key, FileAccessEncrypted::MODE_WRITE_AES256, false); + ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); + ftmp = fae; + } + while (to_write > 0) { int read = src->get_buffer(buf, MIN(to_write, buf_max)); - file->store_buffer(buf, read); + ftmp->store_buffer(buf, read); to_write -= read; } - uint64_t pos = file->get_position(); - file->seek(files[i].offset_offset); // go back to store the file's offset - file->store_64(ofs); - file->seek(pos); + if (fae) { + fae->release(); + memdelete(fae); + } - ofs = _align(ofs + files[i].size, alignment); - _pad(file, ofs - pos); + int pad = _get_pad(alignment, file->get_position()); + for (int j = 0; j < pad; j++) { + file->store_8(Math::rand() % 256); + } src->close(); memdelete(src); count += 1; - if (p_verbose && files.size() > 0) { + const int file_num = files.size(); + if (p_verbose && (file_num > 0)) { if (count % 100 == 0) { - printf("%i/%i (%.2f)\r", count, files.size(), float(count) / files.size() * 100); + printf("%i/%i (%.2f)\r", count, file_num, float(count) / file_num * 100); fflush(stdout); } } diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index 2929967a68..a6054dff2c 100644 --- a/core/io/pck_packer.h +++ b/core/io/pck_packer.h @@ -40,20 +40,26 @@ class PCKPacker : public Reference { FileAccess *file = nullptr; int alignment; + uint64_t ofs = 0; + + Vector<uint8_t> key; + bool enc_dir = false; static void _bind_methods(); struct File { String path; String src_path; - int size; - uint64_t offset_offset; + uint64_t ofs; + uint64_t size; + bool encrypted; + Vector<uint8_t> md5; }; Vector<File> files; public: - Error pck_start(const String &p_file, int p_alignment = 0); - Error add_file(const String &p_file, const String &p_src); + Error pck_start(const String &p_file, int p_alignment = 0, const String &p_key = String(), bool p_encrypt_directory = false); + Error add_file(const String &p_file, const String &p_src, bool p_encrypt = false); Error flush(bool p_verbose = false); PCKPacker() {} diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index b11267b60f..fc75ac7d1e 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -36,7 +36,7 @@ VARIANT_ENUM_CAST(XMLParser::NodeType); -static bool _equalsn(const CharType *str1, const CharType *str2, int len) { +static bool _equalsn(const char32_t *str1, const char32_t *str2, int len) { int i; for (i = 0; i < len && str1[i] && str2[i]; ++i) { if (str1[i] != str2[i]) { @@ -64,7 +64,7 @@ String XMLParser::_replace_special_characters(const String &origstr) { int specialChar = -1; for (int i = 0; i < (int)special_characters.size(); ++i) { - const CharType *p = &origstr[pos] + 1; + const char32_t *p = &origstr[pos] + 1; if (_equalsn(&special_characters[i][1], p, special_characters[i].length() - 1)) { specialChar = i; diff --git a/core/list.h b/core/list.h index f850db5241..1cef3c484d 100644 --- a/core/list.h +++ b/core/list.h @@ -395,28 +395,38 @@ public: ERR_FAIL_COND(p_A->data != _data); ERR_FAIL_COND(p_B->data != _data); + if (p_A == p_B) { + return; + } Element *A_prev = p_A->prev_ptr; Element *A_next = p_A->next_ptr; + Element *B_prev = p_B->prev_ptr; + Element *B_next = p_B->next_ptr; - p_A->next_ptr = p_B->next_ptr; - p_A->prev_ptr = p_B->prev_ptr; - - p_B->next_ptr = A_next; - p_B->prev_ptr = A_prev; - - if (p_A->prev_ptr) { - p_A->prev_ptr->next_ptr = p_A; + if (A_prev) { + A_prev->next_ptr = p_B; + } else { + _data->first = p_B; } - if (p_A->next_ptr) { - p_A->next_ptr->prev_ptr = p_A; + if (B_prev) { + B_prev->next_ptr = p_A; + } else { + _data->first = p_A; } - - if (p_B->prev_ptr) { - p_B->prev_ptr->next_ptr = p_B; + if (A_next) { + A_next->prev_ptr = p_B; + } else { + _data->last = p_B; } - if (p_B->next_ptr) { - p_B->next_ptr->prev_ptr = p_B; + if (B_next) { + B_next->prev_ptr = p_A; + } else { + _data->last = p_A; } + p_A->prev_ptr = A_next == p_B ? p_B : B_prev; + p_A->next_ptr = B_next == p_A ? p_B : B_next; + p_B->prev_ptr = B_next == p_A ? p_A : A_prev; + p_B->next_ptr = A_next == p_B ? p_A : A_next; } /** * copy the list diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index 91f533eafb..43d4a63cd3 100644 --- a/core/math/audio_frame.h +++ b/core/math/audio_frame.h @@ -121,7 +121,7 @@ struct AudioFrame { r = p_frame.r; } - _ALWAYS_INLINE_ AudioFrame operator=(const AudioFrame &p_frame) { + _ALWAYS_INLINE_ AudioFrame &operator=(const AudioFrame &p_frame) { l = p_frame.l; r = p_frame.r; return *this; diff --git a/core/math/basis.h b/core/math/basis.h index 985fb0e44f..a86937ceb4 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -36,7 +36,11 @@ class Basis { public: - Vector3 elements[3]; + Vector3 elements[3] = { + Vector3(1, 0, 0), + Vector3(0, 1, 0), + Vector3(0, 0, 1) + }; _FORCE_INLINE_ const Vector3 &operator[](int axis) const { return elements[axis]; @@ -254,17 +258,7 @@ public: elements[2] = row2; } - _FORCE_INLINE_ Basis() { - elements[0][0] = 1; - elements[0][1] = 0; - elements[0][2] = 0; - elements[1][0] = 0; - elements[1][1] = 1; - elements[1][2] = 0; - elements[2][0] = 0; - elements[2][1] = 0; - elements[2][2] = 1; - } + _FORCE_INLINE_ Basis() {} }; _FORCE_INLINE_ void Basis::operator*=(const Basis &p_matrix) { diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 735a30f6cc..1040f9e0e4 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -596,7 +596,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant } break; case TEXT_CHAR: { - CharType result[2] = { *p_inputs[0], 0 }; + char32_t result[2] = { *p_inputs[0], 0 }; *r_return = String(result); @@ -739,7 +739,7 @@ void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant //////// -static bool _is_number(CharType c) { +static bool _is_number(char32_t c) { return (c >= '0' && c <= '9'); } @@ -747,7 +747,7 @@ Error Expression::_get_token(Token &r_token) { while (true) { #define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++]) - CharType cchar = GET_CHAR(); + char32_t cchar = GET_CHAR(); switch (cchar) { case 0: { @@ -900,7 +900,7 @@ Error Expression::_get_token(Token &r_token) { case '"': { String str; while (true) { - CharType ch = GET_CHAR(); + char32_t ch = GET_CHAR(); if (ch == 0) { _set_error("Unterminated String"); @@ -912,13 +912,13 @@ Error Expression::_get_token(Token &r_token) { } else if (ch == '\\') { //escaped characters... - CharType next = GET_CHAR(); + char32_t next = GET_CHAR(); if (next == 0) { _set_error("Unterminated String"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -939,7 +939,7 @@ Error Expression::_get_token(Token &r_token) { case 'u': { // hex number for (int j = 0; j < 4; j++) { - CharType c = GET_CHAR(); + char32_t c = GET_CHAR(); if (c == 0) { _set_error("Unterminated String"); @@ -951,7 +951,7 @@ Error Expression::_get_token(Token &r_token) { r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType v; + char32_t v; if (_is_number(c)) { v = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -992,7 +992,7 @@ Error Expression::_get_token(Token &r_token) { break; } - CharType next_char = (str_ofs >= expression.length()) ? 0 : expression[str_ofs]; + char32_t next_char = (str_ofs >= expression.length()) ? 0 : expression[str_ofs]; if (_is_number(cchar) || (cchar == '.' && _is_number(next_char))) { //a number @@ -1004,7 +1004,7 @@ Error Expression::_get_token(Token &r_token) { #define READING_DONE 4 int reading = READING_INT; - CharType c = cchar; + char32_t c = cchar; bool exp_sign = false; bool exp_beg = false; bool is_float = false; diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 9f8d4da5b3..24b42790f0 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -46,7 +46,8 @@ class Math { public: Math() {} // useless to instance - static const uint64_t RANDOM_MAX = 0xFFFFFFFF; + // Not using 'RANDOM_MAX' to avoid conflict with system headers on some OSes (at least NetBSD). + static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF; static _ALWAYS_INLINE_ double sin(double p_x) { return ::sin(p_x); } static _ALWAYS_INLINE_ float sin(float p_x) { return ::sinf(p_x); } @@ -283,8 +284,8 @@ public: static void randomize(); static uint32_t rand_from_seed(uint64_t *seed); static uint32_t rand(); - static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_MAX; } - static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_MAX; } + static _ALWAYS_INLINE_ double randd() { return (double)rand() / (double)Math::RANDOM_32BIT_MAX; } + static _ALWAYS_INLINE_ float randf() { return (float)rand() / (float)Math::RANDOM_32BIT_MAX; } static double random(double from, double to); static float random(float from, float to); diff --git a/core/math/quat.h b/core/math/quat.h index 64d0f00912..8619ea3c5c 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -130,7 +130,7 @@ public: w(q.w) { } - Quat operator=(const Quat &q) { + Quat &operator=(const Quat &q) { x = q.x; y = q.y; z = q.z; diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index 8fd5a056fa..09b13ab74d 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -31,12 +31,12 @@ #ifndef RANDOM_PCG_H #define RANDOM_PCG_H -#include <math.h> - #include "core/math/math_defs.h" #include "thirdparty/misc/pcg.h" +#include <math.h> + #if defined(__GNUC__) #define CLZ32(x) __builtin_clz(x) #elif defined(_MSC_VER) @@ -67,7 +67,6 @@ class RandomPCG { public: static const uint64_t DEFAULT_SEED = 12047754176567800795U; static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64; - static const uint64_t RANDOM_MAX = 0xFFFFFFFF; RandomPCG(uint64_t p_seed = DEFAULT_SEED, uint64_t p_inc = DEFAULT_INC); diff --git a/core/math/vector2.h b/core/math/vector2.h index 8a08d3bf64..0966d3392f 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -114,10 +114,10 @@ struct Vector2 { bool operator==(const Vector2 &p_vec2) const; bool operator!=(const Vector2 &p_vec2) const; - bool operator<(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } - bool operator>(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); } - bool operator<=(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y <= p_vec2.y) : (x < p_vec2.x); } - bool operator>=(const Vector2 &p_vec2) const { return Math::is_equal_approx(x, p_vec2.x) ? (y >= p_vec2.y) : (x > p_vec2.x); } + bool operator<(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y < p_vec2.y) : (x < p_vec2.x); } + bool operator>(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y > p_vec2.y) : (x > p_vec2.x); } + bool operator<=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y <= p_vec2.y) : (x < p_vec2.x); } + bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); } real_t angle() const; diff --git a/core/math/vector3.h b/core/math/vector3.h index 0bc1a467f2..5370b297f1 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -322,8 +322,8 @@ bool Vector3::operator!=(const Vector3 &p_v) const { } bool Vector3::operator<(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) { + if (x == p_v.x) { + if (y == p_v.y) { return z < p_v.z; } else { return y < p_v.y; @@ -334,8 +334,8 @@ bool Vector3::operator<(const Vector3 &p_v) const { } bool Vector3::operator>(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) { + if (x == p_v.x) { + if (y == p_v.y) { return z > p_v.z; } else { return y > p_v.y; @@ -346,8 +346,8 @@ bool Vector3::operator>(const Vector3 &p_v) const { } bool Vector3::operator<=(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) { + if (x == p_v.x) { + if (y == p_v.y) { return z <= p_v.z; } else { return y < p_v.y; @@ -358,8 +358,8 @@ bool Vector3::operator<=(const Vector3 &p_v) const { } bool Vector3::operator>=(const Vector3 &p_v) const { - if (Math::is_equal_approx(x, p_v.x)) { - if (Math::is_equal_approx(y, p_v.y)) { + if (x == p_v.x) { + if (y == p_v.y) { return z >= p_v.z; } else { return y > p_v.y; diff --git a/core/method_bind.h b/core/method_bind.h index ff2c771f81..942e2e0036 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -181,18 +181,18 @@ VARIANT_ENUM_CAST(Variant::Type); VARIANT_ENUM_CAST(Variant::Operator); template <> -struct VariantCaster<wchar_t> { - static _FORCE_INLINE_ wchar_t cast(const Variant &p_variant) { - return (wchar_t)p_variant.operator int(); +struct VariantCaster<char32_t> { + static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) { + return (char32_t)p_variant.operator int(); } }; #ifdef PTRCALL_ENABLED template <> -struct PtrToArg<wchar_t> { - _FORCE_INLINE_ static wchar_t convert(const void *p_ptr) { - return wchar_t(*reinterpret_cast<const int *>(p_ptr)); +struct PtrToArg<char32_t> { + _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { + return char32_t(*reinterpret_cast<const int *>(p_ptr)); } - _FORCE_INLINE_ static void encode(wchar_t p_val, const void *p_ptr) { + _FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) { *(int *)p_ptr = p_val; } }; diff --git a/core/object.h b/core/object.h index f9a12da8f6..12ef600dfc 100644 --- a/core/object.h +++ b/core/object.h @@ -658,7 +658,7 @@ public: Variant call(const StringName &p_name, VARIANT_ARG_LIST); // C++ helper void notification(int p_notification, bool p_reversed = false); - String to_string(); + virtual String to_string(); //used mainly by script, get and set all INCLUDING string virtual Variant getvar(const Variant &p_key, bool *r_valid = nullptr) const; diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 20b3435911..9dbb2952f7 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -234,7 +234,7 @@ double FileAccess::get_double() const { String FileAccess::get_token() const { CharString token; - CharType c = get_8(); + char32_t c = get_8(); while (!eof_reached()) { if (c <= ' ') { @@ -299,7 +299,7 @@ public: String FileAccess::get_line() const { CharBuffer line; - CharType c = get_8(); + char32_t c = get_8(); while (!eof_reached()) { if (c == '\n' || c == '\0') { @@ -342,8 +342,8 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const { bool in_quote = false; String current; for (int i = 0; i < l.length(); i++) { - CharType c = l[i]; - CharType s[2] = { 0, 0 }; + char32_t c = l[i]; + char32_t s[2] = { 0, 0 }; if (!in_quote && c == p_delim[0]) { strings.push_back(current); diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 4f094dd6c6..a2b3f75bea 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -232,7 +232,7 @@ void register_core_types() { } void register_core_settings() { - //since in register core types, globals may not e present + // Since in register core types, globals may not be present. GLOBAL_DEF("network/limits/tcp/connect_timeout_seconds", (30)); ProjectSettings::get_singleton()->set_custom_property_info("network/limits/tcp/connect_timeout_seconds", PropertyInfo(Variant::INT, "network/limits/tcp/connect_timeout_seconds", PROPERTY_HINT_RANGE, "1,1800,1")); GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16)); diff --git a/core/string_buffer.h b/core/string_buffer.h index f9cf31075a..a685720851 100644 --- a/core/string_buffer.h +++ b/core/string_buffer.h @@ -35,21 +35,21 @@ template <int SHORT_BUFFER_SIZE = 64> class StringBuffer { - CharType short_buffer[SHORT_BUFFER_SIZE]; + char32_t short_buffer[SHORT_BUFFER_SIZE]; String buffer; int string_length = 0; - _FORCE_INLINE_ CharType *current_buffer_ptr() { + _FORCE_INLINE_ char32_t *current_buffer_ptr() { return static_cast<String &>(buffer).empty() ? short_buffer : buffer.ptrw(); } public: - StringBuffer &append(CharType p_char); + StringBuffer &append(char32_t p_char); StringBuffer &append(const String &p_string); StringBuffer &append(const char *p_str); - StringBuffer &append(const CharType *p_str, int p_clip_to_len = -1); + StringBuffer &append(const char32_t *p_str, int p_clip_to_len = -1); - _FORCE_INLINE_ void operator+=(CharType p_char) { + _FORCE_INLINE_ void operator+=(char32_t p_char) { append(p_char); } @@ -61,7 +61,7 @@ public: append(p_str); } - _FORCE_INLINE_ void operator+=(const CharType *p_str) { + _FORCE_INLINE_ void operator+=(const char32_t *p_str) { append(p_str); } @@ -80,7 +80,7 @@ public: }; template <int SHORT_BUFFER_SIZE> -StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(CharType p_char) { +StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(char32_t p_char) { reserve(string_length + 2); current_buffer_ptr()[string_length++] = p_char; return *this; @@ -88,7 +88,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(CharTyp template <int SHORT_BUFFER_SIZE> StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const String &p_string) { - return append(p_string.c_str()); + return append(p_string.get_data()); } template <int SHORT_BUFFER_SIZE> @@ -96,7 +96,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const c int len = strlen(p_str); reserve(string_length + len + 1); - CharType *buf = current_buffer_ptr(); + char32_t *buf = current_buffer_ptr(); for (const char *c_ptr = p_str; *c_ptr; ++c_ptr) { buf[string_length++] = *c_ptr; } @@ -104,13 +104,13 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const c } template <int SHORT_BUFFER_SIZE> -StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const CharType *p_str, int p_clip_to_len) { +StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::append(const char32_t *p_str, int p_clip_to_len) { int len = 0; while ((p_clip_to_len < 0 || len < p_clip_to_len) && p_str[len]) { ++len; } reserve(string_length + len + 1); - memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(CharType)); + memcpy(&(current_buffer_ptr()[string_length]), p_str, len * sizeof(char32_t)); string_length += len; return *this; @@ -125,7 +125,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::reserve(int p_ bool need_copy = string_length > 0 && buffer.empty(); buffer.resize(next_power_of_2(p_size)); if (need_copy) { - memcpy(buffer.ptrw(), short_buffer, string_length * sizeof(CharType)); + memcpy(buffer.ptrw(), short_buffer, string_length * sizeof(char32_t)); } return *this; diff --git a/core/string_builder.cpp b/core/string_builder.cpp index c8d6498f27..dec299ffa3 100644 --- a/core/string_builder.cpp +++ b/core/string_builder.cpp @@ -61,7 +61,7 @@ String StringBuilder::as_string() const { return ""; } - CharType *buffer = memnew_arr(CharType, string_length); + char32_t *buffer = memnew_arr(char32_t, string_length); int current_position = 0; @@ -73,7 +73,7 @@ String StringBuilder::as_string() const { // Godot string const String &s = strings[godot_string_elem]; - memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(CharType)); + memcpy(buffer + current_position, s.ptr(), s.length() * sizeof(char32_t)); current_position += s.length(); diff --git a/core/string_name.cpp b/core/string_name.cpp index cbf6009681..6260e3ce8c 100644 --- a/core/string_name.cpp +++ b/core/string_name.cpp @@ -317,7 +317,7 @@ StringName StringName::search(const char *p_name) { return StringName(); //does not exist } -StringName StringName::search(const CharType *p_name) { +StringName StringName::search(const char32_t *p_name) { ERR_FAIL_COND_V(!configured, StringName()); ERR_FAIL_COND_V(!p_name, StringName()); diff --git a/core/string_name.h b/core/string_name.h index 886ddd0ee7..4f90479bda 100644 --- a/core/string_name.h +++ b/core/string_name.h @@ -122,7 +122,7 @@ public: } static StringName search(const char *p_name); - static StringName search(const CharType *p_name); + static StringName search(const char32_t *p_name); static StringName search(const String &p_name); struct AlphCompare { diff --git a/core/translation_po.h b/core/translation_po.h index 730635f63d..88830210ef 100644 --- a/core/translation_po.h +++ b/core/translation_po.h @@ -42,7 +42,7 @@ class TranslationPO : public Translation { // TLDR: Maps context to a list of source strings and translated strings. In PO terms, maps msgctxt to a list of msgid and msgstr. // The first key corresponds to context, and the second key (of the contained HashMap) corresponds to source string. // The value Vector<StringName> in the second map stores the translated strings. Index 0, 1, 2 matches msgstr[0], msgstr[1], msgstr[2]... in the case of plurals. - // Otherwise index 0 mathes to msgstr in a singular translation. + // Otherwise index 0 matches to msgstr in a singular translation. // Strings without context have "" as first key. HashMap<StringName, HashMap<StringName, Vector<StringName>>> translation_map; diff --git a/core/type_info.h b/core/type_info.h index e3d2b5bd53..3c7f59bb84 100644 --- a/core/type_info.h +++ b/core/type_info.h @@ -132,7 +132,8 @@ MAKE_TYPE_INFO_WITH_META(uint32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_ MAKE_TYPE_INFO_WITH_META(int32_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT32) MAKE_TYPE_INFO_WITH_META(uint64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_UINT64) MAKE_TYPE_INFO_WITH_META(int64_t, Variant::INT, GodotTypeInfo::METADATA_INT_IS_INT64) -MAKE_TYPE_INFO(wchar_t, Variant::INT) +MAKE_TYPE_INFO(char16_t, Variant::INT) +MAKE_TYPE_INFO(char32_t, Variant::INT) MAKE_TYPE_INFO_WITH_META(float, Variant::FLOAT, GodotTypeInfo::METADATA_REAL_IS_FLOAT) MAKE_TYPE_INFO_WITH_META(double, Variant::FLOAT, GodotTypeInfo::METADATA_REAL_IS_DOUBLE) diff --git a/core/ustring.cpp b/core/ustring.cpp index 9d2d938eaf..d5afbc2b47 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -39,7 +39,6 @@ #include "core/ucaps.h" #include "core/variant.h" -#include <wchar.h> #include <cstdint> #ifndef NO_USE_STDLIB @@ -62,9 +61,10 @@ #define IS_HEX_DIGIT(m_d) (((m_d) >= '0' && (m_d) <= '9') || ((m_d) >= 'a' && (m_d) <= 'f') || ((m_d) >= 'A' && (m_d) <= 'F')) const char CharString::_null = 0; -const CharType String::_null = 0; +const char16_t Char16String::_null = 0; +const char32_t String::_null = 0; -bool is_symbol(CharType c) { +bool is_symbol(char32_t c) { return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' '); } @@ -96,9 +96,11 @@ bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end) { } } -/** STRING **/ +/*************************************************************************/ +/* Char16String */ +/*************************************************************************/ -bool CharString::operator<(const CharString &p_right) const { +bool Char16String::operator<(const Char16String &p_right) const { if (length() == 0) { return p_right.length() != 0; } @@ -106,7 +108,7 @@ bool CharString::operator<(const CharString &p_right) const { return is_str_less(get_data(), p_right.get_data()); } -CharString &CharString::operator+=(char p_char) { +Char16String &Char16String::operator+=(char16_t p_char) { resize(size() ? size() + 1 : 2); set(length(), 0); set(length() - 1, p_char); @@ -114,19 +116,75 @@ CharString &CharString::operator+=(char p_char) { return *this; } -const char *CharString::get_data() const { +Char16String &Char16String::operator=(const char16_t *p_cstr) { + copy_from(p_cstr); + return *this; +} + +const char16_t *Char16String::get_data() const { if (size()) { return &operator[](0); } else { - return ""; + return u""; } } +void Char16String::copy_from(const char16_t *p_cstr) { + if (!p_cstr) { + resize(0); + return; + } + + const char16_t *s = p_cstr; + for (; *s; s++) { + } + size_t len = s - p_cstr; + + if (len == 0) { + resize(0); + return; + } + + Error err = resize(++len); // include terminating null char + + ERR_FAIL_COND_MSG(err != OK, "Failed to copy char16_t string."); + + memcpy(ptrw(), p_cstr, len * sizeof(char16_t)); +} + +/*************************************************************************/ +/* CharString */ +/*************************************************************************/ + +bool CharString::operator<(const CharString &p_right) const { + if (length() == 0) { + return p_right.length() != 0; + } + + return is_str_less(get_data(), p_right.get_data()); +} + +CharString &CharString::operator+=(char p_char) { + resize(size() ? size() + 1 : 2); + set(length(), 0); + set(length() - 1, p_char); + + return *this; +} + CharString &CharString::operator=(const char *p_cstr) { copy_from(p_cstr); return *this; } +const char *CharString::get_data() const { + if (size()) { + return &operator[](0); + } else { + return ""; + } +} + void CharString::copy_from(const char *p_cstr) { if (!p_cstr) { resize(0); @@ -147,7 +205,44 @@ void CharString::copy_from(const char *p_cstr) { memcpy(ptrw(), p_cstr, len); } +/*************************************************************************/ +/* String */ +/*************************************************************************/ + +//TODO: move to TextServer +//kind of poor should be rewritten properly +String String::word_wrap(int p_chars_per_line) const { + int from = 0; + int last_space = 0; + String ret; + for (int i = 0; i < length(); i++) { + if (i - from >= p_chars_per_line) { + if (last_space == -1) { + ret += substr(from, i - from + 1) + "\n"; + } else { + ret += substr(from, last_space - from) + "\n"; + i = last_space; //rewind + } + from = i + 1; + last_space = -1; + } else if (operator[](i) == ' ' || operator[](i) == '\t') { + last_space = i; + } else if (operator[](i) == '\n') { + ret += substr(from, i - from) + "\n"; + from = i + 1; + last_space = -1; + } + } + + if (from < length()) { + ret += substr(from, length()); + } + + return ret; +} + void String::copy_from(const char *p_cstr) { + // copy Latin-1 encoded c-string directly if (!p_cstr) { resize(0); return; @@ -166,21 +261,22 @@ void String::copy_from(const char *p_cstr) { resize(len + 1); // include 0 - CharType *dst = this->ptrw(); + char32_t *dst = this->ptrw(); for (int i = 0; i < len + 1; i++) { dst[i] = p_cstr[i]; } } -void String::copy_from(const CharType *p_cstr, const int p_clip_to) { +void String::copy_from(const char *p_cstr, const int p_clip_to) { + // copy Latin-1 encoded c-string directly if (!p_cstr) { resize(0); return; } int len = 0; - const CharType *ptr = p_cstr; + const char *ptr = p_cstr; while ((p_clip_to < 0 || len < p_clip_to) && *(ptr++) != 0) { len++; } @@ -190,55 +286,117 @@ void String::copy_from(const CharType *p_cstr, const int p_clip_to) { return; } - copy_from_unchecked(p_cstr, len); -} - -// assumes the following have already been validated: -// p_char != nullptr -// p_length > 0 -// p_length <= p_char strlen -void String::copy_from_unchecked(const CharType *p_char, const int p_length) { - resize(p_length + 1); - set(p_length, 0); + resize(len + 1); // include 0 - CharType *dst = ptrw(); + char32_t *dst = this->ptrw(); - for (int i = 0; i < p_length; i++) { - dst[i] = p_char[i]; + for (int i = 0; i < len; i++) { + dst[i] = p_cstr[i]; } + dst[len] = 0; } -void String::copy_from(const CharType &p_char) { +void String::copy_from(const wchar_t *p_cstr) { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit, parse as UTF-16 + parse_utf16((const char16_t *)p_cstr); +#else + // wchar_t is 32-bit, copy directly + copy_from((const char32_t *)p_cstr); +#endif +} + +void String::copy_from(const wchar_t *p_cstr, const int p_clip_to) { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit, parse as UTF-16 + parse_utf16((const char16_t *)p_cstr, p_clip_to); +#else + // wchar_t is 32-bit, copy directly + copy_from((const char32_t *)p_cstr, p_clip_to); +#endif +} + +void String::copy_from(const char32_t &p_char) { resize(2); - set(0, p_char); + if ((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff)) { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(p_char, 16) + "."); + set(0, 0xfffd); + } else { + set(0, p_char); + } set(1, 0); } -bool String::operator==(const String &p_str) const { - if (length() != p_str.length()) { - return false; +void String::copy_from(const char32_t *p_cstr) { + if (!p_cstr) { + resize(0); + return; } - if (empty()) { - return true; + + int len = 0; + const char32_t *ptr = p_cstr; + while (*(ptr++) != 0) { + len++; } - int l = length(); + if (len == 0) { + resize(0); + return; + } - const CharType *src = c_str(); - const CharType *dst = p_str.c_str(); + copy_from_unchecked(p_cstr, len); +} - /* Compare char by char */ - for (int i = 0; i < l; i++) { - if (src[i] != dst[i]) { - return false; +void String::copy_from(const char32_t *p_cstr, const int p_clip_to) { + if (!p_cstr) { + resize(0); + return; + } + + int len = 0; + const char32_t *ptr = p_cstr; + while ((p_clip_to < 0 || len < p_clip_to) && *(ptr++) != 0) { + len++; + } + + if (len == 0) { + resize(0); + return; + } + + copy_from_unchecked(p_cstr, len); +} + +// assumes the following have already been validated: +// p_char != nullptr +// p_length > 0 +// p_length <= p_char strlen +void String::copy_from_unchecked(const char32_t *p_char, const int p_length) { + resize(p_length + 1); + set(p_length, 0); + + char32_t *dst = ptrw(); + + for (int i = 0; i < p_length; i++) { + if ((p_char[i] >= 0xd800 && p_char[i] <= 0xdfff) || (p_char[i] > 0x10ffff)) { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(p_char[i], 16) + "."); + dst[i] = 0xfffd; + } else { + dst[i] = p_char[i]; } } +} - return true; +void String::operator=(const char *p_str) { + copy_from(p_str); } -bool String::operator!=(const String &p_str) const { - return !(*this == p_str); +void String::operator=(const char32_t *p_str) { + copy_from(p_str); +} + +void String::operator=(const wchar_t *p_str) { + copy_from(p_str); } String String::operator+(const String &p_str) const { @@ -247,6 +405,28 @@ String String::operator+(const String &p_str) const { return res; } +String operator+(const char *p_chr, const String &p_str) { + String tmp = p_chr; + tmp += p_str; + return tmp; +} + +String operator+(const wchar_t *p_chr, const String &p_str) { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit + String tmp = String::utf16((const char16_t *)p_chr); +#else + // wchar_t is 32-bi + String tmp = (const char32_t *)p_chr; +#endif + tmp += p_str; + return tmp; +} + +String operator+(char32_t p_chr, const String &p_str) { + return (String::chr(p_chr) + p_str); +} + String &String::operator+=(const String &p_str) { if (empty()) { *this = p_str; @@ -261,8 +441,8 @@ String &String::operator+=(const String &p_str) { resize(length() + p_str.size()); - const CharType *src = p_str.c_str(); - CharType *dst = ptrw(); + const char32_t *src = p_str.get_data(); + char32_t *dst = ptrw(); set(length(), 0); @@ -273,19 +453,6 @@ String &String::operator+=(const String &p_str) { return *this; } -String &String::operator+=(const CharType *p_str) { - *this += String(p_str); - return *this; -} - -String &String::operator+=(CharType p_char) { - resize(size() ? size() + 1 : 2); - set(length(), 0); - set(length() - 1, p_char); - - return *this; -} - String &String::operator+=(const char *p_str) { if (!p_str || p_str[0] == 0) { return *this; @@ -301,7 +468,7 @@ String &String::operator+=(const char *p_str) { resize(from + src_len + 1); - CharType *dst = ptrw(); + char32_t *dst = ptrw(); set(length(), 0); @@ -312,16 +479,43 @@ String &String::operator+=(const char *p_str) { return *this; } -void String::operator=(const char *p_str) { - copy_from(p_str); +String &String::operator+=(const wchar_t *p_str) { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit + *this += String::utf16((const char16_t *)p_str); +#else + // wchar_t is 32-bit + *this += String((const char32_t *)p_str); +#endif + return *this; } -void String::operator=(const CharType *p_str) { - copy_from(p_str); +String &String::operator+=(const char32_t *p_str) { + *this += String(p_str); + return *this; } -bool String::operator==(const StrRange &p_str_range) const { - int len = p_str_range.len; +String &String::operator+=(char32_t p_char) { + resize(size() ? size() + 1 : 2); + set(length(), 0); + if ((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff)) { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(p_char, 16) + "."); + set(length() - 1, 0xfffd); + } else { + set(length() - 1, p_char); + } + + return *this; +} + +bool String::operator==(const char *p_str) const { + // compare Latin-1 encoded c-string + int len = 0; + const char *aux = p_str; + + while (*(aux++) != 0) { + len++; + } if (length() != len) { return false; @@ -330,12 +524,13 @@ bool String::operator==(const StrRange &p_str_range) const { return true; } - const CharType *c_str = p_str_range.c_str; - const CharType *dst = &operator[](0); + int l = length(); - /* Compare char by char */ - for (int i = 0; i < len; i++) { - if (c_str[i] != dst[i]) { + const char32_t *dst = get_data(); + + // Compare char by char + for (int i = 0; i < l; i++) { + if ((char32_t)p_str[i] != dst[i]) { return false; } } @@ -343,9 +538,19 @@ bool String::operator==(const StrRange &p_str_range) const { return true; } -bool String::operator==(const char *p_str) const { +bool String::operator==(const wchar_t *p_str) const { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit, parse as UTF-16 + return *this == String::utf16((const char16_t *)p_str); +#else + // wchar_t is 32-bit, compare char by char + return *this == (const char32_t *)p_str; +#endif +} + +bool String::operator==(const char32_t *p_str) const { int len = 0; - const char *aux = p_str; + const char32_t *aux = p_str; while (*(aux++) != 0) { len++; @@ -360,7 +565,7 @@ bool String::operator==(const char *p_str) const { int l = length(); - const CharType *dst = c_str(); + const char32_t *dst = get_data(); /* Compare char by char */ for (int i = 0; i < l; i++) { @@ -372,14 +577,32 @@ bool String::operator==(const char *p_str) const { return true; } -bool String::operator==(const CharType *p_str) const { - int len = 0; - const CharType *aux = p_str; +bool String::operator==(const String &p_str) const { + if (length() != p_str.length()) { + return false; + } + if (empty()) { + return true; + } - while (*(aux++) != 0) { - len++; + int l = length(); + + const char32_t *src = get_data(); + const char32_t *dst = p_str.get_data(); + + /* Compare char by char */ + for (int i = 0; i < l; i++) { + if (src[i] != dst[i]) { + return false; + } } + return true; +} + +bool String::operator==(const StrRange &p_str_range) const { + int len = p_str_range.len; + if (length() != len) { return false; } @@ -387,13 +610,12 @@ bool String::operator==(const CharType *p_str) const { return true; } - int l = length(); - - const CharType *dst = c_str(); + const char32_t *c_str = p_str_range.c_str; + const char32_t *dst = &operator[](0); /* Compare char by char */ - for (int i = 0; i < l; i++) { - if (p_str[i] != dst[i]) { + for (int i = 0; i < len; i++) { + if (c_str[i] != dst[i]) { return false; } } @@ -401,30 +623,68 @@ bool String::operator==(const CharType *p_str) const { return true; } +bool operator==(const char *p_chr, const String &p_str) { + return p_str == p_chr; +} + +bool operator==(const wchar_t *p_chr, const String &p_str) { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit + return p_str == String::utf16((const char16_t *)p_chr); +#else + // wchar_t is 32-bi + return p_str == String((const char32_t *)p_chr); +#endif +} + bool String::operator!=(const char *p_str) const { return (!(*this == p_str)); } -bool String::operator!=(const CharType *p_str) const { +bool String::operator!=(const wchar_t *p_str) const { return (!(*this == p_str)); } -bool String::operator<(const CharType *p_str) const { +bool String::operator!=(const char32_t *p_str) const { + return (!(*this == p_str)); +} + +bool String::operator!=(const String &p_str) const { + return !((*this == p_str)); +} + +bool String::operator<=(const String &p_str) const { + return (*this < p_str) || (*this == p_str); +} + +bool String::operator<(const char *p_str) const { if (empty() && p_str[0] == 0) { return false; } if (empty()) { return true; } - - return is_str_less(c_str(), p_str); + return is_str_less(get_data(), p_str); } -bool String::operator<=(const String &p_str) const { - return (*this < p_str) || (*this == p_str); +bool String::operator<(const wchar_t *p_str) const { + if (empty() && p_str[0] == 0) { + return false; + } + if (empty()) { + return true; + } + +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit + return is_str_less(get_data(), String::utf16((const char16_t *)p_str).get_data()); +#else + // wchar_t is 32-bit + return is_str_less(get_data(), (const char32_t *)p_str); +#endif } -bool String::operator<(const char *p_str) const { +bool String::operator<(const char32_t *p_str) const { if (empty() && p_str[0] == 0) { return false; } @@ -432,11 +692,11 @@ bool String::operator<(const char *p_str) const { return true; } - return is_str_less(c_str(), p_str); + return is_str_less(get_data(), p_str); } bool String::operator<(const String &p_str) const { - return operator<(p_str.c_str()); + return operator<(p_str.get_data()); } signed char String::nocasecmp_to(const String &p_str) const { @@ -450,8 +710,8 @@ signed char String::nocasecmp_to(const String &p_str) const { return 1; } - const CharType *that_str = p_str.c_str(); - const CharType *this_str = c_str(); + const char32_t *that_str = p_str.get_data(); + const char32_t *this_str = get_data(); while (true) { if (*that_str == 0 && *this_str == 0) { @@ -482,8 +742,8 @@ signed char String::casecmp_to(const String &p_str) const { return 1; } - const CharType *that_str = p_str.c_str(); - const CharType *this_str = c_str(); + const char32_t *that_str = p_str.get_data(); + const char32_t *this_str = get_data(); while (true) { if (*that_str == 0 && *this_str == 0) { @@ -504,8 +764,8 @@ signed char String::casecmp_to(const String &p_str) const { } signed char String::naturalnocasecmp_to(const String &p_str) const { - const CharType *this_str = c_str(); - const CharType *that_str = p_str.c_str(); + const char32_t *this_str = get_data(); + const char32_t *that_str = p_str.get_data(); if (this_str && that_str) { while (*this_str == '.' || *that_str == '.') { @@ -571,6 +831,11 @@ signed char String::naturalnocasecmp_to(const String &p_str) const { return 0; } +const char32_t *String::get_data() const { + static const char32_t zero = 0; + return size() ? &operator[](0) : &zero; +} + void String::erase(int p_pos, int p_chars) { *this = left(p_pos) + substr(p_pos + p_chars, length() - ((p_pos + p_chars))); } @@ -593,7 +858,7 @@ String String::capitalize() const { } String String::camelcase_to_underscore(bool lowercase) const { - const CharType *cstr = c_str(); + const char32_t *cstr = get_data(); String new_string; const char A = 'A', Z = 'Z'; const char a = 'a', z = 'z'; @@ -705,7 +970,7 @@ String String::get_slice(String p_splitter, int p_slice) const { return ""; //no find! } -String String::get_slicec(CharType p_splitter, int p_slice) const { +String String::get_slicec(char32_t p_splitter, int p_slice) const { if (empty()) { return String(); } @@ -714,7 +979,7 @@ String String::get_slicec(CharType p_splitter, int p_slice) const { return String(); } - const CharType *c = this->ptr(); + const char32_t *c = this->ptr(); int i = 0; int prev = 0; int count = 0; @@ -851,7 +1116,7 @@ Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) end = len; } if (p_allow_empty || (end > from)) { - ret.push_back(String::to_float(&c_str()[from])); + ret.push_back(String::to_float(&get_data()[from])); } if (end == len) { @@ -880,7 +1145,7 @@ Vector<float> String::split_floats_mk(const Vector<String> &p_splitters, bool p_ } if (p_allow_empty || (end > from)) { - ret.push_back(String::to_float(&c_str()[from])); + ret.push_back(String::to_float(&get_data()[from])); } if (end == len) { @@ -904,7 +1169,7 @@ Vector<int> String::split_ints(const String &p_splitter, bool p_allow_empty) con end = len; } if (p_allow_empty || (end > from)) { - ret.push_back(String::to_int(&c_str()[from], end - from)); + ret.push_back(String::to_int(&get_data()[from], end - from)); } if (end == len) { @@ -933,7 +1198,7 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo } if (p_allow_empty || (end > from)) { - ret.push_back(String::to_int(&c_str()[from], end - from)); + ret.push_back(String::to_int(&get_data()[from], end - from)); } if (end == len) { @@ -946,7 +1211,7 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo return ret; } -String String::join(Vector<String> parts) { +String String::join(Vector<String> parts) const { String ret; for (int i = 0; i < parts.size(); ++i) { if (i > 0) { @@ -957,11 +1222,11 @@ String String::join(Vector<String> parts) { return ret; } -CharType String::char_uppercase(CharType p_char) { +char32_t String::char_uppercase(char32_t p_char) { return _find_upper(p_char); } -CharType String::char_lowercase(CharType p_char) { +char32_t String::char_lowercase(char32_t p_char) { return _find_lower(p_char); } @@ -969,8 +1234,8 @@ String String::to_upper() const { String upper = *this; for (int i = 0; i < upper.size(); i++) { - const CharType s = upper[i]; - const CharType t = _find_upper(s); + const char32_t s = upper[i]; + const char32_t t = _find_upper(s); if (s != t) { // avoid copy on write upper[i] = t; } @@ -983,8 +1248,8 @@ String String::to_lower() const { String lower = *this; for (int i = 0; i < lower.size(); i++) { - const CharType s = lower[i]; - const CharType t = _find_lower(s); + const char32_t s = lower[i]; + const char32_t t = _find_lower(s); if (s != t) { // avoid copy on write lower[i] = t; } @@ -993,34 +1258,8 @@ String String::to_lower() const { return lower; } -const CharType *String::c_str() const { - static const CharType zero = 0; - - return size() ? &operator[](0) : &zero; -} - -String String::md5(const uint8_t *p_md5) { - return String::hex_encode_buffer(p_md5, 16); -} - -String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) { - static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - - String ret; - char v[2] = { 0, 0 }; - - for (int i = 0; i < p_len; i++) { - v[0] = hex[p_buffer[i] >> 4]; - ret += v; - v[0] = hex[p_buffer[i] & 0xF]; - ret += v; - } - - return ret; -} - -String String::chr(CharType p_char) { - CharType c[2] = { p_char, 0 }; +String String::chr(char32_t p_char) { + char32_t c[2] = { p_char, 0 }; return String(c); } @@ -1028,6 +1267,14 @@ String String::num(double p_num, int p_decimals) { if (Math::is_nan(p_num)) { return "nan"; } + + if (Math::is_inf(p_num)) { + if (signbit(p_num)) { + return "-inf"; + } else { + return "inf"; + } + } #ifndef NO_USE_STDLIB if (p_decimals > 16) { @@ -1106,7 +1353,7 @@ String String::num(double p_num, int p_decimals) { /* decimal part */ if (p_decimals > 0 || (p_decimals == -1 && (int)p_num != p_num)) { - double dec = p_num - (float)((int)p_num); + double dec = p_num - (double)((int)p_num); int digit = 0; if (p_decimals > MAX_DIGITS) @@ -1125,7 +1372,7 @@ String String::num(double p_num, int p_decimals) { if (digit == MAX_DIGITS) //no point in going to infinite break; - if ((dec - (float)((int)dec)) < 1e-6) + if ((dec - (double)((int)dec)) < 1e-6) break; } @@ -1159,7 +1406,7 @@ String String::num(double p_num, int p_decimals) { s = "0"; else { while (intn) { - CharType num = '0' + (intn % 10); + char32_t num = '0' + (intn % 10); intn /= 10; s = num + s; } @@ -1188,7 +1435,7 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { } String s; s.resize(chars + 1); - CharType *c = s.ptrw(); + char32_t *c = s.ptrw(); c[chars] = 0; n = p_num; do { @@ -1221,7 +1468,7 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { String s; s.resize(chars + 1); - CharType *c = s.ptrw(); + char32_t *c = s.ptrw(); c[chars] = 0; n = p_num; do { @@ -1240,6 +1487,18 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) { } String String::num_real(double p_num) { + if (Math::is_nan(p_num)) { + return "nan"; + } + + if (Math::is_inf(p_num)) { + if (signbit(p_num)) { + return "-inf"; + } else { + return "inf"; + } + } + String s; String sd; /* integer part */ @@ -1251,7 +1510,7 @@ String String::num_real(double p_num) { /* decimal part */ if ((int)p_num != p_num) { - double dec = p_num - (float)((int)p_num); + double dec = p_num - (double)((int)p_num); int digit = 0; int decimals = MAX_DIGITS; @@ -1265,7 +1524,7 @@ String String::num_real(double p_num) { dec_max = dec_max * 10 + 9; digit++; - if ((dec - (float)((int)dec)) < 1e-6) { + if ((dec - (double)((int)dec)) < 1e-6) { break; } @@ -1302,7 +1561,7 @@ String String::num_real(double p_num) { s = "0"; } else { while (intn) { - CharType num = '0' + (intn % 10); + char32_t num = '0' + (intn % 10); intn /= 10; s = num + s; } @@ -1319,6 +1578,14 @@ String String::num_scientific(double p_num) { if (Math::is_nan(p_num)) { return "nan"; } + + if (Math::is_inf(p_num)) { + if (signbit(p_num)) { + return "-inf"; + } else { + return "inf"; + } + } #ifndef NO_USE_STDLIB char buf[256]; @@ -1348,6 +1615,26 @@ String String::num_scientific(double p_num) { #endif } +String String::md5(const uint8_t *p_md5) { + return String::hex_encode_buffer(p_md5, 16); +} + +String String::hex_encode_buffer(const uint8_t *p_buffer, int p_len) { + static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + String ret; + char v[2] = { 0, 0 }; + + for (int i = 0; i < p_len; i++) { + v[0] = hex[p_buffer[i] >> 4]; + ret += v; + v[0] = hex[p_buffer[i] & 0xF]; + ret += v; + } + + return ret; +} + CharString String::ascii(bool p_allow_extended) const { if (!length()) { return CharString(); @@ -1357,7 +1644,13 @@ CharString String::ascii(bool p_allow_extended) const { cs.resize(size()); for (int i = 0; i < size(); i++) { - cs[i] = operator[](i); + char32_t c = operator[](i); + if ((c <= 0x7f) || (c <= 0xff && p_allow_extended)) { + cs[i] = c; + } else { + print_error("Unicode parsing error: Cannot represent " + num_int64(c, 16) + " as ASCII/Latin-1 character."); + cs[i] = 0x20; + } } return cs; @@ -1371,7 +1664,7 @@ String String::utf8(const char *p_utf8, int p_len) { } bool String::parse_utf8(const char *p_utf8, int p_len) { -#define _UNICERROR(m_err) print_line("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?"); +#define _UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-8?"); if (!p_utf8) { return true; @@ -1384,9 +1677,9 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { /* HANDLE BOM (Byte Order Mark) */ if (p_len < 0 || p_len >= 3) { - bool has_bom = uint8_t(p_utf8[0]) == 0xEF && uint8_t(p_utf8[1]) == 0xBB && uint8_t(p_utf8[2]) == 0xBF; + bool has_bom = uint8_t(p_utf8[0]) == 0xef && uint8_t(p_utf8[1]) == 0xbb && uint8_t(p_utf8[2]) == 0xbf; if (has_bom) { - //just skip it + //8-bit encoding, byte order has no meaning in UTF-8, just skip it if (p_len >= 0) { p_len -= 3; } @@ -1405,24 +1698,19 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { /* Determine the number of characters in sequence */ if ((c & 0x80) == 0) { skip = 0; - } else if ((c & 0xE0) == 0xC0) { + } else if ((c & 0xe0) == 0xc0) { skip = 1; - } else if ((c & 0xF0) == 0xE0) { + } else if ((c & 0xf0) == 0xe0) { skip = 2; - } else if ((c & 0xF8) == 0xF0) { + } else if ((c & 0xf8) == 0xf0) { skip = 3; - } else if ((c & 0xFC) == 0xF8) { - skip = 4; - } else if ((c & 0xFE) == 0xFC) { - skip = 5; } else { - _UNICERROR("invalid skip"); + _UNICERROR("invalid skip at " + num_int64(cstr_size)); return true; //invalid utf8 } - if (skip == 1 && (c & 0x1E) == 0) { - //printf("overlong rejected\n"); - _UNICERROR("overlong rejected"); + if (skip == 1 && (c & 0x1e) == 0) { + _UNICERROR("overlong rejected at " + num_int64(cstr_size)); return true; //reject overlong } @@ -1448,7 +1736,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } resize(str_size + 1); - CharType *dst = ptrw(); + char32_t *dst = ptrw(); dst[str_size] = 0; while (cstr_size) { @@ -1457,19 +1745,14 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { /* Determine the number of characters in sequence */ if ((*p_utf8 & 0x80) == 0) { len = 1; - } else if ((*p_utf8 & 0xE0) == 0xC0) { + } else if ((*p_utf8 & 0xe0) == 0xc0) { len = 2; - } else if ((*p_utf8 & 0xF0) == 0xE0) { + } else if ((*p_utf8 & 0xf0) == 0xe0) { len = 3; - } else if ((*p_utf8 & 0xF8) == 0xF0) { + } else if ((*p_utf8 & 0xf8) == 0xf0) { len = 4; - } else if ((*p_utf8 & 0xFC) == 0xF8) { - len = 5; - } else if ((*p_utf8 & 0xFE) == 0xFC) { - len = 6; } else { _UNICERROR("invalid len"); - return true; //invalid UTF8 } @@ -1479,7 +1762,6 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } if (len == 2 && (*p_utf8 & 0x1E) == 0) { - //printf("overlong rejected\n"); _UNICERROR("no space left"); return true; //reject overlong } @@ -1491,24 +1773,23 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { if (len == 1) { unichar = *p_utf8; } else { - unichar = (0xFF >> (len + 1)) & *p_utf8; + unichar = (0xff >> (len + 1)) & *p_utf8; for (int i = 1; i < len; i++) { - if ((p_utf8[i] & 0xC0) != 0x80) { + if ((p_utf8[i] & 0xc0) != 0x80) { _UNICERROR("invalid utf8"); return true; //invalid utf8 } - if (unichar == 0 && i == 2 && ((p_utf8[i] & 0x7F) >> (7 - len)) == 0) { + if (unichar == 0 && i == 2 && ((p_utf8[i] & 0x7f) >> (7 - len)) == 0) { _UNICERROR("invalid utf8 overlong"); return true; //no overlong } - unichar = (unichar << 6) | (p_utf8[i] & 0x3F); + unichar = (unichar << 6) | (p_utf8[i] & 0x3f); } } - - //printf("char %i, len %i\n",unichar,len); - if (sizeof(wchar_t) == 2 && unichar > 0xFFFF) { - unichar = ' '; //too long for windows + if (unichar >= 0xd800 && unichar <= 0xdfff) { + _UNICERROR("invalid code point"); + return CharString(); } *(dst++) = unichar; @@ -1517,6 +1798,7 @@ bool String::parse_utf8(const char *p_utf8, int p_len) { } return false; +#undef _UNICERROR } CharString String::utf8() const { @@ -1525,7 +1807,7 @@ CharString String::utf8() const { return CharString(); } - const CharType *d = &operator[](0); + const char32_t *d = &operator[](0); int fl = 0; for (int i = 0; i < l; i++) { uint32_t c = d[i]; @@ -1535,13 +1817,15 @@ CharString String::utf8() const { fl += 2; } else if (c <= 0xffff) { // 16 bits fl += 3; - } else if (c <= 0x001fffff) { // 21 bits + } else if (c <= 0x0010ffff) { // 21 bits fl += 4; - - } else if (c <= 0x03ffffff) { // 26 bits - fl += 5; - } else if (c <= 0x7fffffff) { // 31 bits - fl += 6; + } else { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + "."); + return CharString(); + } + if (c >= 0xd800 && c <= 0xdfff) { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + "."); + return CharString(); } } @@ -1561,35 +1845,17 @@ CharString String::utf8() const { if (c <= 0x7f) { // 7 bits. APPEND_CHAR(c); } else if (c <= 0x7ff) { // 11 bits - APPEND_CHAR(uint32_t(0xc0 | ((c >> 6) & 0x1f))); // Top 5 bits. APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits. } else if (c <= 0xffff) { // 16 bits - APPEND_CHAR(uint32_t(0xe0 | ((c >> 12) & 0x0f))); // Top 4 bits. APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Middle 6 bits. APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits. - } else if (c <= 0x001fffff) { // 21 bits - + } else { // 21 bits APPEND_CHAR(uint32_t(0xf0 | ((c >> 18) & 0x07))); // Top 3 bits. APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // Upper middle 6 bits. APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower middle 6 bits. APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits. - } else if (c <= 0x03ffffff) { // 26 bits - - APPEND_CHAR(uint32_t(0xf8 | ((c >> 24) & 0x03))); // Top 2 bits. - APPEND_CHAR(uint32_t(0x80 | ((c >> 18) & 0x3f))); // Upper middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits. - } else if (c <= 0x7fffffff) { // 31 bits - - APPEND_CHAR(uint32_t(0xfc | ((c >> 30) & 0x01))); // Top 1 bit. - APPEND_CHAR(uint32_t(0x80 | ((c >> 24) & 0x3f))); // Upper upper middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | ((c >> 18) & 0x3f))); // Lower upper middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | ((c >> 12) & 0x3f))); // Upper lower middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | ((c >> 6) & 0x3f))); // Lower lower middle 6 bits. - APPEND_CHAR(uint32_t(0x80 | (c & 0x3f))); // Bottom 6 bits. } } #undef APPEND_CHAR @@ -1598,21 +1864,191 @@ CharString String::utf8() const { return utf8s; } -/* -String::String(CharType p_char) { +String String::utf16(const char16_t *p_utf16, int p_len) { + String ret; + ret.parse_utf16(p_utf16, p_len); + + return ret; +} + +bool String::parse_utf16(const char16_t *p_utf16, int p_len) { +#define _UNICERROR(m_err) print_error("Unicode parsing error: " + String(m_err) + ". Is the string valid UTF-16?"); + + if (!p_utf16) { + return true; + } + + String aux; + + int cstr_size = 0; + int str_size = 0; + + /* HANDLE BOM (Byte Order Mark) */ + bool byteswap = false; // assume correct endianness if no BOM found + if (p_len < 0 || p_len >= 1) { + bool has_bom = false; + if (uint16_t(p_utf16[0]) == 0xfeff) { // correct BOM, read as is + has_bom = true; + byteswap = false; + } else if (uint16_t(p_utf16[0]) == 0xfffe) { // backwards BOM, swap bytes + has_bom = true; + byteswap = true; + } + if (has_bom) { + if (p_len >= 0) { + p_len -= 1; + } + p_utf16 += 1; + } + } + + { + const char16_t *ptrtmp = p_utf16; + const char16_t *ptrtmp_limit = &p_utf16[p_len]; + int skip = 0; + while (ptrtmp != ptrtmp_limit && *ptrtmp) { + uint32_t c = (byteswap) ? BSWAP16(*ptrtmp) : *ptrtmp; + if (skip == 0) { + if ((c & 0xfffffc00) == 0xd800) { + skip = 1; // lead surrogate + } else if ((c & 0xfffffc00) == 0xdc00) { + _UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size)); + return true; // invalid UTF16 + } else { + skip = 0; + } + str_size++; + } else { + if ((c & 0xfffffc00) == 0xdc00) { // trail surrogate + --skip; + } else { + _UNICERROR("invalid utf16 surrogate at " + num_int64(cstr_size)); + return true; // invalid UTF16 + } + } + + cstr_size++; + ptrtmp++; + } + + if (skip) { + _UNICERROR("no space left"); + return true; // not enough space + } + } + + if (str_size == 0) { + clear(); + return false; + } + + resize(str_size + 1); + char32_t *dst = ptrw(); + dst[str_size] = 0; + + while (cstr_size) { + int len = 0; + uint32_t c = (byteswap) ? BSWAP16(*p_utf16) : *p_utf16; + + if ((c & 0xfffffc00) == 0xd800) { + len = 2; + } else { + len = 1; + } + + if (len > cstr_size) { + _UNICERROR("no space left"); + return true; //not enough space + } + + uint32_t unichar = 0; + if (len == 1) { + unichar = c; + } else { + uint32_t c2 = (byteswap) ? BSWAP16(p_utf16[1]) : p_utf16[1]; + unichar = (c << 10UL) + c2 - ((0xd800 << 10UL) + 0xdc00 - 0x10000); + } + + *(dst++) = unichar; + cstr_size -= len; + p_utf16 += len; + } - shared=nullptr; - copy_from(p_char); + return false; +#undef _UNICERROR } +Char16String String::utf16() const { + int l = length(); + if (!l) { + return Char16String(); + } -*/ + const char32_t *d = &operator[](0); + int fl = 0; + for (int i = 0; i < l; i++) { + uint32_t c = d[i]; + if (c <= 0xffff) { // 16 bits. + fl += 1; + } else if (c <= 0x10ffff) { // 32 bits. + fl += 2; + } else { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + "."); + return Char16String(); + } + if (c >= 0xd800 && c <= 0xdfff) { + print_error("Unicode parsing error: Invalid unicode codepoint " + num_int64(c, 16) + "."); + return Char16String(); + } + } + + Char16String utf16s; + if (fl == 0) { + return utf16s; + } + + utf16s.resize(fl + 1); + uint16_t *cdst = (uint16_t *)utf16s.get_data(); + +#define APPEND_CHAR(m_c) *(cdst++) = m_c + + for (int i = 0; i < l; i++) { + uint32_t c = d[i]; + + if (c <= 0xffff) { // 16 bits. + APPEND_CHAR(c); + } else { // 32 bits. + APPEND_CHAR(uint32_t((c >> 10) + 0xd7c0)); // lead surrogate. + APPEND_CHAR(uint32_t((c & 0x3ff) | 0xdc00)); // trail surrogate. + } + } +#undef APPEND_CHAR + *cdst = 0; //trailing zero + + return utf16s; +} String::String(const char *p_str) { copy_from(p_str); } -String::String(const CharType *p_str, int p_clip_to_len) { +String::String(const wchar_t *p_str) { + copy_from(p_str); +} + +String::String(const char32_t *p_str) { + copy_from(p_str); +} + +String::String(const char *p_str, int p_clip_to_len) { + copy_from(p_str, p_clip_to_len); +} + +String::String(const wchar_t *p_str, int p_clip_to_len) { + copy_from(p_str, p_clip_to_len); +} + +String::String(const char32_t *p_str, int p_clip_to_len) { copy_from(p_str, p_clip_to_len); } @@ -1620,7 +2056,6 @@ String::String(const StrRange &p_range) { if (!p_range.c_str) { return; } - copy_from(p_range.c_str, p_range.len); } @@ -1629,7 +2064,7 @@ int64_t String::hex_to_int(bool p_with_prefix) const { return 0; } - const CharType *s = ptr(); + const char32_t *s = ptr(); int64_t sign = s[0] == '-' ? -1 : 1; @@ -1647,7 +2082,7 @@ int64_t String::hex_to_int(bool p_with_prefix) const { int64_t hex = 0; while (*s) { - CharType c = LOWERCASE(*s); + char32_t c = LOWERCASE(*s); int64_t n; if (c >= '0' && c <= '9') { n = c - '0'; @@ -1672,7 +2107,7 @@ int64_t String::bin_to_int(bool p_with_prefix) const { return 0; } - const CharType *s = ptr(); + const char32_t *s = ptr(); int64_t sign = s[0] == '-' ? -1 : 1; @@ -1690,7 +2125,7 @@ int64_t String::bin_to_int(bool p_with_prefix) const { int64_t binary = 0; while (*s) { - CharType c = LOWERCASE(*s); + char32_t c = LOWERCASE(*s); int64_t n; if (c == '0' || c == '1') { n = c - '0'; @@ -1719,7 +2154,7 @@ int64_t String::to_int() const { int64_t sign = 1; for (int i = 0; i < to; i++) { - CharType c = operator[](i); + char32_t c = operator[](i); if (c >= '0' && c <= '9') { bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8'))); ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); @@ -1765,6 +2200,37 @@ int64_t String::to_int(const char *p_str, int p_len) { return integer * sign; } +int64_t String::to_int(const wchar_t *p_str, int p_len) { + int to = 0; + if (p_len >= 0) { + to = p_len; + } else { + while (p_str[to] != 0 && p_str[to] != '.') { + to++; + } + } + + int64_t integer = 0; + int64_t sign = 1; + + for (int i = 0; i < to; i++) { + wchar_t c = p_str[i]; + if (c >= '0' && c <= '9') { + bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8'))); + ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + integer *= 10; + integer += c - '0'; + + } else if (c == '-' && integer == 0) { + sign = -sign; + } else if (c != ' ') { + break; + } + } + + return integer * sign; +} + bool String::is_numeric() const { if (length() == 0) { return false; @@ -1776,14 +2242,13 @@ bool String::is_numeric() const { } bool dot = false; for (int i = s; i < length(); i++) { - CharType c = operator[](i); + char32_t c = operator[](i); if (c == '.') { if (dot) { return false; } dot = true; - } - if (c < '0' || c > '9') { + } else if (c < '0' || c > '9') { return false; } } @@ -1945,11 +2410,11 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point } expSign = false; } - if (!IS_DIGIT(CharType(*p))) { + if (!IS_DIGIT(char32_t(*p))) { p = pExp; goto done; } - while (IS_DIGIT(CharType(*p))) { + while (IS_DIGIT(char32_t(*p))) { exp = exp * 10 + (*p - '0'); p += 1; } @@ -2007,19 +2472,18 @@ done: #define READING_DONE 4 double String::to_float(const char *p_str) { -#ifndef NO_USE_STDLIB - return built_in_strtod<char>(p_str); -//return atof(p_str); DOES NOT WORK ON ANDROID(??) -#else return built_in_strtod<char>(p_str); -#endif } -double String::to_float(const CharType *p_str, const CharType **r_end) { - return built_in_strtod<CharType>(p_str, (CharType **)r_end); +double String::to_float(const char32_t *p_str, const char32_t **r_end) { + return built_in_strtod<char32_t>(p_str, (char32_t **)r_end); } -int64_t String::to_int(const CharType *p_str, int p_len, bool p_clamp) { +double String::to_float(const wchar_t *p_str, const wchar_t **r_end) { + return built_in_strtod<wchar_t>(p_str, (wchar_t **)r_end); +} + +int64_t String::to_int(const char32_t *p_str, int p_len, bool p_clamp) { if (p_len == 0 || !p_str[0]) { return 0; } @@ -2029,11 +2493,11 @@ int64_t String::to_int(const CharType *p_str, int p_len, bool p_clamp) { int64_t sign = 1; int reading = READING_SIGN; - const CharType *str = p_str; - const CharType *limit = &p_str[p_len]; + const char32_t *str = p_str; + const char32_t *limit = &p_str[p_len]; while (*str && reading != READING_DONE && str != limit) { - CharType c = *(str++); + char32_t c = *(str++); switch (reading) { case READING_SIGN: { if (c >= '0' && c <= '9') { @@ -2087,26 +2551,7 @@ double String::to_float() const { if (empty()) { return 0; } -#ifndef NO_USE_STDLIB - return built_in_strtod<CharType>(c_str()); -//return wcstod(c_str(),nullptr ); DOES NOT WORK ON ANDROID :( -#else - return built_in_strtod<CharType>(c_str()); -#endif -} - -bool operator==(const char *p_chr, const String &p_str) { - return p_str == p_chr; -} - -String operator+(const char *p_chr, const String &p_str) { - String tmp = p_chr; - tmp += p_str; - return tmp; -} - -String operator+(CharType p_chr, const String &p_str) { - return (String::chr(p_chr) + p_str); + return built_in_strtod<char32_t>(get_data()); } uint32_t String::hash(const char *p_cstr) { @@ -2129,7 +2574,27 @@ uint32_t String::hash(const char *p_cstr, int p_len) { return hashv; } -uint32_t String::hash(const CharType *p_cstr, int p_len) { +uint32_t String::hash(const wchar_t *p_cstr, int p_len) { + uint32_t hashv = 5381; + for (int i = 0; i < p_len; i++) { + hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */ + } + + return hashv; +} + +uint32_t String::hash(const wchar_t *p_cstr) { + uint32_t hashv = 5381; + uint32_t c; + + while ((c = *p_cstr++)) { + hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } + + return hashv; +} + +uint32_t String::hash(const char32_t *p_cstr, int p_len) { uint32_t hashv = 5381; for (int i = 0; i < p_len; i++) { hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */ @@ -2138,7 +2603,7 @@ uint32_t String::hash(const CharType *p_cstr, int p_len) { return hashv; } -uint32_t String::hash(const CharType *p_cstr) { +uint32_t String::hash(const char32_t *p_cstr) { uint32_t hashv = 5381; uint32_t c; @@ -2152,7 +2617,7 @@ uint32_t String::hash(const CharType *p_cstr) { uint32_t String::hash() const { /* simple djb2 hashing */ - const CharType *chr = c_str(); + const char32_t *chr = get_data(); uint32_t hashv = 5381; uint32_t c; @@ -2166,7 +2631,7 @@ uint32_t String::hash() const { uint64_t String::hash64() const { /* simple djb2 hashing */ - const CharType *chr = c_str(); + const char32_t *chr = get_data(); uint64_t hashv = 5381; uint64_t c; @@ -2278,7 +2743,7 @@ String String::substr(int p_from, int p_chars) const { } String s = String(); - s.copy_from_unchecked(&c_str()[p_from], p_chars); + s.copy_from_unchecked(&get_data()[p_from], p_chars); return s; } @@ -2295,8 +2760,8 @@ int String::find(const String &p_str, int p_from) const { return -1; // won't find anything! } - const CharType *src = c_str(); - const CharType *str = p_str.c_str(); + const char32_t *src = get_data(); + const char32_t *str = p_str.get_data(); for (int i = p_from; i <= (len - src_len); i++) { bool found = true; @@ -2333,7 +2798,7 @@ int String::find(const char *p_str, int p_from) const { return -1; // won't find anything! } - const CharType *src = c_str(); + const char32_t *src = get_data(); int src_len = 0; while (p_str[src_len] != '\0') { @@ -2341,7 +2806,7 @@ int String::find(const char *p_str, int p_from) const { } if (src_len == 1) { - const char needle = p_str[0]; + const char32_t needle = p_str[0]; for (int i = p_from; i < len; i++) { if (src[i] == needle) { @@ -2360,7 +2825,7 @@ int String::find(const char *p_str, int p_from) const { return -1; } - if (src[read_pos] != p_str[j]) { + if (src[read_pos] != (char32_t)p_str[j]) { found = false; break; } @@ -2375,7 +2840,7 @@ int String::find(const char *p_str, int p_from) const { return -1; } -int String::find_char(const CharType &p_char, int p_from) const { +int String::find_char(const char32_t &p_char, int p_from) const { return _cowdata.find(p_char, p_from); } @@ -2396,7 +2861,7 @@ int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const { return -1; // won't find anything! } - const CharType *src = c_str(); + const char32_t *src = get_data(); for (int i = p_from; i < len; i++) { bool found = true; @@ -2405,7 +2870,7 @@ int String::findmk(const Vector<String> &p_keys, int p_from, int *r_key) const { if (r_key) { *r_key = k; } - const CharType *cmp = keys[k].c_str(); + const char32_t *cmp = keys[k].get_data(); int l = keys[k].length(); for (int j = 0; j < l; j++) { @@ -2445,7 +2910,7 @@ int String::findn(const String &p_str, int p_from) const { return -1; // won't find anything! } - const CharType *srcd = c_str(); + const char32_t *srcd = get_data(); for (int i = p_from; i <= (length() - src_len); i++) { bool found = true; @@ -2457,8 +2922,8 @@ int String::findn(const String &p_str, int p_from) const { return -1; } - CharType src = _find_lower(srcd[read_pos]); - CharType dst = _find_lower(p_str[j]); + char32_t src = _find_lower(srcd[read_pos]); + char32_t dst = _find_lower(p_str[j]); if (src != dst) { found = false; @@ -2495,7 +2960,7 @@ int String::rfind(const String &p_str, int p_from) const { return -1; // won't find anything! } - const CharType *src = c_str(); + const char32_t *src = get_data(); for (int i = p_from; i >= 0; i--) { bool found = true; @@ -2542,7 +3007,7 @@ int String::rfindn(const String &p_str, int p_from) const { return -1; // won't find anything! } - const CharType *src = c_str(); + const char32_t *src = get_data(); for (int i = p_from; i >= 0; i--) { bool found = true; @@ -2554,8 +3019,8 @@ int String::rfindn(const String &p_str, int p_from) const { return -1; } - CharType srcc = _find_lower(src[read_pos]); - CharType dstc = _find_lower(p_str[j]); + char32_t srcc = _find_lower(src[read_pos]); + char32_t dstc = _find_lower(p_str[j]); if (srcc != dstc) { found = false; @@ -2589,8 +3054,8 @@ bool String::begins_with(const String &p_string) const { return true; } - const CharType *src = &p_string[0]; - const CharType *str = &operator[](0); + const char32_t *src = &p_string[0]; + const char32_t *str = &operator[](0); int i = 0; for (; i < l; i++) { @@ -2609,11 +3074,11 @@ bool String::begins_with(const char *p_string) const { return false; } - const CharType *str = &operator[](0); + const char32_t *str = &operator[](0); int i = 0; while (*p_string && i < l) { - if (*p_string != str[i]) { + if ((char32_t)*p_string != str[i]) { return false; } i++; @@ -2657,7 +3122,7 @@ int String::_count(const String &p_string, int p_from, int p_to, bool p_case_ins } if (p_from == 0 && p_to == len) { str = String(); - str.copy_from_unchecked(&c_str()[0], len); + str.copy_from_unchecked(&get_data()[0], len); } else { str = substr(p_from, p_to - p_from); } @@ -2695,14 +3160,14 @@ bool String::_base_is_subsequence_of(const String &p_string, bool case_insensiti return false; } - const CharType *src = &operator[](0); - const CharType *tgt = &p_string[0]; + const char32_t *src = &operator[](0); + const char32_t *tgt = &p_string[0]; for (; *src && *tgt; tgt++) { bool match = false; if (case_insensitive) { - CharType srcc = _find_lower(*src); - CharType tgtc = _find_lower(*tgt); + char32_t srcc = _find_lower(*src); + char32_t tgtc = _find_lower(*tgt); match = srcc == tgtc; } else { match = *src == *tgt; @@ -2748,8 +3213,8 @@ float String::similarity(const String &p_string) const { int src_size = src_bigrams.size(); int tgt_size = tgt_bigrams.size(); - float sum = src_size + tgt_size; - float inter = 0; + double sum = src_size + tgt_size; + double inter = 0; for (int i = 0; i < src_size; i++) { for (int j = 0; j < tgt_size; j++) { if (src_bigrams[i] == tgt_bigrams[j]) { @@ -2762,7 +3227,7 @@ float String::similarity(const String &p_string) const { return (2.0f * inter) / sum; } -static bool _wildcard_match(const CharType *p_pattern, const CharType *p_string, bool p_case_sensitive) { +static bool _wildcard_match(const char32_t *p_pattern, const char32_t *p_string, bool p_case_sensitive) { switch (*p_pattern) { case '\0': return !*p_string; @@ -2781,14 +3246,14 @@ bool String::match(const String &p_wildcard) const { return false; } - return _wildcard_match(p_wildcard.c_str(), c_str(), true); + return _wildcard_match(p_wildcard.get_data(), get_data(), true); } bool String::matchn(const String &p_wildcard) const { if (!p_wildcard.length() || !length()) { return false; } - return _wildcard_match(p_wildcard.c_str(), c_str(), false); + return _wildcard_match(p_wildcard.get_data(), get_data(), false); } String String::format(const Variant &values, String placeholder) const { @@ -2938,9 +3403,10 @@ String String::repeat(int p_count) const { ERR_FAIL_COND_V_MSG(p_count < 0, "", "Parameter count should be a positive number."); String new_string; - const CharType *src = this->c_str(); + const char32_t *src = this->get_data(); new_string.resize(length() * p_count + 1); + new_string[length() * p_count] = 0; for (int i = 0; i < p_count; i++) { for (int j = 0; j < length(); j++) { @@ -2975,7 +3441,7 @@ String String::right(int p_pos) const { return substr(p_pos, (length() - p_pos)); } -CharType String::ord_at(int p_idx) const { +char32_t String::ord_at(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, length(), 0); return operator[](p_idx); } @@ -2989,7 +3455,7 @@ String String::dedent() const { int indent_stop = -1; for (int i = 0; i < length(); i++) { - CharType c = operator[](i); + char32_t c = operator[](i); if (c == '\n') { if (has_text) { new_string += substr(indent_stop, i - indent_stop); @@ -3218,7 +3684,7 @@ bool String::is_valid_identifier() const { return false; } - const wchar_t *str = &operator[](0); + const char32_t *str = &operator[](0); for (int i = 0; i < len; i++) { if (i == 0) { @@ -3237,36 +3703,14 @@ bool String::is_valid_identifier() const { return true; } -//kind of poor should be rewritten properly - -String String::word_wrap(int p_chars_per_line) const { - int from = 0; - int last_space = 0; - String ret; - for (int i = 0; i < length(); i++) { - if (i - from >= p_chars_per_line) { - if (last_space == -1) { - ret += substr(from, i - from + 1) + "\n"; - } else { - ret += substr(from, last_space - from) + "\n"; - i = last_space; //rewind - } - from = i + 1; - last_space = -1; - } else if (operator[](i) == ' ' || operator[](i) == '\t') { - last_space = i; - } else if (operator[](i) == '\n') { - ret += substr(from, i - from) + "\n"; - from = i + 1; - last_space = -1; - } - } - - if (from < length()) { - ret += substr(from, length()); +bool String::is_valid_string() const { + int l = length(); + const char32_t *src = get_data(); + bool valid = true; + for (int i = 0; i < l; i++) { + valid = valid && (src[i] < 0xd800 || (src[i] > 0xdfff && src[i] <= 0x10ffff)); } - - return ret; + return valid; } String String::http_escape() const { @@ -3297,9 +3741,9 @@ String String::http_unescape() const { String res; for (int i = 0; i < length(); ++i) { if (ord_at(i) == '%' && i + 2 < length()) { - CharType ord1 = ord_at(i + 1); + char32_t ord1 = ord_at(i + 1); if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) { - CharType ord2 = ord_at(i + 2); + char32_t ord2 = ord_at(i + 2); if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) { char bytes[3] = { (char)ord1, (char)ord2, 0 }; res += (char)strtol(bytes, nullptr, 16); @@ -3389,18 +3833,18 @@ for (int i=1;i<32;i++) { return str; } -static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src, int p_src_len, CharType *p_dst) { +static _FORCE_INLINE_ int _xml_unescape(const char32_t *p_src, int p_src_len, char32_t *p_dst) { int len = 0; while (p_src_len) { if (*p_src == '&') { int eat = 0; if (p_src_len >= 4 && p_src[1] == '#') { - CharType c = 0; + char32_t c = 0; for (int i = 2; i < p_src_len; i++) { eat = i + 1; - CharType ct = p_src[i]; + char32_t ct = p_src[i]; if (ct == ';') { break; } else if (ct >= '0' && ct <= '9') { @@ -3476,12 +3920,12 @@ static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src, int p_src_len, Ch String String::xml_unescape() const { String str; int l = length(); - int len = _xml_unescape(c_str(), l, nullptr); + int len = _xml_unescape(get_data(), l, nullptr); if (len == 0) { return String(); } str.resize(len + 1); - _xml_unescape(c_str(), l, str.ptrw()); + _xml_unescape(get_data(), l, str.ptrw()); str[len] = 0; return str; } @@ -3602,7 +4046,7 @@ bool String::is_valid_hex_number(bool p_with_prefix) const { } for (int i = from; i < len; i++) { - CharType c = operator[](i); + char32_t c = operator[](i); if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { continue; } @@ -3917,7 +4361,7 @@ String String::percent_decode() const { String String::property_name_encode() const { // Escape and quote strings with extended ASCII or further Unicode characters // as well as '"', '=' or ' ' (32) - const CharType *cstr = c_str(); + const char32_t *cstr = get_data(); for (int i = 0; cstr[i]; i++) { if (cstr[i] == '=' || cstr[i] == '"' || cstr[i] < 33 || cstr[i] > 126) { return "\"" + c_escape_multiline() + "\""; @@ -3984,7 +4428,7 @@ String String::lpad(int min_length, const String &character) const { // In case of an error, the string returned is the error description and "error" is true. String String::sprintf(const Array &values, bool *error) const { String formatted; - CharType *self = (CharType *)c_str(); + char32_t *self = (char32_t *)get_data(); bool in_format = false; int value_index = 0; int min_chars = 0; @@ -3997,7 +4441,7 @@ String String::sprintf(const Array &values, bool *error) const { *error = true; for (; *self; self++) { - const CharType c = *self; + const char32_t c = *self; if (in_format) { // We have % - lets see what else we get. switch (c) { @@ -4134,9 +4578,11 @@ String String::sprintf(const Array &values, bool *error) const { if (values[value_index].is_num()) { int value = values[value_index]; if (value < 0) { - return "unsigned byte integer is lower than maximum"; - } else if (value > 255) { - return "unsigned byte integer is greater than maximum"; + return "unsigned integer is lower than minimum"; + } else if (value >= 0xd800 && value <= 0xdfff) { + return "unsigned integer is invalid Unicode character"; + } else if (value > 0x10ffff) { + return "unsigned integer is greater than maximum"; } str = chr(values[value_index]); } else if (values[value_index].get_type() == Variant::STRING) { diff --git a/core/ustring.h b/core/ustring.h index 7a1c1a5232..1f8a5d7e7d 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -36,8 +36,13 @@ #include "core/typedefs.h" #include "core/vector.h" +/*************************************************************************/ +/* CharProxy */ +/*************************************************************************/ + template <class T> class CharProxy { + friend class Char16String; friend class CharString; friend class String; @@ -71,6 +76,54 @@ public: } }; +/*************************************************************************/ +/* Char16String */ +/*************************************************************************/ + +class Char16String { + CowData<char16_t> _cowdata; + static const char16_t _null; + +public: + _FORCE_INLINE_ char16_t *ptrw() { return _cowdata.ptrw(); } + _FORCE_INLINE_ const char16_t *ptr() const { return _cowdata.ptr(); } + _FORCE_INLINE_ int size() const { return _cowdata.size(); } + Error resize(int p_size) { return _cowdata.resize(p_size); } + + _FORCE_INLINE_ char16_t get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ void set(int p_index, const char16_t &p_elem) { _cowdata.set(p_index, p_elem); } + _FORCE_INLINE_ const char16_t &operator[](int p_index) const { + if (unlikely(p_index == _cowdata.size())) { + return _null; + } + + return _cowdata.get(p_index); + } + _FORCE_INLINE_ CharProxy<char16_t> operator[](int p_index) { return CharProxy<char16_t>(p_index, _cowdata); } + + _FORCE_INLINE_ Char16String() {} + _FORCE_INLINE_ Char16String(const Char16String &p_str) { _cowdata._ref(p_str._cowdata); } + _FORCE_INLINE_ Char16String &operator=(const Char16String &p_str) { + _cowdata._ref(p_str._cowdata); + return *this; + } + _FORCE_INLINE_ Char16String(const char16_t *p_cstr) { copy_from(p_cstr); } + + Char16String &operator=(const char16_t *p_cstr); + bool operator<(const Char16String &p_right) const; + Char16String &operator+=(char16_t p_char); + int length() const { return size() ? size() - 1 : 0; } + const char16_t *get_data() const; + operator const char16_t *() const { return get_data(); }; + +protected: + void copy_from(const char16_t *p_cstr); +}; + +/*************************************************************************/ +/* CharString */ +/*************************************************************************/ + class CharString { CowData<char> _cowdata; static const char _null; @@ -94,7 +147,7 @@ public: _FORCE_INLINE_ CharString() {} _FORCE_INLINE_ CharString(const CharString &p_str) { _cowdata._ref(p_str._cowdata); } - _FORCE_INLINE_ CharString operator=(const CharString &p_str) { + _FORCE_INLINE_ CharString &operator=(const CharString &p_str) { _cowdata._ref(p_str._cowdata); return *this; } @@ -111,26 +164,35 @@ protected: void copy_from(const char *p_cstr); }; -typedef wchar_t CharType; +/*************************************************************************/ +/* String */ +/*************************************************************************/ struct StrRange { - const CharType *c_str; + const char32_t *c_str; int len; - StrRange(const CharType *p_c_str = nullptr, int p_len = 0) { + StrRange(const char32_t *p_c_str = nullptr, int p_len = 0) { c_str = p_c_str; len = p_len; } }; class String { - CowData<CharType> _cowdata; - static const CharType _null; + CowData<char32_t> _cowdata; + static const char32_t _null; void copy_from(const char *p_cstr); - void copy_from(const CharType *p_cstr, const int p_clip_to = -1); - void copy_from(const CharType &p_char); - void copy_from_unchecked(const CharType *p_char, const int p_length); + void copy_from(const char *p_cstr, const int p_clip_to); + void copy_from(const wchar_t *p_cstr); + void copy_from(const wchar_t *p_cstr, const int p_clip_to); + void copy_from(const char32_t *p_cstr); + void copy_from(const char32_t *p_cstr, const int p_clip_to); + + void copy_from(const char32_t &p_char); + + void copy_from_unchecked(const char32_t *p_char, const int p_length); + bool _base_is_subsequence_of(const String &p_string, bool case_insensitive) const; int _count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const; @@ -140,48 +202,56 @@ public: npos = -1 ///<for "some" compatibility with std::string (npos is a huge value in std::string) }; - _FORCE_INLINE_ CharType *ptrw() { return _cowdata.ptrw(); } - _FORCE_INLINE_ const CharType *ptr() const { return _cowdata.ptr(); } + _FORCE_INLINE_ char32_t *ptrw() { return _cowdata.ptrw(); } + _FORCE_INLINE_ const char32_t *ptr() const { return _cowdata.ptr(); } void remove(int p_index) { _cowdata.remove(p_index); } _FORCE_INLINE_ void clear() { resize(0); } - _FORCE_INLINE_ CharType get(int p_index) const { return _cowdata.get(p_index); } - _FORCE_INLINE_ void set(int p_index, const CharType &p_elem) { _cowdata.set(p_index, p_elem); } + _FORCE_INLINE_ char32_t get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ void set(int p_index, const char32_t &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ int size() const { return _cowdata.size(); } Error resize(int p_size) { return _cowdata.resize(p_size); } - _FORCE_INLINE_ const CharType &operator[](int p_index) const { + _FORCE_INLINE_ const char32_t &operator[](int p_index) const { if (unlikely(p_index == _cowdata.size())) { return _null; } return _cowdata.get(p_index); } - _FORCE_INLINE_ CharProxy<CharType> operator[](int p_index) { return CharProxy<CharType>(p_index, _cowdata); } + _FORCE_INLINE_ CharProxy<char32_t> operator[](int p_index) { return CharProxy<char32_t>(p_index, _cowdata); } bool operator==(const String &p_str) const; bool operator!=(const String &p_str) const; String operator+(const String &p_str) const; - //String operator+(CharType p_char) const; String &operator+=(const String &); - String &operator+=(CharType p_char); + String &operator+=(char32_t p_char); String &operator+=(const char *p_str); - String &operator+=(const CharType *p_str); + String &operator+=(const wchar_t *p_str); + String &operator+=(const char32_t *p_str); /* Compatibility Operators */ void operator=(const char *p_str); - void operator=(const CharType *p_str); + void operator=(const wchar_t *p_str); + void operator=(const char32_t *p_str); + bool operator==(const char *p_str) const; - bool operator==(const CharType *p_str) const; + bool operator==(const wchar_t *p_str) const; + bool operator==(const char32_t *p_str) const; bool operator==(const StrRange &p_str_range) const; + bool operator!=(const char *p_str) const; - bool operator!=(const CharType *p_str) const; - bool operator<(const CharType *p_str) const; + bool operator!=(const wchar_t *p_str) const; + bool operator!=(const char32_t *p_str) const; + + bool operator<(const char32_t *p_str) const; bool operator<(const char *p_str) const; + bool operator<(const wchar_t *p_str) const; + bool operator<(const String &p_str) const; bool operator<=(const String &p_str) const; @@ -189,7 +259,7 @@ public: signed char nocasecmp_to(const String &p_str) const; signed char naturalnocasecmp_to(const String &p_str) const; - const CharType *c_str() const; + const char32_t *get_data() const; /* standard size stuff */ _FORCE_INLINE_ int length() const { @@ -197,11 +267,13 @@ public: return s ? (s - 1) : 0; // length does not include zero } + bool is_valid_string() const; + /* complex helpers */ String substr(int p_from, int p_chars = -1) const; int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed - int find_char(const CharType &p_char, int p_from = 0) const; ///< return <0 if failed + int find_char(const char32_t &p_char, int p_from = 0) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed int rfindn(const String &p_str, int p_from = -1) const; ///< return <0 if failed, case insensitive @@ -238,26 +310,31 @@ public: static String num_real(double p_num); static String num_int64(int64_t p_num, int base = 10, bool capitalize_hex = false); static String num_uint64(uint64_t p_num, int base = 10, bool capitalize_hex = false); - static String chr(CharType p_char); + static String chr(char32_t p_char); static String md5(const uint8_t *p_md5); static String hex_encode_buffer(const uint8_t *p_buffer, int p_len); bool is_numeric() const; - double to_float() const; + double to_float() const; int64_t hex_to_int(bool p_with_prefix = true) const; int64_t bin_to_int(bool p_with_prefix = true) const; int64_t to_int() const; + static int64_t to_int(const char *p_str, int p_len = -1); + static int64_t to_int(const wchar_t *p_str, int p_len = -1); + static int64_t to_int(const char32_t *p_str, int p_len = -1, bool p_clamp = false); + static double to_float(const char *p_str); - static double to_float(const CharType *p_str, const CharType **r_end = nullptr); - static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false); + static double to_float(const wchar_t *p_str, const wchar_t **r_end = nullptr); + static double to_float(const char32_t *p_str, const char32_t **r_end = nullptr); + String capitalize() const; String camelcase_to_underscore(bool lowercase = true) const; String get_with_code_lines() const; int get_slice_count(String p_splitter) const; String get_slice(String p_splitter, int p_slice) const; - String get_slicec(CharType p_splitter, int p_slice) const; + String get_slicec(char32_t p_splitter, int p_slice) const; Vector<String> split(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> rsplit(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; @@ -267,10 +344,10 @@ public: Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const; Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; - String join(Vector<String> parts); + String join(Vector<String> parts) const; - static CharType char_uppercase(CharType p_char); - static CharType char_lowercase(CharType p_char); + static char32_t char_uppercase(char32_t p_char); + static char32_t char_lowercase(char32_t p_char); String to_upper() const; String to_lower() const; @@ -287,7 +364,7 @@ public: String get_extension() const; String get_basename() const; String plus_file(const String &p_file) const; - CharType ord_at(int p_idx) const; + char32_t ord_at(int p_idx) const; void erase(int p_pos, int p_chars); @@ -296,8 +373,14 @@ public: bool parse_utf8(const char *p_utf8, int p_len = -1); //return true on error static String utf8(const char *p_utf8, int p_len = -1); - static uint32_t hash(const CharType *p_cstr, int p_len); /* hash the string */ - static uint32_t hash(const CharType *p_cstr); /* hash the string */ + Char16String utf16() const; + bool parse_utf16(const char16_t *p_utf16, int p_len = -1); //return true on error + static String utf16(const char16_t *p_utf16, int p_len = -1); + + static uint32_t hash(const char32_t *p_cstr, int p_len); /* hash the string */ + static uint32_t hash(const char32_t *p_cstr); /* hash the string */ + static uint32_t hash(const wchar_t *p_cstr, int p_len); /* hash the string */ + static uint32_t hash(const wchar_t *p_cstr); /* hash the string */ static uint32_t hash(const char *p_cstr, int p_len); /* hash the string */ static uint32_t hash(const char *p_cstr); /* hash the string */ uint32_t hash() const; /* hash the string */ @@ -348,24 +431,30 @@ public: /** * The constructors must not depend on other overloads */ - /* String(CharType p_char);*/ + /* String(char32_t p_char);*/ _FORCE_INLINE_ String() {} _FORCE_INLINE_ String(const String &p_str) { _cowdata._ref(p_str._cowdata); } - String operator=(const String &p_str) { + String &operator=(const String &p_str) { _cowdata._ref(p_str._cowdata); return *this; } String(const char *p_str); - String(const CharType *p_str, int p_clip_to_len = -1); + String(const wchar_t *p_str); + String(const char32_t *p_str); + String(const char *p_str, int p_clip_to_len); + String(const wchar_t *p_str, int p_clip_to_len); + String(const char32_t *p_str, int p_clip_to_len); String(const StrRange &p_range); }; bool operator==(const char *p_chr, const String &p_str); +bool operator==(const wchar_t *p_chr, const String &p_str); String operator+(const char *p_chr, const String &p_str); -String operator+(CharType p_chr, const String &p_str); +String operator+(const wchar_t *p_chr, const String &p_str); +String operator+(char32_t p_chr, const String &p_str); String itos(int64_t p_val); String uitos(uint64_t p_val); @@ -387,15 +476,18 @@ struct NaturalNoCaseComparator { template <typename L, typename R> _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) { while (true) { - if (*l_ptr == 0 && *r_ptr == 0) { + const char32_t l = *l_ptr; + const char32_t r = *r_ptr; + + if (l == 0 && r == 0) { return false; - } else if (*l_ptr == 0) { + } else if (l == 0) { return true; - } else if (*r_ptr == 0) { + } else if (r == 0) { return false; - } else if (*l_ptr < *r_ptr) { + } else if (l < r) { return true; - } else if (*l_ptr > *r_ptr) { + } else if (l > r) { return false; } @@ -432,7 +524,7 @@ String DTRN(const String &p_text, const String &p_text_plural, int p_n, const St String RTR(const String &p_text, const String &p_context = ""); String RTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context = ""); -bool is_symbol(CharType c); +bool is_symbol(char32_t c); bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end); #endif // USTRING_H diff --git a/core/variant.cpp b/core/variant.cpp index c19ce79e64..181ced0f32 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1558,7 +1558,7 @@ Variant::operator unsigned char() const { } } -Variant::operator CharType() const { +Variant::operator char32_t() const { return operator unsigned int(); } @@ -2445,7 +2445,7 @@ Variant::Variant(const char *const p_cstring) { memnew_placement(_data._mem, String((const char *)p_cstring)); } -Variant::Variant(const CharType *p_wstring) { +Variant::Variant(const char32_t *p_wstring) { type = STRING; memnew_placement(_data._mem, String(p_wstring)); } diff --git a/core/variant.h b/core/variant.h index 27a709b473..112003a7ae 100644 --- a/core/variant.h +++ b/core/variant.h @@ -246,7 +246,7 @@ public: operator ObjectID() const; - operator CharType() const; + operator char32_t() const; operator float() const; operator double() const; operator String() const; @@ -323,7 +323,7 @@ public: Variant(const String &p_string); Variant(const StringName &p_string); Variant(const char *const p_cstring); - Variant(const CharType *p_wstring); + Variant(const char32_t *p_wstring); Variant(const Vector2 &p_vector2); Variant(const Vector2i &p_vector2i); Variant(const Rect2 &p_rect2); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 91af127d32..0ebb2f04a1 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -239,6 +239,7 @@ struct _VariantCall { VCALL_LOCALMEM1R(String, casecmp_to); VCALL_LOCALMEM1R(String, nocasecmp_to); + VCALL_LOCALMEM1R(String, naturalnocasecmp_to); VCALL_LOCALMEM0R(String, length); VCALL_LOCALMEM3R(String, count); VCALL_LOCALMEM3R(String, countn); @@ -311,6 +312,8 @@ struct _VariantCall { VCALL_LOCALMEM0R(String, to_int); VCALL_LOCALMEM0R(String, to_float); VCALL_LOCALMEM0R(String, hex_to_int); + VCALL_LOCALMEM2R(String, lpad); + VCALL_LOCALMEM2R(String, rpad); VCALL_LOCALMEM1R(String, pad_decimals); VCALL_LOCALMEM1R(String, pad_zeros); VCALL_LOCALMEM1R(String, trim_prefix); @@ -350,6 +353,39 @@ struct _VariantCall { r_ret = retval; } + static void _call_String_to_utf16(Variant &r_ret, Variant &p_self, const Variant **p_args) { + String *s = reinterpret_cast<String *>(p_self._data._mem); + if (s->empty()) { + r_ret = PackedByteArray(); + return; + } + Char16String charstr = s->utf16(); + + PackedByteArray retval; + size_t len = charstr.length() * 2; + retval.resize(len); + uint8_t *w = retval.ptrw(); + copymem(w, (const void *)charstr.ptr(), len); + + r_ret = retval; + } + + static void _call_String_to_utf32(Variant &r_ret, Variant &p_self, const Variant **p_args) { + String *s = reinterpret_cast<String *>(p_self._data._mem); + if (s->empty()) { + r_ret = PackedByteArray(); + return; + } + + PackedByteArray retval; + size_t len = s->length() * 4; + retval.resize(len); + uint8_t *w = retval.ptrw(); + copymem(w, (const void *)s->ptr(), len); + + r_ret = retval; + } + VCALL_LOCALMEM1R(Vector2, distance_to); VCALL_LOCALMEM1R(Vector2, distance_squared_to); VCALL_LOCALMEM0R(Vector2, length); @@ -594,14 +630,14 @@ struct _VariantCall { VCALL_LOCALMEM0R(Array, min); static void _call_PackedByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); + Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); String s; - if (ba->size() > 0) { - const uint8_t *r = ba->ptr(); + if (ba->array.size() > 0) { + const uint8_t *r = ba->array.ptr(); CharString cs; - cs.resize(ba->size() + 1); - copymem(cs.ptrw(), r, ba->size()); - cs[ba->size()] = 0; + cs.resize(ba->array.size() + 1); + copymem(cs.ptrw(), r, ba->array.size()); + cs[ba->array.size()] = 0; s = cs.get_data(); } @@ -609,32 +645,54 @@ struct _VariantCall { } static void _call_PackedByteArray_get_string_from_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { + Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); + + String s; + if (ba->array.size() > 0) { + const uint8_t *r = ba->array.ptr(); + s.parse_utf8((const char *)r, ba->array.size()); + } + r_ret = s; + } + + static void _call_PackedByteArray_get_string_from_utf16(Variant &r_ret, Variant &p_self, const Variant **p_args) { PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); String s; if (ba->size() > 0) { const uint8_t *r = ba->ptr(); - s.parse_utf8((const char *)r, ba->size()); + s.parse_utf16((const char16_t *)r, ba->size() / 2); } r_ret = s; } - static void _call_PackedByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) { + static void _call_PackedByteArray_get_string_from_utf32(Variant &r_ret, Variant &p_self, const Variant **p_args) { PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); - PackedByteArray compressed; + String s; if (ba->size() > 0) { - Compression::Mode mode = (Compression::Mode)(int)(*p_args[0]); + const uint8_t *r = ba->ptr(); + s = String((const char32_t *)r, ba->size() / 4); + } + r_ret = s; + } + + static void _call_PackedByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) { + Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); + PackedByteArray compressed; - compressed.resize(Compression::get_max_compressed_buffer_size(ba->size(), mode)); - int result = Compression::compress(compressed.ptrw(), ba->ptr(), ba->size(), mode); + if (ba->array.size() > 0) { + Compression::Mode mode = (Compression::Mode)(int)(*p_args[0]); + compressed.resize(Compression::get_max_compressed_buffer_size(ba->array.size(), mode)); + int result = Compression::compress(compressed.ptrw(), ba->array.ptr(), ba->array.size(), mode); result = result >= 0 ? result : 0; compressed.resize(result); } + r_ret = compressed; } static void _call_PackedByteArray_decompress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); + Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); PackedByteArray decompressed; Compression::Mode mode = (Compression::Mode)(int)(*p_args[1]); @@ -646,7 +704,7 @@ struct _VariantCall { } decompressed.resize(buffer_size); - int result = Compression::decompress(decompressed.ptrw(), buffer_size, ba->ptr(), ba->size(), mode); + int result = Compression::decompress(decompressed.ptrw(), buffer_size, ba->array.ptr(), ba->array.size(), mode); result = result >= 0 ? result : 0; decompressed.resize(result); @@ -654,14 +712,31 @@ struct _VariantCall { r_ret = decompressed; } + static void _call_PackedByteArray_decompress_dynamic(Variant &r_ret, Variant &p_self, const Variant **p_args) { + Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); + PackedByteArray decompressed; + int max_output_size = (int)(*p_args[0]); + Compression::Mode mode = (Compression::Mode)(int)(*p_args[1]); + + int result = Compression::decompress_dynamic(&decompressed, max_output_size, ba->array.ptr(), ba->array.size(), mode); + + if (result == OK) { + r_ret = decompressed; + } else { + decompressed.clear(); + r_ret = decompressed; + ERR_FAIL_MSG("Decompression failed."); + } + } + static void _call_PackedByteArray_hex_encode(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); - if (ba->size() == 0) { + Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); + if (ba->array.size() == 0) { r_ret = String(); return; } - const uint8_t *r = ba->ptr(); - String s = String::hex_encode_buffer(&r[0], ba->size()); + const uint8_t *r = ba->array.ptr(); + String s = String::hex_encode_buffer(&r[0], ba->array.size()); r_ret = s; } @@ -1789,6 +1864,7 @@ void register_variant_methods() { /* STRING */ ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray()); ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray()); + ADDFUNC1R(STRING, INT, String, naturalnocasecmp_to, STRING, "to", varray()); ADDFUNC0R(STRING, INT, String, length, varray()); ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray(-1)); @@ -1867,6 +1943,8 @@ void register_variant_methods() { ADDFUNC0R(STRING, INT, String, to_int, varray()); ADDFUNC0R(STRING, FLOAT, String, to_float, varray()); ADDFUNC0R(STRING, INT, String, hex_to_int, varray()); + ADDFUNC2R(STRING, STRING, String, lpad, INT, "min_length", STRING, "character", varray(" ")); + ADDFUNC2R(STRING, STRING, String, rpad, INT, "min_length", STRING, "character", varray(" ")); ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray()); ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray()); ADDFUNC1R(STRING, STRING, String, trim_prefix, STRING, "prefix", varray()); @@ -1874,6 +1952,8 @@ void register_variant_methods() { ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_ascii, varray()); ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf8, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf16, varray()); + ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf32, varray()); ADDFUNC0R(VECTOR2, FLOAT, Vector2, angle, varray()); ADDFUNC1R(VECTOR2, FLOAT, Vector2, angle_to, VECTOR2, "to", varray()); @@ -2109,9 +2189,12 @@ void register_variant_methods() { ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_ascii, varray()); ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf8, varray()); + ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf16, varray()); + ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf32, varray()); ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, hex_encode, varray()); ADDFUNC1R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, compress, INT, "compression_mode", varray(0)); ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); + ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, decompress_dynamic, INT, "max_output_size", INT, "compression_mode", varray(0)); ADDFUNC0R(PACKED_INT32_ARRAY, INT, PackedInt32Array, size, varray()); ADDFUNC0R(PACKED_INT32_ARRAY, BOOL, PackedInt32Array, empty, varray()); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 0cb2fe29a1..ec4eea05bf 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -245,22 +245,22 @@ bool Variant::booleanize() const { _RETURN(p_a._data.m_type); \ } -#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) \ - _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) \ - _RETURN(p_a._data.m_type m_op p_b._data._float); \ - if (p_b.type == VECTOR2) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR2I) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3I) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ - \ - _RETURN_FAIL \ +#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ + CASE_TYPE(m_prefix, m_op_name, m_name) { \ + if (p_b.type == INT) \ + _RETURN(p_a._data.m_type m_op p_b._data._int); \ + if (p_b.type == FLOAT) \ + _RETURN(p_a._data.m_type m_op p_b._data._float); \ + if (p_b.type == VECTOR2) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ + if (p_b.type == VECTOR3) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ + if (p_b.type == VECTOR2I) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2i *>(p_b._data._mem)); \ + if (p_b.type == VECTOR3I) \ + _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3i *>(p_b._data._mem)); \ + \ + _RETURN_FAIL \ } #define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ @@ -4215,7 +4215,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & int split = csize / 2; for (int i = 0; i < csize; i++) { - CharType chr = ' '; + char32_t chr = ' '; if (i < split) { if (i < sa.length()) { diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 74f4f32c0e..3c4fed68fb 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -35,7 +35,7 @@ #include "core/os/keyboard.h" #include "core/string_buffer.h" -CharType VariantParser::StreamFile::get_char() { +char32_t VariantParser::StreamFile::get_char() { return f->get_8(); } @@ -47,7 +47,7 @@ bool VariantParser::StreamFile::is_eof() const { return f->eof_reached(); } -CharType VariantParser::StreamString::get_char() { +char32_t VariantParser::StreamString::get_char() { if (pos > s.length()) { return 0; } else if (pos == s.length()) { @@ -94,7 +94,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri bool string_name = false; while (true) { - CharType cchar; + char32_t cchar; if (p_stream->saved) { cchar = p_stream->saved; p_stream->saved = 0; @@ -145,7 +145,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri } case ';': { while (true) { - CharType ch = p_stream->get_char(); + char32_t ch = p_stream->get_char(); if (p_stream->is_eof()) { r_token.type = TK_EOF; return OK; @@ -173,7 +173,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri StringBuffer<> color_str; color_str += '#'; while (true) { - CharType ch = p_stream->get_char(); + char32_t ch = p_stream->get_char(); if (p_stream->is_eof()) { r_token.type = TK_EOF; return OK; @@ -204,7 +204,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri case '"': { String str; while (true) { - CharType ch = p_stream->get_char(); + char32_t ch = p_stream->get_char(); if (ch == 0) { r_err_str = "Unterminated String"; @@ -214,13 +214,13 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri break; } else if (ch == '\\') { //escaped characters... - CharType next = p_stream->get_char(); + char32_t next = p_stream->get_char(); if (next == 0) { r_err_str = "Unterminated String"; r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -241,7 +241,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri case 'u': { //hex number for (int j = 0; j < 4; j++) { - CharType c = p_stream->get_char(); + char32_t c = p_stream->get_char(); if (c == 0) { r_err_str = "Unterminated String"; r_token.type = TK_ERROR; @@ -252,7 +252,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType v; + char32_t v; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -321,7 +321,7 @@ Error VariantParser::get_token(Stream *p_stream, Token &r_token, int &line, Stri cchar = p_stream->get_char(); } - CharType c = cchar; + char32_t c = cchar; bool exp_sign = false; bool exp_beg = false; bool is_float = false; @@ -421,7 +421,7 @@ Error VariantParser::_parse_enginecfg(Stream *p_stream, Vector<String> &strings, String accum; while (true) { - CharType c = p_stream->get_char(); + char32_t c = p_stream->get_char(); if (p_stream->is_eof()) { r_err_str = "Unexpected EOF while parsing old-style project.godot construct"; @@ -1206,7 +1206,7 @@ Error VariantParser::_parse_tag(Token &token, Stream *p_stream, int &line, Strin r_tag.fields.clear(); while (true) { - CharType c = p_stream->get_char(); + char32_t c = p_stream->get_char(); if (p_stream->is_eof()) { r_err_str = "Unexpected EOF while parsing simple tag"; return ERR_PARSE_ERROR; @@ -1305,7 +1305,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r String what; while (true) { - CharType c; + char32_t c; if (p_stream->saved) { c = p_stream->saved; p_stream->saved = 0; @@ -1320,7 +1320,7 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r if (c == ';') { //comment while (true) { - CharType ch = p_stream->get_char(); + char32_t ch = p_stream->get_char(); if (p_stream->is_eof()) { return ERR_FILE_EOF; } diff --git a/core/variant_parser.h b/core/variant_parser.h index b55d7b2df0..12329e2db6 100644 --- a/core/variant_parser.h +++ b/core/variant_parser.h @@ -38,11 +38,11 @@ class VariantParser { public: struct Stream { - virtual CharType get_char() = 0; + virtual char32_t get_char() = 0; virtual bool is_utf8() const = 0; virtual bool is_eof() const = 0; - CharType saved = 0; + char32_t saved = 0; Stream() {} virtual ~Stream() {} @@ -51,7 +51,7 @@ public: struct StreamFile : public Stream { FileAccess *f = nullptr; - virtual CharType get_char(); + virtual char32_t get_char(); virtual bool is_utf8() const; virtual bool is_eof() const; @@ -62,7 +62,7 @@ public: String s; int pos = 0; - virtual CharType get_char(); + virtual char32_t get_char(); virtual bool is_utf8() const; virtual bool is_eof() const; diff --git a/core/vector.h b/core/vector.h index 5fb630c21c..5a61f0eae3 100644 --- a/core/vector.h +++ b/core/vector.h @@ -82,7 +82,7 @@ public: _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); } - _FORCE_INLINE_ const T get(int p_index) const { return _cowdata.get(p_index); } + _FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); } _FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } _FORCE_INLINE_ int size() const { return _cowdata.size(); } Error resize(int p_size) { return _cowdata.resize(p_size); } diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 61df5e092e..20579e0159 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -119,7 +119,8 @@ <return type="Variant"> </return> <description> - Returns the last element of the array. Throws an error and returns [code]null[/code] if the array is empty. + Returns the last element of the array. Prints an error and returns [code]null[/code] if the array is empty. + [b]Note:[/b] Calling this function is not the same as writing [code]array[-1][/code]. If the array is empty, accessing by index will pause project execution when running from the editor. </description> </method> <method name="bsearch"> @@ -216,7 +217,8 @@ <return type="Variant"> </return> <description> - Returns the first element of the array. Throws an error and returns [code]null[/code] if the array is empty. + Returns the first element of the array. Prints an error and returns [code]null[/code] if the array is empty. + [b]Note:[/b] Calling this function is not the same as writing [code]array[0][/code]. If the array is empty, accessing by index will pause project execution when running from the editor. </description> </method> <method name="has"> @@ -283,14 +285,14 @@ <return type="Variant"> </return> <description> - Removes and returns the last element of the array. Returns [code]null[/code] if the array is empty. + Removes and returns the last element of the array. Returns [code]null[/code] if the array is empty, without printing an error message. </description> </method> <method name="pop_front"> <return type="Variant"> </return> <description> - Removes and returns the first element of the array. Returns [code]null[/code] if the array is empty. + Removes and returns the first element of the array. Returns [code]null[/code] if the array is empty, wwithout printing an error message. </description> </method> <method name="push_back"> @@ -317,7 +319,7 @@ <argument index="0" name="position" type="int"> </argument> <description> - Removes an element from the array by index. + Removes an element from the array by index. If the index does not exist in the array, nothing happens. </description> </method> <method name="resize"> diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml index 3cfeaadb23..24a145b0f3 100644 --- a/doc/classes/AudioEffectDistortion.xml +++ b/doc/classes/AudioEffectDistortion.xml @@ -2,13 +2,14 @@ <class name="AudioEffectDistortion" inherits="AudioEffect" version="4.0"> <brief_description> Adds a distortion audio effect to an Audio bus. - Modify the sound to make it dirty. + Modify the sound to make it distorted. </brief_description> <description> - Modify the sound and make it dirty. Different types are available: clip, tan, lo-fi (bit crushing), overdrive, or waveshape. + Different types are available: clip, tan, lo-fi (bit crushing), overdrive, or waveshape. By distorting the waveform the frequency content change, which will often make the sound "crunchy" or "abrasive". For games, it can simulate sound coming from some saturated device or speaker very efficiently. </description> <tutorials> + <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> </tutorials> <methods> </methods> diff --git a/doc/classes/AudioEffectFilter.xml b/doc/classes/AudioEffectFilter.xml index f548fb49cc..293848d204 100644 --- a/doc/classes/AudioEffectFilter.xml +++ b/doc/classes/AudioEffectFilter.xml @@ -7,6 +7,7 @@ Allows frequencies other than the [member cutoff_hz] to pass. </description> <tutorials> + <link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link> </tutorials> <methods> </methods> @@ -20,7 +21,7 @@ Gain amount of the frequencies after the filter. </member> <member name="resonance" type="float" setter="set_resonance" getter="get_resonance" default="0.5"> - Amount of boost in the overtones near the cutoff frequency. + Amount of boost in the frequency range near the cutoff frequency. </member> </members> <constants> diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 3812b45b13..bf4d9383ac 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -65,8 +65,8 @@ <member name="pressed" type="bool" setter="set_pressed" getter="is_pressed" default="false"> If [code]true[/code], the button's state is pressed. Means the button is pressed down or toggled (if [member toggle_mode] is active). </member> - <member name="shortcut" type="ShortCut" setter="set_shortcut" getter="get_shortcut"> - [ShortCut] associated to the button. + <member name="shortcut" type="Shortcut" setter="set_shortcut" getter="get_shortcut"> + [Shortcut] associated to the button. </member> <member name="shortcut_in_tooltip" type="bool" setter="set_shortcut_in_tooltip" getter="is_shortcut_in_tooltip_enabled" default="true"> If [code]true[/code], the button will add information about its shortcut in the tooltip. diff --git a/doc/classes/CodeEdit.xml b/doc/classes/CodeEdit.xml new file mode 100644 index 0000000000..f6bc9e2cca --- /dev/null +++ b/doc/classes/CodeEdit.xml @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="CodeEdit" inherits="TextEdit" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="clear_bookmarked_lines"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="clear_breakpointed_lines"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="clear_executing_lines"> + <return type="void"> + </return> + <description> + </description> + </method> + <method name="get_bookmarked_lines" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> + <method name="get_breakpointed_lines" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> + <method name="get_executing_lines" qualifiers="const"> + <return type="Array"> + </return> + <description> + </description> + </method> + <method name="is_line_bookmarked" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_line_breakpointed" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_line_executing" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </method> + <method name="set_line_as_bookmarked"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="bookmarked" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_line_as_breakpoint"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="breakpointed" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_line_as_executing"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="executing" type="bool"> + </argument> + <description> + </description> + </method> + </methods> + <members> + <member name="draw_bookmarks" type="bool" setter="set_draw_bookmarks_gutter" getter="is_drawing_bookmarks_gutter" default="false"> + </member> + <member name="draw_breakpoints_gutter" type="bool" setter="set_draw_breakpoints_gutter" getter="is_drawing_breakpoints_gutter" default="false"> + </member> + <member name="draw_executing_lines" type="bool" setter="set_draw_executing_lines_gutter" getter="is_drawing_executing_lines_gutter" default="false"> + </member> + <member name="draw_fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false"> + </member> + <member name="draw_line_numbers" type="bool" setter="set_draw_line_numbers" getter="is_draw_line_numbers_enabled" default="false"> + </member> + <member name="zero_pad_line_numbers" type="bool" setter="set_line_numbers_zero_padded" getter="is_line_numbers_zero_padded" default="false"> + </member> + </members> + <signals> + <signal name="breakpoint_toggled"> + <argument index="0" name="line" type="int"> + </argument> + <description> + </description> + </signal> + </signals> + <constants> + </constants> + <theme_items> + <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )"> + </theme_item> + <theme_item name="bookmark" type="Texture2D"> + </theme_item> + <theme_item name="bookmark_color" type="Color" default="Color( 0.5, 0.64, 1, 0.8 )"> + </theme_item> + <theme_item name="brace_mismatch_color" type="Color" default="Color( 1, 0.2, 0.2, 1 )"> + </theme_item> + <theme_item name="breakpoint" type="Texture2D"> + </theme_item> + <theme_item name="breakpoint_color" type="Color" default="Color( 0.9, 0.29, 0.3, 1 )"> + </theme_item> + <theme_item name="can_fold" type="Texture2D"> + </theme_item> + <theme_item name="caret_background_color" type="Color" default="Color( 0, 0, 0, 1 )"> + </theme_item> + <theme_item name="caret_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + </theme_item> + <theme_item name="code_folding_color" type="Color" default="Color( 0.8, 0.8, 0.8, 0.8 )"> + </theme_item> + <theme_item name="completion" type="StyleBox"> + </theme_item> + <theme_item name="completion_background_color" type="Color" default="Color( 0.17, 0.16, 0.2, 1 )"> + </theme_item> + <theme_item name="completion_existing_color" type="Color" default="Color( 0.87, 0.87, 0.87, 0.13 )"> + </theme_item> + <theme_item name="completion_font_color" type="Color" default="Color( 0.67, 0.67, 0.67, 1 )"> + </theme_item> + <theme_item name="completion_lines" type="int" default="7"> + </theme_item> + <theme_item name="completion_max_width" type="int" default="50"> + </theme_item> + <theme_item name="completion_scroll_color" type="Color" default="Color( 1, 1, 1, 1 )"> + </theme_item> + <theme_item name="completion_scroll_width" type="int" default="3"> + </theme_item> + <theme_item name="completion_selected_color" type="Color" default="Color( 0.26, 0.26, 0.27, 1 )"> + </theme_item> + <theme_item name="current_line_color" type="Color" default="Color( 0.25, 0.25, 0.26, 0.8 )"> + </theme_item> + <theme_item name="executing_line" type="Texture2D"> + </theme_item> + <theme_item name="executing_line_color" type="Color" default="Color( 0.98, 0.89, 0.27, 1 )"> + </theme_item> + <theme_item name="focus" type="StyleBox"> + </theme_item> + <theme_item name="folded" type="Texture2D"> + </theme_item> + <theme_item name="font" type="Font"> + </theme_item> + <theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> + </theme_item> + <theme_item name="font_color_readonly" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )"> + </theme_item> + <theme_item name="font_color_selected" type="Color" default="Color( 0, 0, 0, 1 )"> + </theme_item> + <theme_item name="line_number_color" type="Color" default="Color( 0.67, 0.67, 0.67, 0.4 )"> + </theme_item> + <theme_item name="line_spacing" type="int" default="4"> + </theme_item> + <theme_item name="mark_color" type="Color" default="Color( 1, 0.4, 0.4, 0.4 )"> + </theme_item> + <theme_item name="normal" type="StyleBox"> + </theme_item> + <theme_item name="read_only" type="StyleBox"> + </theme_item> + <theme_item name="safe_line_number_color" type="Color" default="Color( 0.67, 0.78, 0.67, 0.6 )"> + </theme_item> + <theme_item name="selection_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )"> + </theme_item> + <theme_item name="space" type="Texture2D"> + </theme_item> + <theme_item name="tab" type="Texture2D"> + </theme_item> + <theme_item name="word_highlighted_color" type="Color" default="Color( 0.8, 0.9, 0.9, 0.15 )"> + </theme_item> + </theme_items> +</class> diff --git a/doc/classes/CollisionShape3D.xml b/doc/classes/CollisionShape3D.xml index 05851e445e..177900dd4f 100644 --- a/doc/classes/CollisionShape3D.xml +++ b/doc/classes/CollisionShape3D.xml @@ -10,7 +10,7 @@ <link title="Physics introduction">https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html</link> </tutorials> <methods> - <method name="make_convex_from_brothers"> + <method name="make_convex_from_siblings"> <return type="void"> </return> <description> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 814c232668..28194587ab 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -901,6 +901,30 @@ <description> </description> </method> + <method name="window_set_mouse_passthrough"> + <return type="void"> + </return> + <argument index="0" name="region" type="PackedVector2Array"> + </argument> + <argument index="1" name="window_id" type="int" default="0"> + </argument> + <description> + Sets a polygonal region of the window which accepts mouse events. Mouse events outside the region will be passed through. + Passing an empty array will disable passthrough support (all mouse events will be intercepted by the window, which is the default behavior). + [codeblock] + # Set region, using Path2D node. + DisplayServer.window_set_mouse_passthrough($Path2D.curve.get_baked_points()) + + # Set region, using Polygon2D node. + DisplayServer.window_set_mouse_passthrough($Polygon2D.polygon) + + # Reset region to default. + DisplayServer.window_set_mouse_passthrough([]) + [/codeblock] + [b]Note:[/b] On Windows, the portion of a window that lies outside the region is not drawn, while on Linux and macOS it is. + [b]Note:[/b] This method is implemented on Linux, macOS and Windows. + </description> + </method> <method name="window_set_position"> <return type="void"> </return> diff --git a/doc/classes/EditorFeatureProfile.xml b/doc/classes/EditorFeatureProfile.xml index eb03d3010f..e05a685dd7 100644 --- a/doc/classes/EditorFeatureProfile.xml +++ b/doc/classes/EditorFeatureProfile.xml @@ -135,15 +135,15 @@ <constant name="FEATURE_SCENE_TREE" value="3" enum="Feature"> Scene tree editing. If this feature is disabled, the Scene tree dock will still be visible but will be read-only. </constant> - <constant name="FEATURE_IMPORT_DOCK" value="4" enum="Feature"> - The Import dock. If this feature is disabled, the Import dock won't be visible. - </constant> - <constant name="FEATURE_NODE_DOCK" value="5" enum="Feature"> + <constant name="FEATURE_NODE_DOCK" value="4" enum="Feature"> The Node dock. If this feature is disabled, signals and groups won't be visible and modifiable from the editor. </constant> - <constant name="FEATURE_FILESYSTEM_DOCK" value="6" enum="Feature"> + <constant name="FEATURE_FILESYSTEM_DOCK" value="5" enum="Feature"> The FileSystem dock. If this feature is disabled, the FileSystem dock won't be visible. </constant> + <constant name="FEATURE_IMPORT_DOCK" value="6" enum="Feature"> + The Import dock. If this feature is disabled, the Import dock won't be visible. + </constant> <constant name="FEATURE_MAX" value="7" enum="Feature"> Represents the size of the [enum Feature] enum. </constant> diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 5bed28aaf7..244bdcf2f3 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -33,7 +33,7 @@ <member name="draw_order" type="int" setter="set_draw_order" getter="get_draw_order" enum="GPUParticles2D.DrawOrder" default="0"> Particle draw order. Uses [enum DrawOrder] values. </member> - <member name="emitting" type="bool" setter="set_emitting" getter="is_emitting" default="false"> + <member name="emitting" type="bool" setter="set_emitting" getter="is_emitting" default="true"> If [code]true[/code], particles are being emitted. </member> <member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio" default="0.0"> diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index 3e17963407..8444610f49 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -18,6 +18,22 @@ Returns the axis-aligned bounding box that contains all the particles that are active in the current frame. </description> </method> + <method name="emit_particle"> + <return type="void"> + </return> + <argument index="0" name="xform" type="Transform"> + </argument> + <argument index="1" name="velocity" type="Vector3"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <argument index="3" name="custom" type="Color"> + </argument> + <argument index="4" name="flags" type="int"> + </argument> + <description> + </description> + </method> <method name="get_draw_pass_mesh" qualifiers="const"> <return type="Mesh"> </return> @@ -68,7 +84,7 @@ <member name="draw_passes" type="int" setter="set_draw_passes" getter="get_draw_passes" default="1"> The number of draw passes when rendering particles. </member> - <member name="emitting" type="bool" setter="set_emitting" getter="is_emitting" default="false"> + <member name="emitting" type="bool" setter="set_emitting" getter="is_emitting" default="true"> If [code]true[/code], particles are being emitted. </member> <member name="explosiveness" type="float" setter="set_explosiveness_ratio" getter="get_explosiveness_ratio" default="0.0"> @@ -101,6 +117,8 @@ <member name="speed_scale" type="float" setter="set_speed_scale" getter="get_speed_scale" default="1.0"> Speed scaling ratio. A value of [code]0[/code] can be used to pause the particles. </member> + <member name="sub_emitter" type="NodePath" setter="set_sub_emitter" getter="get_sub_emitter" default="NodePath("")"> + </member> <member name="visibility_aabb" type="AABB" setter="set_visibility_aabb" getter="get_visibility_aabb" default="AABB( -4, -4, -4, 8, 8, 8 )"> The [AABB] that determines the area of the world part of which needs to be visible on screen for the particle system to be active. </member> @@ -115,6 +133,16 @@ <constant name="DRAW_ORDER_VIEW_DEPTH" value="2" enum="DrawOrder"> Particles are drawn in order of depth. </constant> + <constant name="EMIT_FLAG_POSITION" value="1" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_ROTATION_SCALE" value="2" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_VELOCITY" value="4" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_COLOR" value="8" enum="EmitFlags"> + </constant> + <constant name="EMIT_FLAG_CUSTOM" value="16" enum="EmitFlags"> + </constant> <constant name="MAX_DRAW_PASSES" value="4"> Maximum number of draw passes supported. </constant> diff --git a/doc/classes/GridContainer.xml b/doc/classes/GridContainer.xml index e13dc43104..6ee794c5c4 100644 --- a/doc/classes/GridContainer.xml +++ b/doc/classes/GridContainer.xml @@ -1,11 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="GridContainer" inherits="Container" version="4.0"> <brief_description> - Grid container used to arrange elements in a grid like layout. + Grid container used to arrange Control-derived children in a grid like layout. </brief_description> <description> - Grid container will arrange its children in a grid like structure, the grid columns are specified using the [member columns] property and the number of rows will be equal to the number of children in the container divided by the number of columns. For example, if the container has 5 children, and 2 columns, there will be 3 rows in the container. + GridContainer will arrange its Control-derived children in a grid like structure, the grid columns are specified using the [member columns] property and the number of rows will be equal to the number of children in the container divided by the number of columns. For example, if the container has 5 children, and 2 columns, there will be 3 rows in the container. Notice that grid layout will preserve the columns and rows for every size of the container, and that empty columns will be expanded automatically. + [b]Note:[/b] GridContainer only works with child nodes inheriting from Control. It won't rearrange child nodes inheriting from Node2D. </description> <tutorials> </tutorials> @@ -13,7 +14,7 @@ </methods> <members> <member name="columns" type="int" setter="set_columns" getter="get_columns" default="1"> - The number of columns in the [GridContainer]. If modified, [GridContainer] reorders its children to accommodate the new layout. + The number of columns in the [GridContainer]. If modified, [GridContainer] reorders its Control-derived children to accommodate the new layout. </member> </members> <constants> diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml index 4801af07d3..8cc7ecfbe3 100644 --- a/doc/classes/HTTPRequest.xml +++ b/doc/classes/HTTPRequest.xml @@ -64,6 +64,11 @@ add_child(texture_rect) texture_rect.texture = texture [/codeblock] + + [b]Gzipped response bodies[/b] + HttpRequest will automatically handle decompression of response bodies. + A "Accept-Encoding" header will be automatically added to each of your requests, unless one is already specified. + Any response with a "Content-Encoding: gzip" header will automatically be decompressed and delivered to you as a uncompressed bytes. [b]Note:[/b] When performing HTTP requests from a project exported to HTML5, keep in mind the remote server may not allow requests from foreign origins due to [url=https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS]CORS[/url]. If you host the server in question, you should modify its backend to allow requests from foreign origins by adding the [code]Access-Control-Allow-Origin: *[/code] HTTP header. </description> <tutorials> @@ -119,10 +124,34 @@ [b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example. </description> </method> + <method name="request_raw"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="url" type="String"> + </argument> + <argument index="1" name="custom_headers" type="PackedStringArray" default="PackedStringArray( )"> + </argument> + <argument index="2" name="ssl_validate_domain" type="bool" default="true"> + </argument> + <argument index="3" name="method" type="int" enum="HTTPClient.Method" default="0"> + </argument> + <argument index="4" name="request_data_raw" type="PackedByteArray" default="PackedByteArray( )"> + </argument> + <description> + Creates request on the underlying [HTTPClient] using a raw array of bytes for the request body. If there is no configuration errors, it tries to connect using [method HTTPClient.connect_to_host] and passes parameters onto [method HTTPClient.request]. + Returns [constant OK] if request is successfully created. (Does not imply that the server has responded), [constant ERR_UNCONFIGURED] if not in the tree, [constant ERR_BUSY] if still processing previous request, [constant ERR_INVALID_PARAMETER] if given string is not a valid URL format, or [constant ERR_CANT_CONNECT] if not using thread and the [HTTPClient] cannot connect to host. + </description> + </method> </methods> <members> + <member name="accept_gzip" type="bool" setter="set_accept_gzip" getter="is_accepting_gzip" default="true"> + If [code]true[/code], this header will be added to each request: [code]Accept-Encoding: gzip, deflate[/code] telling servers that it's okay to compress response bodies. + Any Response body declaring a [code]Content-Encoding[/code] of either [code]gzip[/code] or [code]deflate[/code] will then be automatically decompressed, and the uncompressed bytes will be delivered via [code]request_completed[/code]. + If the user has specified their own [code]Accept-Encoding[/code] header, then no header will be added regaurdless of [code]accept_gzip[/code]. + If [code]false[/code] no header will be added, and no decompression will be performed on response bodies. The raw bytes of the response body will be returned via [code]request_completed[/code]. + </member> <member name="body_size_limit" type="int" setter="set_body_size_limit" getter="get_body_size_limit" default="-1"> - Maximum allowed size for response bodies. + Maximum allowed size for response bodies. If the response body is compressed, this will be used as the maximum allowed size for the decompressed body. </member> <member name="download_chunk_size" type="int" setter="set_download_chunk_size" getter="get_download_chunk_size" default="4096"> The size of the buffer used and maximum bytes to read per iteration. See [member HTTPClient.read_chunk_size]. @@ -179,19 +208,21 @@ <constant name="RESULT_BODY_SIZE_LIMIT_EXCEEDED" value="7" enum="Result"> Request exceeded its maximum size limit, see [member body_size_limit]. </constant> - <constant name="RESULT_REQUEST_FAILED" value="8" enum="Result"> + <constant name="RESULT_BODY_DECOMPRESS_FAILED" value="8" enum="Result"> + </constant> + <constant name="RESULT_REQUEST_FAILED" value="9" enum="Result"> Request failed (currently unused). </constant> - <constant name="RESULT_DOWNLOAD_FILE_CANT_OPEN" value="9" enum="Result"> + <constant name="RESULT_DOWNLOAD_FILE_CANT_OPEN" value="10" enum="Result"> HTTPRequest couldn't open the download file. </constant> - <constant name="RESULT_DOWNLOAD_FILE_WRITE_ERROR" value="10" enum="Result"> + <constant name="RESULT_DOWNLOAD_FILE_WRITE_ERROR" value="11" enum="Result"> HTTPRequest couldn't write to the download file. </constant> - <constant name="RESULT_REDIRECT_LIMIT_REACHED" value="11" enum="Result"> + <constant name="RESULT_REDIRECT_LIMIT_REACHED" value="12" enum="Result"> Request reached its maximum redirect limit, see [member max_redirects]. </constant> - <constant name="RESULT_TIMEOUT" value="12" enum="Result"> + <constant name="RESULT_TIMEOUT" value="13" enum="Result"> </constant> </constants> </class> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 5aa5de1dae..20be20db34 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -233,7 +233,7 @@ <return type="PackedByteArray"> </return> <description> - Returns the image's raw data. + Returns a copy of the image's raw data. </description> </method> <method name="get_format" qualifiers="const"> diff --git a/doc/classes/ImageTexture3D.xml b/doc/classes/ImageTexture3D.xml new file mode 100644 index 0000000000..d05082487d --- /dev/null +++ b/doc/classes/ImageTexture3D.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="ImageTexture3D" inherits="Texture3D" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="create"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="format" type="int" enum="Image.Format"> + </argument> + <argument index="1" name="width" type="int"> + </argument> + <argument index="2" name="height" type="int"> + </argument> + <argument index="3" name="depth" type="int"> + </argument> + <argument index="4" name="use_mipmaps" type="bool"> + </argument> + <argument index="5" name="data" type="Image[]"> + </argument> + <description> + </description> + </method> + <method name="update"> + <return type="void"> + </return> + <argument index="0" name="data" type="Image[]"> + </argument> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index 367099e455..1efa72a2b2 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -44,7 +44,7 @@ <return type="AABB"> </return> <description> - Returns the smallest [AABB] enclosing this mesh. Not affected by [code]custom_aabb[/code]. + Returns the smallest [AABB] enclosing this mesh in local space. Not affected by [code]custom_aabb[/code]. See also [method VisualInstance3D.get_transformed_aabb]. [b]Note:[/b] This is only implemented for [ArrayMesh] and [PrimitiveMesh]. </description> </method> diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml index 8a6c560cdd..e1b3ffa2e4 100644 --- a/doc/classes/MultiMesh.xml +++ b/doc/classes/MultiMesh.xml @@ -18,7 +18,7 @@ <return type="AABB"> </return> <description> - Returns the visibility axis-aligned bounding box. + Returns the visibility axis-aligned bounding box in local space. See also [method VisualInstance3D.get_transformed_aabb]. </description> </method> <method name="get_instance_color" qualifiers="const"> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index b342fc0813..1548800901 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -525,7 +525,7 @@ â” â•´Menu ┃ â” â•´Label ┃ â”–â•´Camera2D - â”–-SplashScreen + â”–â•´SplashScreen â”–â•´Camera2D [/codeblock] </description> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 2395ccd211..50d91c7943 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -395,7 +395,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Removes a given entry from the object's metadata. + Removes a given entry from the object's metadata. See also [method set_meta]. </description> </method> <method name="set"> @@ -464,7 +464,8 @@ <argument index="1" name="value" type="Variant"> </argument> <description> - Adds or changes a given entry in the object's metadata. Metadata are serialized, and can take any [Variant] value. + Adds, changes or removes a given entry in the object's metadata. Metadata are serialized and can take any [Variant] value. + To remove a given entry from the object's metadata, use [method remove_meta]. Metadata is also removed if its value is set to [code]null[/code]. This means you can also use [code]set_meta("name", null)[/code] to remove metadata for [code]"name"[/code]. </description> </method> <method name="set_script"> diff --git a/doc/classes/PCKPacker.xml b/doc/classes/PCKPacker.xml index 314869be49..6b500d5ac3 100644 --- a/doc/classes/PCKPacker.xml +++ b/doc/classes/PCKPacker.xml @@ -23,6 +23,8 @@ </argument> <argument index="1" name="source_path" type="String"> </argument> + <argument index="2" name="encrypt" type="bool" default="false"> + </argument> <description> Adds the [code]source_path[/code] file to the current PCK package at the [code]pck_path[/code] internal path (should start with [code]res://[/code]). </description> @@ -43,6 +45,10 @@ </argument> <argument index="1" name="alignment" type="int" default="0"> </argument> + <argument index="2" name="key" type="String" default=""""> + </argument> + <argument index="3" name="encrypt_directory" type="bool" default="false"> + </argument> <description> Creates a new PCK file with the name [code]pck_name[/code]. The [code].pck[/code] file extension isn't added automatically, so it should be part of [code]pck_name[/code] (even though it's not required). </description> diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml index 08f8558881..0b43522bce 100644 --- a/doc/classes/PackedByteArray.xml +++ b/doc/classes/PackedByteArray.xml @@ -57,6 +57,19 @@ Returns a new [PackedByteArray] with the data decompressed. Set [code]buffer_size[/code] to the size of the uncompressed data. Set the compression mode using one of [enum File.CompressionMode]'s constants. </description> </method> + <method name="decompress_dynamic"> + <return type="PackedByteArray"> + </return> + <argument index="0" name="max_output_size" type="int"> + </argument> + <argument index="1" name="compression_mode" type="int" default="0"> + </argument> + <description> + Returns a new [PackedByteArray] with the data decompressed. Set the compression mode using one of [enum File.CompressionMode]'s constants. [b]This method only accepts gzip and deflate compression modes.[/b] + This method is potentially slower than [code]decompress[/code], as it may have to re-allocate it's output buffer multiple times while decompressing, where as [code]decompress[/code] knows it's output buffer size from the beginning. + GZIP has a maximal compression ratio of 1032:1, meaning it's very possible for a small compressed payload to decompress to a potentially very large output. To guard against this, you may provide a maximum size this function is allowed to allocate in bytes via [code]max_output_size[/code]. Passing -1 will allow for unbounded output. If any positive value is passed, and the decompression exceeds that amount in bytes, then an error will be returned. + </description> + </method> <method name="empty"> <return type="bool"> </return> @@ -68,14 +81,28 @@ <return type="String"> </return> <description> - Returns a copy of the array's contents as [String]. Fast alternative to [method get_string_from_utf8] if the content is ASCII-only. Unlike the UTF-8 function this function maps every byte to a character in the array. Multibyte sequences will not be interpreted correctly. For parsing user input always use [method get_string_from_utf8]. + Converts ASCII/Latin-1 encoded array to [String]. Fast alternative to [method get_string_from_utf8] if the content is ASCII/Latin-1 only. Unlike the UTF-8 function this function maps every byte to a character in the array. Multibyte sequences will not be interpreted correctly. For parsing user input always use [method get_string_from_utf8]. + </description> + </method> + <method name="get_string_from_utf16"> + <return type="String"> + </return> + <description> + Converts UTF-16 encoded array to [String]. If the BOM is missing, system endianness is assumed. Returns empty string if source array is not valid UTF-16 string. + </description> + </method> + <method name="get_string_from_utf32"> + <return type="String"> + </return> + <description> + Converts UTF-32 encoded array to [String]. System endianness is assumed. Returns empty string if source array is not valid UTF-32 string. </description> </method> <method name="get_string_from_utf8"> <return type="String"> </return> <description> - Returns a copy of the array's contents as [String]. Slower than [method get_string_from_ascii] but supports UTF-8 encoded data. Use this function if you are unsure about the source of the data. For user input this function should always be preferred. + Converts UTF-8 encoded array to [String]. Slower than [method get_string_from_ascii] but supports UTF-8 encoded data. Use this function if you are unsure about the source of the data. For user input this function should always be preferred. Returns empty string if source array is not valid UTF-8 string. </description> </method> <method name="has"> diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml index d04ac5bdce..f6fa3cf38b 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticlesMaterial.xml @@ -243,6 +243,14 @@ <member name="spread" type="float" setter="set_spread" getter="get_spread" default="45.0"> Each particle's initial direction range from [code]+spread[/code] to [code]-spread[/code] degrees. Applied to X/Z plane and Y/Z planes. </member> + <member name="sub_emitter_amount_at_end" type="int" setter="set_sub_emitter_amount_at_end" getter="get_sub_emitter_amount_at_end"> + </member> + <member name="sub_emitter_frequency" type="float" setter="set_sub_emitter_frequency" getter="get_sub_emitter_frequency"> + </member> + <member name="sub_emitter_keep_velocity" type="bool" setter="set_sub_emitter_keep_velocity" getter="get_sub_emitter_keep_velocity" default="false"> + </member> + <member name="sub_emitter_mode" type="int" setter="set_sub_emitter_mode" getter="get_sub_emitter_mode" enum="ParticlesMaterial.SubEmitterMode" default="0"> + </member> <member name="tangential_accel" type="float" setter="set_param" getter="get_param" default="0.0"> Tangential acceleration applied to each particle. Tangential acceleration is perpendicular to the particle's velocity giving the particles a swirling motion. </member> @@ -252,15 +260,6 @@ <member name="tangential_accel_random" type="float" setter="set_param_randomness" getter="get_param_randomness" default="0.0"> Tangential acceleration randomness ratio. </member> - <member name="trail_color_modifier" type="GradientTexture" setter="set_trail_color_modifier" getter="get_trail_color_modifier"> - Trail particles' color will vary along this [GradientTexture]. - </member> - <member name="trail_divisor" type="int" setter="set_trail_divisor" getter="get_trail_divisor" default="1"> - Emitter will emit [code]amount[/code] divided by [code]trail_divisor[/code] particles. The remaining particles will be used as trail(s). - </member> - <member name="trail_size_modifier" type="CurveTexture" setter="set_trail_size_modifier" getter="get_trail_size_modifier"> - Trail particles' size will vary along this [CurveTexture]. - </member> </members> <constants> <constant name="PARAM_INITIAL_LINEAR_VELOCITY" value="0" enum="Parameter"> @@ -332,5 +331,15 @@ <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape"> Represents the size of the [enum EmissionShape] enum. </constant> + <constant name="SUB_EMITTER_DISABLED" value="0" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_CONSTANT" value="1" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_AT_END" value="2" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_AT_COLLISION" value="3" enum="SubEmitterMode"> + </constant> + <constant name="SUB_EMITTER_MAX" value="4" enum="SubEmitterMode"> + </constant> </constants> </class> diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml index 2af0f500a0..b1ec9a222a 100644 --- a/doc/classes/PopupMenu.xml +++ b/doc/classes/PopupMenu.xml @@ -29,14 +29,14 @@ <method name="add_check_shortcut"> <return type="void"> </return> - <argument index="0" name="shortcut" type="ShortCut"> + <argument index="0" name="shortcut" type="Shortcut"> </argument> <argument index="1" name="id" type="int" default="-1"> </argument> <argument index="2" name="global" type="bool" default="false"> </argument> <description> - Adds a new checkable item and assigns the specified [ShortCut] to it. Sets the label of the checkbox to the [ShortCut]'s name. + Adds a new checkable item and assigns the specified [Shortcut] to it. Sets the label of the checkbox to the [Shortcut]'s name. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. [b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it. </description> @@ -63,14 +63,14 @@ </return> <argument index="0" name="texture" type="Texture2D"> </argument> - <argument index="1" name="shortcut" type="ShortCut"> + <argument index="1" name="shortcut" type="Shortcut"> </argument> <argument index="2" name="id" type="int" default="-1"> </argument> <argument index="3" name="global" type="bool" default="false"> </argument> <description> - Adds a new checkable item and assigns the specified [ShortCut] and icon [code]texture[/code] to it. Sets the label of the checkbox to the [ShortCut]'s name. + Adds a new checkable item and assigns the specified [Shortcut] and icon [code]texture[/code] to it. Sets the label of the checkbox to the [Shortcut]'s name. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. [b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it. </description> @@ -111,7 +111,7 @@ </return> <argument index="0" name="texture" type="Texture2D"> </argument> - <argument index="1" name="shortcut" type="ShortCut"> + <argument index="1" name="shortcut" type="Shortcut"> </argument> <argument index="2" name="id" type="int" default="-1"> </argument> @@ -126,14 +126,14 @@ </return> <argument index="0" name="texture" type="Texture2D"> </argument> - <argument index="1" name="shortcut" type="ShortCut"> + <argument index="1" name="shortcut" type="Shortcut"> </argument> <argument index="2" name="id" type="int" default="-1"> </argument> <argument index="3" name="global" type="bool" default="false"> </argument> <description> - Adds a new item and assigns the specified [ShortCut] and icon [code]texture[/code] to it. Sets the label of the checkbox to the [ShortCut]'s name. + Adds a new item and assigns the specified [Shortcut] and icon [code]texture[/code] to it. Sets the label of the checkbox to the [Shortcut]'s name. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. </description> </method> @@ -188,14 +188,14 @@ <method name="add_radio_check_shortcut"> <return type="void"> </return> - <argument index="0" name="shortcut" type="ShortCut"> + <argument index="0" name="shortcut" type="Shortcut"> </argument> <argument index="1" name="id" type="int" default="-1"> </argument> <argument index="2" name="global" type="bool" default="false"> </argument> <description> - Adds a new radio check button and assigns a [ShortCut] to it. Sets the label of the checkbox to the [ShortCut]'s name. + Adds a new radio check button and assigns a [Shortcut] to it. Sets the label of the checkbox to the [Shortcut]'s name. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. [b]Note:[/b] Checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method set_item_checked] for more info on how to control it. </description> @@ -212,14 +212,14 @@ <method name="add_shortcut"> <return type="void"> </return> - <argument index="0" name="shortcut" type="ShortCut"> + <argument index="0" name="shortcut" type="Shortcut"> </argument> <argument index="1" name="id" type="int" default="-1"> </argument> <argument index="2" name="global" type="bool" default="false"> </argument> <description> - Adds a [ShortCut]. + Adds a [Shortcut]. An [code]id[/code] can optionally be provided. If no [code]id[/code] is provided, one will be created from the index. </description> </method> @@ -303,12 +303,12 @@ </description> </method> <method name="get_item_shortcut" qualifiers="const"> - <return type="ShortCut"> + <return type="Shortcut"> </return> <argument index="0" name="idx" type="int"> </argument> <description> - Returns the [ShortCut] associated with the specified [code]idx[/code] item. + Returns the [Shortcut] associated with the specified [code]idx[/code] item. </description> </method> <method name="get_item_submenu" qualifiers="const"> @@ -521,12 +521,12 @@ </return> <argument index="0" name="idx" type="int"> </argument> - <argument index="1" name="shortcut" type="ShortCut"> + <argument index="1" name="shortcut" type="Shortcut"> </argument> <argument index="2" name="global" type="bool" default="false"> </argument> <description> - Sets a [ShortCut] for the specified item [code]idx[/code]. + Sets a [Shortcut] for the specified item [code]idx[/code]. </description> </method> <method name="set_item_shortcut_disabled"> @@ -537,7 +537,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> - Disables the [ShortCut] of the specified index [code]idx[/code]. + Disables the [Shortcut] of the specified index [code]idx[/code]. </description> </method> <method name="set_item_submenu"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 38d65f6338..ed8eddda07 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -873,7 +873,7 @@ Size of the hash table used for the broad-phase 2D hash grid algorithm. </member> <member name="physics/2d/cell_size" type="int" setter="" getter="" default="128"> - Cell size used for the broad-phase 2D hash grid algorithm. + Cell size used for the broad-phase 2D hash grid algorithm (in pixels). </member> <member name="physics/2d/default_angular_damp" type="float" setter="" getter="" default="1.0"> The default angular damp in 2D. @@ -1199,7 +1199,7 @@ <member name="rendering/vulkan/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64"> </member> <member name="world/2d/cell_size" type="int" setter="" getter="" default="100"> - Cell size used for the 2D hash grid that [VisibilityNotifier2D] uses. + Cell size used for the 2D hash grid that [VisibilityNotifier2D] uses (in pixels). </member> </members> <constants> diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml index db4b9a0383..e30d7df63f 100644 --- a/doc/classes/RayCast2D.xml +++ b/doc/classes/RayCast2D.xml @@ -4,8 +4,8 @@ Query the closest object intersecting a ray. </brief_description> <description> - A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 2D space in order to find the closest object along the path of the ray. - RayCast2D can ignore some objects by adding them to the exception list via [code]add_exception[/code], by setting proper filtering with collision layers, or by filtering object types with type masks. + A RayCast represents a line from its origin to its destination position, [member target_position]. It is used to query the 2D space in order to find the closest object along the path of the ray. + RayCast2D can ignore some objects by adding them to the exception list via [method add_exception], by setting proper filtering with collision layers, or by filtering object types with type masks. RayCast2D can be configured to report collisions with [Area2D]s ([member collide_with_areas]) and/or [PhysicsBody2D]s ([member collide_with_bodies]). Only enabled raycasts will be able to query the space and report collisions. RayCast2D calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame) use [method force_raycast_update] after adjusting the raycast. @@ -123,9 +123,6 @@ </method> </methods> <members> - <member name="cast_to" type="Vector2" setter="set_cast_to" getter="get_cast_to" default="Vector2( 0, 50 )"> - The ray's destination point, relative to the RayCast's [code]position[/code]. - </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], collision with [Area2D]s will be reported. </member> @@ -141,6 +138,9 @@ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> If [code]true[/code], the parent node will be excluded from collision detection. </member> + <member name="target_position" type="Vector2" setter="set_target_position" getter="get_target_position" default="Vector2( 0, 50 )"> + The ray's destination point, relative to the RayCast's [code]position[/code]. + </member> </members> <constants> </constants> diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml index 1e61664a7d..1d8edf0adb 100644 --- a/doc/classes/RayCast3D.xml +++ b/doc/classes/RayCast3D.xml @@ -4,8 +4,8 @@ Query the closest object intersecting a ray. </brief_description> <description> - A RayCast represents a line from its origin to its destination position, [code]cast_to[/code]. It is used to query the 3D space in order to find the closest object along the path of the ray. - RayCast3D can ignore some objects by adding them to the exception list via [code]add_exception[/code] or by setting proper filtering with collision layers and masks. + A RayCast represents a line from its origin to its destination position, [member target_position]. It is used to query the 3D space in order to find the closest object along the path of the ray. + RayCast3D can ignore some objects by adding them to the exception list via [method add_exception] or by setting proper filtering with collision layers and masks. RayCast3D can be configured to report collisions with [Area3D]s ([member collide_with_areas]) and/or [PhysicsBody3D]s ([member collide_with_bodies]). Only enabled raycasts will be able to query the space and report collisions. RayCast3D calculates intersection every physics frame (see [Node]), and the result is cached so it can be used later until the next frame. If multiple queries are required between physics frames (or during the same frame), use [method force_raycast_update] after adjusting the raycast. @@ -126,9 +126,6 @@ </method> </methods> <members> - <member name="cast_to" type="Vector3" setter="set_cast_to" getter="get_cast_to" default="Vector3( 0, -1, 0 )"> - The ray's destination point, relative to the RayCast's [code]position[/code]. - </member> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> If [code]true[/code], collision with [Area3D]s will be reported. </member> @@ -144,6 +141,9 @@ <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> If [code]true[/code], collisions will be ignored for this RayCast3D's immediate parent. </member> + <member name="target_position" type="Vector3" setter="set_target_position" getter="get_target_position" default="Vector3( 0, -1, 0 )"> + The ray's destination point, relative to the RayCast's [code]position[/code]. + </member> </members> <constants> </constants> diff --git a/doc/classes/ShortCut.xml b/doc/classes/Shortcut.xml index 9a2a761969..55bbb083c9 100644 --- a/doc/classes/ShortCut.xml +++ b/doc/classes/Shortcut.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ShortCut" inherits="Resource" version="4.0"> +<class name="Shortcut" inherits="Resource" version="4.0"> <brief_description> A shortcut for binding input. </brief_description> diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml index 516ae25e92..1c7d84c5a2 100644 --- a/doc/classes/SpriteFrames.xml +++ b/doc/classes/SpriteFrames.xml @@ -54,7 +54,7 @@ <argument index="0" name="anim" type="StringName"> </argument> <description> - If [code]true[/code], the given animation will loop. + Returns [code]true[/code] if the given animation is configured to loop when it finishes playing. Otherwise, returns [code]false[/code]. </description> </method> <method name="get_animation_names" qualifiers="const"> diff --git a/doc/classes/StreamTexture3D.xml b/doc/classes/StreamTexture3D.xml new file mode 100644 index 0000000000..7054a4ee99 --- /dev/null +++ b/doc/classes/StreamTexture3D.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="StreamTexture3D" inherits="Texture3D" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="load"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="path" type="String"> + </argument> + <description> + </description> + </method> + </methods> + <members> + <member name="load_path" type="String" setter="load" getter="get_load_path" default=""""> + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index e134ae03e0..40fff25fc4 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -654,6 +654,17 @@ Returns the string's amount of characters. </description> </method> + <method name="lpad"> + <return type="String"> + </return> + <argument index="0" name="min_length" type="int"> + </argument> + <argument index="1" name="character" type="String" default="" ""> + </argument> + <description> + Formats a string to be at least [code]min_length[/code] long by adding [code]character[/code]s to the left of the string. + </description> + </method> <method name="lstrip"> <return type="String"> </return> @@ -695,6 +706,15 @@ Returns the MD5 hash of the string as a string. </description> </method> + <method name="naturalnocasecmp_to"> + <return type="int"> + </return> + <argument index="0" name="to" type="String"> + </argument> + <description> + Performs a case-insensitive natural order comparison to another string. Returns [code]-1[/code] if less than, [code]+1[/code] if greater than, or [code]0[/code] if equal. + </description> + </method> <method name="nocasecmp_to"> <return type="int"> </return> @@ -816,6 +836,17 @@ Returns the right side of the string from a given position. </description> </method> + <method name="rpad"> + <return type="String"> + </return> + <argument index="0" name="min_length" type="int"> + </argument> + <argument index="1" name="character" type="String" default="" ""> + </argument> + <description> + Formats a string to be at least [code]min_length[/code] long by adding [code]character[/code]s to the right of the string. + </description> + </method> <method name="rsplit"> <return type="PackedStringArray"> </return> @@ -953,7 +984,7 @@ <return type="PackedByteArray"> </return> <description> - Converts the String (which is a character array) to [PackedByteArray] (which is an array of bytes). The conversion is faster compared to [method to_utf8], as this method assumes that all the characters in the String are ASCII characters. + Converts the String (which is a character array) to ASCII/Latin-1 encoded [PackedByteArray] (which is an array of bytes). The conversion is faster compared to [method to_utf8], as this method assumes that all the characters in the String are ASCII/Latin-1 characters, unsupported characters are replaced with spaces. </description> </method> <method name="to_float"> @@ -984,11 +1015,25 @@ Returns the string converted to uppercase. </description> </method> + <method name="to_utf16"> + <return type="PackedByteArray"> + </return> + <description> + Converts the String (which is an array of characters) to UTF-16 encoded [PackedByteArray] (which is an array of bytes). + </description> + </method> + <method name="to_utf32"> + <return type="PackedByteArray"> + </return> + <description> + Converts the String (which is an array of characters) to UTF-32 encoded [PackedByteArray] (which is an array of bytes). + </description> + </method> <method name="to_utf8"> <return type="PackedByteArray"> </return> <description> - Converts the String (which is an array of characters) to [PackedByteArray] (which is an array of bytes). The conversion is a bit slower than [method to_ascii], but supports all UTF-8 characters. Therefore, you should prefer this function over [method to_ascii]. + Converts the String (which is an array of characters) to UTF-8 encode [PackedByteArray] (which is an array of bytes). The conversion is a bit slower than [method to_ascii], but supports all UTF-8 characters. Therefore, you should prefer this function over [method to_ascii]. </description> </method> <method name="trim_prefix"> diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index 3fc1db9dc6..ef1f370185 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -36,6 +36,13 @@ Returns [code]true[/code] if the offset buttons (the ones that appear when there's not enough space for all tabs) are visible. </description> </method> + <method name="get_previous_tab" qualifiers="const"> + <return type="int"> + </return> + <description> + Returns the previously active tab index. + </description> + </method> <method name="get_select_with_rmb" qualifiers="const"> <return type="bool"> </return> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index ccc99dc8e3..a23a4936f8 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -9,6 +9,14 @@ <tutorials> </tutorials> <methods> + <method name="add_gutter"> + <return type="void"> + </return> + <argument index="0" name="at" type="int" default="-1"> + </argument> + <description> + </description> + </method> <method name="can_fold" qualifiers="const"> <return type="bool"> </return> @@ -112,11 +120,34 @@ Folds the given line, if possible (see [method can_fold]). </description> </method> - <method name="get_breakpoints" qualifiers="const"> - <return type="Array"> + <method name="get_gutter_count" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_gutter_name" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_gutter_type" qualifiers="const"> + <return type="int" enum="TextEdit.GutterType"> </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_gutter_width" qualifiers="const"> + <return type="int"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> <description> - Returns an array containing the line number of each breakpoint. </description> </method> <method name="get_line" qualifiers="const"> @@ -135,6 +166,46 @@ Returns the amount of total lines in the text. </description> </method> + <method name="get_line_gutter_icon" qualifiers="const"> + <return type="Texture2D"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_line_gutter_item_color"> + <return type="Color"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_line_gutter_metadata" qualifiers="const"> + <return type="Variant"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="get_line_gutter_text" qualifiers="const"> + <return type="String"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> <method name="get_menu" qualifiers="const"> <return type="PopupMenu"> </return> @@ -202,6 +273,40 @@ Returns whether the line at the specified index is folded or not. </description> </method> + <method name="is_gutter_clickable" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_gutter_drawn" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_gutter_overwritable" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <description> + </description> + </method> + <method name="is_line_gutter_clickable" qualifiers="const"> + <return type="bool"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <description> + </description> + </method> <method name="is_line_hidden" qualifiers="const"> <return type="bool"> </return> @@ -241,11 +346,12 @@ Perform redo operation. </description> </method> - <method name="remove_breakpoints"> + <method name="remove_gutter"> <return type="void"> </return> + <argument index="0" name="gutter" type="int"> + </argument> <description> - Removes all the breakpoints. This will not fire the [signal breakpoint_toggled] signal. </description> </method> <method name="search" qualifiers="const"> @@ -295,6 +401,78 @@ If [member selecting_enabled] is [code]false[/code], no selection will occur. </description> </method> + <method name="set_gutter_clickable"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="clickable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_custom_draw"> + <return type="void"> + </return> + <argument index="0" name="column" type="int"> + </argument> + <argument index="1" name="object" type="Object"> + </argument> + <argument index="2" name="callback" type="StringName"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_draw"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="draw" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_name"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="name" type="String"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_overwritable"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="overwritable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_type"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="type" type="int" enum="TextEdit.GutterType"> + </argument> + <description> + </description> + </method> + <method name="set_gutter_width"> + <return type="void"> + </return> + <argument index="0" name="gutter" type="int"> + </argument> + <argument index="1" name="width" type="int"> + </argument> + <description> + </description> + </method> <method name="set_line"> <return type="void"> </return> @@ -317,6 +495,66 @@ If [code]true[/code], hides the line of the specified index. </description> </method> + <method name="set_line_gutter_clickable"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="clickable" type="bool"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_icon"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="icon" type="Texture2D"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_item_color"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="color" type="Color"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_metadata"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="metadata" type="Variant"> + </argument> + <description> + </description> + </method> + <method name="set_line_gutter_text"> + <return type="void"> + </return> + <argument index="0" name="line" type="int"> + </argument> + <argument index="1" name="gutter" type="int"> + </argument> + <argument index="2" name="text" type="String"> + </argument> + <description> + </description> + </method> <method name="toggle_fold_line"> <return type="void"> </return> @@ -351,9 +589,6 @@ </method> </methods> <members> - <member name="breakpoint_gutter" type="bool" setter="set_breakpoint_gutter_enabled" getter="is_breakpoint_gutter_enabled" default="false"> - If [code]true[/code], the breakpoint gutter is visible. - </member> <member name="caret_blink" type="bool" setter="cursor_set_blink_enabled" getter="cursor_get_blink_enabled" default="false"> If [code]true[/code], the caret (visual cursor) blinks. </member> @@ -378,9 +613,6 @@ If [code]true[/code], the "tab" character will have a visible representation. </member> <member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" override="true" enum="Control.FocusMode" default="2" /> - <member name="fold_gutter" type="bool" setter="set_draw_fold_gutter" getter="is_drawing_fold_gutter" default="false"> - If [code]true[/code], the fold gutter is visible. This enables folding groups of indented lines. - </member> <member name="hiding_enabled" type="bool" setter="set_hiding_enabled" getter="is_hiding_enabled" default="false"> If [code]true[/code], all lines that have been set to hidden by [method set_line_as_hidden], will not be visible. </member> @@ -416,9 +648,6 @@ <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled. </member> - <member name="show_line_numbers" type="bool" setter="set_show_line_numbers" getter="is_show_line_numbers_enabled" default="false"> - If [code]true[/code], line numbers are displayed to the left of the text. - </member> <member name="smooth_scrolling" type="bool" setter="set_smooth_scroll_enable" getter="is_smooth_scroll_enabled" default="false"> If [code]true[/code], sets the [code]step[/code] of the scrollbars to [code]0.25[/code] which results in smoother scrolling. </member> @@ -438,29 +667,31 @@ </member> </members> <signals> - <signal name="breakpoint_toggled"> - <argument index="0" name="row" type="int"> - </argument> + <signal name="cursor_changed"> <description> - Emitted when a breakpoint is placed via the breakpoint gutter. + Emitted when the cursor changes. </description> </signal> - <signal name="cursor_changed"> + <signal name="gutter_added"> <description> - Emitted when the cursor changes. </description> </signal> - <signal name="info_clicked"> - <argument index="0" name="row" type="int"> + <signal name="gutter_clicked"> + <argument index="0" name="line" type="int"> </argument> - <argument index="1" name="info" type="String"> + <argument index="1" name="gutter" type="int"> </argument> <description> - Emitted when the info icon is clicked. </description> </signal> - <signal name="line_edited_from"> - <argument index="0" name="line" type="int"> + <signal name="gutter_removed"> + <description> + </description> + </signal> + <signal name="lines_edited_from"> + <argument index="0" name="from_line" type="int"> + </argument> + <argument index="1" name="to_line" type="int"> </argument> <description> </description> @@ -501,6 +732,12 @@ <constant name="SEARCH_BACKWARDS" value="4" enum="SearchFlags"> Search from end to beginning. </constant> + <constant name="GUTTER_TYPE_STRING" value="0" enum="GutterType"> + </constant> + <constant name="GUTTER_TPYE_ICON" value="1" enum="GutterType"> + </constant> + <constant name="GUTTER_TPYE_CUSTOM" value="2" enum="GutterType"> + </constant> <constant name="MENU_CUT" value="0" enum="MenuItems"> Cuts (copies and clears) the selected text. </constant> @@ -530,14 +767,8 @@ <theme_item name="background_color" type="Color" default="Color( 0, 0, 0, 0 )"> Sets the background [Color] of this [TextEdit]. [member syntax_highlighting] has to be enabled. </theme_item> - <theme_item name="bookmark_color" type="Color" default="Color( 0.08, 0.49, 0.98, 1 )"> - Sets the [Color] of the bookmark marker. [member syntax_highlighting] has to be enabled. - </theme_item> <theme_item name="brace_mismatch_color" type="Color" default="Color( 1, 0.2, 0.2, 1 )"> </theme_item> - <theme_item name="breakpoint_color" type="Color" default="Color( 0.8, 0.8, 0.4, 0.2 )"> - Sets the [Color] of the breakpoints. [member breakpoint_gutter] has to be enabled. - </theme_item> <theme_item name="caret_background_color" type="Color" default="Color( 0, 0, 0, 1 )"> </theme_item> <theme_item name="caret_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )"> @@ -565,14 +796,8 @@ <theme_item name="current_line_color" type="Color" default="Color( 0.25, 0.25, 0.26, 0.8 )"> Sets the [Color] of the breakpoints. [member breakpoint_gutter] has to be enabled. </theme_item> - <theme_item name="executing_line_color" type="Color" default="Color( 0.2, 0.8, 0.2, 0.4 )"> - </theme_item> <theme_item name="focus" type="StyleBox"> </theme_item> - <theme_item name="fold" type="Texture2D"> - </theme_item> - <theme_item name="folded" type="Texture2D"> - </theme_item> <theme_item name="font" type="Font"> Sets the default [Font]. </theme_item> @@ -584,9 +809,6 @@ <theme_item name="font_color_selected" type="Color" default="Color( 0, 0, 0, 1 )"> Sets the [Color] of the selected text. [member override_selected_font_color] has to be enabled. </theme_item> - <theme_item name="line_number_color" type="Color" default="Color( 0.67, 0.67, 0.67, 0.4 )"> - Sets the [Color] of the line numbers. [member show_line_numbers] has to be enabled. - </theme_item> <theme_item name="line_spacing" type="int" default="4"> Sets the spacing between the lines. </theme_item> @@ -599,8 +821,6 @@ <theme_item name="read_only" type="StyleBox"> Sets the [StyleBox] of this [TextEdit] when [member readonly] is enabled. </theme_item> - <theme_item name="safe_line_number_color" type="Color" default="Color( 0.67, 0.78, 0.67, 0.6 )"> - </theme_item> <theme_item name="selection_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )"> Sets the highlight [Color] of text selections. </theme_item> diff --git a/doc/classes/Texture3D.xml b/doc/classes/Texture3D.xml new file mode 100644 index 0000000000..85e940716d --- /dev/null +++ b/doc/classes/Texture3D.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="Texture3D" inherits="Texture" version="4.0"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_data" qualifiers="const"> + <return type="Image[]"> + </return> + <description> + </description> + </method> + <method name="get_depth" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_format" qualifiers="const"> + <return type="int" enum="Image.Format"> + </return> + <description> + </description> + </method> + <method name="get_height" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_width" qualifiers="const"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="has_mipmaps" qualifiers="const"> + <return type="bool"> + </return> + <description> + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml index 6451b3f330..01d569d9c8 100644 --- a/doc/classes/VisualInstance3D.xml +++ b/doc/classes/VisualInstance3D.xml @@ -13,7 +13,7 @@ <return type="AABB"> </return> <description> - Returns the [AABB] (also known as the bounding box) for this [VisualInstance3D]. + Returns the [AABB] (also known as the bounding box) for this [VisualInstance3D]. See also [method get_transformed_aabb]. </description> </method> <method name="get_base" qualifiers="const"> @@ -44,7 +44,7 @@ </return> <description> Returns the transformed [AABB] (also known as the bounding box) for this [VisualInstance3D]. - Transformed in this case means the [AABB] plus the position, rotation, and scale of the [Node3D]'s [Transform]. + Transformed in this case means the [AABB] plus the position, rotation, and scale of the [Node3D]'s [Transform]. See also [method get_aabb]. </description> </method> <method name="set_base"> diff --git a/doc/classes/VisualShader.xml b/doc/classes/VisualShader.xml index 40b0f52469..f03550bd5e 100644 --- a/doc/classes/VisualShader.xml +++ b/doc/classes/VisualShader.xml @@ -193,7 +193,6 @@ </method> </methods> <members> - <member name="code" type="String" setter="set_code" getter="get_code" override="true" default=""shader_type spatial;void vertex() {// Output:0}void fragment() {// Output:0}void light() {// Output:0}"" /> <member name="graph_offset" type="Vector2" setter="set_graph_offset" getter="get_graph_offset" default="Vector2( 0, 0 )"> The offset vector of the whole graph. </member> @@ -210,7 +209,13 @@ <constant name="TYPE_LIGHT" value="2" enum="Type"> A shader for light calculations. </constant> - <constant name="TYPE_MAX" value="3" enum="Type"> + <constant name="TYPE_EMIT" value="3" enum="Type"> + </constant> + <constant name="TYPE_PROCESS" value="4" enum="Type"> + </constant> + <constant name="TYPE_END" value="5" enum="Type"> + </constant> + <constant name="TYPE_MAX" value="6" enum="Type"> Represents the size of the [enum Type] enum. </constant> <constant name="NODE_ID_INVALID" value="-1"> diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml index 6327ab534f..3bb527f3d4 100644 --- a/doc/classes/VisualShaderNode.xml +++ b/doc/classes/VisualShaderNode.xml @@ -57,6 +57,12 @@ Emitted when the node requests an editor refresh. Currently called only in setter of [member VisualShaderNodeTexture.source], [VisualShaderNodeTexture], and [VisualShaderNodeCubemap] (and their derivatives). </description> </signal> + <signal name="show_port_preview"> + <argument index="0" name="port_id" type="int"> + </argument> + <description> + </description> + </signal> </signals> <constants> <constant name="PORT_TYPE_SCALAR" value="0" enum="PortType"> diff --git a/doc/classes/VisualShaderNodeCustom.xml b/doc/classes/VisualShaderNodeCustom.xml index 3be9b803e9..59b501660a 100644 --- a/doc/classes/VisualShaderNodeCustom.xml +++ b/doc/classes/VisualShaderNodeCustom.xml @@ -5,9 +5,9 @@ </brief_description> <description> By inheriting this class you can create a custom [VisualShader] script addon which will be automatically added to the Visual Shader Editor. The [VisualShaderNode]'s behavior is defined by overriding the provided virtual methods. - In order for the node to be registered as an editor addon, you must use the [code]tool[/code] keyword and provide a [code]class_name[/code] for your custom script. For example: + In order for the node to be registered as an editor addon, you must use the [code]@tool[/code] annotation and provide a [code]class_name[/code] for your custom script. For example: [codeblock] - tool + @tool extends VisualShaderNodeCustom class_name VisualShaderNodeNoise [/codeblock] diff --git a/doc/classes/VisualShaderNodeTexture.xml b/doc/classes/VisualShaderNodeTexture.xml index 8e389e0b40..0c83ffffe4 100644 --- a/doc/classes/VisualShaderNodeTexture.xml +++ b/doc/classes/VisualShaderNodeTexture.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeTexture" inherits="VisualShaderNode" version="4.0"> <brief_description> - Performs a texture lookup within the visual shader graph. + Performs a 2D texture lookup within the visual shader graph. </brief_description> <description> Performs a lookup operation on the provided texture, with support for multiple texture sources to choose from. diff --git a/doc/classes/VisualShaderNodeTexture3D.xml b/doc/classes/VisualShaderNodeTexture3D.xml new file mode 100644 index 0000000000..17929e823e --- /dev/null +++ b/doc/classes/VisualShaderNodeTexture3D.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeTexture3D" inherits="VisualShaderNodeSample3D" version="4.0"> + <brief_description> + Performs a 3D texture lookup within the visual shader graph. + </brief_description> + <description> + Performs a lookup operation on the provided texture, with support for multiple texture sources to choose from. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <members> + <member name="texture" type="Texture3D" setter="set_texture" getter="get_texture"> + A source texture. Used if [member VisualShaderNodeSample3D.source] is set to [constant VisualShaderNodeSample3D.SOURCE_TEXTURE]. + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/VisualShaderNodeTexture3DUniform.xml b/doc/classes/VisualShaderNodeTexture3DUniform.xml new file mode 100644 index 0000000000..d9e9acf117 --- /dev/null +++ b/doc/classes/VisualShaderNodeTexture3DUniform.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeTexture3DUniform" inherits="VisualShaderNodeTextureUniform" version="4.0"> + <brief_description> + Provides a 3D texture uniform within the visual shader graph. + </brief_description> + <description> + Translated to [code]uniform sampler3D[/code] in the shader language. + </description> + <tutorials> + </tutorials> + <methods> + </methods> + <constants> + </constants> +</class> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index b594f652b3..ed147f31cd 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -1041,7 +1041,7 @@ def make_footer(): # type: () -> str return ( ".. |virtual| replace:: :abbr:`virtual (This method should typically be overridden by the user to have any effect.)`\n" ".. |const| replace:: :abbr:`const (This method has no side effects. It doesn't modify any of the instance's member variables.)`\n" - ".. |vararg| replace:: :abbr:`vararg (This method accepts any number of arguments after the ones described here.)`" + ".. |vararg| replace:: :abbr:`vararg (This method accepts any number of arguments after the ones described here.)`\n" ) # fmt: on diff --git a/doc/translations/classes.pot b/doc/translations/classes.pot index 0e89e02762..7f352bce28 100644 --- a/doc/translations/classes.pot +++ b/doc/translations/classes.pot @@ -41208,7 +41208,7 @@ msgid "" "result, it should not be depended upon for reproducible random streams " "across Godot versions.\n" "To generate a random float number (within a given range) based on a time-" -"dependant seed:\n" +"dependent seed:\n" "[codeblock]\n" "var rng = RandomNumberGenerator.new()\n" "func _ready():\n" diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h index 7aec0c4071..d1220d126e 100644 --- a/drivers/alsa/audio_driver_alsa.h +++ b/drivers/alsa/audio_driver_alsa.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef ALSA_ENABLED - #ifndef AUDIO_DRIVER_ALSA_H #define AUDIO_DRIVER_ALSA_H +#ifdef ALSA_ENABLED + #include "core/os/mutex.h" #include "core/os/thread.h" #include "servers/audio_server.h" @@ -88,6 +88,6 @@ public: ~AudioDriverALSA() {} }; -#endif // AUDIO_DRIVER_ALSA_H - #endif // ALSA_ENABLED + +#endif // AUDIO_DRIVER_ALSA_H diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h index e8ed6df5b0..6aabe8e3fd 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef ALSAMIDI_ENABLED - #ifndef MIDI_DRIVER_ALSAMIDI_H #define MIDI_DRIVER_ALSAMIDI_H +#ifdef ALSAMIDI_ENABLED + #include "core/os/midi_driver.h" #include "core/os/mutex.h" #include "core/os/thread.h" @@ -64,5 +64,6 @@ public: virtual ~MIDIDriverALSAMidi(); }; -#endif // MIDI_DRIVER_ALSAMIDI_H #endif // ALSAMIDI_ENABLED + +#endif // MIDI_DRIVER_ALSAMIDI_H diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h index 2f2ad0fc38..35ccae94b8 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.h +++ b/drivers/pulseaudio/audio_driver_pulseaudio.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef PULSEAUDIO_ENABLED - #ifndef AUDIO_DRIVER_PULSEAUDIO_H #define AUDIO_DRIVER_PULSEAUDIO_H +#ifdef PULSEAUDIO_ENABLED + #include "core/os/mutex.h" #include "core/os/thread.h" #include "servers/audio_server.h" @@ -124,6 +124,6 @@ public: ~AudioDriverPulseAudio() {} }; -#endif // AUDIO_DRIVER_PULSEAUDIO_H - #endif // PULSEAUDIO_ENABLED + +#endif // AUDIO_DRIVER_PULSEAUDIO_H diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp index 06bad9f385..51c657007c 100644 --- a/drivers/unix/file_access_unix.cpp +++ b/drivers/unix/file_access_unix.cpp @@ -78,7 +78,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) { path_src = p_path; path = fix_path(p_path); - //printf("opening %ls, %i\n", path.c_str(), Memory::get_static_mem_usage()); + //printf("opening %s, %i\n", path.utf8().get_data(), Memory::get_static_mem_usage()); ERR_FAIL_COND_V_MSG(f, ERR_ALREADY_IN_USE, "File is already in use."); const char *mode_string; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 3c212cadb8..96c338f86b 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -48,7 +48,7 @@ #include <mach/mach_time.h> #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #include <sys/param.h> #include <sys/sysctl.h> #endif @@ -171,52 +171,53 @@ double OS_Unix::get_unix_time() const { OS::Date OS_Unix::get_date(bool utc) const { time_t t = time(nullptr); - struct tm *lt; + struct tm lt; if (utc) { - lt = gmtime(&t); + gmtime_r(&t, <); } else { - lt = localtime(&t); + localtime_r(&t, <); } Date ret; - ret.year = 1900 + lt->tm_year; + ret.year = 1900 + lt.tm_year; // Index starting at 1 to match OS_Unix::get_date // and Windows SYSTEMTIME and tm_mon follows the typical structure // of 0-11, noted here: http://www.cplusplus.com/reference/ctime/tm/ - ret.month = (Month)(lt->tm_mon + 1); - ret.day = lt->tm_mday; - ret.weekday = (Weekday)lt->tm_wday; - ret.dst = lt->tm_isdst; + ret.month = (Month)(lt.tm_mon + 1); + ret.day = lt.tm_mday; + ret.weekday = (Weekday)lt.tm_wday; + ret.dst = lt.tm_isdst; return ret; } OS::Time OS_Unix::get_time(bool utc) const { time_t t = time(nullptr); - struct tm *lt; + struct tm lt; if (utc) { - lt = gmtime(&t); + gmtime_r(&t, <); } else { - lt = localtime(&t); + localtime_r(&t, <); } Time ret; - ret.hour = lt->tm_hour; - ret.min = lt->tm_min; - ret.sec = lt->tm_sec; + ret.hour = lt.tm_hour; + ret.min = lt.tm_min; + ret.sec = lt.tm_sec; get_time_zone_info(); return ret; } OS::TimeZoneInfo OS_Unix::get_time_zone_info() const { time_t t = time(nullptr); - struct tm *lt = localtime(&t); + struct tm lt; + localtime_r(&t, <); char name[16]; - strftime(name, 16, "%Z", lt); + strftime(name, 16, "%Z", <); name[15] = 0; TimeZoneInfo ret; ret.name = name; char bias_buf[16]; - strftime(bias_buf, 16, "%z", lt); + strftime(bias_buf, 16, "%z", <); int bias; bias_buf[15] = 0; sscanf(bias_buf, "%d", &bias); @@ -476,7 +477,7 @@ String OS_Unix::get_executable_path() const { return OS::get_executable_path(); } return b; -#elif defined(__OpenBSD__) +#elif defined(__OpenBSD__) || defined(__NetBSD__) char resolved_path[MAXPATHLEN]; realpath(OS::get_executable_path().utf8().get_data(), resolved_path); diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp index aa1b5019ca..285088342b 100644 --- a/drivers/unix/thread_posix.cpp +++ b/drivers/unix/thread_posix.cpp @@ -29,17 +29,17 @@ /*************************************************************************/ #include "thread_posix.h" -#include "core/script_language.h" #if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS) +#include "core/os/memory.h" +#include "core/safe_refcount.h" +#include "core/script_language.h" + #ifdef PTHREAD_BSD_SET_NAME #include <pthread_np.h> #endif -#include "core/os/memory.h" -#include "core/safe_refcount.h" - static void _thread_id_key_destr_callback(void *p_value) { memdelete(static_cast<Thread::ID *>(p_value)); } @@ -126,6 +126,8 @@ Error ThreadPosix::set_name_func_posix(const String &p_name) { #ifdef PTHREAD_BSD_SET_NAME pthread_set_name_np(running_thread, p_name.utf8().get_data()); int err = 0; // Open/FreeBSD ignore errors in this function +#elif defined(PTHREAD_NETBSD_SET_NAME) + int err = pthread_setname_np(running_thread, "%s", const_cast<char *>(p_name.utf8().get_data())); #else int err = pthread_setname_np(running_thread, p_name.utf8().get_data()); #endif // PTHREAD_BSD_SET_NAME diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index fb890491a4..9fe3f7e6c0 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -3650,7 +3650,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa //print_line("DEBUG: SAMPLER: texel buffer"); } else { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' is of unsupported buffer type."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported buffer type."; } return false; } @@ -3673,7 +3673,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa } else { //print_line("DEBUG: sampler unknown"); if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' is of unsupported sampler type."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported sampler type."; } return false; } @@ -3698,7 +3698,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa if (reflection.getType()->getQualifier().layoutPushConstant) { uint32_t len = reflection.size; if (push_constant.push_constant_size != 0 && push_constant.push_constant_size != len) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' push constants for different stages should all be the same size."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' push constants for different stages should all be the same size."; return false; } push_constant.push_constant_size = len; @@ -3714,7 +3714,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa //print_line("DEBUG: Storage buffer"); } else { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' is of unsupported block type: (" + itos(reflection.getType()->getQualifier().storage) + ")."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' is of unsupported block type: (" + itos(reflection.getType()->getQualifier().storage) + ")."; } return false; } @@ -3743,7 +3743,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa } if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' unsupported uniform type."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' unsupported uniform type."; } return false; } @@ -3751,7 +3751,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa if (!reflection.getType()->getQualifier().hasBinding()) { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' lacks a binding number."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' lacks a binding number."; } return false; } @@ -3760,14 +3760,14 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa if (set >= MAX_UNIFORM_SETS) { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ")."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ")."; } return false; } if (set >= limits.maxBoundDescriptorSets) { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ")."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ")."; } return false; } @@ -3781,7 +3781,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa //already exists, verify that it's the same type if (bindings[set][i].descriptorType != layout_binding.descriptorType) { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform type."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform type."; } return false; } @@ -3789,7 +3789,7 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa //also, verify that it's the same size if (bindings[set][i].descriptorCount != layout_binding.descriptorCount || uniform_infos[set][i].length != info.length) { if (r_error) { - *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name.c_str() + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform size."; + *r_error = "On shader stage '" + String(shader_stage_names[p_stage]) + "', uniform '" + reflection.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(binding) + " with different uniform size."; } return false; } diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index b8153907a9..03e4e30797 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -65,7 +65,7 @@ Error DirAccessWindows::list_dir_begin() { _cishidden = false; list_dir_end(); - p->h = FindFirstFileExW((current_dir + "\\*").c_str(), FindExInfoStandard, &p->fu, FindExSearchNameMatch, nullptr, 0); + p->h = FindFirstFileExW((LPCWSTR)(String(current_dir + "\\*").utf16().get_data()), FindExInfoStandard, &p->fu, FindExSearchNameMatch, nullptr, 0); if (p->h == INVALID_HANDLE_VALUE) { return ERR_CANT_OPEN; @@ -75,13 +75,14 @@ Error DirAccessWindows::list_dir_begin() { } String DirAccessWindows::get_next() { - if (p->h == INVALID_HANDLE_VALUE) + if (p->h == INVALID_HANDLE_VALUE) { return ""; + } _cisdir = (p->fu.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); _cishidden = (p->fu.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN); - String name = p->fu.cFileName; + String name = String::utf16((const char16_t *)(p->fu.cFileName)); if (FindNextFileW(p->h, &p->fu) == 0) { FindClose(p->h); @@ -111,8 +112,9 @@ int DirAccessWindows::get_drive_count() { } String DirAccessWindows::get_drive(int p_drive) { - if (p_drive < 0 || p_drive >= drive_count) + if (p_drive < 0 || p_drive >= drive_count) { return ""; + } return String::chr(drives[p_drive]) + ":"; } @@ -122,18 +124,17 @@ Error DirAccessWindows::change_dir(String p_dir) { p_dir = fix_path(p_dir); - wchar_t real_current_dir_name[2048]; + WCHAR real_current_dir_name[2048]; GetCurrentDirectoryW(2048, real_current_dir_name); - String prev_dir = real_current_dir_name; + String prev_dir = String::utf16((const char16_t *)real_current_dir_name); - SetCurrentDirectoryW(current_dir.c_str()); - bool worked = (SetCurrentDirectoryW(p_dir.c_str()) != 0); + SetCurrentDirectoryW((LPCWSTR)(current_dir.utf16().get_data())); + bool worked = (SetCurrentDirectoryW((LPCWSTR)(p_dir.utf16().get_data())) != 0); String base = _get_root_path(); if (base != "") { GetCurrentDirectoryW(2048, real_current_dir_name); - String new_dir; - new_dir = String(real_current_dir_name).replace("\\", "/"); + String new_dir = String::utf16((const char16_t *)real_current_dir_name).replace("\\", "/"); if (!new_dir.begins_with(base)) { worked = false; } @@ -141,13 +142,11 @@ Error DirAccessWindows::change_dir(String p_dir) { if (worked) { GetCurrentDirectoryW(2048, real_current_dir_name); - current_dir = real_current_dir_name; // TODO, utf8 parser + current_dir = String::utf16((const char16_t *)real_current_dir_name); current_dir = current_dir.replace("\\", "/"); + } - } //else { - - SetCurrentDirectoryW(prev_dir.c_str()); - //} + SetCurrentDirectoryW((LPCWSTR)(prev_dir.utf16().get_data())); return worked ? OK : ERR_INVALID_PARAMETER; } @@ -156,8 +155,9 @@ Error DirAccessWindows::make_dir(String p_dir) { GLOBAL_LOCK_FUNCTION p_dir = fix_path(p_dir); - if (p_dir.is_rel_path()) + if (p_dir.is_rel_path()) { p_dir = current_dir.plus_file(p_dir); + } p_dir = p_dir.replace("/", "\\"); @@ -167,16 +167,16 @@ Error DirAccessWindows::make_dir(String p_dir) { p_dir = "\\\\?\\" + p_dir; //done according to // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx - success = CreateDirectoryW(p_dir.c_str(), nullptr); + success = CreateDirectoryW((LPCWSTR)(p_dir.utf16().get_data()), nullptr); err = GetLastError(); if (success) { return OK; - }; + } if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) { return ERR_ALREADY_EXISTS; - }; + } return ERR_CANT_CREATE; } @@ -185,12 +185,11 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) { String base = _get_root_path(); if (base != "") { String bd = current_dir.replace("\\", "/").replace_first(base, ""); - if (bd.begins_with("/")) + if (bd.begins_with("/")) { return _get_root_string() + bd.substr(1, bd.length()); - else + } else { return _get_root_string() + bd; - - } else { + } } if (p_include_drive) { @@ -209,20 +208,18 @@ String DirAccessWindows::get_current_dir(bool p_include_drive) { bool DirAccessWindows::file_exists(String p_file) { GLOBAL_LOCK_FUNCTION - if (!p_file.is_abs_path()) + if (!p_file.is_abs_path()) { p_file = get_current_dir().plus_file(p_file); + } p_file = fix_path(p_file); - //p_file.replace("/","\\"); - - //WIN32_FILE_ATTRIBUTE_DATA fileInfo; - DWORD fileAttr; - fileAttr = GetFileAttributesW(p_file.c_str()); - if (INVALID_FILE_ATTRIBUTES == fileAttr) + fileAttr = GetFileAttributesW((LPCWSTR)(p_file.utf16().get_data())); + if (INVALID_FILE_ATTRIBUTES == fileAttr) { return false; + } return !(fileAttr & FILE_ATTRIBUTE_DIRECTORY); } @@ -230,31 +227,30 @@ bool DirAccessWindows::file_exists(String p_file) { bool DirAccessWindows::dir_exists(String p_dir) { GLOBAL_LOCK_FUNCTION - if (p_dir.is_rel_path()) + if (p_dir.is_rel_path()) { p_dir = get_current_dir().plus_file(p_dir); + } p_dir = fix_path(p_dir); - //p_dir.replace("/","\\"); - - //WIN32_FILE_ATTRIBUTE_DATA fileInfo; - DWORD fileAttr; - - fileAttr = GetFileAttributesW(p_dir.c_str()); - if (INVALID_FILE_ATTRIBUTES == fileAttr) + fileAttr = GetFileAttributesW((LPCWSTR)(p_dir.utf16().get_data())); + if (INVALID_FILE_ATTRIBUTES == fileAttr) { return false; + } return (fileAttr & FILE_ATTRIBUTE_DIRECTORY); } Error DirAccessWindows::rename(String p_path, String p_new_path) { - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { p_path = get_current_dir().plus_file(p_path); + } p_path = fix_path(p_path); - if (p_new_path.is_rel_path()) + if (p_new_path.is_rel_path()) { p_new_path = get_current_dir().plus_file(p_new_path); + } p_new_path = fix_path(p_new_path); @@ -262,16 +258,16 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) { if (p_path.to_lower() == p_new_path.to_lower()) { WCHAR tmpfile[MAX_PATH]; - if (!GetTempFileNameW(fix_path(get_current_dir()).c_str(), nullptr, 0, tmpfile)) { + if (!GetTempFileNameW((LPCWSTR)(fix_path(get_current_dir()).utf16().get_data()), nullptr, 0, tmpfile)) { return FAILED; } - if (!::ReplaceFileW(tmpfile, p_path.c_str(), nullptr, 0, nullptr, nullptr)) { + if (!::ReplaceFileW(tmpfile, (LPCWSTR)(p_path.utf16().get_data()), nullptr, 0, nullptr, nullptr)) { DeleteFileW(tmpfile); return FAILED; } - return ::_wrename(tmpfile, p_new_path.c_str()) == 0 ? OK : FAILED; + return ::_wrename(tmpfile, (LPCWSTR)(p_new_path.utf16().get_data())) == 0 ? OK : FAILED; } else { if (file_exists(p_new_path)) { @@ -280,60 +276,60 @@ Error DirAccessWindows::rename(String p_path, String p_new_path) { } } - return ::_wrename(p_path.c_str(), p_new_path.c_str()) == 0 ? OK : FAILED; + return ::_wrename((LPCWSTR)(p_path.utf16().get_data()), (LPCWSTR)(p_new_path.utf16().get_data())) == 0 ? OK : FAILED; } } Error DirAccessWindows::remove(String p_path) { - if (p_path.is_rel_path()) + if (p_path.is_rel_path()) { p_path = get_current_dir().plus_file(p_path); + } p_path = fix_path(p_path); DWORD fileAttr; - fileAttr = GetFileAttributesW(p_path.c_str()); - if (INVALID_FILE_ATTRIBUTES == fileAttr) + fileAttr = GetFileAttributesW((LPCWSTR)(p_path.utf16().get_data())); + if (INVALID_FILE_ATTRIBUTES == fileAttr) { return FAILED; - if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY)) - return ::_wrmdir(p_path.c_str()) == 0 ? OK : FAILED; - else - return ::_wunlink(p_path.c_str()) == 0 ? OK : FAILED; + } + if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY)) { + return ::_wrmdir((LPCWSTR)(p_path.utf16().get_data())) == 0 ? OK : FAILED; + } else { + return ::_wunlink((LPCWSTR)(p_path.utf16().get_data())) == 0 ? OK : FAILED; + } } /* FileType DirAccessWindows::get_file_type(const String& p_file) const { + WCHAR real_current_dir_name[2048]; + GetCurrentDirectoryW(2048, real_current_dir_name); + String prev_dir = Strong::utf16((const char16_t *)real_current_dir_name); - - wchar_t real_current_dir_name[2048]; - GetCurrentDirectoryW(2048,real_current_dir_name); - String prev_dir=real_current_dir_name; - - bool worked SetCurrentDirectoryW(current_dir.c_str()); + bool worked = SetCurrentDirectoryW((LPCWSTR)(current_dir.utf16().get_data())); DWORD attr; if (worked) { - - WIN32_FILE_ATTRIBUTE_DATA fileInfo; - attr = GetFileAttributesExW(p_file.c_str(), GetFileExInfoStandard, &fileInfo); - + WIN32_FILE_ATTRIBUTE_DATA fileInfo; + attr = GetFileAttributesExW((LPCWSTR)(p_file.utf16().get_data()), GetFileExInfoStandard, &fileInfo); } - SetCurrentDirectoryW(prev_dir.c_str()); + SetCurrentDirectoryW((LPCWSTR)(prev_dir.utf16().get_data())); - if (!worked) + if (!worked) { return FILE_TYPE_NONE; + } - - return (attr&FILE_ATTRIBUTE_DIRECTORY)?FILE_TYPE_ + return (attr & FILE_ATTRIBUTE_DIRECTORY) ? FILE_TYPE_ } */ size_t DirAccessWindows::get_space_left() { uint64_t bytes = 0; - if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) + if (!GetDiskFreeSpaceEx(nullptr, (PULARGE_INTEGER)&bytes, nullptr, nullptr)) { return 0; + } //this is either 0 or a value in bytes. return (size_t)bytes; @@ -352,7 +348,7 @@ String DirAccessWindows::get_filesystem_type() const { DWORD dwMaxFileNameLength = 0; DWORD dwFileSystemFlags = 0; - if (::GetVolumeInformationW(unit.c_str(), + if (::GetVolumeInformationW((LPCWSTR)(unit.utf16().get_data()), szVolumeName, sizeof(szVolumeName), &dwSerialNumber, @@ -360,7 +356,7 @@ String DirAccessWindows::get_filesystem_type() const { &dwFileSystemFlags, szFileSystemName, sizeof(szFileSystemName)) == TRUE) { - return String(szFileSystemName); + return String::utf16((const char16_t *)szFileSystemName); } ERR_FAIL_V(""); diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 50366d0b2d..dd86061ea7 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -59,29 +59,32 @@ void FileAccessWindows::check_errors() const { Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { path_src = p_path; path = fix_path(p_path); - if (f) + if (f) { close(); + } - const wchar_t *mode_string; + const WCHAR *mode_string; - if (p_mode_flags == READ) + if (p_mode_flags == READ) { mode_string = L"rb"; - else if (p_mode_flags == WRITE) + } else if (p_mode_flags == WRITE) { mode_string = L"wb"; - else if (p_mode_flags == READ_WRITE) + } else if (p_mode_flags == READ_WRITE) { mode_string = L"rb+"; - else if (p_mode_flags == WRITE_READ) + } else if (p_mode_flags == WRITE_READ) { mode_string = L"wb+"; - else + } else { return ERR_INVALID_PARAMETER; + } /* pretty much every implementation that uses fopen as primary backend supports utf8 encoding */ struct _stat st; - if (_wstat(path.c_str(), &st) == 0) { - if (!S_ISREG(st.st_mode)) + if (_wstat((LPCWSTR)(path.utf16().get_data()), &st) == 0) { + if (!S_ISREG(st.st_mode)) { return ERR_FILE_CANT_OPEN; + } }; #ifdef TOOLS_ENABLED @@ -91,9 +94,9 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { // platforms). if (p_mode_flags == READ) { WIN32_FIND_DATAW d; - HANDLE f = FindFirstFileW(path.c_str(), &d); + HANDLE f = FindFirstFileW((LPCWSTR)(path.utf16().get_data()), &d); if (f != INVALID_HANDLE_VALUE) { - String fname = d.cFileName; + String fname = String::utf16((const char16_t *)(d.cFileName)); if (fname != String()) { String base_file = path.get_file(); if (base_file != fname && base_file.findn(fname) == 0) { @@ -110,7 +113,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { path = path + ".tmp"; } - errno_t errcode = _wfopen_s(&f, path.c_str(), mode_string); + errno_t errcode = _wfopen_s(&f, (LPCWSTR)(path.utf16().get_data()), mode_string); if (f == nullptr) { switch (errcode) { @@ -130,8 +133,9 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) { } void FileAccessWindows::close() { - if (!f) + if (!f) { return; + } fclose(f); f = nullptr; @@ -148,16 +152,16 @@ void FileAccessWindows::close() { // UWP has no PathFileExists, so we check attributes instead DWORD fileAttr; - fileAttr = GetFileAttributesW(save_path.c_str()); + fileAttr = GetFileAttributesW((LPCWSTR)(save_path.utf16().get_data())); if (INVALID_FILE_ATTRIBUTES == fileAttr) { #else - if (!PathFileExistsW(save_path.c_str())) { + if (!PathFileExistsW((LPCWSTR)(save_path.utf16().get_data()))) { #endif //creating new file - rename_error = _wrename((save_path + ".tmp").c_str(), save_path.c_str()) != 0; + rename_error = _wrename((LPCWSTR)((save_path + ".tmp").utf16().get_data()), (LPCWSTR)(save_path.utf16().get_data())) != 0; } else { //atomic replace for existing file - rename_error = !ReplaceFileW(save_path.c_str(), (save_path + ".tmp").c_str(), nullptr, 2 | 4, nullptr, nullptr); + rename_error = !ReplaceFileW((LPCWSTR)(save_path.utf16().get_data()), (LPCWSTR)((save_path + ".tmp").utf16().get_data()), nullptr, 2 | 4, nullptr, nullptr); } if (rename_error) { attempts--; @@ -192,15 +196,17 @@ bool FileAccessWindows::is_open() const { void FileAccessWindows::seek(size_t p_position) { ERR_FAIL_COND(!f); last_error = OK; - if (fseek(f, p_position, SEEK_SET)) + if (fseek(f, p_position, SEEK_SET)) { check_errors(); + } prev_op = 0; } void FileAccessWindows::seek_end(int64_t p_position) { ERR_FAIL_COND(!f); - if (fseek(f, p_position, SEEK_END)) + if (fseek(f, p_position, SEEK_END)) { check_errors(); + } prev_op = 0; } @@ -209,7 +215,7 @@ size_t FileAccessWindows::get_position() const { aux_position = ftell(f); if (!aux_position) { check_errors(); - }; + } return aux_position; } @@ -241,7 +247,7 @@ uint8_t FileAccessWindows::get_8() const { if (fread(&b, 1, 1, f) == 0) { check_errors(); b = '\0'; - }; + } return b; } @@ -266,8 +272,9 @@ Error FileAccessWindows::get_error() const { void FileAccessWindows::flush() { ERR_FAIL_COND(!f); fflush(f); - if (prev_op == WRITE) + if (prev_op == WRITE) { prev_op = 0; + } } void FileAccessWindows::store_8(uint8_t p_dest) { @@ -298,9 +305,9 @@ void FileAccessWindows::store_buffer(const uint8_t *p_src, int p_length) { bool FileAccessWindows::file_exists(const String &p_name) { FILE *g; - //printf("opening file %s\n", p_fname.c_str()); + //printf("opening file %s\n", p_fname.utf8().get_data()); String filename = fix_path(p_name); - _wfopen_s(&g, filename.c_str(), L"rb"); + _wfopen_s(&g, (LPCWSTR)(filename.utf16().get_data()), L"rb"); if (g == nullptr) { return false; } else { @@ -315,7 +322,7 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) { file = file.substr(0, file.length() - 1); struct _stat st; - int rv = _wstat(file.c_str(), &st); + int rv = _wstat((LPCWSTR)(file.utf16().get_data()), &st); if (rv == 0) { return st.st_mtime; diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 37db3ba780..ede6dde239 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -40,7 +40,7 @@ #include "scene/gui/separator.h" #include "scene/resources/dynamic_font.h" -void GotoLineDialog::popup_find_line(TextEdit *p_edit) { +void GotoLineDialog::popup_find_line(CodeEdit *p_edit) { text_editor = p_edit; line->set_text(itos(text_editor->cursor_get_line())); @@ -113,7 +113,7 @@ void FindReplaceBar::_unhandled_input(const Ref<InputEvent> &p_event) { } Control *focus_owner = get_focus_owner(); - if (text_edit->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) { + if (text_editor->has_focus() || (focus_owner && vbc_lineedit->is_a_parent_of(focus_owner))) { bool accepted = true; switch (k->get_keycode()) { @@ -135,20 +135,20 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) int line, col; String text = get_search_text(); - bool found = text_edit->search(text, p_flags, p_from_line, p_from_col, line, col); + bool found = text_editor->search(text, p_flags, p_from_line, p_from_col, line, col); if (found) { if (!preserve_cursor) { - text_edit->unfold_line(line); - text_edit->cursor_set_line(line, false); - text_edit->cursor_set_column(col + text.length(), false); - text_edit->center_viewport_to_cursor(); - text_edit->select(line, col, line, col + text.length()); + text_editor->unfold_line(line); + text_editor->cursor_set_line(line, false); + text_editor->cursor_set_column(col + text.length(), false); + text_editor->center_viewport_to_cursor(); + text_editor->select(line, col, line, col + text.length()); } - text_edit->set_search_text(text); - text_edit->set_search_flags(p_flags); - text_edit->set_current_search_result(line, col); + text_editor->set_search_text(text); + text_editor->set_search_flags(p_flags); + text_editor->set_current_search_result(line, col); result_line = line; result_col = col; @@ -158,9 +158,9 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) results_count = 0; result_line = -1; result_col = -1; - text_edit->set_search_text(""); - text_edit->set_search_flags(p_flags); - text_edit->set_current_search_result(line, col); + text_editor->set_search_text(""); + text_editor->set_search_flags(p_flags); + text_editor->set_current_search_result(line, col); } _update_matches_label(); @@ -169,67 +169,67 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) } void FindReplaceBar::_replace() { - bool selection_enabled = text_edit->is_selection_active(); + bool selection_enabled = text_editor->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()); + selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column()); + selection_end = Point2i(text_editor->get_selection_to_line(), text_editor->get_selection_to_column()); } String replace_text = get_replace_text(); int search_text_len = get_search_text().length(); - text_edit->begin_complex_operation(); + text_editor->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); + text_editor->cursor_set_line(selection_begin.width); + text_editor->cursor_set_column(selection_begin.height); } if (search_current()) { - text_edit->unfold_line(result_line); - text_edit->select(result_line, result_col, result_line, result_col + search_text_len); + text_editor->unfold_line(result_line); + text_editor->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); + text_editor->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_editor->insert_text_at_cursor(replace_text); } } - text_edit->end_complex_operation(); + text_editor->end_complex_operation(); results_count = -1; 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); + text_editor->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); } else { - text_edit->deselect(); + text_editor->deselect(); } } void FindReplaceBar::_replace_all() { - text_edit->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); + text_editor->disconnect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); // Line as x so it gets priority in comparison, column as y. - Point2i orig_cursor(text_edit->cursor_get_line(), text_edit->cursor_get_column()); + Point2i orig_cursor(text_editor->cursor_get_line(), text_editor->cursor_get_column()); Point2i prev_match = Point2(-1, -1); - bool selection_enabled = text_edit->is_selection_active(); + bool selection_enabled = text_editor->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()); + selection_begin = Point2i(text_editor->get_selection_from_line(), text_editor->get_selection_from_column()); + selection_end = Point2i(text_editor->get_selection_to_line(), text_editor->get_selection_to_column()); } - int vsval = text_edit->get_v_scroll(); + int vsval = text_editor->get_v_scroll(); - text_edit->cursor_set_line(0); - text_edit->cursor_set_column(0); + text_editor->cursor_set_line(0); + text_editor->cursor_set_column(0); String replace_text = get_replace_text(); int search_text_len = get_search_text().length(); @@ -238,11 +238,11 @@ void FindReplaceBar::_replace_all() { replace_all_mode = true; - text_edit->begin_complex_operation(); + text_editor->begin_complex_operation(); if (selection_enabled && is_selection_only()) { - text_edit->cursor_set_line(selection_begin.width); - text_edit->cursor_set_column(selection_begin.height); + text_editor->cursor_set_line(selection_begin.width); + text_editor->cursor_set_column(selection_begin.height); } if (search_current()) { do { @@ -256,8 +256,8 @@ void FindReplaceBar::_replace_all() { prev_match = Point2i(result_line, result_col + replace_text.length()); - text_edit->unfold_line(result_line); - text_edit->select(result_line, result_col, result_line, match_to.y); + text_editor->unfold_line(result_line); + text_editor->select(result_line, result_col, result_line, match_to.y); if (selection_enabled && is_selection_only()) { if (match_from < selection_begin || match_to > selection_end) { @@ -265,48 +265,48 @@ void FindReplaceBar::_replace_all() { } // Replace but adjust selection bounds. - text_edit->insert_text_at_cursor(replace_text); + text_editor->insert_text_at_cursor(replace_text); if (match_to.x == selection_end.x) { selection_end.y += replace_text.length() - search_text_len; } } else { // Just replace. - text_edit->insert_text_at_cursor(replace_text); + text_editor->insert_text_at_cursor(replace_text); } rc++; } while (search_next()); } - text_edit->end_complex_operation(); + text_editor->end_complex_operation(); replace_all_mode = false; // Restore editor state (selection, cursor, scroll). - text_edit->cursor_set_line(orig_cursor.x); - text_edit->cursor_set_column(orig_cursor.y); + text_editor->cursor_set_line(orig_cursor.x); + text_editor->cursor_set_column(orig_cursor.y); if (selection_enabled && is_selection_only()) { // Reselect. - text_edit->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); + text_editor->select(selection_begin.x, selection_begin.y, selection_end.x, selection_end.y); } else { - text_edit->deselect(); + text_editor->deselect(); } - text_edit->set_v_scroll(vsval); + text_editor->set_v_scroll(vsval); matches_label->add_theme_color_override("font_color", rc > 0 ? get_theme_color("font_color", "Label") : get_theme_color("error_color", "Editor")); matches_label->set_text(vformat(TTR("%d replaced."), rc)); - text_edit->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed")); + text_editor->call_deferred("connect", "text_changed", Callable(this, "_editor_text_changed")); results_count = -1; } void FindReplaceBar::_get_search_from(int &r_line, int &r_col) { - r_line = text_edit->cursor_get_line(); - r_col = text_edit->cursor_get_column(); + r_line = text_editor->cursor_get_line(); + r_col = text_editor->cursor_get_column(); - if (text_edit->is_selection_active() && is_selection_only()) { + if (text_editor->is_selection_active() && is_selection_only()) { return; } @@ -327,7 +327,7 @@ void FindReplaceBar::_update_results_count() { return; } - String full_text = text_edit->get_text(); + String full_text = text_editor->get_text(); int from_pos = 0; @@ -399,7 +399,7 @@ bool FindReplaceBar::search_prev() { int line, col; _get_search_from(line, col); - if (text_edit->is_selection_active()) { + if (text_editor->is_selection_active()) { col--; // Skip currently selected word. } @@ -407,9 +407,9 @@ bool FindReplaceBar::search_prev() { if (col < 0) { line -= 1; if (line < 0) { - line = text_edit->get_line_count() - 1; + line = text_editor->get_line_count() - 1; } - col = text_edit->get_line(line).length(); + col = text_editor->get_line(line).length(); } return _search(flags, line, col); @@ -440,9 +440,9 @@ bool FindReplaceBar::search_next() { if (line == result_line && col == result_col) { col += text.length(); - if (col > text_edit->get_line(line).length()) { + if (col > text_editor->get_line(line).length()) { line += 1; - if (line >= text_edit->get_line_count()) { + if (line >= text_editor->get_line_count()) { line = 0; } col = 0; @@ -454,10 +454,10 @@ bool FindReplaceBar::search_next() { void FindReplaceBar::_hide_bar() { if (replace_text->has_focus() || search_text->has_focus()) { - text_edit->grab_focus(); + text_editor->grab_focus(); } - text_edit->set_search_text(""); + text_editor->set_search_text(""); result_line = -1; result_col = -1; hide(); @@ -477,8 +477,8 @@ void FindReplaceBar::_show_search(bool p_focus_replace, bool p_show_only) { search_text->call_deferred("grab_focus"); } - if (text_edit->is_selection_active() && !selection_only->is_pressed()) { - search_text->set_text(text_edit->get_selection_text()); + if (text_editor->is_selection_active() && !selection_only->is_pressed()) { + search_text->set_text(text_editor->get_selection_text()); } if (!get_search_text().empty()) { @@ -511,9 +511,9 @@ void FindReplaceBar::popup_replace() { hbc_option_replace->show(); } - selection_only->set_pressed((text_edit->is_selection_active() && text_edit->get_selection_from_line() < text_edit->get_selection_to_line())); + selection_only->set_pressed((text_editor->is_selection_active() && text_editor->get_selection_from_line() < text_editor->get_selection_to_line())); - _show_search(is_visible() || text_edit->is_selection_active()); + _show_search(is_visible() || text_editor->is_selection_active()); } void FindReplaceBar::_search_options_changed(bool p_pressed) { @@ -544,7 +544,7 @@ void FindReplaceBar::_search_text_entered(const String &p_text) { } void FindReplaceBar::_replace_text_entered(const String &p_text) { - if (selection_only->is_pressed() && text_edit->is_selection_active()) { + if (selection_only->is_pressed() && text_editor->is_selection_active()) { _replace_all(); _hide_bar(); } else if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { @@ -579,10 +579,10 @@ void FindReplaceBar::set_error(const String &p_label) { emit_signal("error", p_label); } -void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) { +void FindReplaceBar::set_text_edit(CodeEdit *p_text_edit) { results_count = -1; - text_edit = p_text_edit; - text_edit->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); + text_editor = p_text_edit; + text_editor->connect("text_changed", callable_mp(this, &FindReplaceBar::_editor_text_changed)); } void FindReplaceBar::_bind_methods() { @@ -932,11 +932,9 @@ void CodeTextEditor::update_editor_settings() { text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed")); text_editor->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap")); text_editor->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE); - text_editor->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); + text_editor->set_draw_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); text_editor->set_line_numbers_zero_padded(EditorSettings::get_singleton()->get("text_editor/appearance/line_numbers_zero_padded")); - text_editor->set_bookmark_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter")); - text_editor->set_breakpoint_gutter_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/show_breakpoint_gutter")); - text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter")); + text_editor->set_draw_bookmarks_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/show_bookmark_gutter")); text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding")); text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/appearance/code_folding")); text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/appearance/word_wrap")); @@ -1390,11 +1388,11 @@ void CodeTextEditor::goto_line_centered(int p_line) { } void CodeTextEditor::set_executing_line(int p_line) { - text_editor->set_executing_line(p_line); + text_editor->set_line_as_executing(p_line, true); } void CodeTextEditor::clear_executing_line() { - text_editor->clear_executing_line(); + text_editor->clear_executing_lines(); } Variant CodeTextEditor::get_edit_state() { @@ -1405,8 +1403,8 @@ Variant CodeTextEditor::get_edit_state() { state["column"] = text_editor->cursor_get_column(); state["row"] = text_editor->cursor_get_line(); - state["selection"] = get_text_edit()->is_selection_active(); - if (get_text_edit()->is_selection_active()) { + state["selection"] = get_text_editor()->is_selection_active(); + if (get_text_editor()->is_selection_active()) { state["selection_from_line"] = text_editor->get_selection_from_line(); state["selection_from_column"] = text_editor->get_selection_from_column(); state["selection_to_line"] = text_editor->get_selection_to_line(); @@ -1414,8 +1412,8 @@ Variant CodeTextEditor::get_edit_state() { } state["folded_lines"] = text_editor->get_folded_lines(); - state["breakpoints"] = text_editor->get_breakpoints_array(); - state["bookmarks"] = text_editor->get_bookmarks_array(); + state["breakpoints"] = text_editor->get_breakpointed_lines(); + state["bookmarks"] = text_editor->get_bookmarked_lines(); Ref<EditorSyntaxHighlighter> syntax_highlighter = text_editor->get_syntax_highlighter(); state["syntax_highlighter"] = syntax_highlighter->_get_name(); @@ -1453,7 +1451,7 @@ void CodeTextEditor::set_edit_state(const Variant &p_state) { if (state.has("bookmarks")) { Array bookmarks = state["bookmarks"]; for (int i = 0; i < bookmarks.size(); i++) { - text_editor->set_line_as_bookmark(bookmarks[i], true); + text_editor->set_line_as_bookmarked(bookmarks[i], true); } } } @@ -1591,27 +1589,26 @@ void CodeTextEditor::set_warning_nb(int p_warning_nb) { void CodeTextEditor::toggle_bookmark() { int line = text_editor->cursor_get_line(); - text_editor->set_line_as_bookmark(line, !text_editor->is_line_set_as_bookmark(line)); + text_editor->set_line_as_bookmarked(line, !text_editor->is_line_bookmarked(line)); } void CodeTextEditor::goto_next_bookmark() { - List<int> bmarks; - text_editor->get_bookmarks(&bmarks); + Array bmarks = text_editor->get_bookmarked_lines(); if (bmarks.size() <= 0) { return; } int line = text_editor->cursor_get_line(); - if (line >= bmarks[bmarks.size() - 1]) { + if (line >= (int)bmarks[bmarks.size() - 1]) { text_editor->unfold_line(bmarks[0]); text_editor->cursor_set_line(bmarks[0]); text_editor->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bmarks.front(); E; E = E->next()) { - int bline = E->get(); - if (bline > line) { - text_editor->unfold_line(bline); - text_editor->cursor_set_line(bline); + for (int i = 0; i < bmarks.size(); i++) { + int bmark_line = bmarks[i]; + if (bmark_line > line) { + text_editor->unfold_line(bmark_line); + text_editor->cursor_set_line(bmark_line); text_editor->center_viewport_to_cursor(); return; } @@ -1620,23 +1617,22 @@ void CodeTextEditor::goto_next_bookmark() { } void CodeTextEditor::goto_prev_bookmark() { - List<int> bmarks; - text_editor->get_bookmarks(&bmarks); + Array bmarks = text_editor->get_bookmarked_lines(); if (bmarks.size() <= 0) { return; } int line = text_editor->cursor_get_line(); - if (line <= bmarks[0]) { + if (line <= (int)bmarks[0]) { text_editor->unfold_line(bmarks[bmarks.size() - 1]); text_editor->cursor_set_line(bmarks[bmarks.size() - 1]); text_editor->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bmarks.back(); E; E = E->prev()) { - int bline = E->get(); - if (bline < line) { - text_editor->unfold_line(bline); - text_editor->cursor_set_line(bline); + for (int i = bmarks.size(); i >= 0; i--) { + int bmark_line = bmarks[i]; + if (bmark_line < line) { + text_editor->unfold_line(bmark_line); + text_editor->cursor_set_line(bmark_line); text_editor->center_viewport_to_cursor(); return; } @@ -1645,12 +1641,7 @@ void CodeTextEditor::goto_prev_bookmark() { } void CodeTextEditor::remove_all_bookmarks() { - List<int> bmarks; - text_editor->get_bookmarks(&bmarks); - - for (List<int>::Element *E = bmarks.front(); E; E = E->next()) { - text_editor->set_line_as_bookmark(E->get(), false); - } + text_editor->clear_bookmarked_lines(); } void CodeTextEditor::_bind_methods() { @@ -1681,7 +1672,7 @@ CodeTextEditor::CodeTextEditor() { ED_SHORTCUT("script_editor/zoom_out", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS); ED_SHORTCUT("script_editor/reset_zoom", TTR("Reset Zoom"), KEY_MASK_CMD | KEY_0); - text_editor = memnew(TextEdit); + text_editor = memnew(CodeEdit); add_child(text_editor); text_editor->set_v_size_flags(SIZE_EXPAND_FILL); @@ -1693,7 +1684,7 @@ CodeTextEditor::CodeTextEditor() { find_replace_bar->set_text_edit(text_editor); - text_editor->set_show_line_numbers(true); + text_editor->set_draw_line_numbers(true); text_editor->set_brace_matching(true); text_editor->set_auto_indent(true); diff --git a/editor/code_editor.h b/editor/code_editor.h index 450c85c64b..b38170cbf5 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -34,9 +34,9 @@ #include "editor/editor_plugin.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" +#include "scene/gui/code_edit.h" #include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" -#include "scene/gui/text_edit.h" #include "scene/main/timer.h" class GotoLineDialog : public ConfirmationDialog { @@ -45,15 +45,15 @@ class GotoLineDialog : public ConfirmationDialog { Label *line_label; LineEdit *line; - TextEdit *text_editor; + CodeEdit *text_editor; virtual void ok_pressed() override; public: - void popup_find_line(TextEdit *p_edit); + void popup_find_line(CodeEdit *p_edit); int get_line() const; - void set_text_editor(TextEdit *p_text_editor); + void set_text_editor(CodeEdit *p_text_editor); GotoLineDialog(); }; @@ -77,7 +77,7 @@ class FindReplaceBar : public HBoxContainer { HBoxContainer *hbc_button_replace; HBoxContainer *hbc_option_replace; - TextEdit *text_edit; + CodeEdit *text_editor; int result_line; int result_col; @@ -120,7 +120,7 @@ public: bool is_selection_only() const; void set_error(const String &p_label); - void set_text_edit(TextEdit *p_text_edit); + void set_text_edit(CodeEdit *p_text_edit); void popup_search(bool p_show_only = false); void popup_replace(); @@ -137,7 +137,7 @@ typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, class CodeTextEditor : public VBoxContainer { GDCLASS(CodeTextEditor, VBoxContainer); - TextEdit *text_editor; + CodeEdit *text_editor; FindReplaceBar *find_replace_bar; HBoxContainer *status_bar; @@ -240,7 +240,7 @@ public: void set_error(const String &p_error); void set_error_pos(int p_line, int p_column); void update_line_and_column() { _line_col_changed(); } - TextEdit *get_text_edit() { return text_editor; } + CodeEdit *get_text_editor() { return text_editor; } FindReplaceBar *get_find_replace_bar() { return find_replace_bar; } virtual void apply_code() {} void goto_error(); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index d3dff3f375..d1661fd7b3 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -714,7 +714,7 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) { const String &signalname = signal; String midname = selectedNode->get_name(); for (int i = 0; i < midname.length(); i++) { //TODO: Regex filter may be cleaner. - CharType c = midname[i]; + char32_t c = midname[i]; if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')) { if (c == ' ') { // Replace spaces with underlines. @@ -754,8 +754,9 @@ void ConnectionsDock::_open_connection_dialog(ConnectDialog::ConnectionData cToE Node *dst = static_cast<Node *>(cToEdit.target); if (src && dst) { + const String &signalname = cToEdit.signal; connect_dialog->set_title(TTR("Edit Connection:") + cToEdit.signal); - connect_dialog->popup_centered(); + connect_dialog->popup_dialog(signalname); connect_dialog->init(cToEdit, true); } } diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index aae476ccf4..cbde7d593a 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -144,7 +144,10 @@ EditorAbout::EditorAbout() { List<String> dev_sections; dev_sections.push_back(TTR("Project Founders")); dev_sections.push_back(TTR("Lead Developer")); - dev_sections.push_back(TTR("Project Manager ")); // " " appended to distinguish between 'project supervisor' and 'project list' + // TRANSLATORS: This refers to a job title. + // The trailing space is used to distinguish with the project list application, + // you do not have to keep it in your translation. + dev_sections.push_back(TTR("Project Manager ")); dev_sections.push_back(TTR("Developers")); const char *const *dev_src[] = { AUTHORS_FOUNDERS, AUTHORS_LEAD_DEVELOPERS, AUTHORS_PROJECT_MANAGERS, AUTHORS_DEVELOPERS }; diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h index 87c060d1f5..b6cf1183b5 100644 --- a/editor/editor_audio_buses.h +++ b/editor/editor_audio_buses.h @@ -230,7 +230,7 @@ private: render_db_value = n.render_db_value; } - _FORCE_INLINE_ AudioNotch operator=(const EditorAudioMeterNotches::AudioNotch &n) { + _FORCE_INLINE_ AudioNotch &operator=(const EditorAudioMeterNotches::AudioNotch &n) { relative_position = n.relative_position; db_value = n.db_value; render_db_value = n.render_db_value; diff --git a/editor/editor_builders.py b/editor/editor_builders.py index ea32e24f6e..86c5c87a68 100644 --- a/editor/editor_builders.py +++ b/editor/editor_builders.py @@ -54,7 +54,6 @@ def make_fonts_header(target, source, env): g.write("#define _EDITOR_FONTS_H\n") # saving uncompressed, since freetype will reference from memory pointer - xl_names = [] for i in range(len(source)): with open(source[i], "rb") as f: buf = f.read() diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 16e69734d3..1d7429eb64 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -32,6 +32,7 @@ #include "core/crypto/crypto_core.h" #include "core/io/config_file.h" +#include "core/io/file_access_encrypted.h" #include "core/io/file_access_pack.h" // PACK_HEADER_MAGIC, PACK_FORMAT_VERSION #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" @@ -222,6 +223,42 @@ String EditorExportPreset::get_custom_features() const { return custom_features; } +void EditorExportPreset::set_enc_in_filter(const String &p_filter) { + enc_in_filters = p_filter; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_enc_in_filter() const { + return enc_in_filters; +} + +void EditorExportPreset::set_enc_ex_filter(const String &p_filter) { + enc_ex_filters = p_filter; + EditorExport::singleton->save_presets(); +} + +String EditorExportPreset::get_enc_ex_filter() const { + return enc_ex_filters; +} + +void EditorExportPreset::set_enc_pck(bool p_enabled) { + enc_pck = p_enabled; + EditorExport::singleton->save_presets(); +} + +bool EditorExportPreset::get_enc_pck() const { + return enc_pck; +} + +void EditorExportPreset::set_enc_directory(bool p_enabled) { + enc_directory = p_enabled; + EditorExport::singleton->save_presets(); +} + +bool EditorExportPreset::get_enc_directory() const { + return enc_directory; +} + void EditorExportPreset::set_script_export_mode(int p_mode) { script_mode = p_mode; EditorExport::singleton->save_presets(); @@ -292,20 +329,55 @@ void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags) } } -Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { +Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { PackData *pd = (PackData *)p_userdata; SavedData sd; sd.path_utf8 = p_path.utf8(); sd.ofs = pd->f->get_position(); sd.size = p_data.size(); + sd.encrypted = false; + + for (int i = 0; i < p_enc_in_filters.size(); ++i) { + if (p_path.matchn(p_enc_in_filters[i]) || p_path.replace("res://", "").matchn(p_enc_in_filters[i])) { + sd.encrypted = true; + break; + } + } + + for (int i = 0; i < p_enc_ex_filters.size(); ++i) { + if (p_path.matchn(p_enc_ex_filters[i]) || p_path.replace("res://", "").matchn(p_enc_ex_filters[i])) { + sd.encrypted = false; + break; + } + } - pd->f->store_buffer(p_data.ptr(), p_data.size()); - int pad = _get_pad(PCK_PADDING, sd.size); + FileAccessEncrypted *fae = nullptr; + FileAccess *ftmp = pd->f; + + if (sd.encrypted) { + fae = memnew(FileAccessEncrypted); + ERR_FAIL_COND_V(!fae, ERR_SKIP); + + Error err = fae->open_and_parse(ftmp, p_key, FileAccessEncrypted::MODE_WRITE_AES256, false); + ERR_FAIL_COND_V(err != OK, ERR_SKIP); + ftmp = fae; + } + + // Store file content. + ftmp->store_buffer(p_data.ptr(), p_data.size()); + + if (fae) { + fae->release(); + memdelete(fae); + } + + int pad = _get_pad(PCK_PADDING, pd->f->get_position()); for (int i = 0; i < pad; i++) { - pd->f->store_8(0); + pd->f->store_8(Math::rand() % 256); } + // Store MD5 of original file. { unsigned char hash[16]; CryptoCore::md5(p_data.ptr(), p_data.size(), hash); @@ -324,7 +396,7 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa return OK; } -Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { +Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { String path = p_path.replace_first("res://", ""); ZipData *zd = (ZipData *)p_userdata; @@ -694,6 +766,61 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & _edit_filter_list(paths, p_preset->get_include_filter(), false); _edit_filter_list(paths, p_preset->get_exclude_filter(), true); + // Get encryption filters. + bool enc_pck = p_preset->get_enc_pck(); + Vector<String> enc_in_filters; + Vector<String> enc_ex_filters; + Vector<uint8_t> key; + + if (enc_pck) { + Vector<String> enc_in_split = p_preset->get_enc_in_filter().split(","); + for (int i = 0; i < enc_in_split.size(); i++) { + String f = enc_in_split[i].strip_edges(); + if (f.empty()) { + continue; + } + enc_in_filters.push_back(f); + } + + Vector<String> enc_ex_split = p_preset->get_enc_ex_filter().split(","); + for (int i = 0; i < enc_ex_split.size(); i++) { + String f = enc_ex_split[i].strip_edges(); + if (f.empty()) { + continue; + } + enc_ex_filters.push_back(f); + } + + // Get encryption key. + String script_key = p_preset->get_script_encryption_key().to_lower(); + key.resize(32); + if (script_key.length() == 64) { + for (int i = 0; i < 32; i++) { + int v = 0; + if (i * 2 < script_key.length()) { + char32_t ct = script_key[i * 2]; + if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = 10 + ct - 'a'; + } + v |= ct << 4; + } + + if (i * 2 + 1 < script_key.length()) { + char32_t ct = script_key[i * 2 + 1]; + if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = 10 + ct - 'a'; + } + v |= ct; + } + key.write[i] = v; + } + } + } + Vector<Ref<EditorExportPlugin>> export_plugins = EditorExport::get_singleton()->get_export_plugins(); for (int i = 0; i < export_plugins.size(); i++) { export_plugins.write[i]->set_export_preset(p_preset); @@ -704,7 +831,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size()); + p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key); } export_plugins.write[i]->_clear(); @@ -756,14 +883,14 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & if (remap == "path") { String remapped_path = config->get_value("remap", remap); Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path); - err = p_func(p_udata, remapped_path, array, idx, total); + err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key); } else if (remap.begins_with("path.")) { String feature = remap.get_slice(".", 1); if (remap_features.has(feature)) { String remapped_path = config->get_value("remap", remap); Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path); - err = p_func(p_udata, remapped_path, array, idx, total); + err = p_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key); } } } @@ -774,7 +901,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & //also save the .import file Vector<uint8_t> array = FileAccess::get_file_as_array(path + ".import"); - err = p_func(p_udata, path + ".import", array, idx, total); + err = p_func(p_udata, path + ".import", array, idx, total, enc_in_filters, enc_ex_filters, key); if (err != OK) { return err; @@ -795,7 +922,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total); + p_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key); if (export_plugins[i]->extra_files[j].remap) { do_export = false; //if remap, do not path_remaps.push_back(path); @@ -815,7 +942,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & //just store it as it comes if (do_export) { Vector<uint8_t> array = FileAccess::get_file_as_array(path); - p_func(p_udata, path, array, idx, total); + p_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key); } } @@ -851,7 +978,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & new_file.write[j] = utf8[j]; } - p_func(p_udata, from + ".remap", new_file, idx, total); + p_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key); } } else { //old remap mode, will still work, but it's unused because it's not multiple pck export friendly @@ -864,11 +991,11 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & String splash = ProjectSettings::get_singleton()->get("application/boot_splash/image"); if (icon != String() && FileAccess::exists(icon)) { Vector<uint8_t> array = FileAccess::get_file_as_array(icon); - p_func(p_udata, icon, array, idx, total); + p_func(p_udata, icon, array, idx, total, enc_in_filters, enc_ex_filters, key); } if (splash != String() && FileAccess::exists(splash) && icon != splash) { Vector<uint8_t> array = FileAccess::get_file_as_array(splash); - p_func(p_udata, splash, array, idx, total); + p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key); } String config_file = "project.binary"; @@ -877,7 +1004,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> & Vector<uint8_t> data = FileAccess::get_file_as_array(engine_cfb); DirAccess::remove_file_or_error(engine_cfb); - p_func(p_udata, "res://" + config_file, data, idx, total); + p_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key); return OK; } @@ -953,6 +1080,17 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c f->store_32(VERSION_MINOR); f->store_32(VERSION_PATCH); + uint32_t pack_flags = 0; + bool enc_pck = p_preset->get_enc_pck(); + bool enc_directory = p_preset->get_enc_directory(); + if (enc_pck && enc_directory) { + pack_flags |= PACK_DIR_ENCRYPTED; + } + f->store_32(pack_flags); // flags + + uint64_t file_base_ofs = f->get_position(); + f->store_64(0); // files base + for (int i = 0; i < 16; i++) { //reserved f->store_32(0); @@ -960,40 +1098,82 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c f->store_32(pd.file_ofs.size()); //amount of files - int64_t header_size = f->get_position(); + FileAccessEncrypted *fae = nullptr; + FileAccess *fhead = f; + + if (enc_pck && enc_directory) { + String script_key = p_preset->get_script_encryption_key().to_lower(); + Vector<uint8_t> key; + key.resize(32); + if (script_key.length() == 64) { + for (int i = 0; i < 32; i++) { + int v = 0; + if (i * 2 < script_key.length()) { + char32_t ct = script_key[i * 2]; + if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = 10 + ct - 'a'; + } + v |= ct << 4; + } - //precalculate header size + if (i * 2 + 1 < script_key.length()) { + char32_t ct = script_key[i * 2 + 1]; + if (ct >= '0' && ct <= '9') { + ct = ct - '0'; + } else if (ct >= 'a' && ct <= 'f') { + ct = 10 + ct - 'a'; + } + v |= ct; + } + key.write[i] = v; + } + } + fae = memnew(FileAccessEncrypted); + ERR_FAIL_COND_V(!fae, ERR_SKIP); - for (int i = 0; i < pd.file_ofs.size(); i++) { - header_size += 4; // size of path string (32 bits is enough) - int string_len = pd.file_ofs[i].path_utf8.length(); - header_size += string_len + _get_pad(4, string_len); ///size of path string - header_size += 8; // offset to file _with_ header size included - header_size += 8; // size of file - header_size += 16; // md5 - } + err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_WRITE_AES256, false); + ERR_FAIL_COND_V(err != OK, ERR_SKIP); - int header_padding = _get_pad(PCK_PADDING, header_size); + fhead = fae; + } for (int i = 0; i < pd.file_ofs.size(); i++) { int string_len = pd.file_ofs[i].path_utf8.length(); int pad = _get_pad(4, string_len); - f->store_32(string_len + pad); - f->store_buffer((const uint8_t *)pd.file_ofs[i].path_utf8.get_data(), string_len); + fhead->store_32(string_len + pad); + fhead->store_buffer((const uint8_t *)pd.file_ofs[i].path_utf8.get_data(), string_len); for (int j = 0; j < pad; j++) { - f->store_8(0); + fhead->store_8(0); } - f->store_64(pd.file_ofs[i].ofs + header_padding + header_size); - f->store_64(pd.file_ofs[i].size); // pay attention here, this is where file is - f->store_buffer(pd.file_ofs[i].md5.ptr(), 16); //also save md5 for file + fhead->store_64(pd.file_ofs[i].ofs); + fhead->store_64(pd.file_ofs[i].size); // pay attention here, this is where file is + fhead->store_buffer(pd.file_ofs[i].md5.ptr(), 16); //also save md5 for file + uint32_t flags = 0; + if (pd.file_ofs[i].encrypted) { + flags |= PACK_FILE_ENCRYPTED; + } + fhead->store_32(flags); } + if (fae) { + fae->release(); + memdelete(fae); + } + + int header_padding = _get_pad(PCK_PADDING, f->get_position()); for (int i = 0; i < header_padding; i++) { - f->store_8(0); + f->store_8(Math::rand() % 256); } + uint64_t file_base = f->get_position(); + f->seek(file_base_ofs); + f->store_64(file_base); // update files base + f->seek(file_base); + // Save the rest of the data. ftmp = FileAccess::open(tmppath, FileAccess::READ); @@ -1162,6 +1342,10 @@ void EditorExport::_save() { config->set_value(section, "exclude_filter", preset->get_exclude_filter()); config->set_value(section, "export_path", preset->get_export_path()); config->set_value(section, "patch_list", preset->get_patches()); + config->set_value(section, "encryption_include_filters", preset->get_enc_in_filter()); + config->set_value(section, "encryption_exclude_filters", preset->get_enc_ex_filter()); + config->set_value(section, "encrypt_pck", preset->get_enc_pck()); + config->set_value(section, "encrypt_directory", preset->get_enc_directory()); config->set_value(section, "script_export_mode", preset->get_script_export_mode()); config->set_value(section, "script_encryption_key", preset->get_script_encryption_key()); @@ -1337,6 +1521,18 @@ void EditorExport::load_config() { preset->add_patch(patch_list[i]); } + if (config->has_section_key(section, "encrypt_pck")) { + preset->set_enc_pck(config->get_value(section, "encrypt_pck")); + } + if (config->has_section_key(section, "encrypt_directory")) { + preset->set_enc_directory(config->get_value(section, "encrypt_directory")); + } + if (config->has_section_key(section, "encryption_include_filters")) { + preset->set_enc_in_filter(config->get_value(section, "encryption_include_filters")); + } + if (config->has_section_key(section, "encryption_exclude_filters")) { + preset->set_enc_ex_filter(config->get_value(section, "encryption_exclude_filters")); + } if (config->has_section_key(section, "script_export_mode")) { preset->set_script_export_mode(config->get_value(section, "script_export_mode")); } diff --git a/editor/editor_export.h b/editor/editor_export.h index bb701b94ec..ac1051571c 100644 --- a/editor/editor_export.h +++ b/editor/editor_export.h @@ -55,7 +55,6 @@ public: enum ScriptExportMode { MODE_SCRIPT_TEXT, MODE_SCRIPT_COMPILED, - MODE_SCRIPT_ENCRYPTED, }; private: @@ -81,6 +80,11 @@ private: String custom_features; + String enc_in_filters; + String enc_ex_filters; + bool enc_pck = false; + bool enc_directory = false; + int script_mode = MODE_SCRIPT_COMPILED; String script_key; @@ -129,6 +133,18 @@ public: void set_export_path(const String &p_path); String get_export_path() const; + void set_enc_in_filter(const String &p_filter); + String get_enc_in_filter() const; + + void set_enc_ex_filter(const String &p_filter); + String get_enc_ex_filter() const; + + void set_enc_pck(bool p_enabled); + bool get_enc_pck() const; + + void set_enc_directory(bool p_enabled); + bool get_enc_directory() const; + void set_script_export_mode(int p_mode); int get_script_export_mode() const; @@ -156,13 +172,14 @@ class EditorExportPlatform : public Reference { GDCLASS(EditorExportPlatform, Reference); public: - typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total); + typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so); private: struct SavedData { uint64_t ofs; uint64_t size; + bool encrypted; Vector<uint8_t> md5; CharString path_utf8; @@ -192,8 +209,8 @@ private: void _export_find_dependencies(const String &p_path, Set<String> &p_paths); void gen_debug_flags(Vector<String> &r_flags, int p_flags); - static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total); - static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total); + static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); + static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); void _edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude); void _edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude); diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 418370a7c3..7335563dd9 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -271,9 +271,9 @@ void EditorFeatureProfile::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_SCRIPT); BIND_ENUM_CONSTANT(FEATURE_ASSET_LIB); BIND_ENUM_CONSTANT(FEATURE_SCENE_TREE); - BIND_ENUM_CONSTANT(FEATURE_IMPORT_DOCK); BIND_ENUM_CONSTANT(FEATURE_NODE_DOCK); BIND_ENUM_CONSTANT(FEATURE_FILESYSTEM_DOCK); + BIND_ENUM_CONSTANT(FEATURE_IMPORT_DOCK); BIND_ENUM_CONSTANT(FEATURE_MAX); } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index bce34db740..30aebd2b1f 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -244,7 +244,7 @@ void EditorHelp::_add_method(const DocData::MethodDoc &p_method, bool p_overview class_desc->push_cell(); class_desc->push_align(RichTextLabel::ALIGN_RIGHT); } else { - static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; class_desc->add_text(String(prefix)); } @@ -761,7 +761,7 @@ 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 }; + static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; class_desc->add_text(String(prefix)); _add_text(cd.signals[i].name); class_desc->pop(); @@ -876,7 +876,7 @@ 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 }; + static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; class_desc->add_text(String(prefix)); _add_text(enum_list[i].name); class_desc->pop(); @@ -890,7 +890,7 @@ void EditorHelp::_update_doc() { if (enum_list[i].description != "") { class_desc->push_font(doc_font); class_desc->push_color(comment_color); - static const CharType dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 }; + static const char32_t dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 }; class_desc->add_text(String(dash)); _add_text(DTR(enum_list[i].description)); class_desc->pop(); @@ -937,12 +937,12 @@ void EditorHelp::_update_doc() { Vector<float> color = stripped.split_floats(","); if (color.size() >= 3) { class_desc->push_color(Color(color[0], color[1], color[2])); - static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; class_desc->add_text(String(prefix)); class_desc->pop(); } } else { - static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; class_desc->add_text(String(prefix)); } @@ -960,7 +960,7 @@ void EditorHelp::_update_doc() { if (constants[i].description != "") { class_desc->push_font(doc_font); class_desc->push_color(comment_color); - static const CharType dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 }; + static const char32_t dash[6] = { ' ', ' ', 0x2013 /* en dash */, ' ', ' ', 0 }; class_desc->add_text(String(dash)); _add_text(DTR(constants[i].description)); class_desc->pop(); @@ -1002,7 +1002,7 @@ void EditorHelp::_update_doc() { class_desc->push_cell(); class_desc->push_font(doc_code_font); - static const CharType prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; + static const char32_t prefix[3] = { 0x25CF /* filled circle */, ' ', 0 }; class_desc->add_text(String(prefix)); _add_type(cd.properties[i].type, cd.properties[i].enumeration); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 16b8c6e0ac..3a52657862 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -157,6 +157,7 @@ #include "editor/plugins/sprite_frames_editor_plugin.h" #include "editor/plugins/style_box_editor_plugin.h" #include "editor/plugins/text_editor.h" +#include "editor/plugins/texture_3d_editor_plugin.h" #include "editor/plugins/texture_editor_plugin.h" #include "editor/plugins/texture_layered_editor_plugin.h" #include "editor/plugins/texture_region_editor_plugin.h" @@ -2625,6 +2626,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case SETTINGS_TOGGLE_CONSOLE: { bool was_visible = DisplayServer::get_singleton()->is_console_visible(); DisplayServer::get_singleton()->console_set_visible(!was_visible); + EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", was_visible); } break; case EDITOR_SCREENSHOT: { screenshot_timer->start(); @@ -2817,9 +2819,9 @@ void EditorNode::_discard_changes(const String &p_str) { } void EditorNode::_update_file_menu_opened() { - Ref<ShortCut> close_scene_sc = ED_GET_SHORTCUT("editor/close_scene"); + Ref<Shortcut> close_scene_sc = ED_GET_SHORTCUT("editor/close_scene"); close_scene_sc->set_name(TTR("Close Scene")); - Ref<ShortCut> reopen_closed_scene_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene"); + Ref<Shortcut> reopen_closed_scene_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene"); reopen_closed_scene_sc->set_name(TTR("Reopen Closed Scene")); PopupMenu *pop = file_menu->get_popup(); pop->set_item_disabled(pop->get_item_index(FILE_OPEN_PREV), previous_scenes.empty()); @@ -4712,10 +4714,10 @@ void EditorNode::_scene_tab_input(const Ref<InputEvent> &p_input) { scene_tabs_context_menu->add_item(TTR("Play This Scene"), RUN_PLAY_SCENE); scene_tabs_context_menu->add_separator(); - Ref<ShortCut> close_tab_sc = ED_GET_SHORTCUT("editor/close_scene"); + Ref<Shortcut> close_tab_sc = ED_GET_SHORTCUT("editor/close_scene"); close_tab_sc->set_name(TTR("Close Tab")); scene_tabs_context_menu->add_shortcut(close_tab_sc, FILE_CLOSE); - Ref<ShortCut> undo_close_tab_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene"); + Ref<Shortcut> undo_close_tab_sc = ED_GET_SHORTCUT("editor/reopen_closed_scene"); undo_close_tab_sc->set_name(TTR("Undo Close Tab")); scene_tabs_context_menu->add_shortcut(undo_close_tab_sc, FILE_OPEN_PREV); if (previous_scenes.empty()) { @@ -5619,10 +5621,10 @@ EditorNode::EditorNode() { import_cubemap_array->set_mode(ResourceImporterLayeredTexture::MODE_CUBEMAP_ARRAY); ResourceFormatImporter::get_singleton()->add_importer(import_cubemap_array); - /*Ref<ResourceImporterLayeredTexture> import_3d; + Ref<ResourceImporterLayeredTexture> import_3d; import_3d.instance(); import_3d->set_mode(ResourceImporterLayeredTexture::MODE_3D); - ResourceFormatImporter::get_singleton()->add_importer(import_3d);*/ + ResourceFormatImporter::get_singleton()->add_importer(import_3d); Ref<ResourceImporterImage> import_image; import_image.instance(); @@ -6196,7 +6198,9 @@ EditorNode::EditorNode() { #else p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN); #endif -#ifdef WINDOWS_ENABLED +#if defined(WINDOWS_ENABLED) && defined(WINDOWS_SUBSYSTEM_CONSOLE) + // The console can only be toggled if the application was built for the console subsystem, + // not the GUI subsystem. p->add_item(TTR("Toggle System Console"), SETTINGS_TOGGLE_CONSOLE); #endif p->add_separator(); @@ -6621,6 +6625,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(CurveEditorPlugin(this))); add_editor_plugin(memnew(TextureEditorPlugin(this))); add_editor_plugin(memnew(TextureLayeredEditorPlugin(this))); + add_editor_plugin(memnew(Texture3DEditorPlugin(this))); add_editor_plugin(memnew(AudioStreamEditorPlugin(this))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(Skeleton3DEditorPlugin(this))); diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp index b49c50fa31..7fada633c9 100644 --- a/editor/editor_run.cpp +++ b/editor/editor_run.cpp @@ -192,9 +192,9 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L String exec = OS::get_singleton()->get_executable_path(); - printf("Running: %ls", exec.c_str()); + printf("Running: %s", exec.utf8().get_data()); for (List<String>::Element *E = args.front(); E; E = E->next()) { - printf(" %ls", E->get().c_str()); + printf(" %s", E->get().utf8().get_data()); }; printf("\n"); diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index 9a834977fd..422534a2e1 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -121,7 +121,7 @@ void EditorRunNative::_run_native(int p_idx, int p_platform) { } if (preset.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("No runnable export preset found for this platform.\nPlease add a runnable preset in the export menu.")); + EditorNode::get_singleton()->show_warning(TTR("No runnable export preset found for this platform.\nPlease add a runnable preset in the Export menu or define an existing preset as runnable.")); return; } diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 7b24e6967a..ac27c4a837 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -77,7 +77,7 @@ bool EditorSettings::_set_only(const StringName &p_name, const Variant &p_value) String name = arr[i]; Ref<InputEvent> shortcut = arr[i + 1]; - Ref<ShortCut> sc; + Ref<Shortcut> sc; sc.instance(); sc->set_shortcut(shortcut); add_shortcut(name, sc); @@ -120,8 +120,8 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const { if (p_name.operator String() == "shortcuts") { Array arr; - for (const Map<String, Ref<ShortCut>>::Element *E = shortcuts.front(); E; E = E->next()) { - Ref<ShortCut> sc = E->get(); + for (const Map<String, Ref<Shortcut>>::Element *E = shortcuts.front(); E; E = E->next()) { + Ref<Shortcut> sc = E->get(); if (optimize_save) { if (!sc->has_meta("original")) { @@ -334,6 +334,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("interface/editor/automatically_open_screenshots", true); _initial_set("interface/editor/single_window_mode", false); hints["interface/editor/single_window_mode"] = PropertyInfo(Variant::BOOL, "interface/editor/single_window_mode", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED); + _initial_set("interface/editor/hide_console_window", false); _initial_set("interface/editor/save_each_scene_on_quit", true); // Regression _initial_set("interface/editor/quit_confirmation", true); @@ -444,7 +445,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/appearance/show_line_numbers", true); _initial_set("text_editor/appearance/line_numbers_zero_padded", false); _initial_set("text_editor/appearance/show_bookmark_gutter", true); - _initial_set("text_editor/appearance/show_breakpoint_gutter", true); _initial_set("text_editor/appearance/show_info_gutter", true); _initial_set("text_editor/appearance/code_folding", true); _initial_set("text_editor/appearance/word_wrap", false); @@ -706,8 +706,8 @@ void EditorSettings::_load_default_text_editor_theme() { _initial_set("text_editor/highlighting/member_variable_color", Color(0.9, 0.31, 0.35)); _initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4)); _initial_set("text_editor/highlighting/bookmark_color", Color(0.08, 0.49, 0.98)); - _initial_set("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2)); - _initial_set("text_editor/highlighting/executing_line_color", Color(0.2, 0.8, 0.2, 0.4)); + _initial_set("text_editor/highlighting/breakpoint_color", Color(0.9, 0.29, 0.3)); + _initial_set("text_editor/highlighting/executing_line_color", Color(0.98, 0.89, 0.27)); _initial_set("text_editor/highlighting/code_folding_color", Color(0.8, 0.8, 0.8, 0.8)); _initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1)); _initial_set("text_editor/highlighting/search_result_border_color", Color(0.41, 0.61, 0.91, 0.38)); @@ -935,6 +935,7 @@ void EditorSettings::create() { String config_file_name = "editor_settings-" + itos(VERSION_MAJOR) + ".tres"; config_file_path = config_dir.plus_file(config_file_name); if (!dir->file_exists(config_file_name)) { + memdelete(dir); goto fail; } @@ -1479,50 +1480,50 @@ String EditorSettings::get_editor_layouts_config() const { // Shortcuts -void EditorSettings::add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut) { +void EditorSettings::add_shortcut(const String &p_name, Ref<Shortcut> &p_shortcut) { shortcuts[p_name] = p_shortcut; } bool EditorSettings::is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const { - const Map<String, Ref<ShortCut>>::Element *E = shortcuts.find(p_name); + const Map<String, Ref<Shortcut>>::Element *E = shortcuts.find(p_name); ERR_FAIL_COND_V_MSG(!E, false, "Unknown Shortcut: " + p_name + "."); return E->get()->is_shortcut(p_event); } -Ref<ShortCut> EditorSettings::get_shortcut(const String &p_name) const { - const Map<String, Ref<ShortCut>>::Element *E = shortcuts.find(p_name); +Ref<Shortcut> EditorSettings::get_shortcut(const String &p_name) const { + const Map<String, Ref<Shortcut>>::Element *E = shortcuts.find(p_name); if (!E) { - return Ref<ShortCut>(); + return Ref<Shortcut>(); } return E->get(); } void EditorSettings::get_shortcut_list(List<String> *r_shortcuts) { - for (const Map<String, Ref<ShortCut>>::Element *E = shortcuts.front(); E; E = E->next()) { + for (const Map<String, Ref<Shortcut>>::Element *E = shortcuts.front(); E; E = E->next()) { r_shortcuts->push_back(E->key()); } } -Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path) { +Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) { if (!EditorSettings::get_singleton()) { return nullptr; } - Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); ERR_FAIL_COND_V_MSG(!sc.is_valid(), sc, "Used ED_GET_SHORTCUT with invalid shortcut: " + p_path + "."); return sc; } -struct ShortCutMapping { +struct ShortcutMapping { const char *path; uint32_t keycode; }; -Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) { +Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) { #ifdef OSX_ENABLED // Use Cmd+Backspace as a general replacement for Delete shortcuts on macOS if (p_keycode == KEY_DELETE) { @@ -1543,7 +1544,7 @@ Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p } if (!EditorSettings::get_singleton()) { - Ref<ShortCut> sc; + Ref<Shortcut> sc; sc.instance(); sc->set_name(p_name); sc->set_shortcut(ie); @@ -1551,7 +1552,7 @@ Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p return sc; } - Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path); if (sc.is_valid()) { sc->set_name(p_name); //keep name (the ones that come from disk have no name) sc->set_meta("original", ie); //to compare against changes diff --git a/editor/editor_settings.h b/editor/editor_settings.h index 13aebb7ea6..4896fb58db 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -85,7 +85,7 @@ private: int last_order; Ref<Resource> clipboard; - Map<String, Ref<ShortCut>> shortcuts; + Map<String, Ref<Shortcut>> shortcuts; String resource_path; String settings_dir; @@ -182,9 +182,9 @@ public: Vector<String> get_script_templates(const String &p_extension, const String &p_custom_path = String()); String get_editor_layouts_config() const; - void add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut); + void add_shortcut(const String &p_name, Ref<Shortcut> &p_shortcut); bool is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const; - Ref<ShortCut> get_shortcut(const String &p_name) const; + Ref<Shortcut> get_shortcut(const String &p_name) const; void get_shortcut_list(List<String> *r_shortcuts); void notify_changes(); @@ -203,7 +203,7 @@ Variant _EDITOR_DEF(const String &p_setting, const Variant &p_default, bool p_re Variant _EDITOR_GET(const String &p_setting); #define ED_IS_SHORTCUT(p_name, p_ev) (EditorSettings::get_singleton()->is_shortcut(p_name, p_ev)) -Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode = 0); -Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path); +Ref<Shortcut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode = 0); +Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path); #endif // EDITOR_SETTINGS_H diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 8d54bc8021..11b0228fd5 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -868,12 +868,24 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("side_margin", "TabContainer", 0); theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons")); theme->set_icon("space", "TextEdit", theme->get_icon("GuiSpace", "EditorIcons")); - theme->set_icon("folded", "TextEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons")); - theme->set_icon("fold", "TextEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons")); theme->set_color("font_color", "TextEdit", font_color); theme->set_color("caret_color", "TextEdit", font_color); theme->set_color("selection_color", "TextEdit", font_color_selection); + // CodeEdit + theme->set_stylebox("normal", "CodeEdit", style_widget); + theme->set_stylebox("focus", "CodeEdit", style_widget_hover); + theme->set_stylebox("read_only", "CodeEdit", style_widget_disabled); + theme->set_constant("side_margin", "TabContainer", 0); + theme->set_icon("tab", "CodeEdit", theme->get_icon("GuiTab", "EditorIcons")); + theme->set_icon("space", "CodeEdit", theme->get_icon("GuiSpace", "EditorIcons")); + theme->set_icon("folded", "CodeEdit", theme->get_icon("GuiTreeArrowRight", "EditorIcons")); + theme->set_icon("can_fold", "CodeEdit", theme->get_icon("GuiTreeArrowDown", "EditorIcons")); + theme->set_icon("executing_line", "CodeEdit", theme->get_icon("MainPlay", "EditorIcons")); + theme->set_color("font_color", "CodeEdit", font_color); + theme->set_color("caret_color", "CodeEdit", font_color); + theme->set_color("selection_color", "CodeEdit", font_color_selection); + // H/VSplitContainer theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1)); theme->set_stylebox("bg", "HSplitContainer", make_stylebox(theme->get_icon("GuiHsplitBg", "EditorIcons"), 1, 1, 1, 1)); @@ -1179,7 +1191,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); const Color bookmark_color = Color(0.08, 0.49, 0.98); const Color breakpoint_color = error_color; - const Color executing_line_color = Color(0.2, 0.8, 0.2, 0.4); + const Color executing_line_color = Color(0.98, 0.89, 0.27); const Color code_folding_color = alpha3; const Color search_result_color = alpha1; const Color search_result_border_color = Color(0.41, 0.61, 0.91, 0.38); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 31903c89be..0071f169ac 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2300,6 +2300,7 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { // Right click is pressed in the tree. Vector<String> paths = _tree_get_selected(false); + tree_popup->clear(); if (paths.size() == 1) { if (paths[0].ends_with("/")) { tree_popup->add_icon_item(get_theme_icon("GuiTreeArrowDown", "EditorIcons"), TTR("Expand All"), FOLDER_EXPAND_ALL); @@ -2310,7 +2311,6 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { // Popup. if (!paths.empty()) { - tree_popup->clear(); tree_popup->set_size(Size2(1, 1)); _file_and_folders_fill_popup(tree_popup, paths); tree_popup->set_position(tree->get_screen_position() + p_pos); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index bd4bb57dcf..c2ccbdb08c 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -54,7 +54,7 @@ inline void pop_back(T &container) { } // TODO Copied from TextEdit private, would be nice to extract it in a single place -static bool is_text_char(CharType c) { +static bool is_text_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } @@ -854,7 +854,7 @@ public: String get_line(FileAccess *f) { _line_buffer.clear(); - CharType c = f->get_8(); + char32_t c = f->get_8(); while (!f->eof_reached()) { if (c == '\n') { diff --git a/editor/icons/ShortCut.svg b/editor/icons/Shortcut.svg index 4ef16f0401..4ef16f0401 100644 --- a/editor/icons/ShortCut.svg +++ b/editor/icons/Shortcut.svg diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp index f954931cee..bbf62596d0 100644 --- a/editor/import/resource_importer_layered_texture.cpp +++ b/editor/import/resource_importer_layered_texture.cpp @@ -70,7 +70,7 @@ String ResourceImporterLayeredTexture::get_visible_name() const { return "CubemapArray"; } break; case MODE_3D: { - return "3D"; + return "Texture3D"; } break; } @@ -156,15 +156,103 @@ void ResourceImporterLayeredTexture::get_import_options(List<ImportOption> *r_op } void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2) { - for (int i = 0; i < p_images.size(); i++) { - if (p_force_po2) { - p_images.write[i]->resize_to_po2(); + Vector<Ref<Image>> mipmap_images; //for 3D + + if (mode == MODE_3D) { + //3D saves in its own way + + for (int i = 0; i < p_images.size(); i++) { + if (p_images.write[i]->has_mipmaps()) { + p_images.write[i]->clear_mipmaps(); + } + + if (p_force_po2) { + p_images.write[i]->resize_to_po2(); + } } if (p_mipmaps) { - p_images.write[i]->generate_mipmaps(); - } else { - p_images.write[i]->clear_mipmaps(); + Vector<Ref<Image>> parent_images = p_images; + //create 3D mipmaps, this is horrible, though not used very often + int w = p_images[0]->get_width(); + int h = p_images[0]->get_height(); + int d = p_images.size(); + + while (w > 1 || h > 1 || d > 1) { + Vector<Ref<Image>> mipmaps; + int mm_w = MAX(1, w >> 1); + int mm_h = MAX(1, h >> 1); + int mm_d = MAX(1, d >> 1); + + for (int i = 0; i < mm_d; i++) { + Ref<Image> mm; + mm.instance(); + mm->create(mm_w, mm_h, false, p_images[0]->get_format()); + Vector3 pos; + pos.z = float(i) * float(d) / float(mm_d) + 0.5; + for (int x = 0; x < mm_w; x++) { + for (int y = 0; y < mm_h; y++) { + pos.x = float(x) * float(w) / float(mm_w) + 0.5; + pos.y = float(y) * float(h) / float(mm_h) + 0.5; + + Vector3i posi = Vector3i(pos); + Vector3 fract = pos - Vector3(posi); + Vector3i posi_n = posi; + if (posi_n.x < w - 1) { + posi_n.x++; + } + if (posi_n.y < h - 1) { + posi_n.y++; + } + if (posi_n.z < d - 1) { + posi_n.z++; + } + + Color c000 = parent_images[posi.z]->get_pixel(posi.x, posi.y); + Color c100 = parent_images[posi.z]->get_pixel(posi_n.x, posi.y); + Color c010 = parent_images[posi.z]->get_pixel(posi.x, posi_n.y); + Color c110 = parent_images[posi.z]->get_pixel(posi_n.x, posi_n.y); + Color c001 = parent_images[posi_n.z]->get_pixel(posi.x, posi.y); + Color c101 = parent_images[posi_n.z]->get_pixel(posi_n.x, posi.y); + Color c011 = parent_images[posi_n.z]->get_pixel(posi.x, posi_n.y); + Color c111 = parent_images[posi_n.z]->get_pixel(posi_n.x, posi_n.y); + + Color cx00 = c000.lerp(c100, fract.x); + Color cx01 = c001.lerp(c101, fract.x); + Color cx10 = c010.lerp(c110, fract.x); + Color cx11 = c011.lerp(c111, fract.x); + + Color cy0 = cx00.lerp(cx10, fract.y); + Color cy1 = cx01.lerp(cx11, fract.y); + + Color cz = cy0.lerp(cy1, fract.z); + + mm->set_pixel(x, y, cz); + } + } + + mipmaps.push_back(mm); + } + + w = mm_w; + h = mm_h; + d = mm_d; + + mipmap_images.append_array(mipmaps); + parent_images = mipmaps; + } + } + } else { + for (int i = 0; i < p_images.size(); i++) { + if (p_force_po2) { + p_images.write[i]->resize_to_po2(); + } + + if (p_mipmaps) { + p_images.write[i]->generate_mipmaps(); + } else { + p_images.write[i]->clear_mipmaps(); + } } } @@ -175,13 +263,12 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons f->store_8('L'); f->store_32(StreamTextureLayered::FORMAT_VERSION); - f->store_32(p_images.size()); + f->store_32(p_images.size()); //2d layers or 3d depth f->store_32(mode); - f->store_32(0); //dataformat - f->store_32(0); //mipmap limit + f->store_32(0); - //reserved f->store_32(0); + f->store_32(mipmap_images.size()); // amount of mipmaps f->store_32(0); f->store_32(0); @@ -189,6 +276,10 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons ResourceImporterTexture::save_to_stex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); } + for (int i = 0; i < mipmap_images.size(); i++) { + ResourceImporterTexture::save_to_stex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy); + } + f->close(); } diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 2d50889e9e..b54923be00 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -93,10 +93,6 @@ private: static const char *compression_formats[]; protected: - static void _texture_reimport_srgb(const Ref<StreamTexture2D> &p_tex); - static void _texture_reimport_3d(const Ref<StreamTexture2D> &p_tex); - static void _texture_reimport_normal(const Ref<StreamTexture2D> &p_tex); - static ResourceImporterLayeredTexture *singleton; public: diff --git a/editor/input_map_editor.cpp b/editor/input_map_editor.cpp index 52cf9c1869..c67e16d371 100644 --- a/editor/input_map_editor.cpp +++ b/editor/input_map_editor.cpp @@ -100,7 +100,7 @@ void InputMapEditor::_notification(int p_what) { } static bool _validate_action_name(const String &p_name) { - const CharType *cstr = p_name.c_str(); + const char32_t *cstr = p_name.get_data(); for (int i = 0; cstr[i]; i++) { if (cstr[i] == '/' || cstr[i] == ':' || cstr[i] == '"' || cstr[i] == '=' || cstr[i] == '\\' || cstr[i] < 32) { diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 2ddcf3d877..6e5fb6389d 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -1912,7 +1912,7 @@ void RayCast3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> lines; lines.push_back(Vector3()); - lines.push_back(raycast->get_cast_to()); + lines.push_back(raycast->get_target_position()); const Ref<StandardMaterial3D> material = get_material(raycast->is_enabled() ? "shape_material" : "shape_material_disabled", p_gizmo); diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 49e67f3605..7a3fb1ff52 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -287,7 +287,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) pre_move_edit = vertices2; edited_point = PosVertex(insert.polygon, insert.vertex + 1, xform.affine_inverse().xform(insert.pos)); vertices2.insert(edited_point.vertex, edited_point.pos); - selected_point = edited_point; + selected_point = Vertex(edited_point.polygon, edited_point.vertex); edge_point = PosVertex(); undo_redo->create_action(TTR("Insert Point")); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 3f9f159d7f..9427f82f9e 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -6256,7 +6256,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { files_str += error_files[i].get_file().get_basename() + ","; } files_str = files_str.substr(0, files_str.length() - 1); - accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); + accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data())); accept->popup_centered(); } } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index ea58fb1e36..859e80befe 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -400,11 +400,11 @@ private: Ref<Texture2D> select_handle; Ref<Texture2D> anchor_handle; - Ref<ShortCut> drag_pivot_shortcut; - Ref<ShortCut> set_pivot_shortcut; - Ref<ShortCut> multiply_grid_step_shortcut; - Ref<ShortCut> divide_grid_step_shortcut; - Ref<ShortCut> pan_view_shortcut; + Ref<Shortcut> drag_pivot_shortcut; + Ref<Shortcut> set_pivot_shortcut; + Ref<Shortcut> multiply_grid_step_shortcut; + Ref<Shortcut> divide_grid_step_shortcut; + Ref<Shortcut> pan_view_shortcut; bool _is_node_locked(const Node *p_node); bool _is_node_movable(const Node *p_node, bool p_popup_warning = false); diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp index 0a4d173923..0747e42045 100644 --- a/editor/plugins/debugger_editor_plugin.cpp +++ b/editor/plugins/debugger_editor_plugin.cpp @@ -47,7 +47,7 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(EditorNode *p_editor, MenuButton *p_d ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")); ED_SHORTCUT("debugger/debug_with_external_editor", TTR("Debug with External Editor")); - // File Server for deploy with remote fs. + // File Server for deploy with remote filesystem. file_server = memnew(EditorFileServer); EditorDebuggerNode *debugger = memnew(EditorDebuggerNode); @@ -59,19 +59,31 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(EditorNode *p_editor, MenuButton *p_d PopupMenu *p = debug_menu->get_popup(); p->set_hide_on_checkable_item_selection(false); p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG); - p->set_item_tooltip(p->get_item_count() - 1, TTR("When exporting or deploying, the resulting executable will attempt to connect to the IP of this computer in order to be debugged.")); - p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network FS")), RUN_FILE_SERVER); - p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is enabled, export or deploy will produce a minimal executable.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploy will use the USB cable for faster performance. This option speeds up testing for games with a large footprint.")); + p->set_item_tooltip( + p->get_item_count() - 1, + TTR("When this option is enabled, using one-click deploy will make the executable attempt to connect to this computer's IP so the running project can be debugged.\nThis option is intended to be used for remote debugging (typically with a mobile device).\nYou don't need to enable it to use the GDScript debugger locally.")); + p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network Filesystem")), RUN_FILE_SERVER); + p->set_item_tooltip( + p->get_item_count() - 1, + TTR("When this option is enabled, using one-click deploy for Android will only export an executable without the project data.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploying will use the USB cable for faster performance. This option speeds up testing for projects with large assets.")); p->add_separator(); p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS); - p->set_item_tooltip(p->get_item_count() - 1, TTR("Collision shapes and raycast nodes (for 2D and 3D) will be visible on the running game if this option is turned on.")); + p->set_item_tooltip( + p->get_item_count() - 1, + TTR("When this option is enabled, collision shapes and raycast nodes (for 2D and 3D) will be visible in the running project.")); p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION); - p->set_item_tooltip(p->get_item_count() - 1, TTR("Navigation meshes and polygons will be visible on the running game if this option is turned on.")); + p->set_item_tooltip( + p->get_item_count() - 1, + TTR("When this option is enabled, navigation meshes and polygons will be visible in the running project.")); p->add_separator(); - p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Sync Scene Changes")), RUN_LIVE_DEBUG); - p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any changes made to the scene in the editor will be replicated in the running game.\nWhen used remotely on a device, this is more efficient with network filesystem.")); - p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Sync Script Changes")), RUN_RELOAD_SCRIPTS); - p->set_item_tooltip(p->get_item_count() - 1, TTR("When this option is turned on, any script that is saved will be reloaded on the running game.\nWhen used remotely on a device, this is more efficient with network filesystem.")); + p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Synchronize Scene Changes")), RUN_LIVE_DEBUG); + p->set_item_tooltip( + p->get_item_count() - 1, + TTR("When this option is enabled, any changes made to the scene in the editor will be replicated in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled.")); + p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Synchronize Script Changes")), RUN_RELOAD_SCRIPTS); + p->set_item_tooltip( + p->get_item_count() - 1, + TTR("When this option is enabled, any script that is saved will be reloaded in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled.")); // Multi-instance, start/stop instances_menu = memnew(PopupMenu); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 2889cb50a0..3cf4dc5ac8 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -466,7 +466,7 @@ EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() { /////////////////////////////////////////////////////////////////////////// -static bool _is_text_char(CharType c) { +static bool _is_text_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } @@ -525,7 +525,7 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size bool prev_is_text = false; bool in_keyword = false; for (int i = 0; i < code.length(); i++) { - CharType c = code[i]; + char32_t c = code[i]; if (c > 32) { if (col < thumbnail_size) { Color color = text_color; diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp index 1b65987af0..5b241deab0 100644 --- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp @@ -138,6 +138,7 @@ void MeshInstance3DEditor::_menu_option(int p_option) { CollisionShape3D *cshape = memnew(CollisionShape3D); cshape->set_shape(shape); + cshape->set_transform(node->get_transform()); Node *owner = node->get_owner(); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 21a75c2f5d..d28bbadf39 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2246,7 +2246,7 @@ Point2i Node3DEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouse } static bool is_shortcut_pressed(const String &p_path) { - Ref<ShortCut> shortcut = ED_GET_SHORTCUT(p_path); + Ref<Shortcut> shortcut = ED_GET_SHORTCUT(p_path); if (shortcut.is_null()) { return false; } @@ -3729,7 +3729,7 @@ void Node3DEditorViewport::_perform_drop_data() { files_str += error_files[i].get_file().get_basename() + ","; } files_str = files_str.substr(0, files_str.length() - 1); - accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.c_str())); + accept->set_text(vformat(TTR("Error instancing scene from %s"), files_str.get_data())); accept->popup_centered(); } } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 20eef1cebd..be8ddf789b 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1585,15 +1585,14 @@ void ScriptEditor::get_breakpoints(List<String> *p_breakpoints) { continue; } - List<int> bpoints; - se->get_breakpoints(&bpoints); String base = script->get_path(); if (base.begins_with("local://") || base == "") { continue; } - for (List<int>::Element *E = bpoints.front(); E; E = E->next()) { - p_breakpoints->push_back(base + ":" + itos(E->get() + 1)); + Array bpoints = se->get_breakpoints(); + for (int j = 0; j < bpoints.size(); j++) { + p_breakpoints->push_back(base + ":" + itos((int)bpoints[j] + 1)); } } } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 1234ebd267..c2b0b458eb 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -151,7 +151,7 @@ public: virtual void ensure_focus() = 0; virtual void tag_saved_version() = 0; virtual void reload(bool p_soft) {} - virtual void get_breakpoints(List<int> *p_breakpoints) = 0; + virtual Array get_breakpoints() = 0; virtual void add_callback(const String &p_function, PackedStringArray p_args) = 0; virtual void update_settings() = 0; virtual void set_debugger_active(bool p_active) = 0; diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 4b89ca1216..7feb7cb3d3 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -111,7 +111,7 @@ ConnectionInfoDialog::ConnectionInfoDialog() { Vector<String> ScriptTextEditor::get_functions() { String errortxt; int line = -1, col; - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); String text = te->get_text(); List<String> fnc; @@ -130,9 +130,9 @@ void ScriptTextEditor::apply_code() { if (script.is_null()) { return; } - script->set_source_code(code_editor->get_text_edit()->get_text()); + script->set_source_code(code_editor->get_text_editor()->get_text()); script->update_exports(); - code_editor->get_text_edit()->get_syntax_highlighter()->update_cache(); + code_editor->get_text_editor()->get_syntax_highlighter()->update_cache(); } RES ScriptTextEditor::get_edited_resource() const { @@ -145,9 +145,9 @@ void ScriptTextEditor::set_edited_resource(const RES &p_res) { script = p_res; - code_editor->get_text_edit()->set_text(script->get_source_code()); - code_editor->get_text_edit()->clear_undo_history(); - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->set_text(script->get_source_code()); + code_editor->get_text_editor()->clear_undo_history(); + code_editor->get_text_editor()->tag_saved_version(); emit_signal("name_changed"); code_editor->update_line_and_column(); @@ -167,9 +167,19 @@ void ScriptTextEditor::enable_editor() { } void ScriptTextEditor::_load_theme_settings() { - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->clear_keywords(); + Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color"); + if (updated_safe_line_number_color != safe_line_number_color) { + safe_line_number_color = updated_safe_line_number_color; + for (int i = 0; i < text_edit->get_line_count(); i++) { + if (text_edit->get_line_gutter_item_color(i, line_number_gutter) != default_line_number_color) { + text_edit->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color); + } + } + } + Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); Color completion_background_color = EDITOR_GET("text_editor/highlighting/completion_background_color"); Color completion_selected_color = EDITOR_GET("text_editor/highlighting/completion_selected_color"); @@ -178,7 +188,6 @@ void ScriptTextEditor::_load_theme_settings() { Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color"); Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color"); - Color safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color"); Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color"); Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color"); Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color"); @@ -203,7 +212,6 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->add_theme_color_override("completion_font_color", completion_font_color); text_edit->add_theme_color_override("font_color", text_color); text_edit->add_theme_color_override("line_number_color", line_number_color); - text_edit->add_theme_color_override("safe_line_number_color", safe_line_number_color); text_edit->add_theme_color_override("caret_color", caret_color); text_edit->add_theme_color_override("caret_background_color", caret_background_color); text_edit->add_theme_color_override("font_color_selected", text_selected_color); @@ -233,7 +241,7 @@ void ScriptTextEditor::_set_theme_for_script() { return; } - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->get_syntax_highlighter()->update_cache(); /* add keywords for auto completion */ @@ -284,10 +292,10 @@ void ScriptTextEditor::_show_warnings_panel(bool p_show) { 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()); + code_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t()); } else if (p_line.get_type() == Variant::DICTIONARY) { Dictionary meta = p_line.operator Dictionary(); - code_editor->get_text_edit()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1); + code_editor->get_text_editor()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1); _validate_script(); } } @@ -295,7 +303,7 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) { void ScriptTextEditor::reload_text() { ERR_FAIL_COND(script.is_null()); - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); int column = te->cursor_get_column(); int row = te->cursor_get_line(); int h = te->get_h_scroll(); @@ -313,20 +321,20 @@ void ScriptTextEditor::reload_text() { } void ScriptTextEditor::add_callback(const String &p_function, PackedStringArray p_args) { - String code = code_editor->get_text_edit()->get_text(); + String code = code_editor->get_text_editor()->get_text(); int pos = script->get_language()->find_function(p_function, code); if (pos == -1) { //does not exist - code_editor->get_text_edit()->deselect(); - pos = code_editor->get_text_edit()->get_line_count() + 2; + code_editor->get_text_editor()->deselect(); + pos = code_editor->get_text_editor()->get_line_count() + 2; String func = script->get_language()->make_function("", p_function, p_args); //code=code+func; - code_editor->get_text_edit()->cursor_set_line(pos + 1); - code_editor->get_text_edit()->cursor_set_column(1000000); //none shall be that big - code_editor->get_text_edit()->insert_text_at_cursor("\n\n" + func); + code_editor->get_text_editor()->cursor_set_line(pos + 1); + code_editor->get_text_editor()->cursor_set_column(1000000); //none shall be that big + code_editor->get_text_editor()->insert_text_at_cursor("\n\n" + func); } - code_editor->get_text_edit()->cursor_set_line(pos); - code_editor->get_text_edit()->cursor_set_column(1); + code_editor->get_text_editor()->cursor_set_line(pos); + code_editor->get_text_editor()->cursor_set_column(1); } bool ScriptTextEditor::show_members_overview() { @@ -334,12 +342,13 @@ bool ScriptTextEditor::show_members_overview() { } void ScriptTextEditor::update_settings() { + code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter")); code_editor->update_editor_settings(); } bool ScriptTextEditor::is_unsaved() { const bool unsaved = - code_editor->get_text_edit()->get_version() != code_editor->get_text_edit()->get_saved_version() || + code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() || script->get_path().empty(); // In memory. return unsaved; } @@ -385,7 +394,7 @@ void ScriptTextEditor::convert_indent_to_tabs() { } void ScriptTextEditor::tag_saved_version() { - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->tag_saved_version(); } void ScriptTextEditor::goto_line(int p_line, bool p_with_error) { @@ -409,7 +418,7 @@ void ScriptTextEditor::clear_executing_line() { } void ScriptTextEditor::ensure_focus() { - code_editor->get_text_edit()->grab_focus(); + code_editor->get_text_editor()->grab_focus(); } String ScriptTextEditor::get_name() { @@ -443,7 +452,7 @@ Ref<Texture2D> ScriptTextEditor::get_theme_icon() { void ScriptTextEditor::_validate_script() { String errortxt; int line = -1, col; - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); String text = te->get_text(); List<String> fnc; @@ -540,16 +549,16 @@ void ScriptTextEditor::_validate_script() { te->set_line_as_marked(i, line == i); if (highlight_safe) { if (safe_lines.has(i + 1)) { - te->set_line_as_safe(i, true); + te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color); last_is_safe = true; } else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().empty())) { - te->set_line_as_safe(i, true); + te->set_line_gutter_item_color(i, line_number_gutter, safe_line_number_color); } else { - te->set_line_as_safe(i, false); + te->set_line_gutter_item_color(i, line_number_gutter, default_line_number_color); last_is_safe = false; } } else { - te->set_line_as_safe(i, false); + te->set_line_gutter_item_color(line, 1, default_line_number_color); } } @@ -566,7 +575,7 @@ void ScriptTextEditor::_update_bookmark_list() { bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); - Array bookmark_list = code_editor->get_text_edit()->get_bookmarks_array(); + Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines(); if (bookmark_list.size() == 0) { return; } @@ -576,7 +585,7 @@ void ScriptTextEditor::_update_bookmark_list() { for (int i = 0; i < bookmark_list.size(); i++) { // Strip edges to remove spaces or tabs. // Also replace any tabs by spaces, since we can't print tabs in the menu. - String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).replace("\t", " ").strip_edges(); + String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).replace("\t", " ").strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { @@ -593,7 +602,7 @@ void ScriptTextEditor::_bookmark_item_pressed(int p_idx) { _edit_option(bookmarks_menu->get_item_id(p_idx)); } else { code_editor->goto_line(bookmarks_menu->get_item_metadata(p_idx)); - code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). + code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). } } @@ -704,7 +713,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCo String hint; Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint); if (err == OK) { - code_editor->get_text_edit()->set_code_hint(hint); + code_editor->get_text_editor()->set_code_hint(hint); } } @@ -717,7 +726,7 @@ void ScriptTextEditor::_update_breakpoint_list() { breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_breakpoint"), DEBUG_GOTO_NEXT_BREAKPOINT); breakpoints_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_breakpoint"), DEBUG_GOTO_PREV_BREAKPOINT); - Array breakpoint_list = code_editor->get_text_edit()->get_breakpoints_array(); + Array breakpoint_list = code_editor->get_text_editor()->get_breakpointed_lines(); if (breakpoint_list.size() == 0) { return; } @@ -727,7 +736,7 @@ void ScriptTextEditor::_update_breakpoint_list() { for (int i = 0; i < breakpoint_list.size(); i++) { // Strip edges to remove spaces or tabs. // Also replace any tabs by spaces, since we can't print tabs in the menu. - String line = code_editor->get_text_edit()->get_line(breakpoint_list[i]).replace("\t", " ").strip_edges(); + String line = code_editor->get_text_editor()->get_line(breakpoint_list[i]).replace("\t", " ").strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { @@ -744,12 +753,12 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) { _edit_option(breakpoints_menu->get_item_id(p_idx)); } else { code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx)); - code_editor->get_text_edit()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). + code_editor->get_text_editor()->call_deferred("center_viewport_to_cursor"); //Need to be deferred, because goto uses call_deferred(). } } void ScriptTextEditor::_breakpoint_toggled(int p_row) { - EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_edit()->is_line_set_as_breakpoint(p_row)); + EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), p_row + 1, code_editor->get_text_editor()->is_line_breakpointed(p_row)); } void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_column) { @@ -771,7 +780,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c EditorNode::get_singleton()->load_resource(p_symbol); } - } else if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) { + } else if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK) { _goto_line(p_row); result.class_name = result.class_name.trim_prefix("_"); @@ -866,7 +875,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c } void ScriptTextEditor::_validate_symbol(const String &p_symbol) { - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); Node *base = get_tree()->get_edited_scene_root(); if (base) { @@ -874,7 +883,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) { } ScriptLanguage::LookupResult result; - if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { + if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { text_edit->set_highlighted_word(p_symbol); } else if (p_symbol.is_rel_path()) { String path = _get_absolute_path(p_symbol); @@ -902,8 +911,15 @@ void ScriptTextEditor::update_toggle_scripts_button() { } void ScriptTextEditor::_update_connected_methods() { - TextEdit *text_edit = code_editor->get_text_edit(); - text_edit->clear_info_icons(); + CodeEdit *text_edit = code_editor->get_text_editor(); + for (int i = 0; i < text_edit->get_line_count(); i++) { + if (text_edit->get_line_gutter_metadata(i, connection_gutter) == "") { + continue; + } + text_edit->set_line_gutter_metadata(i, connection_gutter, ""); + text_edit->set_line_gutter_icon(i, connection_gutter, nullptr); + text_edit->set_line_gutter_clickable(i, connection_gutter, false); + } missing_connections.clear(); if (!script_is_valid) { @@ -943,8 +959,10 @@ void ScriptTextEditor::_update_connected_methods() { for (int j = 0; j < functions.size(); j++) { String name = functions[j].get_slice(":", 0); if (name == connection.callable.get_method()) { - line = functions[j].get_slice(":", 1).to_int(); - text_edit->set_line_info_icon(line - 1, get_parent_control()->get_theme_icon("Slot", "EditorIcons"), connection.callable.get_method()); + line = functions[j].get_slice(":", 1).to_int() - 1; + text_edit->set_line_gutter_metadata(line, connection_gutter, connection.callable.get_method()); + text_edit->set_line_gutter_icon(line, connection_gutter, get_parent_control()->get_theme_icon("Slot", "EditorIcons")); + text_edit->set_line_gutter_clickable(line, connection_gutter, true); methods_found.insert(connection.callable.get_method()); break; } @@ -974,18 +992,41 @@ void ScriptTextEditor::_update_connected_methods() { } } -void ScriptTextEditor::_lookup_connections(int p_row, String p_method) { +void ScriptTextEditor::_update_gutter_indexes() { + for (int i = 0; i < code_editor->get_text_editor()->get_gutter_count(); i++) { + if (code_editor->get_text_editor()->get_gutter_name(i) == "connection_gutter") { + connection_gutter = i; + continue; + } + + if (code_editor->get_text_editor()->get_gutter_name(i) == "line_numbers") { + line_number_gutter = i; + continue; + } + } +} + +void ScriptTextEditor::_gutter_clicked(int p_line, int p_gutter) { + if (p_gutter != connection_gutter) { + return; + } + + String method = code_editor->get_text_editor()->get_line_gutter_metadata(p_line, p_gutter); + if (method == "") { + return; + } + Node *base = get_tree()->get_edited_scene_root(); if (!base) { return; } Vector<Node *> nodes = _find_all_node_for_script(base, base, script); - connection_info_dialog->popup_connections(p_method, nodes); + connection_info_dialog->popup_connections(method, nodes); } void ScriptTextEditor::_edit_option(int p_op) { - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); switch (p_op) { case EDIT_UNDO: { @@ -1109,7 +1150,7 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case EDIT_EVALUATE: { Expression expression; - Vector<String> lines = code_editor->get_text_edit()->get_selection_text().split("\n"); + Vector<String> lines = code_editor->get_text_editor()->get_selection_text().split("\n"); PackedStringArray results; for (int i = 0; i < lines.size(); i++) { @@ -1128,9 +1169,9 @@ void ScriptTextEditor::_edit_option(int p_op) { } } - code_editor->get_text_edit()->begin_complex_operation(); //prevents creating a two-step undo - code_editor->get_text_edit()->insert_text_at_cursor(String("\n").join(results)); - code_editor->get_text_edit()->end_complex_operation(); + code_editor->get_text_editor()->begin_complex_operation(); //prevents creating a two-step undo + code_editor->get_text_editor()->insert_text_at_cursor(String("\n").join(results)); + code_editor->get_text_editor()->end_complex_operation(); } break; case SEARCH_FIND: { code_editor->get_find_replace_bar()->popup_search(); @@ -1145,14 +1186,14 @@ void ScriptTextEditor::_edit_option(int p_op) { code_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); // Yep, because it doesn't make sense to instance this dialog for every single script open... // So this will be delegated to the ScriptEditor. emit_signal("search_in_files_requested", selected_text); } break; case REPLACE_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); emit_signal("replace_in_files_requested", selected_text); } break; @@ -1177,24 +1218,22 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case DEBUG_TOGGLE_BREAKPOINT: { int line = tx->cursor_get_line(); - bool dobreak = !tx->is_line_set_as_breakpoint(line); + bool dobreak = !tx->is_line_breakpointed(line); tx->set_line_as_breakpoint(line, dobreak); EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak); } break; case DEBUG_REMOVE_ALL_BREAKPOINTS: { - List<int> bpoints; - tx->get_breakpoints(&bpoints); + Array bpoints = tx->get_breakpointed_lines(); - for (List<int>::Element *E = bpoints.front(); E; E = E->next()) { - int line = E->get(); - bool dobreak = !tx->is_line_set_as_breakpoint(line); + for (int i = 0; i < bpoints.size(); i++) { + int line = bpoints[i]; + bool dobreak = !tx->is_line_breakpointed(line); tx->set_line_as_breakpoint(line, dobreak); EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak); } } break; case DEBUG_GOTO_NEXT_BREAKPOINT: { - List<int> bpoints; - tx->get_breakpoints(&bpoints); + Array bpoints = tx->get_breakpointed_lines(); if (bpoints.size() <= 0) { return; } @@ -1202,13 +1241,13 @@ void ScriptTextEditor::_edit_option(int p_op) { int line = tx->cursor_get_line(); // wrap around - if (line >= bpoints[bpoints.size() - 1]) { + if (line >= (int)bpoints[bpoints.size() - 1]) { tx->unfold_line(bpoints[0]); tx->cursor_set_line(bpoints[0]); tx->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bpoints.front(); E; E = E->next()) { - int bline = E->get(); + for (int i = 0; i < bpoints.size(); i++) { + int bline = bpoints[i]; if (bline > line) { tx->unfold_line(bline); tx->cursor_set_line(bline); @@ -1220,21 +1259,20 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case DEBUG_GOTO_PREV_BREAKPOINT: { - List<int> bpoints; - tx->get_breakpoints(&bpoints); + Array bpoints = tx->get_breakpointed_lines(); if (bpoints.size() <= 0) { return; } int line = tx->cursor_get_line(); // wrap around - if (line <= bpoints[0]) { + if (line <= (int)bpoints[0]) { tx->unfold_line(bpoints[bpoints.size() - 1]); tx->cursor_set_line(bpoints[bpoints.size() - 1]); tx->center_viewport_to_cursor(); } else { - for (List<int>::Element *E = bpoints.back(); E; E = E->prev()) { - int bline = E->get(); + for (int i = bpoints.size(); i >= 0; i--) { + int bline = bpoints[i]; if (bline < line) { tx->unfold_line(bline); tx->cursor_set_line(bline); @@ -1303,7 +1341,7 @@ void ScriptTextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_hig el = el->next(); } - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); p_highlighter->_set_edited_resource(script); te->set_syntax_highlighter(p_highlighter); } @@ -1312,6 +1350,16 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) { set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]); } +void ScriptTextEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: { + code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_row_height()); + } break; + default: + break; + } +} + void ScriptTextEditor::_bind_methods() { ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods); @@ -1331,7 +1379,7 @@ void ScriptTextEditor::clear_edit_menu() { } void ScriptTextEditor::reload(bool p_soft) { - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); Ref<Script> scr = script; if (scr.is_null()) { return; @@ -1342,12 +1390,12 @@ void ScriptTextEditor::reload(bool p_soft) { scr->get_language()->reload_tool_script(scr, soft); } -void ScriptTextEditor::get_breakpoints(List<int> *p_breakpoints) { - code_editor->get_text_edit()->get_breakpoints(p_breakpoints); +Array ScriptTextEditor::get_breakpoints() { + return code_editor->get_text_editor()->get_breakpointed_lines(); } void ScriptTextEditor::set_tooltip_request_func(String p_method, Object *p_obj) { - code_editor->get_text_edit()->set_tooltip_request_func(p_obj, p_method, this); + code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this); } void ScriptTextEditor::set_debugger_active(bool p_active) { @@ -1393,7 +1441,7 @@ static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { Dictionary d = p_data; - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); int row, col; te->_get_mouse_pos(p_point, row, col); @@ -1466,7 +1514,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Point2 local_pos; bool create_menu = false; - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); if (mb.is_valid() && mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { local_pos = mb->get_global_position() - tx->get_global_position(); create_menu = true; @@ -1519,7 +1567,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { base = _find_node_for_script(base, base, script); } ScriptLanguage::LookupResult result; - if (script->get_language()->lookup_code(code_editor->get_text_edit()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) { + if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_lookup_completion(), word_at_pos, script->get_path(), base, result) == OK) { open_docs = true; } } @@ -1567,17 +1615,17 @@ void ScriptTextEditor::_color_changed(const Color &p_color) { new_args = String("(" + rtos(p_color.r) + ", " + rtos(p_color.g) + ", " + rtos(p_color.b) + ", " + rtos(p_color.a) + ")"); } - String line = code_editor->get_text_edit()->get_line(color_position.x); + String line = code_editor->get_text_editor()->get_line(color_position.x); int color_args_pos = line.find(color_args, color_position.y); String line_with_replaced_args = line; line_with_replaced_args.erase(color_args_pos, color_args.length()); line_with_replaced_args = line_with_replaced_args.insert(color_args_pos, new_args); color_args = new_args; - code_editor->get_text_edit()->begin_complex_operation(); - code_editor->get_text_edit()->set_line(color_position.x, line_with_replaced_args); - code_editor->get_text_edit()->end_complex_operation(); - code_editor->get_text_edit()->update(); + code_editor->get_text_editor()->begin_complex_operation(); + code_editor->get_text_editor()->set_line(color_position.x, line_with_replaced_args); + code_editor->get_text_editor()->end_complex_operation(); + code_editor->get_text_editor()->update(); } void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) { @@ -1636,12 +1684,15 @@ void ScriptTextEditor::_enable_code_editor() { code_editor->connect("show_warnings_panel", callable_mp(this, &ScriptTextEditor::_show_warnings_panel)); code_editor->connect("validate_script", callable_mp(this, &ScriptTextEditor::_validate_script)); code_editor->connect("load_theme_settings", callable_mp(this, &ScriptTextEditor::_load_theme_settings)); - code_editor->get_text_edit()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled)); - code_editor->get_text_edit()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol)); - code_editor->get_text_edit()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol)); - code_editor->get_text_edit()->connect("info_clicked", callable_mp(this, &ScriptTextEditor::_lookup_connections)); - code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input)); + code_editor->get_text_editor()->connect("breakpoint_toggled", callable_mp(this, &ScriptTextEditor::_breakpoint_toggled)); + code_editor->get_text_editor()->connect("symbol_lookup", callable_mp(this, &ScriptTextEditor::_lookup_symbol)); + code_editor->get_text_editor()->connect("symbol_validate", callable_mp(this, &ScriptTextEditor::_validate_symbol)); + code_editor->get_text_editor()->connect("gutter_added", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes)); + code_editor->get_text_editor()->connect("gutter_removed", callable_mp(this, &ScriptTextEditor::_update_gutter_indexes)); + code_editor->get_text_editor()->connect("gutter_clicked", callable_mp(this, &ScriptTextEditor::_gutter_clicked)); + code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ScriptTextEditor::_text_edit_gui_input)); code_editor->show_toggle_scripts_button(); + _update_gutter_indexes(); editor_box->add_child(warnings_panel); warnings_panel->add_theme_font_override( @@ -1758,6 +1809,16 @@ ScriptTextEditor::ScriptTextEditor() { code_editor->set_code_complete_func(_code_complete_scripts, this); code_editor->set_v_size_flags(SIZE_EXPAND_FILL); + code_editor->get_text_editor()->set_draw_breakpoints_gutter(true); + code_editor->get_text_editor()->set_draw_executing_lines_gutter(true); + + connection_gutter = 1; + code_editor->get_text_editor()->add_gutter(connection_gutter); + code_editor->get_text_editor()->set_gutter_name(connection_gutter, "connection_gutter"); + code_editor->get_text_editor()->set_gutter_draw(connection_gutter, false); + code_editor->get_text_editor()->set_gutter_overwritable(connection_gutter, true); + code_editor->get_text_editor()->set_gutter_type(connection_gutter, TextEdit::GUTTER_TPYE_ICON); + warnings_panel = memnew(RichTextLabel); warnings_panel->set_custom_minimum_size(Size2(0, 100 * EDSCALE)); warnings_panel->set_h_size_flags(SIZE_EXPAND_FILL); @@ -1768,12 +1829,12 @@ ScriptTextEditor::ScriptTextEditor() { update_settings(); - code_editor->get_text_edit()->set_callhint_settings( + code_editor->get_text_editor()->set_callhint_settings( EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"), EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset")); - code_editor->get_text_edit()->set_select_identifiers_on_hover(true); - code_editor->get_text_edit()->set_context_menu_enabled(false); + code_editor->get_text_editor()->set_select_identifiers_on_hover(true); + code_editor->get_text_editor()->set_context_menu_enabled(false); context_menu = memnew(PopupMenu); @@ -1816,7 +1877,7 @@ ScriptTextEditor::ScriptTextEditor() { connection_info_dialog = memnew(ConnectionInfoDialog); - code_editor->get_text_edit()->set_drag_forwarding(this); + code_editor->get_text_editor()->set_drag_forwarding(this); } ScriptTextEditor::~ScriptTextEditor() { diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index e931c9fdc6..1e436fbe65 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -81,6 +81,14 @@ class ScriptTextEditor : public ScriptEditorBase { ScriptEditorQuickOpen *quick_open = nullptr; ConnectionInfoDialog *connection_info_dialog = nullptr; + int connection_gutter = -1; + void _gutter_clicked(int p_line, int p_gutter); + void _update_gutter_indexes(); + + int line_number_gutter = -1; + Color default_line_number_color = Color(1, 1, 1); + Color safe_line_number_color = Color(1, 1, 1); + PopupPanel *color_panel = nullptr; ColorPicker *color_picker = nullptr; Vector2 color_position; @@ -154,6 +162,7 @@ protected: void _show_warnings_panel(bool p_show); void _warning_clicked(Variant p_line); + void _notification(int p_what); static void _bind_methods(); Map<String, Ref<EditorSyntaxHighlighter>> highlighters; @@ -169,8 +178,6 @@ protected: void _lookup_symbol(const String &p_symbol, int p_row, int p_column); void _validate_symbol(const String &p_symbol); - void _lookup_connections(int p_row, String p_method); - void _convert_case(CodeTextEditor::CaseStyle p_case); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); @@ -211,7 +218,7 @@ public: virtual void clear_executing_line() override; virtual void reload(bool p_soft) override; - virtual void get_breakpoints(List<int> *p_breakpoints) override; + virtual Array get_breakpoints() override; virtual void add_callback(const String &p_function, PackedStringArray p_args) override; virtual void update_settings() override; diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 2a7f3f0656..29db284b44 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -55,8 +55,8 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) { _load_theme_settings(); - get_text_edit()->set_text(p_shader->get_code()); - get_text_edit()->clear_undo_history(); + get_text_editor()->set_text(p_shader->get_code()); + get_text_editor()->clear_undo_history(); _validate_script(); _line_col_changed(); @@ -65,7 +65,7 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) { void ShaderTextEditor::reload_text() { ERR_FAIL_COND(shader.is_null()); - TextEdit *te = get_text_edit(); + CodeEdit *te = get_text_editor(); int column = te->cursor_get_column(); int row = te->cursor_get_line(); int h = te->get_h_scroll(); @@ -107,29 +107,29 @@ void ShaderTextEditor::_load_theme_settings() { Color search_result_color = EDITOR_GET("text_editor/highlighting/search_result_color"); Color search_result_border_color = EDITOR_GET("text_editor/highlighting/search_result_border_color"); - get_text_edit()->add_theme_color_override("background_color", background_color); - get_text_edit()->add_theme_color_override("completion_background_color", completion_background_color); - get_text_edit()->add_theme_color_override("completion_selected_color", completion_selected_color); - get_text_edit()->add_theme_color_override("completion_existing_color", completion_existing_color); - get_text_edit()->add_theme_color_override("completion_scroll_color", completion_scroll_color); - get_text_edit()->add_theme_color_override("completion_font_color", completion_font_color); - get_text_edit()->add_theme_color_override("font_color", text_color); - get_text_edit()->add_theme_color_override("line_number_color", line_number_color); - get_text_edit()->add_theme_color_override("caret_color", caret_color); - get_text_edit()->add_theme_color_override("caret_background_color", caret_background_color); - get_text_edit()->add_theme_color_override("font_color_selected", text_selected_color); - get_text_edit()->add_theme_color_override("selection_color", selection_color); - get_text_edit()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); - get_text_edit()->add_theme_color_override("current_line_color", current_line_color); - get_text_edit()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); - get_text_edit()->add_theme_color_override("word_highlighted_color", word_highlighted_color); - get_text_edit()->add_theme_color_override("mark_color", mark_color); - get_text_edit()->add_theme_color_override("bookmark_color", bookmark_color); - get_text_edit()->add_theme_color_override("breakpoint_color", breakpoint_color); - get_text_edit()->add_theme_color_override("executing_line_color", executing_line_color); - get_text_edit()->add_theme_color_override("code_folding_color", code_folding_color); - get_text_edit()->add_theme_color_override("search_result_color", search_result_color); - get_text_edit()->add_theme_color_override("search_result_border_color", search_result_border_color); + get_text_editor()->add_theme_color_override("background_color", background_color); + get_text_editor()->add_theme_color_override("completion_background_color", completion_background_color); + get_text_editor()->add_theme_color_override("completion_selected_color", completion_selected_color); + get_text_editor()->add_theme_color_override("completion_existing_color", completion_existing_color); + get_text_editor()->add_theme_color_override("completion_scroll_color", completion_scroll_color); + get_text_editor()->add_theme_color_override("completion_font_color", completion_font_color); + get_text_editor()->add_theme_color_override("font_color", text_color); + get_text_editor()->add_theme_color_override("line_number_color", line_number_color); + get_text_editor()->add_theme_color_override("caret_color", caret_color); + get_text_editor()->add_theme_color_override("caret_background_color", caret_background_color); + get_text_editor()->add_theme_color_override("font_color_selected", text_selected_color); + get_text_editor()->add_theme_color_override("selection_color", selection_color); + get_text_editor()->add_theme_color_override("brace_mismatch_color", brace_mismatch_color); + get_text_editor()->add_theme_color_override("current_line_color", current_line_color); + get_text_editor()->add_theme_color_override("line_length_guideline_color", line_length_guideline_color); + get_text_editor()->add_theme_color_override("word_highlighted_color", word_highlighted_color); + get_text_editor()->add_theme_color_override("mark_color", mark_color); + get_text_editor()->add_theme_color_override("bookmark_color", bookmark_color); + get_text_editor()->add_theme_color_override("breakpoint_color", breakpoint_color); + get_text_editor()->add_theme_color_override("executing_line_color", executing_line_color); + get_text_editor()->add_theme_color_override("code_folding_color", code_folding_color); + get_text_editor()->add_theme_color_override("search_result_color", search_result_color); + get_text_editor()->add_theme_color_override("search_result_border_color", search_result_border_color); syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color")); syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color")); @@ -176,7 +176,7 @@ void ShaderTextEditor::_load_theme_settings() { } void ShaderTextEditor::_check_shader_mode() { - String type = ShaderLanguage::get_shader_type(get_text_edit()->get_text()); + String type = ShaderLanguage::get_shader_type(get_text_editor()->get_text()); Shader::Mode mode; @@ -189,7 +189,7 @@ void ShaderTextEditor::_check_shader_mode() { } if (shader->get_mode() != mode) { - shader->set_code(get_text_edit()->get_text()); + shader->set_code(get_text_editor()->get_text()); _load_theme_settings(); } } @@ -207,13 +207,13 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptCo sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), _get_global_variable_type, r_options, calltip); - get_text_edit()->set_code_hint(calltip); + get_text_editor()->set_code_hint(calltip); } void ShaderTextEditor::_validate_script() { _check_shader_mode(); - String code = get_text_edit()->get_text(); + String code = get_text_editor()->get_text(); //List<StringName> params; //shader->get_param_list(¶ms); @@ -225,14 +225,14 @@ void ShaderTextEditor::_validate_script() { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); set_error(error_text); set_error_pos(sl.get_error_line() - 1, 0); - for (int i = 0; i < get_text_edit()->get_line_count(); i++) { - get_text_edit()->set_line_as_marked(i, false); + for (int i = 0; i < get_text_editor()->get_line_count(); i++) { + get_text_editor()->set_line_as_marked(i, false); } - get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true); + get_text_editor()->set_line_as_marked(sl.get_error_line() - 1, true); } else { - for (int i = 0; i < get_text_edit()->get_line_count(); i++) { - get_text_edit()->set_line_as_marked(i, false); + for (int i = 0; i < get_text_editor()->get_line_count(); i++) { + get_text_editor()->set_line_as_marked(i, false); } set_error(""); } @@ -245,7 +245,7 @@ void ShaderTextEditor::_bind_methods() { ShaderTextEditor::ShaderTextEditor() { syntax_highlighter.instance(); - get_text_edit()->set_syntax_highlighter(syntax_highlighter); + get_text_editor()->set_syntax_highlighter(syntax_highlighter); } /*** SCRIPT EDITOR ******/ @@ -253,22 +253,22 @@ ShaderTextEditor::ShaderTextEditor() { void ShaderEditor::_menu_option(int p_option) { switch (p_option) { case EDIT_UNDO: { - shader_editor->get_text_edit()->undo(); + shader_editor->get_text_editor()->undo(); } break; case EDIT_REDO: { - shader_editor->get_text_edit()->redo(); + shader_editor->get_text_editor()->redo(); } break; case EDIT_CUT: { - shader_editor->get_text_edit()->cut(); + shader_editor->get_text_editor()->cut(); } break; case EDIT_COPY: { - shader_editor->get_text_edit()->copy(); + shader_editor->get_text_editor()->copy(); } break; case EDIT_PASTE: { - shader_editor->get_text_edit()->paste(); + shader_editor->get_text_editor()->paste(); } break; case EDIT_SELECT_ALL: { - shader_editor->get_text_edit()->select_all(); + shader_editor->get_text_editor()->select_all(); } break; case EDIT_MOVE_LINE_UP: { shader_editor->move_lines_up(); @@ -281,7 +281,7 @@ void ShaderEditor::_menu_option(int p_option) { return; } - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); tx->indent_left(); } break; @@ -290,7 +290,7 @@ void ShaderEditor::_menu_option(int p_option) { return; } - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); tx->indent_right(); } break; @@ -309,7 +309,7 @@ void ShaderEditor::_menu_option(int p_option) { } break; case EDIT_COMPLETE: { - shader_editor->get_text_edit()->query_code_comple(); + shader_editor->get_text_editor()->query_code_comple(); } break; case SEARCH_FIND: { shader_editor->get_find_replace_bar()->popup_search(); @@ -324,7 +324,7 @@ void ShaderEditor::_menu_option(int p_option) { shader_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_GOTO_LINE: { - goto_line_dialog->popup_find_line(shader_editor->get_text_edit()); + goto_line_dialog->popup_find_line(shader_editor->get_text_editor()); } break; case BOOKMARK_TOGGLE: { shader_editor->toggle_bookmark(); @@ -343,7 +343,7 @@ void ShaderEditor::_menu_option(int p_option) { } break; } if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) { - shader_editor->get_text_edit()->call_deferred("grab_focus"); + shader_editor->get_text_editor()->call_deferred("grab_focus"); } } @@ -358,28 +358,11 @@ void ShaderEditor::_params_changed() { } void ShaderEditor::_editor_settings_changed() { - shader_editor->get_text_edit()->set_auto_brace_completion(EditorSettings::get_singleton()->get("text_editor/completion/auto_brace_complete")); - shader_editor->get_text_edit()->set_scroll_pass_end_of_file(EditorSettings::get_singleton()->get("text_editor/cursor/scroll_past_end_of_file")); - shader_editor->get_text_edit()->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size")); - shader_editor->get_text_edit()->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type")); - shader_editor->get_text_edit()->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent")); - shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs")); - shader_editor->get_text_edit()->set_draw_spaces(EditorSettings::get_singleton()->get("text_editor/indent/draw_spaces")); - shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_numbers")); - shader_editor->get_text_edit()->set_highlight_all_occurrences(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_all_occurrences")); - shader_editor->get_text_edit()->set_highlight_current_line(EditorSettings::get_singleton()->get("text_editor/highlighting/highlight_current_line")); - shader_editor->get_text_edit()->cursor_set_blink_enabled(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink")); - shader_editor->get_text_edit()->cursor_set_blink_speed(EditorSettings::get_singleton()->get("text_editor/cursor/caret_blink_speed")); - shader_editor->get_text_edit()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); - shader_editor->get_text_edit()->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret")); - shader_editor->get_text_edit()->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/navigation/smooth_scrolling")); - shader_editor->get_text_edit()->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/navigation/v_scroll_speed")); - shader_editor->get_text_edit()->set_draw_minimap(EditorSettings::get_singleton()->get("text_editor/navigation/show_minimap")); - shader_editor->get_text_edit()->set_minimap_width((int)EditorSettings::get_singleton()->get("text_editor/navigation/minimap_width") * EDSCALE); - shader_editor->get_text_edit()->set_show_line_length_guidelines(EditorSettings::get_singleton()->get("text_editor/appearance/show_line_length_guidelines")); - shader_editor->get_text_edit()->set_line_length_guideline_soft_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_soft_column")); - shader_editor->get_text_edit()->set_line_length_guideline_hard_column(EditorSettings::get_singleton()->get("text_editor/appearance/line_length_guideline_hard_column")); - shader_editor->get_text_edit()->set_breakpoint_gutter_enabled(false); + shader_editor->update_editor_settings(); + + shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); + shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false); + shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false); } void ShaderEditor::_bind_methods() { @@ -466,7 +449,7 @@ void ShaderEditor::save_external_data(const String &p_str) { void ShaderEditor::apply_shaders() { if (shader.is_valid()) { String shader_code = shader->get_code(); - String editor_code = shader_editor->get_text_edit()->get_text(); + String editor_code = shader_editor->get_text_editor()->get_text(); if (shader_code != editor_code) { shader->set_code(editor_code); shader->set_edited(true); @@ -480,7 +463,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { int col, row; - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); @@ -507,7 +490,7 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventKey> k = ev; if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) { - TextEdit *tx = shader_editor->get_text_edit(); + CodeEdit *tx = shader_editor->get_text_editor(); _make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); context_menu->grab_focus(); } @@ -521,7 +504,7 @@ void ShaderEditor::_update_bookmark_list() { bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); - Array bookmark_list = shader_editor->get_text_edit()->get_bookmarks_array(); + Array bookmark_list = shader_editor->get_text_editor()->get_bookmarked_lines(); if (bookmark_list.size() == 0) { return; } @@ -529,7 +512,7 @@ void ShaderEditor::_update_bookmark_list() { bookmarks_menu->add_separator(); for (int i = 0; i < bookmark_list.size(); i++) { - String line = shader_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges(); + String line = shader_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { line = line.substr(0, 50); @@ -581,13 +564,13 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) { shader_editor->connect("script_changed", callable_mp(this, &ShaderEditor::apply_shaders)); EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ShaderEditor::_editor_settings_changed)); - shader_editor->get_text_edit()->set_callhint_settings( + shader_editor->get_text_editor()->set_callhint_settings( EditorSettings::get_singleton()->get("text_editor/completion/put_callhint_tooltip_below_current_line"), EditorSettings::get_singleton()->get("text_editor/completion/callhint_tooltip_offset")); - shader_editor->get_text_edit()->set_select_identifiers_on_hover(true); - shader_editor->get_text_edit()->set_context_menu_enabled(false); - shader_editor->get_text_edit()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input)); + shader_editor->get_text_editor()->set_select_identifiers_on_hover(true); + shader_editor->get_text_editor()->set_context_menu_enabled(false); + shader_editor->get_text_editor()->connect("gui_input", callable_mp(this, &ShaderEditor::_text_edit_gui_input)); shader_editor->update_editor_settings(); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 18942b371c..5007983581 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -995,11 +995,16 @@ SpriteFramesEditor::SpriteFramesEditor() { animations->connect("item_edited", callable_mp(this, &SpriteFramesEditor::_animation_name_edited)); animations->set_allow_reselect(true); + HBoxContainer *hbc_anim_speed = memnew(HBoxContainer); + hbc_anim_speed->add_child(memnew(Label(TTR("Speed:")))); + vbc_animlist->add_child(hbc_anim_speed); anim_speed = memnew(SpinBox); - vbc_animlist->add_margin_child(TTR("Speed (FPS):"), anim_speed); + anim_speed->set_suffix(TTR("FPS")); anim_speed->set_min(0); anim_speed->set_max(100); anim_speed->set_step(0.01); + anim_speed->set_h_size_flags(SIZE_EXPAND_FILL); + hbc_anim_speed->add_child(anim_speed); anim_speed->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_animation_fps_changed)); anim_loop = memnew(CheckButton); diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 82e231e396..8935b698b6 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -50,7 +50,7 @@ void TextEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlight el = el->next(); } - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); te->set_syntax_highlighter(p_highlighter); } @@ -59,7 +59,7 @@ void TextEditor::_change_syntax_highlighter(int p_idx) { } void TextEditor::_load_theme_settings() { - TextEdit *text_edit = code_editor->get_text_edit(); + CodeEdit *text_edit = code_editor->get_text_editor(); text_edit->get_syntax_highlighter()->update_cache(); Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); @@ -147,9 +147,9 @@ void TextEditor::set_edited_resource(const RES &p_res) { text_file = p_res; - code_editor->get_text_edit()->set_text(text_file->get_text()); - code_editor->get_text_edit()->clear_undo_history(); - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->set_text(text_file->get_text()); + code_editor->get_text_editor()->clear_undo_history(); + code_editor->get_text_editor()->tag_saved_version(); emit_signal("name_changed"); code_editor->update_line_and_column(); @@ -171,13 +171,14 @@ void TextEditor::add_callback(const String &p_function, PackedStringArray p_args void TextEditor::set_debugger_active(bool p_active) { } -void TextEditor::get_breakpoints(List<int> *p_breakpoints) { +Array TextEditor::get_breakpoints() { + return Array(); } void TextEditor::reload_text() { ERR_FAIL_COND(text_file.is_null()); - TextEdit *te = code_editor->get_text_edit(); + CodeEdit *te = code_editor->get_text_editor(); int column = te->cursor_get_column(); int row = te->cursor_get_line(); int h = te->get_h_scroll(); @@ -207,7 +208,7 @@ void TextEditor::_update_bookmark_list() { bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_next_bookmark"), BOOKMARK_GOTO_NEXT); bookmarks_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/goto_previous_bookmark"), BOOKMARK_GOTO_PREV); - Array bookmark_list = code_editor->get_text_edit()->get_bookmarks_array(); + Array bookmark_list = code_editor->get_text_editor()->get_bookmarked_lines(); if (bookmark_list.size() == 0) { return; } @@ -215,7 +216,7 @@ void TextEditor::_update_bookmark_list() { bookmarks_menu->add_separator(); for (int i = 0; i < bookmark_list.size(); i++) { - String line = code_editor->get_text_edit()->get_line(bookmark_list[i]).strip_edges(); + String line = code_editor->get_text_editor()->get_line(bookmark_list[i]).strip_edges(); // Limit the size of the line if too big. if (line.length() > 50) { line = line.substr(0, 50); @@ -235,12 +236,12 @@ void TextEditor::_bookmark_item_pressed(int p_idx) { } void TextEditor::apply_code() { - text_file->set_text(code_editor->get_text_edit()->get_text()); + text_file->set_text(code_editor->get_text_editor()->get_text()); } bool TextEditor::is_unsaved() { const bool unsaved = - code_editor->get_text_edit()->get_version() != code_editor->get_text_edit()->get_saved_version() || + code_editor->get_text_editor()->get_version() != code_editor->get_text_editor()->get_saved_version() || text_file->get_path().empty(); // In memory. return unsaved; } @@ -280,7 +281,7 @@ void TextEditor::convert_indent_to_tabs() { } void TextEditor::tag_saved_version() { - code_editor->get_text_edit()->tag_saved_version(); + code_editor->get_text_editor()->tag_saved_version(); } void TextEditor::goto_line(int p_line, bool p_with_error) { @@ -300,7 +301,7 @@ void TextEditor::clear_executing_line() { } void TextEditor::ensure_focus() { - code_editor->get_text_edit()->grab_focus(); + code_editor->get_text_editor()->grab_focus(); } Vector<String> TextEditor::get_functions() { @@ -316,7 +317,7 @@ void TextEditor::update_settings() { } void TextEditor::set_tooltip_request_func(String p_method, Object *p_obj) { - code_editor->get_text_edit()->set_tooltip_request_func(p_obj, p_method, this); + code_editor->get_text_editor()->set_tooltip_request_func(p_obj, p_method, this); } Control *TextEditor::get_edit_menu() { @@ -328,7 +329,7 @@ void TextEditor::clear_edit_menu() { } void TextEditor::_edit_option(int p_op) { - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); switch (p_op) { case EDIT_UNDO: { @@ -416,14 +417,14 @@ void TextEditor::_edit_option(int p_op) { code_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); // Yep, because it doesn't make sense to instance this dialog for every single script open... // So this will be delegated to the ScriptEditor. emit_signal("search_in_files_requested", selected_text); } break; case REPLACE_IN_FILES: { - String selected_text = code_editor->get_text_edit()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selection_text(); emit_signal("replace_in_files_requested", selected_text); } break; @@ -470,7 +471,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { if (mb->get_button_index() == BUTTON_RIGHT) { int col, row; - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); @@ -503,7 +504,7 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { Ref<InputEventKey> k = ev; if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) { - TextEdit *tx = code_editor->get_text_edit(); + CodeEdit *tx = code_editor->get_text_editor(); int line = tx->cursor_get_line(); _make_context_menu(tx->is_selection_active(), tx->can_fold(line), tx->is_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); context_menu->grab_focus(); @@ -552,8 +553,8 @@ TextEditor::TextEditor() { update_settings(); - code_editor->get_text_edit()->set_context_menu_enabled(false); - code_editor->get_text_edit()->connect("gui_input", callable_mp(this, &TextEditor::_text_edit_gui_input)); + code_editor->get_text_editor()->set_context_menu_enabled(false); + code_editor->get_text_editor()->connect("gui_input", callable_mp(this, &TextEditor::_text_edit_gui_input)); context_menu = memnew(PopupMenu); add_child(context_menu); @@ -649,7 +650,7 @@ TextEditor::TextEditor() { goto_line_dialog = memnew(GotoLineDialog); add_child(goto_line_dialog); - code_editor->get_text_edit()->set_drag_forwarding(this); + code_editor->get_text_editor()->set_drag_forwarding(this); } TextEditor::~TextEditor() { diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index f3e9e599cf..ea425bd033 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -119,7 +119,7 @@ public: virtual Variant get_edit_state() override; virtual void set_edit_state(const Variant &p_state) override; virtual Vector<String> get_functions() override; - virtual void get_breakpoints(List<int> *p_breakpoints) override; + virtual Array get_breakpoints() override; virtual void goto_line(int p_line, bool p_with_error = false) override; void goto_line_selection(int p_line, int p_begin, int p_end); virtual void set_executing_line(int p_line) override; diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp new file mode 100644 index 0000000000..ba2eef8484 --- /dev/null +++ b/editor/plugins/texture_3d_editor_plugin.cpp @@ -0,0 +1,213 @@ +/*************************************************************************/ +/* texture_3d_editor_plugin.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 "texture_3d_editor_plugin.h" + +#include "core/io/resource_loader.h" +#include "core/project_settings.h" +#include "editor/editor_settings.h" + +void Texture3DEditor::_gui_input(Ref<InputEvent> p_event) { +} + +void Texture3DEditor::_texture_rect_draw() { + texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1)); +} + +void Texture3DEditor::_notification(int p_what) { + if (p_what == NOTIFICATION_READY) { + //get_scene()->connect("node_removed",this,"_node_removed"); + } + if (p_what == NOTIFICATION_RESIZED) { + _texture_rect_update_area(); + } + + if (p_what == NOTIFICATION_DRAW) { + Ref<Texture2D> checkerboard = get_theme_icon("Checkerboard", "EditorIcons"); + Size2 size = get_size(); + + draw_texture_rect(checkerboard, Rect2(Point2(), size), true); + } +} + +void Texture3DEditor::_changed_callback(Object *p_changed, const char *p_prop) { + if (!is_visible()) { + return; + } + update(); +} + +void Texture3DEditor::_update_material() { + material->set_shader_param("layer", (layer->get_value() + 0.5) / texture->get_depth()); + material->set_shader_param("tex", texture->get_rid()); + + String format = Image::get_format_name(texture->get_format()); + + String text; + text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + "x" + itos(texture->get_depth()) + " " + format; + + info->set_text(text); +} + +void Texture3DEditor::_make_shaders() { + String shader_3d = "" + "shader_type canvas_item;\n" + "uniform sampler3D tex;\n" + "uniform float layer;\n" + "void fragment() {\n" + " COLOR = textureLod(tex,vec3(UV,layer),0.0);\n" + "}"; + + shader.instance(); + shader->set_code(shader_3d); + material.instance(); + material->set_shader(shader); +} + +void Texture3DEditor::_texture_rect_update_area() { + Size2 size = get_size(); + int tex_width = texture->get_width() * size.height / texture->get_height(); + int tex_height = size.height; + + if (tex_width > size.width) { + tex_width = size.width; + tex_height = texture->get_height() * tex_width / texture->get_width(); + } + + // Prevent the texture from being unpreviewable after the rescale, so that we can still see something + if (tex_height <= 0) { + tex_height = 1; + } + if (tex_width <= 0) { + tex_width = 1; + } + + int ofs_x = (size.width - tex_width) / 2; + int ofs_y = (size.height - tex_height) / 2; + + texture_rect->set_position(Vector2(ofs_x, ofs_y)); + texture_rect->set_size(Vector2(tex_width, tex_height)); +} + +void Texture3DEditor::edit(Ref<Texture3D> p_texture) { + if (!texture.is_null()) { + texture->remove_change_receptor(this); + } + + texture = p_texture; + + if (!texture.is_null()) { + if (shader.is_null()) { + _make_shaders(); + } + + texture->add_change_receptor(this); + update(); + texture_rect->set_material(material); + setting = true; + layer->set_max(texture->get_depth() - 1); + layer->set_value(0); + layer->show(); + _update_material(); + setting = false; + _texture_rect_update_area(); + } else { + hide(); + } +} + +void Texture3DEditor::_bind_methods() { + ClassDB::bind_method(D_METHOD("_gui_input"), &Texture3DEditor::_gui_input); + ClassDB::bind_method(D_METHOD("_layer_changed"), &Texture3DEditor::_layer_changed); +} + +Texture3DEditor::Texture3DEditor() { + set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); + set_custom_minimum_size(Size2(1, 150)); + texture_rect = memnew(Control); + texture_rect->connect("draw", callable_mp(this, &Texture3DEditor::_texture_rect_draw)); + texture_rect->set_mouse_filter(MOUSE_FILTER_IGNORE); + add_child(texture_rect); + + layer = memnew(SpinBox); + layer->set_step(1); + layer->set_max(100); + add_child(layer); + layer->set_anchor(MARGIN_RIGHT, 1); + layer->set_anchor(MARGIN_LEFT, 1); + layer->set_h_grow_direction(GROW_DIRECTION_BEGIN); + layer->set_modulate(Color(1, 1, 1, 0.8)); + info = memnew(Label); + add_child(info); + info->set_anchor(MARGIN_RIGHT, 1); + info->set_anchor(MARGIN_LEFT, 1); + info->set_anchor(MARGIN_BOTTOM, 1); + info->set_anchor(MARGIN_TOP, 1); + info->set_h_grow_direction(GROW_DIRECTION_BEGIN); + info->set_v_grow_direction(GROW_DIRECTION_BEGIN); + info->add_theme_color_override("font_color", Color(1, 1, 1, 1)); + info->add_theme_color_override("font_color_shadow", Color(0, 0, 0, 0.5)); + info->add_theme_color_override("font_color_shadow", Color(0, 0, 0, 0.5)); + info->add_theme_constant_override("shadow_as_outline", 1); + info->add_theme_constant_override("shadow_offset_x", 2); + info->add_theme_constant_override("shadow_offset_y", 2); + + setting = false; + layer->connect("value_changed", Callable(this, "_layer_changed")); +} + +Texture3DEditor::~Texture3DEditor() { + if (!texture.is_null()) { + texture->remove_change_receptor(this); + } +} + +// +bool EditorInspectorPlugin3DTexture::can_handle(Object *p_object) { + return Object::cast_to<Texture3D>(p_object) != nullptr; +} + +void EditorInspectorPlugin3DTexture::parse_begin(Object *p_object) { + Texture3D *texture = Object::cast_to<Texture3D>(p_object); + if (!texture) { + return; + } + Ref<Texture3D> m(texture); + + Texture3DEditor *editor = memnew(Texture3DEditor); + editor->edit(m); + add_custom_control(editor); +} + +Texture3DEditorPlugin::Texture3DEditorPlugin(EditorNode *p_node) { + Ref<EditorInspectorPlugin3DTexture> plugin; + plugin.instance(); + add_inspector_plugin(plugin); +} diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h new file mode 100644 index 0000000000..4fbf47ecfe --- /dev/null +++ b/editor/plugins/texture_3d_editor_plugin.h @@ -0,0 +1,93 @@ +/*************************************************************************/ +/* texture_3d_editor_plugin.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 TEXTURE_3D_EDITOR_PLUGIN_H +#define TEXTURE_3D_EDITOR_PLUGIN_H + +#include "editor/editor_node.h" +#include "editor/editor_plugin.h" +#include "scene/resources/shader.h" +#include "scene/resources/texture.h" + +class Texture3DEditor : public Control { + GDCLASS(Texture3DEditor, Control); + + SpinBox *layer; + Label *info; + Ref<Texture3D> texture; + + Ref<Shader> shader; + Ref<ShaderMaterial> material; + + Control *texture_rect; + + void _make_shaders(); + + void _update_material(); + bool setting; + void _layer_changed(double) { + if (!setting) { + _update_material(); + } + } + + void _texture_rect_update_area(); + void _texture_rect_draw(); + +protected: + void _notification(int p_what); + void _gui_input(Ref<InputEvent> p_event); + void _changed_callback(Object *p_changed, const char *p_prop) override; + static void _bind_methods(); + +public: + void edit(Ref<Texture3D> p_texture); + Texture3DEditor(); + ~Texture3DEditor(); +}; + +class EditorInspectorPlugin3DTexture : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPlugin3DTexture, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual void parse_begin(Object *p_object) override; +}; + +class Texture3DEditorPlugin : public EditorPlugin { + GDCLASS(Texture3DEditorPlugin, EditorPlugin); + +public: + virtual String get_name() const override { return "Texture3D"; } + + Texture3DEditorPlugin(EditorNode *p_node); +}; + +#endif // TEXTURE_EDITOR_PLUGIN_H diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index e71485e9fc..8cd8aaf277 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -802,7 +802,6 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p r.size = node->get_tileset()->autotile_get_size(p_cell); r.position += (r.size + Vector2(spacing, spacing)) * offset; } - Size2 sc = p_xform.get_scale(); Size2 cell_size = node->get_cell_size(); bool centered_texture = node->is_centered_textures_enabled(); bool compatibility_mode_enabled = node->is_compatibility_mode_enabled(); @@ -838,12 +837,12 @@ void TileMapEditor::_draw_cell(Control *p_viewport, int p_cell, const Point2i &p } if (p_flip_h) { - sc.x *= -1.0; + rect.size.x *= -1.0; tile_ofs.x *= -1.0; } if (p_flip_v) { - sc.y *= -1.0; + rect.size.y *= -1.0; tile_ofs.y *= -1.0; } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 217294464c..e34f0855b2 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -60,6 +60,579 @@ void VisualShaderNodePlugin::_bind_methods() { /////////////////// +static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { + Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); + style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE); + style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE); + style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE); + style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE); + return style; +} + +/////////////////// + +VisualShaderGraphPlugin::VisualShaderGraphPlugin() { +} + +void VisualShaderGraphPlugin::_bind_methods() { + ClassDB::bind_method("add_node", &VisualShaderGraphPlugin::add_node); + ClassDB::bind_method("remove_node", &VisualShaderGraphPlugin::remove_node); + ClassDB::bind_method("connect_nodes", &VisualShaderGraphPlugin::connect_nodes); + ClassDB::bind_method("disconnect_nodes", &VisualShaderGraphPlugin::disconnect_nodes); + ClassDB::bind_method("set_node_position", &VisualShaderGraphPlugin::set_node_position); + ClassDB::bind_method("set_node_size", &VisualShaderGraphPlugin::set_node_size); + ClassDB::bind_method("show_port_preview", &VisualShaderGraphPlugin::show_port_preview); + ClassDB::bind_method("update_property_editor", &VisualShaderGraphPlugin::update_property_editor); + ClassDB::bind_method("update_property_editor_deferred", &VisualShaderGraphPlugin::update_property_editor_deferred); + ClassDB::bind_method("set_input_port_default_value", &VisualShaderGraphPlugin::set_input_port_default_value); +} + +void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) { + visual_shader = Ref<VisualShader>(p_shader); +} + +void VisualShaderGraphPlugin::set_connections(List<VisualShader::Connection> &p_connections) { + connections = p_connections; +} + +void VisualShaderGraphPlugin::show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id) { + if (visual_shader->get_shader_type() == p_type && links.has(p_node_id)) { + for (Map<int, Port>::Element *E = links[p_node_id].output_ports.front(); E; E = E->next()) { + E->value().preview_button->set_pressed(false); + } + + if (links[p_node_id].preview_visible && !is_dirty() && links[p_node_id].preview_box != nullptr) { + links[p_node_id].graph_node->remove_child(links[p_node_id].preview_box); + memdelete(links[p_node_id].preview_box); + links[p_node_id].graph_node->set_size(Vector2(-1, -1)); + links[p_node_id].preview_visible = false; + } + + if (p_port_id != -1) { + if (is_dirty()) { + links[p_node_id].preview_pos = links[p_node_id].graph_node->get_child_count(); + } + + VBoxContainer *vbox = memnew(VBoxContainer); + links[p_node_id].graph_node->add_child(vbox); + if (links[p_node_id].preview_pos != -1) { + links[p_node_id].graph_node->move_child(vbox, links[p_node_id].preview_pos); + } + + Control *offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); + vbox->add_child(offset); + + VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview); + port_preview->setup(visual_shader, visual_shader->get_shader_type(), p_node_id, p_port_id); + port_preview->set_h_size_flags(Control::SIZE_SHRINK_CENTER); + vbox->add_child(port_preview); + links[p_node_id].preview_visible = true; + links[p_node_id].preview_box = vbox; + links[p_node_id].output_ports[p_port_id].preview_button->set_pressed(true); + } + } +} + +void VisualShaderGraphPlugin::update_property_editor_deferred(VisualShader::Type p_type, int p_node_id) { + call_deferred("update_property_editor", p_type, p_node_id); +} + +void VisualShaderGraphPlugin::update_property_editor(VisualShader::Type p_type, int p_node_id) { + if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id)) { + return; + } + remove_node(p_type, p_node_id); + add_node(p_type, p_node_id); +} + +void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value) { + if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id)) { + return; + } + + Button *button = links[p_node_id].input_ports[p_port_id].default_input_button; + + switch (p_value.get_type()) { + case Variant::COLOR: { + button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); + if (!button->is_connected("draw", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_draw_color_over_button))) { + button->connect("draw", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_draw_color_over_button), varray(button, p_value)); + } + } break; + case Variant::BOOL: { + button->set_text(((bool)p_value) ? "true" : "false"); + } break; + case Variant::INT: + case Variant::FLOAT: { + button->set_text(String::num(p_value, 4)); + } break; + case Variant::VECTOR3: { + Vector3 v = p_value; + button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); + } break; + default: { + } + } +} + +void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p_port_id, Button *p_button) { + links[p_node_id].input_ports.insert(p_port_id, { p_button }); +} + +VisualShader::Type VisualShaderGraphPlugin::get_shader_type() const { + return visual_shader->get_shader_type(); +} + +void VisualShaderGraphPlugin::set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->set_offset(p_position); + } +} + +void VisualShaderGraphPlugin::set_node_size(VisualShader::Type p_type, int p_id, const Vector2 &p_size) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + links[p_id].graph_node->set_size(p_size); + } +} + +bool VisualShaderGraphPlugin::is_preview_visible(int p_id) const { + return links[p_id].preview_visible; +} + +void VisualShaderGraphPlugin::clear_links() { + links.clear(); +} + +bool VisualShaderGraphPlugin::is_dirty() const { + return dirty; +} + +void VisualShaderGraphPlugin::make_dirty(bool p_enabled) { + dirty = p_enabled; +} + +void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) { + links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr }); +} + +void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { + links[p_node_id].output_ports.insert(p_port, { p_button }); +} + +void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { + if (p_type != visual_shader->get_shader_type()) { + return; + } + + Control *offset; + + static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); + + static const Color type_color[6] = { + Color(0.38, 0.85, 0.96), // scalar (float) + Color(0.49, 0.78, 0.94), // scalar (int) + Color(0.84, 0.49, 0.93), // vector + Color(0.55, 0.65, 0.94), // boolean + Color(0.96, 0.66, 0.43), // transform + Color(1.0, 1.0, 0.0), // sampler + }; + + Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id); + + Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr()); + bool is_group = !group_node.is_null(); + Size2 size = Size2(0, 0); + + Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr()); + bool is_expression = !expression_node.is_null(); + String expression = ""; + + GraphNode *node = memnew(GraphNode); + register_link(p_type, p_id, vsnode.ptr(), node); + + if (is_group) { + size = group_node->get_size(); + + node->set_resizable(true); + node->connect("resize_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_resized), varray((int)p_type, p_id)); + } + if (is_expression) { + expression = expression_node->get_expression(); + } + + node->set_offset(visual_shader->get_node_position(p_type, p_id)); + node->set_title(vsnode->get_caption()); + node->set_name(itos(p_id)); + + if (p_id >= 2) { + node->set_show_close_button(true); + node->connect("close_request", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_delete_request), varray(p_id), CONNECT_DEFERRED); + } + + node->connect("dragged", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_dragged), varray(p_id)); + + Control *custom_editor = nullptr; + int port_offset = 0; + + if (is_group) { + port_offset += 2; + } + + Ref<VisualShaderNodeUniform> uniform = vsnode; + + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->call_deferred("_update_uniforms"); + } + + Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; + Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; + Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; + Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; + Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; + Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode; + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->graph->add_child(node); + VisualShaderEditor::get_singleton()->_update_created_node(node); + + LineEdit *uniform_name = memnew(LineEdit); + uniform_name->set_text(uniform->get_uniform_name()); + node->add_child(uniform_name); + uniform_name->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_line_edit_changed), varray(uniform_name, p_id)); + uniform_name->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_line_edit_focus_out), varray(uniform_name, p_id)); + + String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + if (error != String()) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); + node->add_child(offset); + Label *error_label = memnew(Label); + error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("error_color", "Editor")); + error_label->set_text(error); + node->add_child(error_label); + } + + if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { + //shortcut + VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); + node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); + if (!float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !color_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid()) { + return; + } + } + port_offset++; + } + + for (int i = 0; i < VisualShaderEditor::get_singleton()->plugins.size(); i++) { + vsnode->set_meta("id", p_id); + vsnode->set_meta("shader_type", (int)p_type); + custom_editor = VisualShaderEditor::get_singleton()->plugins.write[i]->create_editor(visual_shader, vsnode); + vsnode->remove_meta("id"); + vsnode->remove_meta("shader_type"); + if (custom_editor) { + break; + } + } + + if (custom_editor && !float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { + //will be embedded in first port + } else if (custom_editor) { + port_offset++; + node->add_child(custom_editor); + if (color_uniform.is_valid()) { + custom_editor->call_deferred("_show_prop_names", true); + } + if (float_uniform.is_valid() || int_uniform.is_valid() || vec3_uniform.is_valid() || bool_uniform.is_valid() || transform_uniform.is_valid()) { + custom_editor->call_deferred("_show_prop_names", true); + return; + } + custom_editor = nullptr; + } + + if (is_group) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); + node->add_child(offset); + + if (group_node->is_editable()) { + HBoxContainer *hb2 = memnew(HBoxContainer); + + Button *add_input_btn = memnew(Button); + add_input_btn->set_text(TTR("Add Input")); + add_input_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_add_input_port), varray(p_id, group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED); + hb2->add_child(add_input_btn); + + hb2->add_spacer(); + + Button *add_output_btn = memnew(Button); + add_output_btn->set_text(TTR("Add Output")); + add_output_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_add_output_port), varray(p_id, group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED); + hb2->add_child(add_output_btn); + + node->add_child(hb2); + } + } + + for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) { + if (vsnode->is_port_separator(i)) { + node->add_child(memnew(HSeparator)); + port_offset++; + } + + bool valid_left = i < vsnode->get_input_port_count(); + VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR; + bool port_left_used = false; + String name_left; + if (valid_left) { + name_left = vsnode->get_input_port_name(i); + port_left = vsnode->get_input_port_type(i); + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { + if (E->get().to_node == p_id && E->get().to_port == i) { + port_left_used = true; + } + } + } + + bool valid_right = i < vsnode->get_output_port_count(); + VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR; + String name_right; + if (valid_right) { + name_right = vsnode->get_output_port_name(i); + port_right = vsnode->get_output_port_type(i); + } + + HBoxContainer *hb = memnew(HBoxContainer); + hb->add_theme_constant_override("separation", 7 * EDSCALE); + + Variant default_value; + + if (valid_left && !port_left_used) { + default_value = vsnode->get_input_port_default_value(i); + } + + Button *button = memnew(Button); + hb->add_child(button); + register_default_input_button(p_id, i, button); + button->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_edit_port_default_input), varray(button, p_id, i)); + if (default_value.get_type() != Variant::NIL) { // only a label + set_input_port_default_value(p_type, p_id, i, default_value); + } else { + button->hide(); + } + + if (i == 0 && custom_editor) { + hb->add_child(custom_editor); + custom_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + } else { + if (valid_left) { + if (is_group) { + OptionButton *type_box = memnew(OptionButton); + hb->add_child(type_box); + type_box->add_item(TTR("Float")); + type_box->add_item(TTR("Int")); + type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Boolean")); + type_box->add_item(TTR("Transform")); + type_box->add_item(TTR("Sampler")); + type_box->select(group_node->get_input_port_type(i)); + type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + type_box->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_type), varray(p_id, i), CONNECT_DEFERRED); + + LineEdit *name_box = memnew(LineEdit); + hb->add_child(name_box); + name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); + name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + name_box->set_text(name_left); + name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_input_port_name), varray(name_box, p_id, i)); + name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, false)); + + Button *remove_btn = memnew(Button); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_input_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(remove_btn); + } else { + Label *label = memnew(Label); + label->set_text(name_left); + label->add_theme_style_override("normal", label_style); //more compact + hb->add_child(label); + + if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { + Label *hint_label = memnew(Label); + hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); + hint_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("font_color_readonly", "TextEdit")); + hint_label->add_theme_style_override("normal", label_style); + hb->add_child(hint_label); + } + } + } + + if (!is_group) { + hb->add_spacer(); + } + + if (valid_right) { + if (is_group) { + Button *remove_btn = memnew(Button); + remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); + remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_remove_output_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(remove_btn); + + LineEdit *name_box = memnew(LineEdit); + hb->add_child(name_box); + name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); + name_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + name_box->set_text(name_right); + name_box->connect("text_entered", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_name), varray(name_box, p_id, i)); + name_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_port_name_focus_out), varray(name_box, p_id, i, true)); + + OptionButton *type_box = memnew(OptionButton); + hb->add_child(type_box); + type_box->add_item(TTR("Float")); + type_box->add_item(TTR("Int")); + type_box->add_item(TTR("Vector")); + type_box->add_item(TTR("Boolean")); + type_box->add_item(TTR("Transform")); + type_box->select(group_node->get_output_port_type(i)); + type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + type_box->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_change_output_port_type), varray(p_id, i), CONNECT_DEFERRED); + } else { + Label *label = memnew(Label); + label->set_text(name_right); + label->add_theme_style_override("normal", label_style); //more compact + hb->add_child(label); + } + } + } + + if (valid_right && visual_shader->get_shader_type() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { + TextureButton *preview = memnew(TextureButton); + preview->set_toggle_mode(true); + preview->set_normal_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityHidden", "EditorIcons")); + preview->set_pressed_texture(VisualShaderEditor::get_singleton()->get_theme_icon("GuiVisibilityVisible", "EditorIcons")); + preview->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + + register_output_port(p_id, i, preview); + + preview->connect("pressed", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_preview_select_port), varray(p_id, i), CONNECT_DEFERRED); + hb->add_child(preview); + } + + if (is_group) { + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); + node->add_child(offset); + port_offset++; + } + + node->add_child(hb); + + node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); + } + + if (vsnode->get_output_port_for_preview() >= 0) { + show_port_preview(p_type, p_id, vsnode->get_output_port_for_preview()); + } + + offset = memnew(Control); + offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); + node->add_child(offset); + + String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + if (error != String()) { + Label *error_label = memnew(Label); + error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color("error_color", "Editor")); + error_label->set_text(error); + node->add_child(error_label); + } + + if (is_expression) { + CodeEdit *expression_box = memnew(CodeEdit); + Ref<CodeHighlighter> expression_syntax_highlighter; + expression_syntax_highlighter.instance(); + expression_node->set_control(expression_box, 0); + node->add_child(expression_box); + + Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); + Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); + Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); + Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); + Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); + Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); + Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); + Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + + expression_box->set_syntax_highlighter(expression_syntax_highlighter); + expression_box->add_theme_color_override("background_color", background_color); + + for (List<String>::Element *E = VisualShaderEditor::get_singleton()->keyword_list.front(); E; E = E->next()) { + expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color); + } + + expression_box->add_theme_font_override("font", VisualShaderEditor::get_singleton()->get_theme_font("expression", "EditorFonts")); + expression_box->add_theme_color_override("font_color", text_color); + expression_syntax_highlighter->set_number_color(number_color); + expression_syntax_highlighter->set_symbol_color(symbol_color); + expression_syntax_highlighter->set_function_color(function_color); + expression_syntax_highlighter->set_member_variable_color(members_color); + expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false); + expression_syntax_highlighter->add_color_region("//", "", comment_color, true); + + expression_box->set_text(expression); + expression_box->set_context_menu_enabled(false); + expression_box->set_draw_line_numbers(true); + + expression_box->connect("focus_exited", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_expression_focus_out), varray(expression_box, p_id)); + } + + if (!uniform.is_valid()) { + VisualShaderEditor::get_singleton()->graph->add_child(node); + VisualShaderEditor::get_singleton()->_update_created_node(node); + if (is_group) { + call_deferred("_set_node_size", (int)p_type, p_id, size); + } + } +} + +void VisualShaderGraphPlugin::remove_node(VisualShader::Type p_type, int p_id) { + if (visual_shader->get_shader_type() == p_type && links.has(p_id)) { + Ref<VisualShaderNodeUniform> uniform = Ref<VisualShaderNode>(links[p_id].visual_node); + + if (uniform.is_valid()) { + VisualShaderEditor::get_singleton()->call_deferred("_update_uniforms"); + } + + links[p_id].graph_node->get_parent()->remove_child(links[p_id].graph_node); + memdelete(links[p_id].graph_node); + links.erase(p_id); + } +} + +void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { + if (visual_shader->get_shader_type() == p_type) { + VisualShaderEditor::get_singleton()->graph->connect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr) { + links[p_to_node].input_ports[p_to_port].default_input_button->hide(); + } + } +} + +void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) { + if (visual_shader->get_shader_type() == p_type) { + VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port); + if (links[p_to_node].input_ports.has(p_to_port) && links[p_to_node].input_ports[p_to_port].default_input_button != nullptr && links[p_to_node].visual_node->get_input_port_default_value(p_to_port).get_type() != Variant::NIL) { + links[p_to_node].input_ports[p_to_port].default_input_button->show(); + set_input_port_default_value(p_type, p_to_node, p_to_port, links[p_to_node].visual_node->get_input_port_default_value(p_to_port)); + } + } +} + +VisualShaderGraphPlugin::~VisualShaderGraphPlugin() { +} + +///////////////// + void VisualShaderEditor::edit(VisualShader *p_visual_shader) { bool changed = false; if (p_visual_shader) { @@ -71,6 +644,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { } } visual_shader = Ref<VisualShader>(p_visual_shader); + graph_plugin->register_shader(visual_shader.ptr()); if (!visual_shader->is_connected("changed", callable_mp(this, &VisualShaderEditor::_update_preview))) { visual_shader->connect("changed", callable_mp(this, &VisualShaderEditor::_update_preview)); } @@ -81,6 +655,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { } #endif visual_shader->set_graph_offset(graph->get_scroll_ofs() / EDSCALE); + _set_mode(visual_shader->get_mode()); } else { if (visual_shader.is_valid()) { if (visual_shader->is_connected("changed", callable_mp(this, &VisualShaderEditor::_update_preview))) { @@ -97,8 +672,8 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { _clear_buffer(); _update_options_menu(); _update_preview(); + _update_graph(); } - _update_graph(); } } @@ -168,41 +743,18 @@ bool VisualShaderEditor::_is_available(int p_mode) { if (p_mode != -1) { switch (current_mode) { - case VisualShader::TYPE_VERTEX: + case 0: // Vertex or Emit current_mode = 1; break; - case VisualShader::TYPE_FRAGMENT: + case 1: // Fragment or Process current_mode = 2; break; - case VisualShader::TYPE_LIGHT: + case 2: // Light or End current_mode = 4; break; - case VisualShader::TYPE_COMPUTE: - current_mode = 8; - break; default: break; } - - int temp_mode = 0; - - if (p_mode & VisualShader::TYPE_FRAGMENT) { - temp_mode |= 2; - } - - if (p_mode & VisualShader::TYPE_LIGHT) { - temp_mode |= 4; - } - - if (p_mode == VisualShader::TYPE_COMPUTE) { - temp_mode = 8; - } - - if (temp_mode == 0) { - temp_mode |= 1; - } - - p_mode = temp_mode; } return (p_mode == -1 || (p_mode & current_mode) != 0); @@ -411,6 +963,21 @@ void VisualShaderEditor::_update_options_menu() { } } +void VisualShaderEditor::_set_mode(int p_which) { + if (p_which == VisualShader::MODE_PARTICLES) { + edit_type_standart->set_visible(false); + edit_type_particles->set_visible(true); + edit_type = edit_type_particles; + particles_mode = true; + } else { + edit_type_particles->set_visible(false); + edit_type_standart->set_visible(true); + edit_type = edit_type_standart; + particles_mode = false; + } + visual_shader->set_shader_type(get_current_shader_type()); +} + Size2 VisualShaderEditor::get_minimum_size() const { return Size2(10, 200); } @@ -425,15 +992,6 @@ void VisualShaderEditor::_draw_color_over_button(Object *obj, Color p_color) { button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } -static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) { - Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty)); - style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE); - style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE); - style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE); - style->set_default_margin(MARGIN_TOP, p_margin_top * EDSCALE); - return style; -} - void VisualShaderEditor::_update_created_node(GraphNode *node) { if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { Ref<StyleBoxFlat> sb = node->get_theme_stylebox("frame", "GraphNode"); @@ -457,49 +1015,9 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) { } } -void VisualShaderEditor::_update_graph() { - if (updating) { - return; - } - - if (visual_shader.is_null()) { - return; - } - - graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); - - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); - graph->clear_connections(); - //erase all nodes - for (int i = 0; i < graph->get_child_count(); i++) { - if (Object::cast_to<GraphNode>(graph->get_child(i))) { - Node *node = graph->get_child(i); - graph->remove_child(node); - memdelete(node); - i--; - } - } - - static const Color type_color[6] = { - Color(0.38, 0.85, 0.96), // scalar (float) - Color(0.49, 0.78, 0.94), // scalar (int) - Color(0.84, 0.49, 0.93), // vector - Color(0.55, 0.65, 0.94), // boolean - Color(0.96, 0.66, 0.43), // transform - Color(1.0, 1.0, 0.0), // sampler - }; - - List<VisualShader::Connection> connections; - visual_shader->get_node_connections(type, &connections); - - Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1); - - Vector<int> nodes = visual_shader->get_node_list(type); - +void VisualShaderEditor::_update_uniforms() { VisualShaderNodeUniformRef::clear_uniforms(); - // scan for all uniforms - for (int t = 0; t < VisualShader::TYPE_MAX; t++) { Vector<int> tnodes = visual_shader->get_node_list((VisualShader::Type)t); for (int i = 0; i < tnodes.size(); i++) { @@ -534,388 +1052,49 @@ void VisualShaderEditor::_update_graph() { } } } +} - Control *offset; - - for (int n_i = 0; n_i < nodes.size(); n_i++) { - Vector2 position = visual_shader->get_node_position(type, nodes[n_i]); - Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]); - - Ref<VisualShaderNodeGroupBase> group_node = Object::cast_to<VisualShaderNodeGroupBase>(vsnode.ptr()); - bool is_group = !group_node.is_null(); - Size2 size = Size2(0, 0); - - Ref<VisualShaderNodeExpression> expression_node = Object::cast_to<VisualShaderNodeExpression>(group_node.ptr()); - bool is_expression = !expression_node.is_null(); - String expression = ""; - - GraphNode *node = memnew(GraphNode); - - if (is_group) { - size = group_node->get_size(); - - node->set_resizable(true); - node->connect("resize_request", callable_mp(this, &VisualShaderEditor::_node_resized), varray((int)type, nodes[n_i])); - } - if (is_expression) { - expression = expression_node->get_expression(); - } - - node->set_offset(position); - - node->set_title(vsnode->get_caption()); - node->set_name(itos(nodes[n_i])); - - if (nodes[n_i] >= 2) { - node->set_show_close_button(true); - node->connect("close_request", callable_mp(this, &VisualShaderEditor::_delete_request), varray(nodes[n_i]), CONNECT_DEFERRED); - } - - node->connect("dragged", callable_mp(this, &VisualShaderEditor::_node_dragged), varray(nodes[n_i])); - - Control *custom_editor = nullptr; - int port_offset = 0; - - if (is_group) { - port_offset += 2; - } - - Ref<VisualShaderNodeUniform> uniform = vsnode; - Ref<VisualShaderNodeFloatUniform> float_uniform = vsnode; - Ref<VisualShaderNodeIntUniform> int_uniform = vsnode; - Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode; - Ref<VisualShaderNodeColorUniform> color_uniform = vsnode; - Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode; - Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode; - if (uniform.is_valid()) { - graph->add_child(node); - _update_created_node(node); - - LineEdit *uniform_name = memnew(LineEdit); - uniform_name->set_text(uniform->get_uniform_name()); - node->add_child(uniform_name); - uniform_name->connect("text_entered", callable_mp(this, &VisualShaderEditor::_line_edit_changed), varray(uniform_name, nodes[n_i])); - uniform_name->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_line_edit_focus_out), varray(uniform_name, nodes[n_i])); - - String error = vsnode->get_warning(visual_shader->get_mode(), type); - if (error != String()) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); - Label *error_label = memnew(Label); - error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - error_label->set_text(error); - node->add_child(error_label); - } - - if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { - //shortcut - VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); - node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); - if (!float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !color_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid()) { - continue; - } - } - port_offset++; - } - - for (int i = 0; i < plugins.size(); i++) { - custom_editor = plugins.write[i]->create_editor(visual_shader, vsnode); - if (custom_editor) { - break; - } - } - - if (custom_editor && !float_uniform.is_valid() && !int_uniform.is_valid() && !vec3_uniform.is_valid() && !bool_uniform.is_valid() && !transform_uniform.is_valid() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { - //will be embedded in first port - } else if (custom_editor) { - port_offset++; - node->add_child(custom_editor); - if (color_uniform.is_valid()) { - custom_editor->call_deferred("_show_prop_names", true); - } - if (float_uniform.is_valid() || int_uniform.is_valid() || vec3_uniform.is_valid() || bool_uniform.is_valid() || transform_uniform.is_valid()) { - custom_editor->call_deferred("_show_prop_names", true); - continue; - } - custom_editor = nullptr; - } - - if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); - node->add_child(offset); - - if (group_node->is_editable()) { - HBoxContainer *hb2 = memnew(HBoxContainer); - - Button *add_input_btn = memnew(Button); - add_input_btn->set_text(TTR("Add Input")); - add_input_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_add_input_port), varray(nodes[n_i], group_node->get_free_input_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "input" + itos(group_node->get_free_input_port_id())), CONNECT_DEFERRED); - hb2->add_child(add_input_btn); - - hb2->add_spacer(); - - Button *add_output_btn = memnew(Button); - add_output_btn->set_text(TTR("Add Output")); - add_output_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_add_output_port), varray(nodes[n_i], group_node->get_free_output_port_id(), VisualShaderNode::PORT_TYPE_VECTOR, "output" + itos(group_node->get_free_output_port_id())), CONNECT_DEFERRED); - hb2->add_child(add_output_btn); - - node->add_child(hb2); - } - } - - for (int i = 0; i < MAX(vsnode->get_input_port_count(), vsnode->get_output_port_count()); i++) { - if (vsnode->is_port_separator(i)) { - node->add_child(memnew(HSeparator)); - port_offset++; - } - - bool valid_left = i < vsnode->get_input_port_count(); - VisualShaderNode::PortType port_left = VisualShaderNode::PORT_TYPE_SCALAR; - bool port_left_used = false; - String name_left; - if (valid_left) { - name_left = vsnode->get_input_port_name(i); - port_left = vsnode->get_input_port_type(i); - for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { - if (E->get().to_node == nodes[n_i] && E->get().to_port == i) { - port_left_used = true; - } - } - } - - bool valid_right = i < vsnode->get_output_port_count(); - VisualShaderNode::PortType port_right = VisualShaderNode::PORT_TYPE_SCALAR; - String name_right; - if (valid_right) { - name_right = vsnode->get_output_port_name(i); - port_right = vsnode->get_output_port_type(i); - } - - HBoxContainer *hb = memnew(HBoxContainer); - hb->add_theme_constant_override("separation", 7 * EDSCALE); - - Variant default_value; - - if (valid_left && !port_left_used) { - default_value = vsnode->get_input_port_default_value(i); - } - - if (default_value.get_type() != Variant::NIL) { // only a label - Button *button = memnew(Button); - hb->add_child(button); - button->connect("pressed", callable_mp(this, &VisualShaderEditor::_edit_port_default_input), varray(button, nodes[n_i], i)); - - switch (default_value.get_type()) { - case Variant::COLOR: { - button->set_custom_minimum_size(Size2(30, 0) * EDSCALE); - button->connect("draw", callable_mp(this, &VisualShaderEditor::_draw_color_over_button), varray(button, default_value)); - } break; - case Variant::BOOL: { - button->set_text(((bool)default_value) ? "true" : "false"); - } break; - case Variant::INT: - case Variant::FLOAT: { - button->set_text(String::num(default_value, 4)); - } break; - case Variant::VECTOR3: { - Vector3 v = default_value; - button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3)); - } break; - default: { - } - } - } - - if (i == 0 && custom_editor) { - hb->add_child(custom_editor); - custom_editor->set_h_size_flags(SIZE_EXPAND_FILL); - } else { - if (valid_left) { - if (is_group) { - OptionButton *type_box = memnew(OptionButton); - hb->add_child(type_box); - type_box->add_item(TTR("Float")); - type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); - type_box->add_item(TTR("Boolean")); - type_box->add_item(TTR("Transform")); - type_box->add_item(TTR("Sampler")); - type_box->select(group_node->get_input_port_type(i)); - type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - type_box->connect("item_selected", callable_mp(this, &VisualShaderEditor::_change_input_port_type), varray(nodes[n_i], i), CONNECT_DEFERRED); - - LineEdit *name_box = memnew(LineEdit); - hb->add_child(name_box); - name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); - name_box->set_h_size_flags(SIZE_EXPAND_FILL); - name_box->set_text(name_left); - name_box->connect("text_entered", callable_mp(this, &VisualShaderEditor::_change_input_port_name), varray(name_box, nodes[n_i], i)); - name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, false)); - - Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_input_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(remove_btn); - } else { - Label *label = memnew(Label); - label->set_text(name_left); - label->add_theme_style_override("normal", label_style); //more compact - hb->add_child(label); - - if (vsnode->get_input_port_default_hint(i) != "" && !port_left_used) { - Label *hint_label = memnew(Label); - hint_label->set_text("[" + vsnode->get_input_port_default_hint(i) + "]"); - hint_label->add_theme_color_override("font_color", get_theme_color("font_color_readonly", "TextEdit")); - hint_label->add_theme_style_override("normal", label_style); - hb->add_child(hint_label); - } - } - } - - if (!is_group) { - hb->add_spacer(); - } - - if (valid_right) { - if (is_group) { - Button *remove_btn = memnew(Button); - remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon("Remove", "EditorIcons")); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); - remove_btn->connect("pressed", callable_mp(this, &VisualShaderEditor::_remove_output_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(remove_btn); - - LineEdit *name_box = memnew(LineEdit); - hb->add_child(name_box); - name_box->set_custom_minimum_size(Size2(65 * EDSCALE, 0)); - name_box->set_h_size_flags(SIZE_EXPAND_FILL); - name_box->set_text(name_right); - name_box->connect("text_entered", callable_mp(this, &VisualShaderEditor::_change_output_port_name), varray(name_box, nodes[n_i], i)); - name_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_port_name_focus_out), varray(name_box, nodes[n_i], i, true)); - - OptionButton *type_box = memnew(OptionButton); - hb->add_child(type_box); - type_box->add_item(TTR("Float")); - type_box->add_item(TTR("Int")); - type_box->add_item(TTR("Vector")); - type_box->add_item(TTR("Boolean")); - type_box->add_item(TTR("Transform")); - type_box->select(group_node->get_output_port_type(i)); - type_box->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - type_box->connect("item_selected", callable_mp(this, &VisualShaderEditor::_change_output_port_type), varray(nodes[n_i], i), CONNECT_DEFERRED); - } else { - Label *label = memnew(Label); - label->set_text(name_right); - label->add_theme_style_override("normal", label_style); //more compact - hb->add_child(label); - } - } - } - - if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM && port_right != VisualShaderNode::PORT_TYPE_SAMPLER) { - TextureButton *preview = memnew(TextureButton); - preview->set_toggle_mode(true); - preview->set_normal_texture(get_theme_icon("GuiVisibilityHidden", "EditorIcons")); - preview->set_pressed_texture(get_theme_icon("GuiVisibilityVisible", "EditorIcons")); - preview->set_v_size_flags(SIZE_SHRINK_CENTER); - - if (vsnode->get_output_port_for_preview() == i) { - preview->set_pressed(true); - } - - preview->connect("pressed", callable_mp(this, &VisualShaderEditor::_preview_select_port), varray(nodes[n_i], i), CONNECT_DEFERRED); - hb->add_child(preview); - } - - if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); - node->add_child(offset); - port_offset++; - } - - node->add_child(hb); - - node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]); - } - - if (vsnode->get_output_port_for_preview() >= 0) { - int port_type = vsnode->get_output_port_type(vsnode->get_output_port_for_preview()); +void VisualShaderEditor::_update_graph() { + if (updating) { + return; + } - if (port_type != VisualShaderNode::PORT_TYPE_TRANSFORM && port_type != VisualShaderNode::PORT_TYPE_SAMPLER) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); - node->add_child(offset); + if (visual_shader.is_null()) { + return; + } - VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview); - port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview()); - port_preview->set_h_size_flags(SIZE_SHRINK_CENTER); - node->add_child(port_preview); - } - } + graph->set_scroll_ofs(visual_shader->get_graph_offset() * EDSCALE); - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 4 * EDSCALE)); - node->add_child(offset); + VisualShader::Type type = get_current_shader_type(); - String error = vsnode->get_warning(visual_shader->get_mode(), type); - if (error != String()) { - Label *error_label = memnew(Label); - error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor")); - error_label->set_text(error); - node->add_child(error_label); + graph->clear_connections(); + //erase all nodes + for (int i = 0; i < graph->get_child_count(); i++) { + if (Object::cast_to<GraphNode>(graph->get_child(i))) { + Node *node = graph->get_child(i); + graph->remove_child(node); + memdelete(node); + i--; } + } - if (is_expression) { - TextEdit *expression_box = memnew(TextEdit); - Ref<CodeHighlighter> expression_syntax_highlighter; - expression_syntax_highlighter.instance(); - expression_node->set_control(expression_box, 0); - node->add_child(expression_box); - - Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); - Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); - Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); - Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); - Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); - - expression_box->set_syntax_highlighter(expression_syntax_highlighter); - expression_box->add_theme_color_override("background_color", background_color); + List<VisualShader::Connection> connections; + visual_shader->get_node_connections(type, &connections); + graph_plugin->set_connections(connections); - for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) { - expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color); - } + Vector<int> nodes = visual_shader->get_node_list(type); - expression_box->add_theme_font_override("font", get_theme_font("expression", "EditorFonts")); - expression_box->add_theme_color_override("font_color", text_color); - expression_syntax_highlighter->set_number_color(number_color); - expression_syntax_highlighter->set_symbol_color(symbol_color); - expression_syntax_highlighter->set_function_color(function_color); - expression_syntax_highlighter->set_member_variable_color(members_color); - expression_syntax_highlighter->add_color_region("/*", "*/", comment_color, false); - expression_syntax_highlighter->add_color_region("//", "", comment_color, true); + _update_uniforms(); - expression_box->set_text(expression); - expression_box->set_context_menu_enabled(false); - expression_box->set_show_line_numbers(true); + graph_plugin->clear_links(); + graph_plugin->make_dirty(true); - expression_box->connect("focus_exited", callable_mp(this, &VisualShaderEditor::_expression_focus_out), varray(expression_box, nodes[n_i])); - } - - if (!uniform.is_valid()) { - graph->add_child(node); - _update_created_node(node); - if (is_group) { - call_deferred("_set_node_size", (int)type, nodes[n_i], size); - } - } + for (int n_i = 0; n_i < nodes.size(); n_i++) { + graph_plugin->add_node(type, nodes[n_i]); } + graph_plugin->make_dirty(false); + for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) { int from = E->get().from_node; int from_idx = E->get().from_port; @@ -926,8 +1105,18 @@ void VisualShaderEditor::_update_graph() { } } +VisualShader::Type VisualShaderEditor::get_current_shader_type() const { + VisualShader::Type type; + if (particles_mode) { + type = VisualShader::Type(edit_type->get_selected() + 3); + } else { + type = VisualShader::Type(edit_type->get_selected()); + } + return type; +} + void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type, const String &p_name) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -944,7 +1133,7 @@ void VisualShaderEditor::_add_input_port(int p_node, int p_port, int p_port_type } void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_type, const String &p_name) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -961,7 +1150,7 @@ void VisualShaderEditor::_add_output_port(int p_node, int p_port, int p_port_typ } void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_port) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -978,7 +1167,7 @@ void VisualShaderEditor::_change_input_port_type(int p_type, int p_node, int p_p } void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_port) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -995,7 +1184,7 @@ void VisualShaderEditor::_change_output_port_type(int p_type, int p_node, int p_ } void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *line_edit, int p_node_id, int p_port_id) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id); ERR_FAIL_COND(!node.is_valid()); @@ -1009,7 +1198,7 @@ void VisualShaderEditor::_change_input_port_name(const String &p_text, Object *l } void VisualShaderEditor::_change_output_port_name(const String &p_text, Object *line_edit, int p_node_id, int p_port_id) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id); ERR_FAIL_COND(!node.is_valid()); @@ -1023,7 +1212,7 @@ void VisualShaderEditor::_change_output_port_name(const String &p_text, Object * } void VisualShaderEditor::_remove_input_port(int p_node, int p_port) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -1066,7 +1255,7 @@ void VisualShaderEditor::_remove_input_port(int p_node, int p_port) { } void VisualShaderEditor::_remove_output_port(int p_node, int p_port) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -1108,14 +1297,14 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) { undo_redo->commit_action(); } -void VisualShaderEditor::_expression_focus_out(Object *text_edit, int p_node) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); +void VisualShaderEditor::_expression_focus_out(Object *code_edit, int p_node) { + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeExpression> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; } - TextEdit *expression_box = Object::cast_to<TextEdit>(text_edit); + CodeEdit *expression_box = Object::cast_to<CodeEdit>(code_edit); if (node->get_expression() == expression_box->get_text()) { return; @@ -1137,7 +1326,7 @@ void VisualShaderEditor::_rebuild() { } void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p_size) { - VisualShader::Type type = VisualShader::Type(p_type); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -1184,7 +1373,7 @@ void VisualShaderEditor::_set_node_size(int p_type, int p_node, const Vector2 &p } void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, int p_node) { - VisualShader::Type type = VisualShader::Type(p_type); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; @@ -1197,25 +1386,25 @@ void VisualShaderEditor::_node_resized(const Vector2 &p_new_size, int p_type, in } void VisualShaderEditor::_preview_select_port(int p_node, int p_port) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNode> node = visual_shader->get_node(type, p_node); if (node.is_null()) { return; } - + int prev_port = node->get_output_port_for_preview(); if (node->get_output_port_for_preview() == p_port) { p_port = -1; //toggle it } - undo_redo->create_action(TTR("Set Uniform Name")); + undo_redo->create_action(p_port == -1 ? TTR("Hide Port Preview") : TTR("Show Port Preview")); undo_redo->add_do_method(node.ptr(), "set_output_port_for_preview", p_port); - undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", node->get_output_port_for_preview()); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_undo_method(node.ptr(), "set_output_port_for_preview", prev_port); + undo_redo->add_do_method(graph_plugin.ptr(), "show_port_preview", (int)type, p_node, p_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "show_port_preview", (int)type, p_node, prev_port); undo_redo->commit_action(); } void VisualShaderEditor::_line_edit_changed(const String &p_text, Object *line_edit, int p_node_id) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeUniform> node = visual_shader->get_node(type, p_node_id); ERR_FAIL_COND(!node.is_valid()); @@ -1240,7 +1429,7 @@ void VisualShaderEditor::_line_edit_focus_out(Object *line_edit, int p_node_id) } void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, int p_port_id, bool p_output) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNodeGroupBase> node = visual_shader->get_node(type, p_node_id); ERR_FAIL_COND(!node.is_valid()); @@ -1291,7 +1480,7 @@ void VisualShaderEditor::_port_name_focus_out(Object *line_edit, int p_node_id, } void VisualShaderEditor::_port_edited() { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Variant value = property_editor->get_variant(); Ref<VisualShaderNode> vsn = visual_shader->get_node(type, editing_node); @@ -1300,15 +1489,15 @@ void VisualShaderEditor::_port_edited() { undo_redo->create_action(TTR("Set Input Default Port")); undo_redo->add_do_method(vsn.ptr(), "set_input_port_default_value", editing_port, value); undo_redo->add_undo_method(vsn.ptr(), "set_input_port_default_value", editing_port, vsn->get_input_port_default_value(editing_port)); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, value); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_input_port_default_value", type, editing_node, editing_port, vsn->get_input_port_default_value(editing_port)); undo_redo->commit_action(); property_editor->hide(); } void VisualShaderEditor::_edit_port_default_input(Object *p_button, int p_node, int p_port) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNode> vsn = visual_shader->get_node(type, p_node); @@ -1474,13 +1663,15 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { } saved_node_pos_dirty = false; - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); int id_to_use = visual_shader->get_valid_node_id(type); undo_redo->create_action(TTR("Add Node to Visual Shader")); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, vsnode, position, id_to_use); undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_to_use); + undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_to_use); + undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_to_use); VisualShaderNodeExpression *expr = Object::cast_to<VisualShaderNodeExpression>(vsnode.ptr()); if (expr) { @@ -1495,6 +1686,8 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { if (visual_shader->is_port_types_compatible(vsnode->get_output_port_type(_from_slot), visual_shader->get_node(type, to_node)->get_input_port_type(to_slot))) { undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, _from_node, _from_slot, to_node, to_slot); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, _from_node, _from_slot, to_node, to_slot); } } } else if (from_node != -1 && from_slot != -1) { @@ -1503,33 +1696,31 @@ VisualShaderNode *VisualShaderEditor::_add_node(int p_idx, int p_op_idx) { int _to_slot = 0; if (visual_shader->is_port_types_compatible(visual_shader->get_node(type, from_node)->get_output_port_type(from_slot), vsnode->get_input_port_type(_to_slot))) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_slot, _to_node, _to_slot); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_slot, _to_node, _to_slot); } } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); undo_redo->commit_action(); return vsnode.ptr(); } void VisualShaderEditor::_node_dragged(const Vector2 &p_from, const Vector2 &p_to, int p_node) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); - updating = true; undo_redo->create_action(TTR("Node Moved")); undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", type, p_node, p_to); undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", type, p_node, p_from); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", type, p_node, p_to); + undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", type, p_node, p_from); undo_redo->commit_action(); - updating = false; } void VisualShaderEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); int from = p_from.to_int(); int to = p_to.to_int(); @@ -1547,20 +1738,22 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in if (E->get().to_node == to && E->get().to_port == p_to_index) { undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->commit_action(); } void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) { graph->disconnect_node(p_from, p_from_index, p_to, p_to_index); - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); int from = p_from.to_int(); int to = p_to.to_int(); @@ -1569,8 +1762,8 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from undo_redo->create_action(TTR("Nodes Disconnected")); undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from, p_from_index, to, p_to_index); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from, p_from_index, to, p_to_index); undo_redo->commit_action(); //updating = false; } @@ -1588,12 +1781,22 @@ void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slo } void VisualShaderEditor::_delete_request(int which) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); Ref<VisualShaderNode> node = Ref<VisualShaderNode>(visual_shader->get_node(type, which)); undo_redo->create_action(TTR("Delete Node")); + + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == which || E->get().to_node == which) { + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, which); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, which), which); + undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, which); undo_redo->add_do_method(this, "_clear_buffer"); undo_redo->add_undo_method(this, "_clear_buffer"); @@ -1612,22 +1815,19 @@ void VisualShaderEditor::_delete_request(int which) { undo_redo->add_undo_method(expression, "set_expression", expression->get_expression()); } - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { if (E->get().from_node == which || E->get().to_node == which) { undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); } } - - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + // delete a node from the graph + undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, which); undo_redo->commit_action(); } void VisualShaderEditor::_node_selected(Object *p_node) { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); GraphNode *gn = Object::cast_to<GraphNode>(p_node); ERR_FAIL_COND(!gn); @@ -1881,12 +2081,13 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in Ref<VisualShaderNode> dupli = node->duplicate(); undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(pasted_type, E->get()) + p_offset, id_from); - undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from); + undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_from); // duplicate size, inputs and outputs if node is group Ref<VisualShaderNodeGroupBase> group = Object::cast_to<VisualShaderNodeGroupBase>(node.ptr()); if (!group.is_null()) { undo_redo->add_do_method(dupli.ptr(), "set_size", group->get_size()); + undo_redo->add_do_method(graph_plugin.ptr(), "set_node_size", type, id_from, group->get_size()); undo_redo->add_do_method(dupli.ptr(), "set_inputs", group->get_inputs()); undo_redo->add_do_method(dupli.ptr(), "set_outputs", group->get_outputs()); } @@ -1907,12 +2108,19 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in continue; } if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) { - undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes_forced", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port); } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + id_from = base_id; + for (List<int>::Element *E = r_nodes.front(); E; E = E->next()) { + undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from); + undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_from); + id_from++; + } + undo_redo->commit_action(); if (p_select) { @@ -1985,7 +2193,7 @@ void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2 } void VisualShaderEditor::_delete_nodes() { - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); List<int> to_erase; for (int i = 0; i < graph->get_child_count(); i++) { @@ -2003,11 +2211,23 @@ void VisualShaderEditor::_delete_nodes() { undo_redo->create_action(TTR("Delete Nodes")); + List<VisualShader::Connection> conns; + visual_shader->get_node_connections(type, &conns); + + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { + for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { + if (E->get().from_node == F->get() || E->get().to_node == F->get()) { + undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + } + } + } + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get()); undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get()); undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get()); + undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F->get()); undo_redo->add_do_method(this, "_clear_buffer"); undo_redo->add_undo_method(this, "_clear_buffer"); @@ -2027,9 +2247,6 @@ void VisualShaderEditor::_delete_nodes() { } } - List<VisualShader::Connection> conns; - visual_shader->get_node_connections(type, &conns); - List<VisualShader::Connection> used_conns; for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) { @@ -2043,18 +2260,23 @@ void VisualShaderEditor::_delete_nodes() { } if (!cancel) { undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); + undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port); used_conns.push_back(E->get()); } } } } - undo_redo->add_do_method(this, "_update_graph"); - undo_redo->add_undo_method(this, "_update_graph"); + // delete nodes from the graph + for (List<int>::Element *F = to_erase.front(); F; F = F->next()) { + undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F->get()); + } + undo_redo->commit_action(); } void VisualShaderEditor::_mode_selected(int p_id) { + visual_shader->set_shader_type(particles_mode ? VisualShader::Type(p_id + 3) : VisualShader::Type(p_id)); _update_options_menu(); _update_graph(); } @@ -2076,7 +2298,7 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> input, St if (type_changed) { //restore connections if type changed - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); int id = visual_shader->find_node_id(type, input); List<VisualShader::Connection> conns; visual_shader->get_node_connections(type, &conns); @@ -2110,7 +2332,7 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_ if (type_changed) { //restore connections if type changed - VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); + VisualShader::Type type = get_current_shader_type(); int id = visual_shader->find_node_id(type, p_uniform_ref); List<VisualShader::Connection> conns; visual_shader->get_node_connections(type, &conns); @@ -2356,6 +2578,8 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_uniform_select_item", &VisualShaderEditor::_uniform_select_item); ClassDB::bind_method("_set_node_size", &VisualShaderEditor::_set_node_size); ClassDB::bind_method("_clear_buffer", &VisualShaderEditor::_clear_buffer); + ClassDB::bind_method("_update_uniforms", &VisualShaderEditor::_update_uniforms); + ClassDB::bind_method("_set_mode", &VisualShaderEditor::_set_mode); ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw); @@ -2435,15 +2659,26 @@ VisualShaderEditor::VisualShaderEditor() { graph->get_zoom_hbox()->add_child(vs); graph->get_zoom_hbox()->move_child(vs, 0); - edit_type = memnew(OptionButton); - edit_type->add_item(TTR("Vertex")); - edit_type->add_item(TTR("Fragment")); - edit_type->add_item(TTR("Light")); - edit_type->add_item(TTR("Compute")); - edit_type->select(1); - edit_type->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected)); - graph->get_zoom_hbox()->add_child(edit_type); - graph->get_zoom_hbox()->move_child(edit_type, 0); + edit_type_standart = memnew(OptionButton); + edit_type_standart->add_item(TTR("Vertex")); + edit_type_standart->add_item(TTR("Fragment")); + edit_type_standart->add_item(TTR("Light")); + edit_type_standart->select(1); + edit_type_standart->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected)); + + edit_type_particles = memnew(OptionButton); + edit_type_particles->add_item(TTR("Emit")); + edit_type_particles->add_item(TTR("Process")); + edit_type_particles->add_item(TTR("End")); + edit_type_particles->select(0); + edit_type_particles->connect("item_selected", callable_mp(this, &VisualShaderEditor::_mode_selected)); + + edit_type = edit_type_standart; + + graph->get_zoom_hbox()->add_child(edit_type_particles); + graph->get_zoom_hbox()->move_child(edit_type_particles, 0); + graph->get_zoom_hbox()->add_child(edit_type_standart); + graph->get_zoom_hbox()->move_child(edit_type_standart, 0); add_node = memnew(Button); add_node->set_flat(true); @@ -2466,14 +2701,14 @@ VisualShaderEditor::VisualShaderEditor() { preview_vbox = memnew(VBoxContainer); preview_vbox->set_visible(preview_showed); main_box->add_child(preview_vbox); - preview_text = memnew(TextEdit); + preview_text = memnew(CodeEdit); syntax_highlighter.instance(); preview_vbox->add_child(preview_text); preview_text->set_h_size_flags(SIZE_EXPAND_FILL); preview_text->set_v_size_flags(SIZE_EXPAND_FILL); preview_text->set_custom_minimum_size(Size2(400 * EDSCALE, 0)); preview_text->set_syntax_highlighter(syntax_highlighter); - preview_text->set_show_line_numbers(true); + preview_text->set_draw_line_numbers(true); preview_text->set_readonly(true); error_text = memnew(Label); @@ -2622,6 +2857,7 @@ VisualShaderEditor::VisualShaderEditor() { // INPUT // SPATIAL-FOR-ALL + const String input_param_shader_modes = TTR("'%s' input parameter for all shader modes."); add_options.push_back(AddOption("Camera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "camera"), "camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("InvCamera", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "inv_camera"), "inv_camera", VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_SPATIAL)); @@ -2652,125 +2888,156 @@ VisualShaderEditor::VisualShaderEditor() { const String input_param_for_fragment_shader_mode = TTR("'%s' input parameter for fragment shader mode."); const String input_param_for_light_shader_mode = TTR("'%s' input parameter for light shader mode."); const String input_param_for_vertex_shader_mode = TTR("'%s' input parameter for vertex shader mode."); - const String input_param_for_compute_shader_mode = TTR("'%s' input parameter for compute shader mode."); + const String input_param_for_emit_shader_mode = TTR("'%s' input parameter for emit shader mode."); + const String input_param_for_process_shader_mode = TTR("'%s' input parameter for process shader mode."); + const String input_param_for_end_shader_mode = TTR("'%s' input parameter for end shader mode."); + const String input_param_for_emit_and_process_shader_mode = TTR("'%s' input parameter for emit and process shader mode."); const String input_param_for_vertex_and_fragment_shader_mode = TTR("'%s' input parameter for vertex and fragment shader mode."); - add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture"), "depth_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing"), "front_facing", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "side"), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("UV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("UV2", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv2"), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); - - add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo"), "albedo", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation"), "attenuation", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "diffuse"), "diffuse", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light"), "light", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness"), "roughness", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular"), "specular", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Transmission", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "transmission"), "transmission", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), "view", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_SPATIAL)); - - add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("ModelView", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview"), "modelview", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("UV", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("UV2", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv2"), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); - add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture"), "depth_texture", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing"), "front_facing", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "side"), "side", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("UV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("UV2", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv2"), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("View", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), "view", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + + add_options.push_back(AddOption("Albedo", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "albedo"), "albedo", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation"), "attenuation", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "diffuse"), "diffuse", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light"), "light", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Roughness", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "roughness"), "roughness", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Specular", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "specular"), "specular", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Transmission", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "transmission"), "transmission", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("View", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "view"), "view", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL)); + + add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ModelView", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview"), "modelview", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("UV", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv"), "uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("UV2", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "uv2"), "uv2", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); // CANVASITEM INPUTS - add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture"), "normal_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size"), "screen_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); - - add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_alpha"), "light_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightHeight", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_height"), "light_height", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_uv"), "light_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightVector", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_vec"), "light_vec", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal"), "normal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ShadowAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_alpha"), "shadow_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ShadowColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_color"), "shadow_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("ShadowVec", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_vec"), "shadow_vec", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Texture", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); - - add_options.push_back(AddOption("Extra", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "extra"), "extra", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("LightPass", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Projection", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "projection"), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); - add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture"), "normal_texture", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size"), "screen_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + + add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_alpha"), "light_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color"), "light_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightHeight", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_height"), "light_height", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_uv"), "light_uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightVector", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_vec"), "light_vec", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal"), "normal", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ShadowAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_alpha"), "shadow_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ShadowColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_color"), "shadow_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ShadowVec", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_vec"), "shadow_vec", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Texture", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM)); + + add_options.push_back(AddOption("Extra", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "extra"), "extra", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("LightPass", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size"), "point_size", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Projection", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "projection"), "projection", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Vertex", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex"), "vertex", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("World", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "world"), "world", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM)); // PARTICLES INPUTS - add_options.push_back(AddOption("Active", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Alpha", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Color", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Custom", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("CustomAlpha", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Delta", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("EmissionTransform", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Index", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("LifeTime", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Restart", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Time", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Transform", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Velocity", "Input", "Compute", "VisualShaderNodeInput", vformat(input_param_for_compute_shader_mode, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_COMPUTE, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Active", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Alpha", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Color", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Custom", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("CustomAlpha", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Delta", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("EmissionTransform", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Index", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("LifeTime", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Restart", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Time", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Transform", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Velocity", "Input", "Emit", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_EMIT, Shader::MODE_PARTICLES)); + + add_options.push_back(AddOption("Active", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Alpha", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Color", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Custom", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("CustomAlpha", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Delta", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("EmissionTransform", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Index", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("LifeTime", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Restart", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Time", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Transform", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Velocity", "Input", "Process", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_PROCESS, Shader::MODE_PARTICLES)); + + add_options.push_back(AddOption("Active", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active"), "active", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Alpha", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Color", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Custom", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom"), "custom", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("CustomAlpha", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Delta", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("EmissionTransform", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Index", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("LifeTime", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Restart", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Time", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Transform", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "transform"), "transform", VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Velocity", "Input", "End", "VisualShaderNodeInput", vformat(input_param_shader_modes, "velocity"), "velocity", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_END, Shader::MODE_PARTICLES)); // SKY INPUTS - add_options.push_back(AddOption("AtCubeMapPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "at_cubemap_pass"), "at_cubemap_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("AtHalfResPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "at_half_res_pass"), "at_half_res_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("AtQuarterResPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "at_quarter_res_pass"), "at_quarter_res_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("EyeDir", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "eyedir"), "eyedir", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("HalfResColor", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "half_res_color"), "half_res_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("HalfResAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "half_res_alpha"), "half_res_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light0Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_color"), "light0_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light0Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_direction"), "light0_direction", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light0Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_enabled"), "light0_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light0Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_energy"), "light0_energy", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light1Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_color"), "light1_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light1Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_direction"), "light1_direction", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light1Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_enabled"), "light1_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light1Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_energy"), "light1_energy", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light2Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_color"), "light2_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light2Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_direction"), "light2_direction", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light2Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_enabled"), "light2_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light2Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_energy"), "light2_energy", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light3Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_color"), "light3_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light3Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_direction"), "light3_direction", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light3Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_enabled"), "light3_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Light3Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_energy"), "light3_energy", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Position", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "position"), "position", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("QuarterResColor", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "quarter_res_color"), "quarter_res_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("QuarterResAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "quarter_res_alpha"), "quarter_res_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Radiance", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "radiance"), "radiance", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("SkyCoords", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "sky_coords"), "sky_coords", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); - add_options.push_back(AddOption("Time", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("AtCubeMapPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "at_cubemap_pass"), "at_cubemap_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("AtHalfResPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "at_half_res_pass"), "at_half_res_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("AtQuarterResPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "at_quarter_res_pass"), "at_quarter_res_pass", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("EyeDir", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "eyedir"), "eyedir", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("HalfResColor", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "half_res_color"), "half_res_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("HalfResAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "half_res_alpha"), "half_res_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light0Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_color"), "light0_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light0Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_direction"), "light0_direction", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light0Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_enabled"), "light0_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light0Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light0_energy"), "light0_energy", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light1Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_color"), "light1_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light1Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_direction"), "light1_direction", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light1Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_enabled"), "light1_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light1Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light1_energy"), "light1_energy", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light2Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_color"), "light2_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light2Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_direction"), "light2_direction", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light2Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_enabled"), "light2_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light2Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light2_energy"), "light2_energy", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light3Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_color"), "light3_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light3Direction", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_direction"), "light3_direction", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light3Enabled", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_enabled"), "light3_enabled", VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Light3Energy", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "light3_energy"), "light3_energy", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Position", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "position"), "position", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("QuarterResColor", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "quarter_res_color"), "quarter_res_color", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("QuarterResAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "quarter_res_alpha"), "quarter_res_alpha", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Radiance", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "radiance"), "radiance", VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("SkyCoords", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "sky_coords"), "sky_coords", VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); + add_options.push_back(AddOption("Time", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SKY)); // SCALAR @@ -2858,12 +3125,15 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1)); 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("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture 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("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D 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("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("TextureUniformTriplanar", "Textures", "Variables", "VisualShaderNodeTextureUniformTriplanar", TTR("2D texture uniform lookup with triplanar."), -1, -1, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_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)); + add_options.push_back(AddOption("Texture3DUniform", "Textures", "Variables", "VisualShaderNodeTexture3DUniform", TTR("3D texture uniform lookup."), -1, -1, -1, -1, -1)); // TRANSFORM @@ -2960,15 +3230,15 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants."))); add_options.push_back(AddOption("UniformRef", "Special", "", "VisualShaderNodeUniformRef", TTR("A reference to an existing uniform."))); - add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("VectorDerivativeFunc", "Special", "Common", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) Vector derivative function."), -1, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("VectorDerivativeFunc", "Special", "Common", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) Vector derivative function."), -1, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("DdX", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("DdXS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'x' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("DdY", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("DdYS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'y' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("Sum", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeVectorDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); - add_options.push_back(AddOption("SumS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeScalarDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("DdX", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("DdXS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'x' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_X, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("DdY", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), VisualShaderNodeVectorDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("DdYS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Derivative in 'y' using local differencing."), VisualShaderNodeScalarDerivativeFunc::FUNC_Y, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("Sum", "Special", "Derivative", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeVectorDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_VECTOR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); + add_options.push_back(AddOption("SumS", "Special", "Derivative", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and 'y'."), VisualShaderNodeScalarDerivativeFunc::FUNC_SUM, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, -1, true)); custom_node_option_idx = add_options.size(); ///////////////////////////////////////////////////////////////////// @@ -2988,12 +3258,16 @@ VisualShaderEditor::VisualShaderEditor() { default_plugin.instance(); add_plugin(default_plugin); + graph_plugin.instance(); + property_editor = memnew(CustomPropertyEditor); add_child(property_editor); property_editor->connect("variant_changed", callable_mp(this, &VisualShaderEditor::_port_edited)); } +///////////////// + void VisualShaderEditorPlugin::edit(Object *p_object) { visual_shader_editor->edit(Object::cast_to<VisualShader>(p_object)); } @@ -3128,6 +3402,8 @@ public: class VisualShaderNodePluginDefaultEditor : public VBoxContainer { GDCLASS(VisualShaderNodePluginDefaultEditor, VBoxContainer); Ref<Resource> parent_resource; + int node_id; + VisualShader::Type shader_type; public: void _property_changed(const String &p_property, const Variant &p_value, const String &p_field = "", bool p_changing = false) { @@ -3156,8 +3432,10 @@ public: } else { undo_redo->add_undo_method(this, "_open_inspector", (RES)parent_resource.ptr()); } - undo_redo->add_do_method(this, "_refresh_request"); - undo_redo->add_undo_method(this, "_refresh_request"); + } + if (p_property != "constant") { + undo_redo->add_do_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_property_editor_deferred", shader_type, node_id); + undo_redo->add_undo_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_property_editor_deferred", shader_type, node_id); } undo_redo->commit_action(); @@ -3173,10 +3451,6 @@ public: } } - void _refresh_request() { - VisualShaderEditor::get_singleton()->call_deferred("_update_graph"); - } - void _resource_selected(const String &p_path, RES p_resource) { _open_inspector(p_resource); } @@ -3202,6 +3476,9 @@ public: node = p_node; properties = p_properties; + node_id = (int)p_node->get_meta("id"); + shader_type = VisualShader::Type((int)p_node->get_meta("shader_type")); + for (int i = 0; i < p_properties.size(); i++) { HBoxContainer *hbox = memnew(HBoxContainer); hbox->set_h_size_flags(SIZE_EXPAND_FILL); @@ -3229,11 +3506,9 @@ public: properties[i]->set_name_split_ratio(0); } node->connect("changed", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_node_changed)); - node->connect("editor_refresh_request", callable_mp(this, &VisualShaderNodePluginDefaultEditor::_refresh_request), varray(), CONNECT_DEFERRED); } static void _bind_methods() { - ClassDB::bind_method("_refresh_request", &VisualShaderNodePluginDefaultEditor::_refresh_request); // Used by UndoRedo. ClassDB::bind_method("_open_inspector", &VisualShaderNodePluginDefaultEditor::_open_inspector); // Used by UndoRedo. ClassDB::bind_method("_show_prop_names", &VisualShaderNodePluginDefaultEditor::_show_prop_names); // Used with call_deferred. } @@ -3322,6 +3597,10 @@ void EditorPropertyShaderMode::_option_selected(int p_which) { //do is easy undo_redo->add_do_method(visual_shader.ptr(), "set_mode", p_which); undo_redo->add_undo_method(visual_shader.ptr(), "set_mode", visual_shader->get_mode()); + + undo_redo->add_do_method(VisualShaderEditor::get_singleton(), "_set_mode", p_which); + undo_redo->add_undo_method(VisualShaderEditor::get_singleton(), "_set_mode", visual_shader->get_mode()); + //now undo is hell //1. restore connections to output diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 9b80488b22..056d4c6a11 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -50,8 +50,68 @@ public: virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node); }; +class VisualShaderGraphPlugin : public Reference { + GDCLASS(VisualShaderGraphPlugin, Reference); + +private: + struct InputPort { + Button *default_input_button; + }; + + struct Port { + TextureButton *preview_button; + }; + + struct Link { + VisualShader::Type type; + VisualShaderNode *visual_node; + GraphNode *graph_node; + bool preview_visible; + int preview_pos; + Map<int, InputPort> input_ports; + Map<int, Port> output_ports; + VBoxContainer *preview_box; + }; + + Ref<VisualShader> visual_shader; + Map<int, Link> links; + List<VisualShader::Connection> connections; + bool dirty = false; + +protected: + static void _bind_methods(); + +public: + void register_shader(VisualShader *p_visual_shader); + void set_connections(List<VisualShader::Connection> &p_connections); + void register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node); + void register_output_port(int p_id, int p_port, TextureButton *p_button); + void clear_links(); + void set_shader_type(VisualShader::Type p_type); + bool is_preview_visible(int p_id) const; + bool is_dirty() const; + void make_dirty(bool p_enabled); + void add_node(VisualShader::Type p_type, int p_id); + void remove_node(VisualShader::Type p_type, int p_id); + void connect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port); + void show_port_preview(VisualShader::Type p_type, int p_node_id, int p_port_id); + void set_node_position(VisualShader::Type p_type, int p_id, const Vector2 &p_position); + void set_node_size(VisualShader::Type p_type, int p_id, const Vector2 &p_size); + void refresh_node_ports(VisualShader::Type p_type, int p_node); + void update_property_editor(VisualShader::Type p_type, int p_node_id); + void update_property_editor_deferred(VisualShader::Type p_type, int p_node_id); + void set_input_port_default_value(VisualShader::Type p_type, int p_node_id, int p_port_id, Variant p_value); + void register_default_input_button(int p_node_id, int p_port_id, Button *p_button); + VisualShader::Type get_shader_type() const; + + VisualShaderGraphPlugin(); + ~VisualShaderGraphPlugin(); +}; + class VisualShaderEditor : public VBoxContainer { GDCLASS(VisualShaderEditor, VBoxContainer); + friend class VisualShaderGraphPlugin; CustomPropertyEditor *property_editor; int editing_node; @@ -63,7 +123,9 @@ class VisualShaderEditor : public VBoxContainer { Button *add_node; Button *preview_shader; - OptionButton *edit_type; + OptionButton *edit_type = nullptr; + OptionButton *edit_type_standart; + OptionButton *edit_type_particles; PanelContainer *error_panel; Label *error_label; @@ -71,7 +133,7 @@ class VisualShaderEditor : public VBoxContainer { bool pending_update_preview; bool shader_error; VBoxContainer *preview_vbox; - TextEdit *preview_text; + CodeEdit *preview_text; Ref<CodeHighlighter> syntax_highlighter; Label *error_text; @@ -84,6 +146,19 @@ class VisualShaderEditor : public VBoxContainer { MenuButton *tools; bool preview_showed; + bool particles_mode; + + enum TypeFlags { + TYPE_FLAGS_VERTEX = 1, + TYPE_FLAGS_FRAGMENT = 2, + TYPE_FLAGS_LIGHT = 4, + }; + + enum ParticlesTypeFlags { + TYPE_FLAGS_EMIT = 1, + TYPE_FLAGS_PROCESS = 2, + TYPE_FLAGS_END = 4 + }; enum ToolsMenuOptions { EXPAND_ALL, @@ -172,6 +247,7 @@ class VisualShaderEditor : public VBoxContainer { void _add_texture_node(const String &p_path); VisualShaderNode *_add_node(int p_idx, int p_op_idx = -1); void _update_options_menu(); + void _set_mode(int p_which); void _show_preview_text(); void _update_preview(); @@ -227,6 +303,7 @@ class VisualShaderEditor : public VBoxContainer { void _paste_nodes(bool p_use_custom_position = false, const Vector2 &p_custom_position = Vector2()); Vector<Ref<VisualShaderNodePlugin>> plugins; + Ref<VisualShaderGraphPlugin> graph_plugin; void _mode_selected(int p_id); void _rebuild(); @@ -234,6 +311,8 @@ class VisualShaderEditor : public VBoxContainer { void _input_select_item(Ref<VisualShaderNodeInput> input, String name); void _uniform_select_item(Ref<VisualShaderNodeUniformRef> p_uniform, String p_name); + VisualShader::Type get_current_shader_type() const; + void _add_input_port(int p_node, int p_port, int p_port_type, const String &p_name); void _remove_input_port(int p_node, int p_port); void _change_input_port_type(int p_type, int p_node, int p_port); @@ -244,7 +323,7 @@ class VisualShaderEditor : public VBoxContainer { void _change_output_port_type(int p_type, int p_node, int p_port); void _change_output_port_name(const String &p_text, Object *line_edit, int p_node, int p_port); - void _expression_focus_out(Object *text_edit, int p_node); + void _expression_focus_out(Object *code_edit, int p_node); void _set_node_size(int p_type, int p_node, const Size2 &p_size); void _node_resized(const Vector2 &p_new_size, int p_type, int p_node); @@ -268,6 +347,7 @@ class VisualShaderEditor : public VBoxContainer { bool _is_available(int p_mode); void _update_created_node(GraphNode *node); + void _update_uniforms(); protected: void _notification(int p_what); @@ -279,6 +359,7 @@ public: void remove_plugin(const Ref<VisualShaderNodePlugin> &p_plugin); static VisualShaderEditor *get_singleton() { return singleton; } + VisualShaderGraphPlugin *get_graph_plugin() { return graph_plugin.ptr(); } void clear_custom_types(); void add_custom_type(const String &p_name, const Ref<Script> &p_script, const String &p_description, int p_return_icon_type, const String &p_category, bool p_highend); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index f45161d87b..1f553ba0de 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -310,6 +310,24 @@ void ProjectExportDialog::_edit_preset(int p_index) { _update_export_all(); child_controls_changed(); + String enc_in_filters_str = current->get_enc_in_filter(); + String enc_ex_filters_str = current->get_enc_ex_filter(); + if (!updating_enc_filters) { + enc_in_filters->set_text(enc_in_filters_str); + enc_ex_filters->set_text(enc_ex_filters_str); + } + + bool enc_pck_mode = current->get_enc_pck(); + enc_pck->set_pressed(enc_pck_mode); + + enc_directory->set_disabled(!enc_pck_mode); + enc_in_filters->set_editable(enc_pck_mode); + enc_ex_filters->set_editable(enc_pck_mode); + script_key->set_editable(enc_pck_mode); + + bool enc_directory_mode = current->get_enc_directory(); + enc_directory->set_pressed(enc_directory_mode); + int script_export_mode = current->get_script_export_mode(); script_mode->select(script_export_mode); @@ -317,7 +335,7 @@ void ProjectExportDialog::_edit_preset(int p_index) { if (!updating_script_key) { script_key->set_text(key); } - if (script_export_mode == EditorExportPreset::MODE_SCRIPT_ENCRYPTED) { + if (enc_pck_mode) { script_key->set_editable(true); bool key_valid = _validate_script_encryption_key(key); @@ -519,6 +537,56 @@ void ProjectExportDialog::_export_path_changed(const StringName &p_property, con _update_presets(); } +void ProjectExportDialog::_enc_filters_changed(const String &p_filters) { + if (updating) { + return; + } + + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + current->set_enc_in_filter(enc_in_filters->get_text()); + current->set_enc_ex_filter(enc_ex_filters->get_text()); + + updating_enc_filters = true; + _update_current_preset(); + updating_enc_filters = false; +} + +void ProjectExportDialog::_open_key_help_link() { + OS::get_singleton()->shell_open("https://docs.godotengine.org/en/latest/development/compiling/compiling_with_script_encryption_key.html"); +} + +void ProjectExportDialog::_enc_pck_changed(bool p_pressed) { + if (updating) { + return; + } + + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + current->set_enc_pck(p_pressed); + enc_directory->set_disabled(!p_pressed); + enc_in_filters->set_editable(p_pressed); + enc_ex_filters->set_editable(p_pressed); + script_key->set_editable(p_pressed); + + _update_current_preset(); +} + +void ProjectExportDialog::_enc_directory_changed(bool p_pressed) { + if (updating) { + return; + } + + Ref<EditorExportPreset> current = get_current_preset(); + ERR_FAIL_COND(current.is_null()); + + current->set_enc_directory(p_pressed); + + _update_current_preset(); +} + void ProjectExportDialog::_script_export_mode_changed(int p_mode) { if (updating) { return; @@ -1148,6 +1216,12 @@ ProjectExportDialog::ProjectExportDialog() { exclude_filters); exclude_filters->connect("text_changed", callable_mp(this, &ProjectExportDialog::_filter_changed)); + script_mode = memnew(OptionButton); + resources_vb->add_margin_child(TTR("Script Export Mode:"), script_mode); + script_mode->add_item(TTR("Text"), (int)EditorExportPreset::MODE_SCRIPT_TEXT); + script_mode->add_item(TTR("Compiled"), (int)EditorExportPreset::MODE_SCRIPT_COMPILED); + script_mode->connect("item_selected", callable_mp(this, &ProjectExportDialog::_script_export_mode_changed)); + // Patch packages. VBoxContainer *patch_vb = memnew(VBoxContainer); @@ -1205,23 +1279,50 @@ ProjectExportDialog::ProjectExportDialog() { // Script export parameters. updating_script_key = false; + updating_enc_filters = false; + + VBoxContainer *sec_vb = memnew(VBoxContainer); + sec_vb->set_name(TTR("Encryption")); + + enc_pck = memnew(CheckButton); + enc_pck->connect("toggled", callable_mp(this, &ProjectExportDialog::_enc_pck_changed)); + enc_pck->set_text(TTR("Encrypt exported PCK")); + sec_vb->add_child(enc_pck); + + enc_directory = memnew(CheckButton); + enc_directory->connect("toggled", callable_mp(this, &ProjectExportDialog::_enc_directory_changed)); + enc_directory->set_text("Encrypt index (file names and info)."); + sec_vb->add_child(enc_directory); + + enc_in_filters = memnew(LineEdit); + enc_in_filters->connect("text_changed", callable_mp(this, &ProjectExportDialog::_enc_filters_changed)); + sec_vb->add_margin_child( + TTR("Filters to include files/folders\n(comma-separated, e.g: *.tscn, *.tres, scenes/*)"), + enc_in_filters); + + enc_ex_filters = memnew(LineEdit); + enc_ex_filters->connect("text_changed", callable_mp(this, &ProjectExportDialog::_enc_filters_changed)); + sec_vb->add_margin_child( + TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.stex, *.import, music/*)"), + enc_ex_filters); - VBoxContainer *script_vb = memnew(VBoxContainer); - script_vb->set_name(TTR("Script")); - script_mode = memnew(OptionButton); - script_vb->add_margin_child(TTR("Script Export Mode:"), script_mode); - script_mode->add_item(TTR("Text"), (int)EditorExportPreset::MODE_SCRIPT_TEXT); - script_mode->add_item(TTR("Compiled"), (int)EditorExportPreset::MODE_SCRIPT_COMPILED); - script_mode->add_item(TTR("Encrypted (Provide Key Below)"), (int)EditorExportPreset::MODE_SCRIPT_ENCRYPTED); - script_mode->connect("item_selected", callable_mp(this, &ProjectExportDialog::_script_export_mode_changed)); script_key = memnew(LineEdit); script_key->connect("text_changed", callable_mp(this, &ProjectExportDialog::_script_encryption_key_changed)); script_key_error = memnew(Label); script_key_error->set_text("- " + TTR("Invalid Encryption Key (must be 64 characters long)")); script_key_error->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("error_color", "Editor")); - script_vb->add_margin_child(TTR("Script Encryption Key (256-bits as hex):"), script_key); - script_vb->add_child(script_key_error); - sections->add_child(script_vb); + sec_vb->add_margin_child(TTR("Encryption Key (256-bits as hex):"), script_key); + sec_vb->add_child(script_key_error); + sections->add_child(sec_vb); + + Label *sec_info = memnew(Label); + sec_info->set_text(TTR("Note: Encryption key needs to be stored in the binary,\nyou need to build the export templates from source.")); + sec_vb->add_child(sec_info); + + LinkButton *sec_more_info = memnew(LinkButton); + sec_more_info->set_text(TTR("More Info...")); + sec_more_info->connect("pressed", callable_mp(this, &ProjectExportDialog::_open_key_help_link)); + sec_vb->add_child(sec_more_info); sections->connect("tab_changed", callable_mp(this, &ProjectExportDialog::_tab_changed)); diff --git a/editor/project_export.h b/editor/project_export.h index cfa00773d8..75402dc334 100644 --- a/editor/project_export.h +++ b/editor/project_export.h @@ -145,6 +145,11 @@ private: CheckBox *export_debug; CheckBox *export_pck_zip_debug; + CheckButton *enc_pck; + CheckButton *enc_directory; + LineEdit *enc_in_filters; + LineEdit *enc_ex_filters; + void _open_export_template_manager(); void _export_pck_zip(); @@ -161,10 +166,16 @@ private: void _custom_features_changed(const String &p_text); bool updating_script_key; + bool updating_enc_filters; + void _enc_pck_changed(bool p_pressed); + void _enc_directory_changed(bool p_pressed); + void _enc_filters_changed(const String &p_text); void _script_export_mode_changed(int p_mode); void _script_encryption_key_changed(const String &p_key); bool _validate_script_encryption_key(const String &p_key); + void _open_key_help_link(); + void _tab_changed(int); protected: diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index ea55029de0..1fb889d793 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -2388,6 +2388,7 @@ ProjectManager::ProjectManager() { String cp; cp += 0xA9; + // TRANSLATORS: This refers to the application where users manage their Godot projects. DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors"); FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files")); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index 35610ef71b..5da682a148 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -202,7 +202,7 @@ void EditorSettingsDialog::_update_shortcuts() { Map<String, TreeItem *> sections; for (List<String>::Element *E = slist.front(); E; E = E->next()) { - Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(E->get()); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(E->get()); if (!sc->has_meta("original")) { continue; } @@ -268,7 +268,7 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column ERR_FAIL_COND(!ti); String item = ti->get_metadata(0); - Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(item); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(item); if (p_idx == 0) { press_a_key_label->set_text(TTR("Press a Key...")); @@ -335,7 +335,7 @@ void EditorSettingsDialog::_press_a_key_confirm() { ie->set_alt(last_wait_for_key->get_alt()); ie->set_metakey(last_wait_for_key->get_metakey()); - Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured); + Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured); undo_redo->create_action(TTR("Change Shortcut") + " '" + shortcut_configured + "'"); undo_redo->add_do_method(sc.ptr(), "set_shortcut", ie); diff --git a/editor/translations/af.po b/editor/translations/af.po index 90dca850de..c439941fb8 100644 --- a/editor/translations/af.po +++ b/editor/translations/af.po @@ -1164,6 +1164,9 @@ msgstr "Projek Stigters" msgid "Lead Developer" msgstr "Hoof Ontwikkelaar" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp #, fuzzy msgid "Project Manager " @@ -1186,6 +1189,16 @@ msgid "Gold Sponsors" msgstr "Goue Borge" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Silver Skenkers" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Brons Skenkers" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Borge" @@ -9903,6 +9916,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Projek Bestuurder" diff --git a/editor/translations/ar.po b/editor/translations/ar.po index 075bc25f6e..fecec9b136 100644 --- a/editor/translations/ar.po +++ b/editor/translations/ar.po @@ -48,8 +48,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-11 14:04+0000\n" -"Last-Translator: Musab Alasaifer <mousablasefer@gmail.com>\n" +"PO-Revision-Date: 2020-08-20 15:20+0000\n" +"Last-Translator: Ø£Øمد مصطÙÙ‰ الطبراني <eltabaraniahmed@gmail.com>\n" "Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/" "godot/ar/>\n" "Language: ar\n" @@ -58,12 +58,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " "&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" -"X-Generator: Weblate 4.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "معامل type خاطئ لدالة Convert, استخدم اØدى الثوابت من مجموعة TYPE_*." +msgstr "معامل خاطئ لدالة ()Convert, استخدم اØدى الثوابت من مجموعة TYPE_*." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." @@ -157,11 +157,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" @@ -185,7 +185,7 @@ msgstr "تغيير وقت الإطار الرئيسي للØركة" #: editor/animation_track_editor.cpp msgid "Anim Change Transition" -msgstr "تغيير إنتقالية التØريك" +msgstr "تغيير إنتقالية الرسوم المتØركة" #: editor/animation_track_editor.cpp msgid "Anim Change Transform" @@ -254,11 +254,11 @@ msgstr "شريط ضبط الØركة" #: editor/animation_track_editor.cpp msgid "Animation length (frames)" -msgstr "مدة الØركة (frames)" +msgstr "مدة الØركة (بالإطارات)" #: editor/animation_track_editor.cpp msgid "Animation length (seconds)" -msgstr "مدة الØركة (seconds)" +msgstr "مدة الØركة (بالثواني)" #: editor/animation_track_editor.cpp msgid "Add Track" @@ -381,7 +381,7 @@ msgstr "Øذ٠مسار التØريك" #: editor/animation_track_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "أنشئ مسار جديد لـ %s Ùˆ أدخل Ù…ÙتاØØŸ" +msgstr "أنشئ مسار جديد لـ %s Ùˆ إدخال Ù…ÙتاØØŸ" #: editor/animation_track_editor.cpp msgid "Create %d NEW tracks and insert keys?" @@ -445,11 +445,11 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Animation tracks can only point to AnimationPlayer nodes." -msgstr "مسارات الØركة يمكنها Ùقط أن تشير إلى عقد مشغّل الØركة." +msgstr "مسارات الØركة يمكنها Ùقط أن تشير إلى عÙقد مشغّل الØركة." #: editor/animation_track_editor.cpp msgid "An animation player can't animate itself, only other players." -msgstr "مشغل الØركة لا يمكنه تØريك Ù†Ùسه, Ùقط الاعبين الأخرين." +msgstr "مشغل الØركة لا يمكنه أن ÙŠØرك Ù†Ùسه, Ùقط الاعبين الأخرين." #: editor/animation_track_editor.cpp msgid "Not possible to add a new track without a root" @@ -457,11 +457,11 @@ msgstr "لا يمكن إضاÙØ© مقطع جديد بدون جذر" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" -msgstr "مقطع غير متواÙÙ‚ مع منØنى بيزير Bezier (خصائص Ùرعية غير متواÙقة)" +msgstr "مقطع غير متواÙÙ‚ مع منØنى بيزر (Bezier) (خصائص Ùرعية غير متواÙقة)" #: editor/animation_track_editor.cpp msgid "Add Bezier Track" -msgstr "إضاÙØ© مسار لمنØنى بريزير" +msgstr "إضاÙØ© مسار لمنØنى بيزر" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a key." @@ -469,7 +469,7 @@ 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" @@ -497,7 +497,7 @@ msgstr "Ù…ÙØªØ§Ø Øركة التØريك" #: editor/animation_track_editor.cpp msgid "Clipboard is empty" -msgstr "ذاكرة التخزين المؤقت (Clipboard) Ùارغة" +msgstr "الØاÙظة (Clipboard) Ùارغة" #: editor/animation_track_editor.cpp msgid "Paste Tracks" @@ -510,7 +510,7 @@ msgstr "Ù…ÙØªØ§Ø ØªÙƒØ¨ÙŠØ± Øركة" #: editor/animation_track_editor.cpp msgid "" "This option does not work for Bezier editing, as it's only a single track." -msgstr "هذا الخيار لا يعمل لتعديل خط (Bezier), لأنه Ùقط مقطع واØد." +msgstr "هذا الخيار لا يعمل لتعديل منØنى بيزر (Bezier), لأنه Ùقط مقطع واØد." #: editor/animation_track_editor.cpp msgid "" @@ -524,12 +524,14 @@ msgid "" "Alternatively, use an import preset that imports animations to separate " "files." msgstr "" -"هذا الانيميشن ينتمي الى مشهد مستورد، لذا Ùإن أي تغييرات ÙÙŠ المسارات " -"المستوردة لن يتم ØÙظها.\n" +"هذه الØركة (رسوم متØركة) تنتمي الى مشهد مستورد، لذا Ùإن أي تغييرات ÙÙŠ " +"المسارات المستوردة لن يتم ØÙظها.\n" "\n" "لتشغيل الامكانية لإضاÙØ© مسارات خاصة، انتقل إلى إعدادات استيراد المشهد واضبط " -"\"Animation > Storage\" إلى \"Files\"ØŒ شغل \"Animation > Keep Custom Tracks" -"\"ØŒ ثم ..." +"\"رسوم متØركة > تخزين\" إلى \"ملÙات\"ØŒ\n" +"شغل \"رسوم متØركة > Ø£ØتÙظ بالمقاطع (المسارات) المخصصة\"ØŒ ثم اعد الاستيراد.\n" +"يمكنك ايضاً استخدام إعدادات استيراد مسبقة تقوم باستيراد الرسم المتØرك الى " +"ملÙات متÙرقة." #: editor/animation_track_editor.cpp msgid "Warning: Editing imported animation" @@ -595,7 +597,7 @@ msgstr "تكرير المØدد" #: editor/animation_track_editor.cpp msgid "Duplicate Transposed" -msgstr "نسخ Ù…Øمّل" +msgstr "نقل مكرر" #: editor/animation_track_editor.cpp msgid "Delete Selection" @@ -623,7 +625,7 @@ msgstr "إختار العقدة التي سو٠يتم تØريكها:" #: editor/animation_track_editor.cpp msgid "Use Bezier Curves" -msgstr "إستعمل منØنيات بيزية" +msgstr "إستعمل منØنيات بيزر" #: editor/animation_track_editor.cpp msgid "Anim. Optimizer" @@ -796,7 +798,7 @@ msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." msgstr "" -"لم يتم العثور على الدالة المستهدÙØ©. Øدّد دالة سليمة أو أرÙÙ‚ كود للعقدة " +"لم يتم العثور على الدالة المستهدÙØ©. Øدّد دالة سليمة أو أرÙÙ‚ نص برمجي للعقدة " "المستهدÙØ©." #: editor/connections_dialog.cpp @@ -922,7 +924,7 @@ msgstr "تعديل الإتصال:" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" -msgstr "هل أنت(ÙŠ) متأكد(Ø©) أنك تود إزالة كل الإتصالات من الإشارة \"%s\"ØŸ" +msgstr "هل أنت متأكد أنك تود إزالة كل الإتصالات من الإشارة \"%s\"ØŸ" #: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp msgid "Signals" @@ -930,7 +932,7 @@ msgstr "الإشارات" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from this signal?" -msgstr "هل أنت(ÙŠ) متأكد(Ø©) أنك تود إزالة كل الإتصالات من هذه الإشارة؟" +msgstr "هل أنت متأكد أنك تود إزالة كل الإتصالات من هذه الإشارة؟" #: editor/connections_dialog.cpp msgid "Disconnect All" @@ -991,7 +993,7 @@ msgstr "البØØ« عن بديل لـ:" #: editor/dependency_editor.cpp msgid "Dependencies For:" -msgstr "تابعة لـ:" +msgstr "تبعيات لـ:" #: editor/dependency_editor.cpp msgid "" @@ -1096,7 +1098,7 @@ msgstr "اخطاء ÙÙŠ التØميل!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" -msgstr "Ø¥Ù…Ø³Ø Ù†Ù‡Ø§Ø¦ÙŠØ§ %d عنصر(عناصر)ØŸ (بلا رجعة!)" +msgstr "هل تريد ØØ°Ù %d عنصر (عناصر) نهائيًا؟ (لا تراجع!)" #: editor/dependency_editor.cpp msgid "Show Dependencies" @@ -1132,11 +1134,11 @@ msgstr "تغيير قيمة ÙÙŠ القاموس" #: editor/editor_about.cpp msgid "Thanks from the Godot community!" -msgstr "شكراً من مجتمع Godot!" +msgstr "شكراً من مجتمع غودوت!" #: editor/editor_about.cpp msgid "Godot Engine contributors" -msgstr "المسهامين ÙÙŠ Ù…Øرك Godot" +msgstr "المسهامين ÙÙŠ Ù…Øرك غودوت" #: editor/editor_about.cpp msgid "Project Founders" @@ -1146,6 +1148,9 @@ msgstr "مؤسسون المشروع" msgid "Lead Developer" msgstr "قائد المطوريين" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "مدير المشروع " @@ -1167,6 +1172,16 @@ msgid "Gold Sponsors" msgstr "الرعاة الذهبيين" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "المانØين الÙضيين" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "المانØين البرنزيين" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "الرعاة الصغار" @@ -1201,9 +1216,9 @@ msgid "" "is an exhaustive list of all such third-party components with their " "respective copyright statements and license terms." msgstr "" -"Ù…Øرك \"Godot\" يعتمد على عدد من المكتبات Ùˆ المكونات البرمجية لملاك اخرين Ùˆ " -"لكنها مجانية Ùˆ Ù…ÙتوØØ© المصدر، Ùˆ كلها متÙقة مع شروط الاستخدام لرخصة \"MIT\". " -"ÙÙŠ ما يلي قائمة تØوي جميع هذه المكونات اضاÙØ© الى Øقوق النشر Ùˆ شروط الاستخدام " +"Ù…Øرك غودوت يعتمد على عدد من المكتبات Ùˆ المكونات البرمجية لملاك اخرين Ùˆ لكنها " +"مجانية Ùˆ Ù…ÙتوØØ© المصدر، Ùˆ كلها متÙقة مع شروط الاستخدام لرخصة \"MIT\". ÙÙŠ ما " +"يلي قائمة تØوي جميع هذه المكونات اضاÙØ© الى Øقوق النشر Ùˆ شروط الاستخدام " "الخاصة بها." #: editor/editor_about.cpp @@ -1224,7 +1239,7 @@ msgstr "Øدث خطأ عندÙØªØ Ù…Ù„Ù Ø§Ù„Øزمة بسبب أن المل٠#: editor/editor_asset_installer.cpp msgid "%s (Already Exists)" -msgstr "%s (موجود أصلاً!)" +msgstr "%s (موجود بالÙعل!)" #: editor/editor_asset_installer.cpp msgid "Uncompressing Assets" @@ -1269,39 +1284,39 @@ msgstr "أض٠تأثير" #: editor/editor_audio_buses.cpp msgid "Rename Audio Bus" -msgstr "إعادة تسمية بيوس الصوت" +msgstr "إعادة تسمية مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Change Audio Bus Volume" -msgstr "تغيير Øجم صوت البيوس" +msgstr "تغيير Øجم صوت مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" -msgstr "تبديل بيوس الصوت إلي Ùردي" +msgstr "تبديل مسار الصوت إلي Ùردي" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Mute" -msgstr "تبديل بيوس الصوت إلي صامت" +msgstr "تبديل مسار الصوت إلي صامت" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Bypass Effects" -msgstr "تبديل بيوس الصوت إلي موثرات التبديل" +msgstr "تبديل مسار الصوت إلي موثرات التبديل" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" -msgstr "Øدد بيوس الصوت للإرسال" +msgstr "Øدد مسار الصوت للإرسال" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" -msgstr "أض٠موثرات إلي بيوس الصوت" +msgstr "أض٠موثرات إلي مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Move Bus Effect" -msgstr "Øرك مؤثر البيوس" +msgstr "Øرك ثأثير مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Delete Bus Effect" -msgstr "Ù…Ø³Ø ØªØ£Ø«ÙŠØ± البيوس" +msgstr "Ù…Ø³Ø ØªØ£Ø«ÙŠØ± مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Drag & drop to rearrange." @@ -1321,7 +1336,7 @@ msgstr "تخطي" #: editor/editor_audio_buses.cpp msgid "Bus options" -msgstr "إعدادات البيوس" +msgstr "إعدادات مسار الصوت" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp @@ -1342,31 +1357,31 @@ msgstr "الصوت" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus" -msgstr "أض٠بيوس الصوت" +msgstr "أض٠مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Master bus can't be deleted!" -msgstr "البيوس الأساسي لا يمكن مسØØ©!" +msgstr "مسار الصوت الأساسي لا يمكن مسØØ©!" #: editor/editor_audio_buses.cpp msgid "Delete Audio Bus" -msgstr "Ø¥Ù…Ø³Ø Ø¨ÙŠÙˆØ³ الصوت" +msgstr "Ø¥Ù…Ø³Ø Ù…Ø³Ø§Ø± الصوت" #: editor/editor_audio_buses.cpp msgid "Duplicate Audio Bus" -msgstr "تكرير بيوس الصوت" +msgstr "تكرار مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Reset Bus Volume" -msgstr "إرجاع صوت البيس" +msgstr "إرجاع صوت المسار" #: editor/editor_audio_buses.cpp msgid "Move Audio Bus" -msgstr "تØريك بيوس الصوت" +msgstr "تØريك مسار الصوت" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As..." -msgstr "Ø¥ØÙظ نسق بيوس الصوت كـ..." +msgstr "ØÙظ تخطيط مسار الصوت كـ…" #: editor/editor_audio_buses.cpp msgid "Location for New Layout..." @@ -1374,7 +1389,7 @@ msgstr "المكان للنسق الجديد..." #: editor/editor_audio_buses.cpp msgid "Open Audio Bus Layout" -msgstr "Ø¥ÙØªØ Ù†Ø³Ù‚ بيوس الصوت" +msgstr "Ø¥ÙØªØ Ù†Ø³Ù‚ مسار الصوت" #: editor/editor_audio_buses.cpp msgid "There is no '%s' file." @@ -1386,15 +1401,15 @@ msgstr "المخطط" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." -msgstr "مل٠خطأ، ليس مل٠نسق بيوس الصوت." +msgstr "مل٠خطأ، ليس مل٠نسق مسار الصوت." #: editor/editor_audio_buses.cpp msgid "Error saving file: %s" -msgstr "خطأ !خطأ ÙÙŠ تسجيل الملÙ: s%" +msgstr "خطأ ÙÙŠ تØميل الملÙ: s%" #: editor/editor_audio_buses.cpp msgid "Add Bus" -msgstr "أض٠بيوس" +msgstr "أض٠مسار" #: editor/editor_audio_buses.cpp msgid "Add a new Audio Bus to this layout." @@ -1408,7 +1423,7 @@ msgstr "تØميل" #: editor/editor_audio_buses.cpp msgid "Load an existing Bus Layout." -msgstr "تØميل نسق بيوس موجود مسبقاً." +msgstr "تØميل نسق مسار موجود مسبقاً." #: editor/editor_audio_buses.cpp msgid "Save As" @@ -1416,7 +1431,7 @@ msgstr "ØÙظ بأسم" #: editor/editor_audio_buses.cpp msgid "Save this Bus Layout to a file." -msgstr "Ø¥ØÙظ نسق البيوس هذا إلي ملÙ." +msgstr "Ø¥ØÙظ نسق هذا مسار إلي ملÙ." #: editor/editor_audio_buses.cpp editor/import_dock.cpp msgid "Load Default" @@ -1424,11 +1439,11 @@ msgstr "تØميل الإÙتراضي" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "تØميل نسق البيوس الإÙتراضي." +msgstr "تØميل نسق المسار الإÙتراضي." #: editor/editor_audio_buses.cpp msgid "Create a new Bus Layout." -msgstr "أنشئ نسق بيوس جديد." +msgstr "أنشئ نسق مسار جديد." #: editor/editor_autoload_settings.cpp msgid "Invalid name." @@ -1476,7 +1491,7 @@ msgstr "ازالة التØميل التلقائي" #: editor/editor_autoload_settings.cpp editor/editor_plugin_settings.cpp msgid "Enable" -msgstr "تمكين" +msgstr "تÙعيل" #: editor/editor_autoload_settings.cpp msgid "Rearrange Autoloads" @@ -1484,7 +1499,7 @@ msgstr "اعادة ترتيب التØميلات التلقائية" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "لا يمكن اضاÙØ© التØميل التلقائي" +msgstr "لا يمكن إضاÙØ© التØميل التلقائي:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -1679,7 +1694,7 @@ msgstr "(المÙØرر Ù…Ùعطّل)" #: editor/editor_feature_profile.cpp msgid "Class Options:" -msgstr "إعدادات الص٠Class:" +msgstr "إعدادات الص٠(Class):" #: editor/editor_feature_profile.cpp msgid "Enable Contextual Editor" @@ -1748,7 +1763,7 @@ msgstr "إعدادات الص٠Class" #: editor/editor_feature_profile.cpp msgid "New profile name:" -msgstr "اسم Ù…ÙŽÙ„Ù profile جديد:" +msgstr "اسم Ù…ÙŽÙ„Ù (profile) جديد:" #: editor/editor_feature_profile.cpp msgid "Erase Profile" @@ -1978,11 +1993,11 @@ msgstr "الاÙتراضي:" #: editor/editor_help.cpp msgid "Methods" -msgstr "قائمة الطرق" +msgstr "الطÙرق" #: editor/editor_help.cpp msgid "Theme Properties" -msgstr "خصائص الثمة" +msgstr "خصائص الثÙمة" #: editor/editor_help.cpp msgid "Enumerations" @@ -2010,7 +2025,7 @@ msgstr "" #: editor/editor_help.cpp msgid "Method Descriptions" -msgstr "أوصا٠الدوال Method" +msgstr "أوصا٠الدوال" #: editor/editor_help.cpp msgid "" @@ -2087,7 +2102,7 @@ msgstr "خاصية" #: editor/editor_help_search.cpp msgid "Theme Property" -msgstr "خاصية الموضوع Theme" +msgstr "خاصية الموضوع (Theme)" #: editor/editor_inspector.cpp editor/project_settings_editor.cpp msgid "Property:" @@ -2232,7 +2247,7 @@ msgstr "ØÙظ المشهد" #: editor/editor_node.cpp msgid "Analyzing" -msgstr "ÙŠØلل" +msgstr "جاري التØليل" #: editor/editor_node.cpp msgid "Creating Thumbnail" @@ -2240,7 +2255,7 @@ msgstr "ينشئ الصورة المصغرة" #: editor/editor_node.cpp msgid "This operation can't be done without a tree root." -msgstr "هذه العملية لا يمكنها الإكتمال من غير جذر شجرة ." +msgstr "هذه العملية لا يمكنها الإكتمال من غير شجرة رئيسة." #: editor/editor_node.cpp msgid "" @@ -2386,7 +2401,7 @@ msgstr "يتطلب ØÙظ المشهد تواÙر عÙقدة رئيسة." #: editor/editor_node.cpp msgid "Save Scene As..." -msgstr "ØÙظ المشهد كـ..." +msgstr "ØÙظ المشهد كـ…" #: editor/editor_node.cpp msgid "No" @@ -2497,31 +2512,33 @@ msgstr "غير قادر علي تÙعيل إضاÙØ© البرنامج المÙس #: editor/editor_node.cpp msgid "Unable to find script field for addon plugin at: 'res://addons/%s'." msgstr "" -"غير قادر علي إيجاد منطقة الكود من أجل إضاÙØ© البرنامج ÙÙŠ: 'res://addons/%s'." +"غير قادر علي إيجاد منطقة النص البرمجي من أجل إضاÙØ© البرنامج ÙÙŠ: 'res://" +"addons/%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "غير قادر علي تØميل كود الإضاÙØ© من المسار: '%s'." +msgstr "غير قادر علي تØميل النص البرمجي للإضاÙØ© من المسار: '%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." msgstr "" -"غير قادر علي تØميل كود الإضاÙØ© من المسار: '%s' يبدو أن الكود يوجد Ùيه " -"أخطاء , الرجاء مراجعة الكود." +"غير قادر علي تØميل النص البرمجي الإضاÙب من المسار: '%s' يبدو أن Ø´ÙÙرة " +"البرمجية يوجد بها أخطاء , الرجاء مراجعة الشÙÙرة البرمجية." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." msgstr "" -"غير قادر علي تØميل كود الإضاÙØ© من المسار: '%s' النوع الأساسي ليس إضاÙØ© " -"المÙعدل." +"غير قادر علي تØميل النص البرمجي الإضاÙÙŠ من المسار: '%s' النوع الأساسي ليس " +"إضاÙØ© المÙعدل." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." msgstr "" -"غير قادر علي تØميل كود الإضاÙØ© من المسار: '%s' الكود ليس ÙÙŠ وضع الأداة." +"غير قادر علي تØميل النص البرمجي الإضاÙÙŠ من المسار: '%s' النص البرمجي ليس ÙÙŠ " +"وضع الأداة." #: editor/editor_node.cpp msgid "" @@ -2706,7 +2723,7 @@ msgstr "تØويل الي..." #: editor/editor_node.cpp msgid "MeshLibrary..." -msgstr "مكتبة الميش..." +msgstr "مكتبة المجسم..." #: editor/editor_node.cpp msgid "TileSet..." @@ -2737,7 +2754,7 @@ msgstr "إعدادات المشروع..." #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Version Control" -msgstr "التØكم ÙÙŠ الإصدار" +msgstr "التØكم بالإصدار" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Set Up Version Control" @@ -2761,7 +2778,7 @@ msgstr "ÙØªØ Ù…Ø¬Ù„Ø¯ بيانات المشروع" #: editor/editor_node.cpp editor/plugins/tile_set_editor_plugin.cpp msgid "Tools" -msgstr "ادوات" +msgstr "أدوات" #: editor/editor_node.cpp msgid "Orphan Resource Explorer..." @@ -2769,7 +2786,7 @@ msgstr "متصÙØ Ø§Ù„Ù…ÙˆØ§Ø±Ø¯ أورÙان..." #: editor/editor_node.cpp msgid "Quit to Project List" -msgstr "غادر إلى قائمه المشاريع" +msgstr "العودة إلى قائمة المشاريع" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/project_export.cpp @@ -2801,11 +2818,11 @@ msgid "" "On Android, deploy will use the USB cable for faster performance. This " "option speeds up testing for games with a large footprint." msgstr "" -"Øينما يتم تÙعيل هذا الإعداد، التصدير او النشر سو٠ينتج مل٠تشغيل بالØد " -"الأدني.\n" +"Øينما يتم تÙعيل هذا الإعداد، التصدير أو النشر سو٠ينتج مل٠تشغيل بالØد " +"الأدنى (مبسط).\n" "نظام الملÙات سو٠يتم توÙيره بواسطة المÙعدل من خلال الشبكة.\n" -"علي الأندرويد، النشر سو٠يستخدم وصلة اليو اس بي من أجل أداء أسرع. هذا " -"الأعداد يسرع الإختبار للإلعاب مع الملÙات الكثيرة." +"على الأندرويد، النشر سو٠يستخدم وصلة اليو إس بي من أجل أداء أسرع. هذا " +"الإعداد يسرّع إختبار الألعاب ذو الØجم الكبير." #: editor/editor_node.cpp msgid "Visible Collision Shapes" @@ -2816,8 +2833,8 @@ msgid "" "Collision shapes and raycast nodes (for 2D and 3D) will be visible on the " "running game if this option is turned on." msgstr "" -"أشكال الإصطدام Ùˆ وعقد الراي كاست (من أجل 2D Ùˆ 3D) سو٠تكون ظاهرة ÙÙŠ اللعبة " -"العاملة إذا كان هذا الإعداد Ù…ÙÙعل." +"أشكال الإصطدام Ùˆ عÙقد الراي كاست (من أجل 2D Ùˆ 3D) سو٠تكون ظاهرة ÙÙŠ اللعبة " +"العاملة إذا كان هذا الإعداد Ù…ÙÙعّل." #: editor/editor_node.cpp msgid "Visible Navigation" @@ -2827,7 +2844,8 @@ msgstr "الإنتقال المرئي" msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." -msgstr "ميشات التنقل والبوليجين سو٠يكونون ظاهرين Øينما يتم تÙعيل هذا الإعداد." +msgstr "" +"مجسمات التنقل والأشكال المضلعة سو٠تكون ظاهرة Øينما يتم تÙعيل هذا الإعداد." #: editor/editor_node.cpp msgid "Sync Scene Changes" @@ -2856,22 +2874,22 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" -"Øينما يكون هذا الإعداد Ù…ÙÙعل، أي كود يتم ØÙظه سيتم إعادة تشغيلة ÙÙŠ اللعبة " -"العاملة.\n" -"Øينما يتم إستخدامة عن بعد علي جهاز، سيكون هذا أكثر Ùعالية مع نظام شبكات " +"Øينما يكون هذا الإعداد Ù…ÙÙعل، أي نص برمجي يتم ØÙظه سيتم إعادة تØميله ÙÙŠ " +"اللعبة العاملة.\n" +"Øينما يتم إستخدامه عن بÙعد على جهاز، سيكون هذا أكثر Ùعالية مع نظام شبكات " "الملÙات." #: editor/editor_node.cpp editor/script_create_dialog.cpp msgid "Editor" -msgstr "المÙعدل" +msgstr "المØرّر" #: editor/editor_node.cpp msgid "Editor Settings..." -msgstr "إعدادات المØرّر" +msgstr "إعدادات المØرّر…" #: editor/editor_node.cpp msgid "Editor Layout" -msgstr "نسق المÙعدل" +msgstr "تنسيق المØرّر" #: editor/editor_node.cpp msgid "Take Screenshot" @@ -2879,11 +2897,11 @@ msgstr "أخذ صورة للشاشة" #: editor/editor_node.cpp msgid "Screenshots are stored in the Editor Data/Settings Folder." -msgstr "لقطات الشاشة تكون Ù…ØÙوظة ÙÙŠ مجلّد البيانات/الإعدادت داخل المØرّر" +msgstr "لقطات الشاشة تكون Ù…ØÙوظة ÙÙŠ مجلّد بيانات/إعدادات المØرّر." #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "إلغاء/تÙعيل وضع الشاشة الكاملة" +msgstr "تÙعيل/إلغاء وضع الشاشة الكاملة" #: editor/editor_node.cpp msgid "Toggle System Console" @@ -2891,11 +2909,11 @@ msgstr "إظهار/إخÙاء ÙˆØدة التØكم بالنظام" #: editor/editor_node.cpp msgid "Open Editor Data/Settings Folder" -msgstr "ÙØªØ Ù…Ø¬Ù„Ù‘Ø¯ البيانات/الإعدادت المØرّر" +msgstr "ÙØªØ Ù…Ø¬Ù„Ù‘Ø¯ بيانات/إعدادات المØرّر" #: editor/editor_node.cpp msgid "Open Editor Data Folder" -msgstr "اÙØªØ Ù…Ù„Ù Ø¨ÙŠØ§Ù†Ø§Øª المØرر" +msgstr "ÙØªØ Ù…Ø¬Ù„Ù‘Ø¯ بيانات المØرّر" #: editor/editor_node.cpp msgid "Open Editor Settings Folder" @@ -2903,7 +2921,7 @@ msgstr "ÙØªØ Ù…Ø¬Ù„Ù‘Ø¯ إعدادات المØرّر" #: editor/editor_node.cpp msgid "Manage Editor Features..." -msgstr "إدارة ميّزات المØرّر" +msgstr "إدارة ميّزات المØرّر…" #: editor/editor_node.cpp msgid "Manage Export Templates..." @@ -2933,7 +2951,7 @@ msgstr "الأسئلة Ùˆ الأجوبة" #: editor/editor_node.cpp msgid "Report a Bug" -msgstr "إرسال تقرير عن bug أو خلل ÙÙŠ شيء ما" +msgstr "إرسال تقرير عن خلل برمجي" #: editor/editor_node.cpp msgid "Send Docs Feedback" @@ -2945,7 +2963,7 @@ msgstr "المجتمع" #: editor/editor_node.cpp msgid "About" -msgstr "عن" +msgstr "عن هذا التطبيق" #: editor/editor_node.cpp msgid "Play the project." @@ -2957,11 +2975,11 @@ msgstr "تشغيل" #: editor/editor_node.cpp msgid "Pause the scene execution for debugging." -msgstr "إيقا٠جلسة المشهد من أجل ØªÙ†Ù‚ÙŠØ Ø§Ù„ÙƒØ¨ÙˆØ§Øª البرمجية debugging." +msgstr "إيقا٠المشهد الØالي من أجل المعالجة البرمجية." #: editor/editor_node.cpp msgid "Pause Scene" -msgstr "إيقا٠مؤقت للمشهد" +msgstr "إيقا٠مؤقّت للمشهد" #: editor/editor_node.cpp msgid "Stop the scene." @@ -2969,7 +2987,7 @@ msgstr "إيقا٠المشهد." #: editor/editor_node.cpp msgid "Play the edited scene." -msgstr "تشغيل المشهد المÙعدل." +msgstr "تشغيل المشهد المÙعدّل." #: editor/editor_node.cpp msgid "Play Scene" @@ -2994,7 +3012,7 @@ msgstr "ØÙظ Ùˆ إعادة تشغيل" #: editor/editor_node.cpp msgid "Spins when the editor window redraws." -msgstr "يدور Øينما يتم إعادة رسم ناÙذة المØرّر" +msgstr "قم بالتدوير أثناء إعادة رسم ناÙذة المØرّر." #: editor/editor_node.cpp msgid "Update Continuously" @@ -3014,7 +3032,7 @@ msgstr "نظام الملÙات" #: editor/editor_node.cpp msgid "Inspector" -msgstr "Ù…Ùراقب" +msgstr "المÙراقب" #: editor/editor_node.cpp msgid "Expand Bottom Panel" @@ -3099,27 +3117,27 @@ msgstr "Øدد" #: editor/editor_node.cpp msgid "Open 2D Editor" -msgstr "ÙØªØ Ø§Ù„Ù…Ùعدل 2D" +msgstr "ÙØªØ Ø§Ù„Ù…ÙØرر 2D" #: editor/editor_node.cpp msgid "Open 3D Editor" -msgstr "ÙØªØ Ø§Ù„Ù…Ùعدل 3D" +msgstr "ÙØªØ Ø§Ù„Ù…ÙØرر 3D" #: editor/editor_node.cpp msgid "Open Script Editor" -msgstr "ÙØªØ Ù…Ùعدل الكود" +msgstr "ÙØªØ Ù…Øرر النص البرمجي" #: editor/editor_node.cpp editor/project_manager.cpp msgid "Open Asset Library" -msgstr "ÙØªØ Ù…ÙƒØªØ¨Ø© الأصول" +msgstr "ÙØªØ Ù…ÙƒØªØ¨Ø© المÙÙ„Øقات" #: editor/editor_node.cpp msgid "Open the next Editor" -msgstr "ÙØªØ ÙÙŠ المÙعدل التالي" +msgstr "ÙØªØ ÙÙŠ المÙØرر التالي" #: editor/editor_node.cpp msgid "Open the previous Editor" -msgstr "Ø¥ÙØªØ Ø§Ù„Ù…Ùعدل السابق" +msgstr "Ø¥ÙØªØ Ø§Ù„Ù…ÙØرر السابق" #: editor/editor_node.h msgid "Warning!" @@ -3236,7 +3254,7 @@ msgstr "إلØاق..." #: editor/editor_properties.cpp msgid "Invalid RID" -msgstr "إسم RID غير صالØ." +msgstr "RID غير صالØ" #: editor/editor_properties.cpp msgid "" @@ -3584,7 +3602,7 @@ msgstr "Øدد مل٠القالب" #: editor/export_template_manager.cpp msgid "Godot Export Templates" -msgstr "إدارة قوالب التصدير Godot" +msgstr "إدارة قوالب التصدير لغودوت" #: editor/export_template_manager.cpp msgid "Export Template Manager" @@ -3708,11 +3726,11 @@ msgstr "مشهد جديد..." #: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp msgid "New Script..." -msgstr "ÙØªØ Ø§Ù„Ø³ÙƒØ±ÙŠØ¨Øª..." +msgstr "ÙØªØ Ø§Ù„Ù†Øµ البرمجي..." #: editor/filesystem_dock.cpp msgid "New Resource..." -msgstr "مورد جديد..." +msgstr "مصدر جديد..." #: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp #: editor/script_editor_debugger.cpp @@ -3733,7 +3751,7 @@ msgstr "إعادة التسمية" #: editor/filesystem_dock.cpp msgid "Previous Folder/File" -msgstr "‪المجلد/المل٠السابق" +msgstr "المجلد/المل٠السابق" #: editor/filesystem_dock.cpp msgid "Next Folder/File" @@ -3793,7 +3811,7 @@ msgstr "مجلد:" #: editor/find_in_files.cpp msgid "Filters:" -msgstr "Ùلتر:" +msgstr "تنقيات:" #: editor/find_in_files.cpp msgid "" @@ -3822,7 +3840,7 @@ msgstr "إيجاد: " #: editor/find_in_files.cpp msgid "Replace: " -msgstr "إستبدال:" +msgstr "إستبدال: " #: editor/find_in_files.cpp msgid "Replace all (no undo)" @@ -3895,7 +3913,7 @@ msgstr "إستيراد كمشهد واØد" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Animations" -msgstr "إستيراد مع إنميشن منÙصلة" +msgstr "إستيراد مع رسوم متØركة منÙصلة" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials" @@ -3911,15 +3929,15 @@ msgstr "إستيراد مع عناصر+موارد منÙصلة" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Animations" -msgstr "إستيراد مع عناصر + إنميشن منÙصلة" +msgstr "إستيراد مع عناصر + رسوم متØركة منÙصلة" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Materials+Animations" -msgstr "إستيراد مع مصادر+ إنميشن منÙصلة" +msgstr "إستيراد مع مصادر+ رسوم متØركة منÙصلة" #: editor/import/resource_importer_scene.cpp msgid "Import with Separate Objects+Materials+Animations" -msgstr "إستيراد مع عناصر + مصادر + إنميشين منÙصلين" +msgstr "إستيراد مع عناصر + مصادر + رسوم متØركة منÙصلين" #: editor/import/resource_importer_scene.cpp msgid "Import as Multiple Scenes" @@ -3944,23 +3962,23 @@ msgstr "انشاء خارطة الضوء" #: editor/import/resource_importer_scene.cpp msgid "Generating for Mesh: " -msgstr "انشاء من اجل الميش: " +msgstr "انشاء من اجل المجسم: " #: editor/import/resource_importer_scene.cpp msgid "Running Custom Script..." -msgstr "تشغيل الكود المÙخصص..." +msgstr "تشغيل النص البرمجي المÙخصص..." #: editor/import/resource_importer_scene.cpp msgid "Couldn't load post-import script:" -msgstr "لا يمكن تØميل الكود المستورد أو المطبوع:" +msgstr "لا يمكن تØميل النص البرمجي المستورد أو المطبوع:" #: editor/import/resource_importer_scene.cpp msgid "Invalid/broken script for post-import (check console):" -msgstr "كود مستورد-ملصق متضرر/خاطئ (تØقق من ÙˆØدة التØكم):" +msgstr "النص البرمجي مستورد-ملصق متضرر/خاطئ (تØقق من ÙˆØدة التØكم):" #: editor/import/resource_importer_scene.cpp msgid "Error running post-import script:" -msgstr "خطأ ÙÙŠ تشغيل الكود الملصق- المستورد:" +msgstr "خطأ ÙÙŠ تشغيل النص البرمجي الملصق- المستورد:" #: editor/import/resource_importer_scene.cpp msgid "Did you return a Node-derived object in the `post_import()` method?" @@ -3980,15 +3998,15 @@ msgstr "Øدد كإÙتراضي من أجل '%s'" #: editor/import_dock.cpp msgid "Clear Default for '%s'" -msgstr "إخلاء الإÙتراضي لـ '%s'" +msgstr "إخلاء الإÙتراضي Ù„ '%s'" #: editor/import_dock.cpp msgid "Import As:" -msgstr "إستيراد كـ:" +msgstr "إستيراد Ùƒ:" #: editor/import_dock.cpp msgid "Preset" -msgstr "إعداد Ù…Ùسبق..." +msgstr "إعداد Ù…Ùسبق" #: editor/import_dock.cpp msgid "Reimport" @@ -4429,38 +4447,38 @@ msgstr "إلغاء/تÙعيل التشغيل التلقائي" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Animation Name:" -msgstr "إسم الØركة الجديد:" +msgstr "إسم رسم المتØرك جديد:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Anim" -msgstr "Øركة جديدة" +msgstr "رسم متØرك جديدة" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Change Animation Name:" -msgstr "تغيير إسم الØركة:" +msgstr "تغيير إسم الرسم المتØرك:" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Delete Animation?" -msgstr "Ù…Ø³Ø Ø§Ù„Øركة؟" +msgstr "Ù…Ø³Ø Ø§Ù„Ø±Ø³Ù… المتØرك؟" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Remove Animation" -msgstr "Ù…Ø³Ø Ø§Ù„Øركة" +msgstr "Ù…Ø³Ø Ø§Ù„Ø±Ø³Ù… المتØرك" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Invalid animation name!" -msgstr "خطأ: إسم الرسوم المتØركة خاطئ!" +msgstr "إسم الرسم المتØرك خاطئ!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation name already exists!" -msgstr "اسم الØركة موجود بالÙعل!" +msgstr "إسم الرسم المتØرك موجود بالÙعل!" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Rename Animation" -msgstr "إعادة تسمية الØركة" +msgstr "إعادة تسمية الرسم المتØرك" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Next Changed" @@ -4472,23 +4490,23 @@ msgstr "تغيير وقت الدمج" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Load Animation" -msgstr "تØميل Øركة" +msgstr "تØميل الرسم المتØرك" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Duplicate Animation" -msgstr "تكرير الØركة" +msgstr "تكرار الرسم المتØرك" #: editor/plugins/animation_player_editor_plugin.cpp msgid "No animation to copy!" -msgstr "لا Øركة رسومية لنسخها!" +msgstr "لا رسم متØرك لنسخها!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "No animation resource on clipboard!" -msgstr "لا يوجد مورد لرسومية متØركة ÙÙŠ الØاÙظة clipboard!" +msgstr "لا يوجد مورد لرسم متØرك ÙÙŠ الØاÙظة clipboard!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Pasted Animation" -msgstr "الØركة الرسومية المÙلصقة" +msgstr "تم لصق الرسوم المتØركة" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Paste Animation" @@ -4500,39 +4518,39 @@ msgstr "لا رسومات متØركة لتØريرها!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from current pos. (A)" -msgstr "تشغيل الØركة المختارة بشكل عكسي من الموقع الØالي. (زر A)" +msgstr "تشغيل الرسم المتØرك المختار بشكل عكسي من الموقع الØالي. (زر A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from end. (Shift+A)" -msgstr "تشيل الØركة المختارة بشكل عكسي من النهاية. (Shift+Ø´)" +msgstr "تشغيل الرسم المتØرك المختار بشكل عكسي من النهاية. (Shift+A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Stop animation playback. (S)" -msgstr "إيقا٠تشغيل الØركة. (س)" +msgstr "إيقا٠تشغيل الرسم المتØرك. (S)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from start. (Shift+D)" -msgstr "تشغيل الØركة المØددة من البداية. (Shift+ÙŠ)" +msgstr "تشغيل الرسم المتØرك المØدد من البداية. (Shift+D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from current pos. (D)" -msgstr "تشغيل الØركة المختارة من الموقع الØالي. (زر D)" +msgstr "تشغيل الرسم المتØرك المختار من الموقع الØالي. (D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation position (in seconds)." -msgstr "موقع الØركة (بالثواني)." +msgstr "موقع الرسم المتØرك (بالثواني)." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Scale animation playback globally for the node." -msgstr "تكبير تشغيل الØركة عالمياً من العقدة." +msgstr "تكبير تشغيل الرسم المتØرك عالمياً من العقدة." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Tools" -msgstr "أدوات الØركة" +msgstr "أدوات الرسم المتØرك" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation" -msgstr "صورة متØركة" +msgstr "الرسم المتØرك" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Transitions..." @@ -4604,11 +4622,11 @@ msgstr "تثبيت Ù…Ùشغّل الرسوميات المتØركة" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Create New Animation" -msgstr "إنشاء Øركة جديدة" +msgstr "إنشاء رسوم متØركة جديدة" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Name:" -msgstr "إسم الØركة:" +msgstr "إسم الرسم المتØرك:" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/resource_preloader_editor_plugin.cpp @@ -4858,7 +4876,7 @@ msgstr "عقدة التنقل" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Import Animations..." -msgstr "إستيراد الØركة..." +msgstr "إستيراد الرسوم المتØركة..." #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Edit Node Filters" @@ -4922,7 +4940,7 @@ msgstr "Ùشل الطلب ØŒ انتهت المهلة" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Timeout." -msgstr "إنتهى الوقت" +msgstr "انتهت المهلة." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." @@ -4962,7 +4980,7 @@ msgstr "خطأ ÙÙŠ إنشاء الطلب" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Idle" -msgstr "عاطل" +msgstr "الخمول (idle)" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Install..." @@ -7320,7 +7338,6 @@ msgid "Audio Listener" msgstr "المستمع الصوتي" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Enable Doppler" msgstr "تÙعيل دوبلر" @@ -7548,7 +7565,6 @@ msgid "View Z-Near:" msgstr "إظهار Z-Near:" #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "View Z-Far:" msgstr "إظهار Z-Far:" @@ -7655,9 +7671,8 @@ msgid "Invalid geometry, can't create light occluder." msgstr "هندسياً غير صالØØŒ لا يمكن إنشاء ØÙظار (occluder) الضوء." #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "Create LightOccluder2D Sibling" -msgstr "أنشئ شكل Ù…Ùطبق" +msgstr "أنشاء ضوء Ù…Øجوب ثنائي الأبعاد" #: editor/plugins/sprite_editor_plugin.cpp msgid "Sprite" @@ -7918,7 +7933,7 @@ msgstr "عنصر Ù…ÙÙعل اختياري" #: editor/plugins/theme_editor_plugin.cpp msgid "Named Sep." -msgstr "الÙاصل المÙسمّى" +msgstr "الÙاصل المÙسمّى." #: editor/plugins/theme_editor_plugin.cpp msgid "Submenu" @@ -7998,9 +8013,8 @@ msgid "Erase Selection" msgstr "إزالة عملية الاختيار" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Fix Invalid Tiles" -msgstr "اسم غير صالØ." +msgstr "Ø£ØµÙ„Ø Ø§Ù„Ø¨Ù„Ø§Ø·Ø© غير الصالØØ©" #: editor/plugins/tile_map_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp @@ -8028,9 +8042,8 @@ msgid "Erase TileMap" msgstr "Ù…Ø³Ø Ø®Ø±ÙŠØ·Ø© البلاط TileMap" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Find Tile" -msgstr "جد" +msgstr "جد البلاطة" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Transpose" @@ -8045,9 +8058,8 @@ msgid "Enable Priority" msgstr "تمكين الأولوية" #: editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Filter tiles" -msgstr "Ùلتر الملÙات..." +msgstr "تنقية البلاطات" #: editor/plugins/tile_map_editor_plugin.cpp msgid "Give a TileSet resource to this TileMap to use its tiles." @@ -8095,9 +8107,8 @@ msgid "Add Texture(s) to TileSet." msgstr "إضاÙØ© نقش(نقوش) إلى Ù…ÙØدد البلاط TileSet." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Remove selected Texture from TileSet." -msgstr "Ù…Ø³Ø Ø§Ù„Ù…Ø¯Ø®Ù„Ø© الØالية" +msgstr "Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø´ المÙختار من رزمة البلاطات." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create from Scene" @@ -8112,9 +8123,8 @@ msgid "New Single Tile" msgstr "بلاطة Ù…ÙÙردة جديدة" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "New Autotile" -msgstr "إظهار الملÙات" +msgstr "بلاط-تلقائي جديد" #: editor/plugins/tile_set_editor_plugin.cpp msgid "New Atlas" @@ -8150,23 +8160,23 @@ msgstr "الإطباق Occlusion" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Navigation" -msgstr "التصÙØ" +msgstr "التنقل" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Bitmask" -msgstr "قناع البÙت Bitmask" +msgstr "قناع البÙت" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Priority" -msgstr "التÙاضل Priority" +msgstr "الأولية" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Z Index" -msgstr "تراتبية المØور Z" +msgstr "ترتيبية المØور Z" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Region Mode" -msgstr "وضع الأقليم Region" +msgstr "وضع الأقليم" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Collision Mode" @@ -8174,19 +8184,19 @@ msgstr "وضع التصادم" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Occlusion Mode" -msgstr "وضع الإطباق Occlusion" +msgstr "وضع الإطباق" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Navigation Mode" -msgstr "وضع التصÙØ" +msgstr "وضع التنقل" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Bitmask Mode" -msgstr "وضع Bitmask" +msgstr "وضع قناع-البÙت" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Priority Mode" -msgstr "وضع التÙاضل Priority" +msgstr "وضع الأولية" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Icon Mode" @@ -8194,21 +8204,19 @@ msgstr "وضع الأيقونة" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Z Index Mode" -msgstr "وضع Z Index" +msgstr "وضع ترتيبية المØور Z" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Copy bitmask." -msgstr "نسخ bitmask." +msgstr "نسخ قناع-البÙت." #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Paste bitmask." -msgstr "لصق الØركة" +msgstr "لصق قناع-البÙت" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Erase bitmask." -msgstr "زر الÙأرة الأيمن: Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©." +msgstr "Ù…Ø³Ø Ù‚Ù†Ø§Ø¹-البÙت." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Create a new rectangle." @@ -8497,7 +8505,7 @@ msgstr "الØالة" #: editor/plugins/version_control_editor_plugin.cpp msgid "View file diffs before committing them to the latest version" -msgstr "إظهار آخر تعديلات المل٠قبل قبولهم ÙÙŠ آخر نسخة." +msgstr "إظهار آخر تعديلات المل٠قبل قبولهم ÙÙŠ آخر نسخة" #: editor/plugins/version_control_editor_plugin.cpp msgid "No file diff is active" @@ -8846,11 +8854,11 @@ msgstr "ثابت جذر-العدد2 (1.414214)ØŒ أي قيمة جذر العدد #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the absolute value of the parameter." -msgstr "ÙŠØسب القيمة المطلقة لقيمة المَعلم." +msgstr "ÙŠÙرجع القيمة المطلقة لقيمة المَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-cosine of the parameter." -msgstr "ÙŠÙرجع قيمة جيب التمام \"arc-cosine\" للمَعلم." +msgstr "ÙŠÙرجع قيمة جيب التمام للمَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse hyperbolic cosine of the parameter." @@ -8866,11 +8874,11 @@ msgstr "ÙŠÙرجع قيمة جيب القطع الزائد العكسي للمَ #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-tangent of the parameter." -msgstr "ÙŠÙرجع قيمة ظل الزاوية العكسية \"arc-tangent\" للمَعلم." +msgstr "ÙŠÙرجع قيمة ظل الزاوية العكسية للمَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the arc-tangent of the parameters." -msgstr "ÙŠÙرجع قيمة ظل الزاوية العكسي \"arc-tangent\" للمعالم." +msgstr "ÙŠÙرجع قيمة ظل الزاوية العكسي للمَعالم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse hyperbolic tangent of the parameter." @@ -8900,11 +8908,11 @@ msgstr "ÙŠØوّل قيمة (كمية) من الراديان إلى الدرجا #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Base-e Exponential." -msgstr "الدالة Base-e." +msgstr "الدالة الأسية Base-e." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Base-2 Exponential." -msgstr "الدالة Base-2." +msgstr "الدالة الأسية Base-2." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest integer less than or equal to the parameter." @@ -8953,7 +8961,7 @@ msgstr "ÙŠÙرجع قيمة المَعلم الأول مرÙوعاً إلى قو #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts a quantity in degrees to radians." -msgstr "ÙŠØول الكمية المقاسة بالدرجات إلى الراديان." +msgstr "ÙŠØول الكمية المقاسة بالدرجات إلى الراديان (الدائري)." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "1.0 / scalar" @@ -8977,11 +8985,11 @@ msgstr "يستخرج إشارة المَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the sine of the parameter." -msgstr "ÙŠÙرجع جيب sine المَعلم parameter." +msgstr "ÙŠÙرجع جيب المَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic sine of the parameter." -msgstr "ÙŠÙرجع قيمة الجيب العكس hyperbolic sine للمَعلم." +msgstr "ÙŠÙرجع قيمة الجيب العكس للمَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the square root of the parameter." @@ -9014,15 +9022,15 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the tangent of the parameter." -msgstr "ÙŠÙرجع قيمة ظل الزاوية tangent للمَعلم." +msgstr "ÙŠÙرجع قيمة ظل الزاوية للمَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic tangent of the parameter." -msgstr "ÙŠÙرجع قيمة ظل الزاوية العكسي hyperbolic tangent للمَعلم." +msgstr "ÙŠÙرجع قيمة ظل الزاوية العكسي للمَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the truncated value of the parameter." -msgstr "يجد قيمة الاقتطاع truncated للمَعلم." +msgstr "يجد قيمة الاقتطاع للمَعلم." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Adds scalar to scalar." @@ -9061,7 +9069,6 @@ msgid "Perform the texture lookup." msgstr "إجراء البØØ« عن النقش." #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Cubic texture uniform lookup." msgstr "البØØ« عن النقش المكعبي الموØد." @@ -9150,7 +9157,7 @@ msgstr "Ùكّ تركيب المÙتجه إلى ثلاث كميات قياسية #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Calculates the cross product of two vectors." -msgstr "Øساب المنتوج الوسيط للمÙتجهين." +msgstr "Øساب Øاصل الضرب الاتجاهي لمتجهين." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the distance between two points." @@ -9273,7 +9280,7 @@ msgstr "جداء (مضاعÙØ©) Ù…Ùتجه بمÙتجه." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the remainder of the two vectors." -msgstr "ÙŠÙرجع باقي كل من المÙتجهين (الشعاعين)." +msgstr "ÙŠÙرجع باقي قسمة كل من المÙتجهين (الشعاعين)." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Subtracts vector from vector." @@ -9866,6 +9873,7 @@ msgstr "" "هل أنت متأكد من ÙØص %s من المجلدات بØثاً عن مشاريع غودوت متواÙرة؟\n" "قد يستغرق وقتاً." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "مدير المشروع" @@ -9945,7 +9953,7 @@ msgid "" "Invalid action name. it cannot be empty nor contain '/', ':', '=', '\\' or " "'\"'" msgstr "" -"اسم Ùعالية غير صØÙŠØ. لا يمكن أن يكون Ùارغاً أو يتضمن '/'ØŒ ':'ØŒ '='ØŒ '\\' أو " +"اسم Ùعالية غير صØÙŠØ. لا يمكن أن يكون Ùارغاً أو يتضمن '/'ØŒ ':'ØŒ '='ØŒ '\\' أو " "'\"'" #: editor/project_settings_editor.cpp @@ -10530,7 +10538,7 @@ msgstr "Øذ٠العÙقدة %d مع جميع أبنائها؟" #: editor/scene_tree_dock.cpp msgid "Delete %d nodes?" -msgstr "Øذ٠العÙقد %d" +msgstr "Øذ٠العÙقد %dØŸ" #: editor/scene_tree_dock.cpp msgid "Delete the root node \"%s\"?" @@ -10677,9 +10685,8 @@ msgid "Change Type" msgstr "تغيير النوع" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Reparent to New Node" -msgstr "إنشاء %s جديد" +msgstr "تعين لعقدة جديدة" #: editor/scene_tree_dock.cpp msgid "Make Scene Root" @@ -10735,22 +10742,19 @@ msgstr "Ù…Ø³Ø Ø§Ù„Ù…ÙˆØ±ÙˆØ«ØŸ (لا تراجع!)" #: editor/scene_tree_editor.cpp msgid "Toggle Visible" -msgstr "تشغيل/إطÙاء الوضوØية" +msgstr "تشغيل/إطÙاء الوضوØية" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Unlock Node" -msgstr "عقدة اللقطة الواØدة" +msgstr "إلغاء تأمين العقدة" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "Button Group" -msgstr "إضاÙØ© إلي مجموعة" +msgstr "مجموعة الأزرار" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "(Connecting From)" -msgstr "خطأ ÙÙŠ الإتصال" +msgstr "(الإتصال من)" #: editor/scene_tree_editor.cpp msgid "Node configuration warning:" @@ -10845,23 +10849,20 @@ msgid "Path is not local." msgstr "المسار ليس Ù…Øلياً." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid base path." msgstr "مسار غير صالØ." #: editor/script_create_dialog.cpp -#, fuzzy msgid "A directory with the same name exists." -msgstr "مل٠أو مجلد مع هذا الأسم موجود بالÙعل." +msgstr "يوجد ملÙ/مجلد بنÙس الاسم." #: editor/script_create_dialog.cpp msgid "File does not exist." msgstr "المل٠غير موجود." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Invalid extension." -msgstr "يجب أن يستخدم صيغة صØÙŠØØ©." +msgstr "صيغة غير صالØØ©." #: editor/script_create_dialog.cpp msgid "Wrong extension chosen." @@ -10912,33 +10913,28 @@ msgid "Invalid inherited parent name or path." msgstr "إن اسم أو مسار الأب (الأصل parent) الموروث غير صالØ." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Script path/name is valid." -msgstr "شجرة الØركة صØÙŠØØ©." +msgstr "مسار/اسم البرنامج النصي صالØ." #: editor/script_create_dialog.cpp msgid "Allowed: a-z, A-Z, 0-9, _ and ." -msgstr "المسموØ: a-zØŒ A-Z ØŒ 0-9 ØŒ _ Ùˆ ." +msgstr "المسموØ: a-zØŒ A-Z ØŒ 0-9 ØŒ _ Ùˆ ." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Built-in script (into scene file)." -msgstr "عمليات مع ملÙات المشهد." +msgstr "نص برمجي مدموج (داخل مل٠المشهد)." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Will create a new script file." -msgstr "إنشاء مل٠كود جديد" +msgstr "سيتم إنشاء مل٠برمجي جديد." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Will load an existing script file." -msgstr "تØميل نسق بيوس موجود مسبقاً." +msgstr "سيتم تØميل مل٠برمجي موجود مسبقاً." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Script file already exists." -msgstr "التØميل التلقائي '%s' موجود اصلا!" +msgstr "المل٠البرمجي موجود بالÙعل." #: editor/script_create_dialog.cpp msgid "" @@ -10949,19 +10945,16 @@ msgstr "" "تعديلها باستخدام Ù…ÙØرر خارجي." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Class Name:" -msgstr "إسم صنÙ" +msgstr "اسم الÙئة:" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Template:" -msgstr "Ù…Ø³Ø Ø§Ù„Ù‚Ø§Ù„Ø¨" +msgstr "القالب:" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Built-in Script:" -msgstr "ÙØªØ Ø§Ù„ÙƒÙˆØ¯" +msgstr "مل٠النص المÙدمج:" #: editor/script_create_dialog.cpp msgid "Attach Node Script" @@ -10976,39 +10969,32 @@ msgid "Bytes:" msgstr "Bytes:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Warning:" -msgstr "تØذيرات" +msgstr "تØذير:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Error:" -msgstr "خطأ!" +msgstr "خطأ:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Error" -msgstr "خطأ ÙÙŠ نسخ" +msgstr "خطأ ÙÙŠ C++" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Error:" -msgstr "خطأ ÙÙŠ نسخ" +msgstr "خطأ C++ :" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Source" -msgstr "مورد" +msgstr "مصدر C++" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Source:" -msgstr "مورد" +msgstr "مصدر:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "C++ Source:" -msgstr "مورد" +msgstr "مصدر C++:" #: editor/script_editor_debugger.cpp msgid "Stack Trace" @@ -11019,9 +11005,8 @@ msgid "Errors" msgstr "أخطاء" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Child process connected." -msgstr "غير متصل" +msgstr "العملية التابعة متصلة." #: editor/script_editor_debugger.cpp msgid "Copy Error" @@ -11029,12 +11014,11 @@ msgstr "خطأ ÙÙŠ نسخ" #: editor/script_editor_debugger.cpp msgid "Video RAM" -msgstr "ذاكرة الÙيديو Video RAM" +msgstr "الذاكرة العشوائية للÙيديو" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Skip Breakpoints" -msgstr "Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø§Ø·" +msgstr "تخطي نقاط التكسّر" #: editor/script_editor_debugger.cpp msgid "Inspect Previous Instance" @@ -11081,9 +11065,8 @@ msgid "Total:" msgstr "المجموع الكلي:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Export list to a CSV file" -msgstr "تصدير الملÙ" +msgstr "تصدير القائمة إلى مل٠CSV" #: editor/script_editor_debugger.cpp msgid "Resource Path" @@ -11126,18 +11109,16 @@ msgid "Export measures as CSV" msgstr "تصدير القياسات Ùƒ CSV" #: editor/settings_config_dialog.cpp -#, fuzzy msgid "Erase Shortcut" -msgstr "تخÙي٠للخارج" +msgstr "Øذ٠الاختصار" #: editor/settings_config_dialog.cpp msgid "Restore Shortcut" msgstr "إعادة تعيين الاختصارات" #: editor/settings_config_dialog.cpp -#, fuzzy msgid "Change Shortcut" -msgstr "تغيير المرتكزات" +msgstr "تغيير الاختصارات" #: editor/settings_config_dialog.cpp msgid "Editor Settings" @@ -11209,19 +11190,16 @@ msgid "Change Ray Shape Length" msgstr "تعديل طول الشكل الشعاعي" #: modules/csg/csg_gizmos.cpp -#, fuzzy msgid "Change Cylinder Radius" -msgstr "تغيير وقت الدمج" +msgstr "تغيير نص٠قطر الاسطوانة" #: modules/csg/csg_gizmos.cpp -#, fuzzy msgid "Change Cylinder Height" -msgstr "تغيير وقت الدمج" +msgstr "تغيير ارتÙاع الاسطوانة" #: modules/csg/csg_gizmos.cpp -#, fuzzy msgid "Change Torus Inner Radius" -msgstr "تغيير المرتكزات Ùˆ الهوامش" +msgstr "تغيير نص٠قطر الدائرة الداخلي" #: modules/csg/csg_gizmos.cpp msgid "Change Torus Outer Radius" @@ -11265,12 +11243,11 @@ msgstr "مكتبة GDNativeLibrary" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Enabled GDNative Singleton" -msgstr "تمكين نمط البرمجة Singleton Ù„Ù GDNative" +msgstr "تمكين نمط البرمجة Singleton لـ GDNative" #: modules/gdnative/gdnative_library_singleton_editor.cpp -#, fuzzy msgid "Disabled GDNative Singleton" -msgstr "تعطيل دوار التØديث" +msgstr "تعطيل نمط البرمجة Singleton لـ GDNative" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Library" @@ -11285,17 +11262,16 @@ msgid "GDNative" msgstr "GDNative" #: modules/gdscript/gdscript_functions.cpp -#, fuzzy msgid "Step argument is zero!" -msgstr "الخطوة (المتغيرة المدخلة/argument) تساوي صÙر !" +msgstr "معامل الخطوة تساوي صÙر!" #: modules/gdscript/gdscript_functions.cpp msgid "Not a script with an instance" -msgstr "ليس كود مع نموذج" +msgstr "ليس نص برمجي مع نموذج" #: modules/gdscript/gdscript_functions.cpp msgid "Not based on a script" -msgstr "لا تستند الى Ø´Ùرة مصدرية" +msgstr "لا تستند الى نص برمجي" #: modules/gdscript/gdscript_functions.cpp msgid "Not based on a resource file" @@ -11303,42 +11279,35 @@ msgstr "لا تستند على مل٠مورد" #: modules/gdscript/gdscript_functions.cpp msgid "Invalid instance dictionary format (missing @path)" -msgstr "" -"instance dictionary format نموذج الشكل القاموسي غير ØµØ§Ù„Ø - المسار Ù…Ùقود" +msgstr "نموذج الشكل القاموسي غير ØµØ§Ù„Ø (@المسار Ù…Ùقود)" #: modules/gdscript/gdscript_functions.cpp msgid "Invalid instance dictionary format (can't load script at @path)" -msgstr "" -"instance dictionary format نموذج الشكل القاموسي غير ØµØ§Ù„Ø - لا يمكن تØميل " -"السكريبت من المسار" +msgstr "نموذج الشكل القاموسي غير ØµØ§Ù„Ø (لا يمكن تØميل النص البرمجي من @المسار)" #: modules/gdscript/gdscript_functions.cpp msgid "Invalid instance dictionary format (invalid script at @path)" -msgstr "" -"instance dictionary format نموذج الشكل القاموسي غير ØµØ§Ù„Ø - السكريبت ÙÙŠ " -"المسار غير صالØ" +msgstr "نموذج الشكل القاموسي غير ØµØ§Ù„Ø ( النص البرمجي غير ØµØ§Ù„Ø ÙÙŠ @المسار)" #: modules/gdscript/gdscript_functions.cpp msgid "Invalid instance dictionary (invalid subclasses)" -msgstr "مجسّد القاموس غير ØµØ§Ù„Ø (أصنا٠Ùرعية غير صالØØ©)" +msgstr "نموذج القاموس غير ØµØ§Ù„Ø (أصنا٠Ùرعية غير صالØØ©)" #: modules/gdscript/gdscript_functions.cpp msgid "Object can't provide a length." -msgstr "لا يمكن للكائن Object أن ÙŠÙ…Ù†Ø Ø·ÙˆÙ„Ø§Ù‹." +msgstr "لا يمكن للكائن أن ÙŠÙ…Ù†Ø Ø·ÙˆÙ„Ø§Ù‹." #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Next Plane" msgstr "التبويب التالي" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Previous Plane" msgstr "التبويب السابق" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Plane:" -msgstr "المستوى:" +msgstr "التبويت:" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Next Floor" @@ -11357,14 +11326,12 @@ msgid "GridMap Delete Selection" msgstr "خريطة الشبكة GridMap Ù„Øذ٠المÙختار" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "GridMap Fill Selection" -msgstr "ÙƒÙÙ„ المÙØدد" +msgstr "تØديد الملئ خريطة-الشبكة" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "GridMap Paste Selection" -msgstr "ÙƒÙÙ„ المÙØدد" +msgstr "تØديد اللصق خريطة-الشبكة" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "GridMap Paint" @@ -11431,9 +11398,8 @@ msgid "Cursor Clear Rotation" msgstr "Ù…Ø³Ø ØªØ¯ÙˆÙŠØ± المؤشر" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Paste Selects" -msgstr "ÙƒÙÙ„ المÙØدد" +msgstr "تØديد اللصق" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clear Selection" @@ -11452,9 +11418,8 @@ msgid "Pick Distance:" msgstr "اختر المساÙØ©:" #: modules/gridmap/grid_map_editor_plugin.cpp -#, fuzzy msgid "Filter meshes" -msgstr "وضع المÙصÙÙŠ:" +msgstr "تنقية المجسمات" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Give a MeshLibrary resource to this GridMap to use its meshes." @@ -11561,7 +11526,7 @@ msgstr "عثر على تسلسل بت ولكن ليس العقدة ÙÙŠ المك #: modules/visual_script/visual_script.cpp msgid "Stack overflow with stack depth: " -msgstr "" +msgstr "Øدوث تجاوز للتكدس ( Stack overflow) مع عمق التكدس: " #: modules/visual_script/visual_script_editor.cpp msgid "Change Signal Arguments" @@ -11584,42 +11549,36 @@ msgid "Set Variable Type" msgstr "تØيد نوع المتغير" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Input Port" -msgstr "أض٠مدخله" +msgstr "أض٠منÙØ° أدخال" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Output Port" -msgstr "أض٠مدخله" +msgstr "أض٠منÙØ° إخراج" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Override an existing built-in function." -msgstr "إسم غير صالØØŒ يجب أن لا يتصادم مع الأسماء المبنية تلقائياً الموجودة." +msgstr "تجاوز لدالة Ù…Ùدمجة موجودة مسبقًا." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new function." -msgstr "إنشاء %s جديد" +msgstr "إنشاء دالة جديدة." #: modules/visual_script/visual_script_editor.cpp msgid "Variables:" msgstr "المتغيرات:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new variable." -msgstr "إنشاء %s جديد" +msgstr "إنشاء متغير جديد." #: modules/visual_script/visual_script_editor.cpp msgid "Signals:" msgstr "الإشارات:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new signal." -msgstr "أنشئ شكل جديد من لا شئ." +msgstr "إنشاء إشارة جديدة." #: modules/visual_script/visual_script_editor.cpp msgid "Name is not a valid identifier:" @@ -11646,9 +11605,8 @@ msgid "Add Function" msgstr "إضاÙØ© وظيÙØ© برمجية" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Delete input port" -msgstr "Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©" +msgstr "Ù…Ø³Ø Ù…Ù†ÙØ° إدخال" #: modules/visual_script/visual_script_editor.cpp msgid "Add Variable" @@ -11659,14 +11617,12 @@ msgid "Add Signal" msgstr "إضاÙØ© إشارة" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove Input Port" -msgstr "Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©" +msgstr "Øذ٠منÙØ° إدخال" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove Output Port" -msgstr "Ù…Ø³Ø Ø§Ù„Ù†Ù‚Ø·Ø©" +msgstr "Øذ٠منÙØ° إخراج" #: modules/visual_script/visual_script_editor.cpp msgid "Change Expression" @@ -11750,19 +11706,16 @@ msgid "Connect Nodes" msgstr "وصل العÙقد" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Disconnect Nodes" -msgstr "غير متصل" +msgstr "عÙقد غير متصلة" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Connect Node Data" -msgstr "صلها بالعقدة:" +msgstr "ربط بيانات العقدة" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Connect Node Sequence" -msgstr "صلها بالعقدة:" +msgstr "ربط تسلسل العقدة" #: modules/visual_script/visual_script_editor.cpp msgid "Script already has function '%s'" @@ -11773,9 +11726,8 @@ msgid "Change Input Value" msgstr "تعديل قيمة الإدخال" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Resize Comment" -msgstr "تعديل العنصر القماشي" +msgstr "تغيير Øجم التعليق" #: modules/visual_script/visual_script_editor.cpp msgid "Can't copy the function node." @@ -11807,9 +11759,8 @@ msgid "Try to only have one sequence input in selection." msgstr "Øاول أن يكون لديك تسلسل إدخال واØد من المÙختار." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create Function" -msgstr "عمل اشتراك" +msgstr "إنشاء دالة" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Function" @@ -11832,33 +11783,28 @@ msgid "Editing Signal:" msgstr "تØرير الإشارة:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Make Tool:" -msgstr "أنشئ عظام" +msgstr "عمل أداة:" #: modules/visual_script/visual_script_editor.cpp msgid "Members:" msgstr "الأعضاء:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Base Type:" -msgstr "غير نوع %s" +msgstr "تغيير اساس النوع:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Nodes..." -msgstr "إضاÙØ© %s..." +msgstr "إضاÙØ© عÙقد..." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Function..." -msgstr "Ù…Ø³Ø Ø§Ù„Ù…Ù‡Ù…Ø©" +msgstr "إضاÙØ© دالة…" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "function_name" -msgstr "الإعدادات:" +msgstr "أسم_الدالة" #: modules/visual_script/visual_script_editor.cpp msgid "Select or create a function to edit its graph." @@ -11881,19 +11827,16 @@ msgid "Cut Nodes" msgstr "قص العÙقد" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Make Function" -msgstr "Ù…Ø³Ø Ø§Ù„Ù…Ù‡Ù…Ø©" +msgstr "عمل دالة" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Refresh Graph" -msgstr "تØديث" +msgstr "تØديث الرسم البياني" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Edit Member" -msgstr "الأعضاء" +msgstr "تعديل العضو" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -11941,7 +11884,7 @@ msgstr "لم يتم إيجاد (Ù…ÙØدد المÙتغير) VariableSet ÙÙŠ ا #: modules/visual_script/visual_script_nodes.cpp msgid "Custom node has no _step() method, can't process graph." -msgstr "العقدة المخصصة لا تØتوي طريقة ()step_ ØŒ لا يمكن معالجة المخطوط." +msgstr "العقدة المخصصة لا تØتوي طريقة ()step_ ØŒ لا يمكن معالجة الشكل البياني." #: modules/visual_script/visual_script_nodes.cpp msgid "" @@ -11952,9 +11895,8 @@ msgstr "" "(خطأ)." #: modules/visual_script/visual_script_property_selector.cpp -#, fuzzy msgid "Search VisualScript" -msgstr "إخلاء الكود" +msgstr "بØØ« VisualScript" #: modules/visual_script/visual_script_property_selector.cpp msgid "Get %s" @@ -12009,11 +11951,8 @@ msgstr "" "الموضوعة سلÙاً." #: platform/android/export/export.cpp -#, fuzzy msgid "Release keystore incorrectly configured in the export preset." -msgstr "" -"Ù…ÙÙ†Ù‚Ø Ø£Ø®Ø·Ø§Ø¡ Ù…ÙØªØ§Ø Ø§Ù„Ù…ØªØ¬Ø± keystore غير Ù…Ùهيئ ÙÙŠ إعدادت المÙØرر أو ÙÙŠ الإعدادات " -"الموضوعة سلÙاً." +msgstr "تØرر مخزن المÙØ§ØªÙŠØ ØºÙŠØ± Ù…Ùهيئ بشكل صØÙŠØ ÙÙŠ إعدادت المسبقة للتصدير." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -12045,26 +11984,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 "" +"\"Degrees Of Freedom\" تكون صالØØ© Ùقط عندما يكون وضع الـ \"Xr Mode\"هو " +"\"Oculus Mobile VR\"." #: platform/android/export/export.cpp msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Hand Tracking\" تكون صالØØ© Ùقط عندما يكون وضع الـ \"Xr Mode\"هو \"Oculus " +"Mobile VR\"." #: platform/android/export/export.cpp msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." msgstr "" +"\"Focus Awareness\" تكون صالØØ© Ùقط عندما يكون وضع الـ \"Xr Mode\"هو \"Oculus " +"Mobile VR\"." #: platform/android/export/export.cpp msgid "" @@ -12213,13 +12160,12 @@ msgid "Invalid splash screen image dimensions (should be 620x300)." msgstr "أبعاد شاشة البداية غير صالØØ© (ينبغي أن تكون 620×300)." #: scene/2d/animated_sprite.cpp -#, fuzzy msgid "" "A SpriteFrames resource must be created or set in the \"Frames\" property in " "order for AnimatedSprite to display frames." msgstr "" -"ليتم إظهار الأطر (اللقطات) ÙÙŠ الAnimatedSprite (النقوش المتØركة), يجب تكوين " -"مصدر لها من نوع SpriteFrames Ùˆ ضبط خاصية الFrames (الأطر) بها." +"ليتم إظهار الإطارات ÙÙŠ الAnimatedSprite (النقوش المتØركة), يجب تكوين مصدر " +"لها من نوع SpriteFrames Ùˆ ضبط خاصية الFrames (الأطر) بها." #: scene/2d/canvas_modulate.cpp msgid "" @@ -12255,7 +12201,9 @@ msgstr "" #: scene/2d/collision_polygon_2d.cpp msgid "An empty CollisionPolygon2D has no effect on collision." -msgstr "Ù…Ùضلع تصادم ثنائي الأبعاد Ùارغ ليس له أي تأثير على التصادم." +msgstr "" +"Ù…Ùضلع تصادم ثنائي الأبعاد (CollisionPolygon2D) الÙارغ ليس له أي تأثير على " +"التصادم." #: scene/2d/collision_shape_2d.cpp msgid "" @@ -12263,32 +12211,37 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" -"يعمل Ù…Ùضلع التصادم ثنائي الأبعاد CollisionPolygon2D Ùقط كشكل تصادمي لكل العÙقد " -"المشتقة من الكائن التصادمي ثنائي الأبعاد CollisionObject2D. من Ùضلك استخدمه " -"Ùقط لكل أبناء الØيز ثنائي الأبعاد Area2DØŒ الجسم السكوني ثنائي الأبعاد " -"StaticBody2D Ùˆ الجسم الجامد ثنائي الأبعاد RigidBody2DØŒ والجسم المتØرك ثنائي " -"الأبعاد KinematicBody2D إلخ.. لكي ØªÙ…Ù†Ø ÙƒÙ„ منهم شكلاً." +"يعمل جسم-تصادم-ثنائي-البÙعد (CollisionPolygon2D) Ùقط كشكل تصادمي لكل العÙقد " +"المشتقة من الكائن التصادمي ثنائي الأبعاد (CollisionObject2D). من Ùضلك " +"استخدمه Ùقط لكل أبناء الØيز-ثنائي-البÙعد (Area2D)ØŒ الجسم-الثابت-ثنائي-البÙعد " +"(StaticBody2D) Ùˆ الجسم-الصلب-ثنائي-البÙعد (RigidBody2D)ØŒ والجسم-المتØرك-ثنائي-" +"البÙعد (KinematicBody2D) إلخ.. لكي ØªÙ…Ù†Ø ÙƒÙ„ منهم شكلاً." #: scene/2d/collision_shape_2d.cpp msgid "" "A shape must be provided for CollisionShape2D to function. Please create a " "shape resource for it!" msgstr "" -"يجب تزويد ال CollisionShape2D بإØدى الأشكال (من نوع Shape2D) لتعمل بالشكل " -"المطلوب. الرجاء تكوين Ùˆ ضبط الشكل لها اولا!" +"يجب تزويد جسم-تصادم-ثنائي-البÙعد (CollisionShape2D) بإØدى الأشكال (من نوع " +"Shape2D) لتعمل بالشكل المطلوب. الرجاء تكوين Ùˆ ضبط الشكل لها اولا!" #: scene/2d/collision_shape_2d.cpp msgid "" "Polygon-based shapes are not meant be used nor edited directly through the " "CollisionShape2D node. Please use the CollisionPolygon2D node instead." msgstr "" +"الأشكال المستندة إلى المضلع (Polygon-based shapes) لا تعني انك قادر على " +"استخدامها او تعديلها بشكل مباشر من خلال عقدة جسم-تصادم-ثنائي-البÙعد " +"(CollisionShape2D). الرجاء استخدام عقدة مضلع-تصادم-ثنائي-البÙعد " +"(CollisionPolygon2D) بدلاً من ذلك." #: scene/2d/cpu_particles_2d.cpp msgid "" "CPUParticles2D animation requires the usage of a CanvasItemMaterial with " "\"Particles Animation\" enabled." msgstr "" -"تتطلب الرسوم المتØركة CPUParticles2D استخدام CanvasItemMaterial مع تمكين " +"تتطلب الرسوم المتØركة للجسيمات-ÙˆØدة-المعالجة-المركزية-ثنائية-الأبعاد " +"(CPUParticles2D) استخدام لوØØ©-مادة-العنصر (CanvasItemMaterial) مع تÙعيل" "\"الرسوم المتØركة للجزيئات\"." #: scene/2d/light_2d.cpp @@ -12301,27 +12254,34 @@ msgstr "يجب توريد نقش بهيئة الضوء لخاصية \"النقش msgid "" "An occluder polygon must be set (or drawn) for this occluder to take effect." msgstr "" +"المÙضلع المÙغلق(occluder polygon) يجب تعينه (او رسمه) ليأخذ هذا الغَلق تأثيره." #: scene/2d/light_occluder_2d.cpp msgid "The occluder polygon for this occluder is empty. Please draw a polygon." -msgstr "" +msgstr "المÙضلع المÙغلق لهذا الغَلق Ùارغ. الرجاء رسم Ù…Ùضلع." #: scene/2d/navigation_polygon.cpp msgid "" "A NavigationPolygon resource must be set or created for this node to work. " "Please set a property or draw a polygon." msgstr "" +"يجب تعيين مصدر Ù…Ùضلع-التنقل (NavigationPolygon) أو إنشاؤه Øتى تعمل هذه " +"العقدة. ÙŠÙرجى تعيين خاصية أو رسم مضلع." #: scene/2d/navigation_polygon.cpp msgid "" "NavigationPolygonInstance must be a child or grandchild to a Navigation2D " "node. It only provides navigation data." msgstr "" +"يجب أن يكون نموذج-المضلع-المتنقل (NavigationPolygonInstance) تابعًا أو ØÙيدًا " +"لعقدة التنقل-ثنائي-الأبعاد (Navigation2D). انه Ùقط يوÙر بيانات التنقل." #: scene/2d/parallax_layer.cpp msgid "" "ParallaxLayer node only works when set as child of a ParallaxBackground node." msgstr "" +"تعمل عقدة طبقة-المنظهر (ParallaxLayer) Ùقط عند تعيينها كعقدة تابعة لعقدة " +"خلÙية-المنظر ParallaxBackground." #: scene/2d/particles_2d.cpp msgid "" @@ -12329,22 +12289,31 @@ msgid "" "Use the CPUParticles2D node instead. You can use the \"Convert to " "CPUParticles\" option for this purpose." msgstr "" +"لا يدعم برنامج تشغيل الÙيديو GLES2 الجسيمات القائمة على ÙˆØدة معالجة الرسومات " +"(GPU-based particles).\n" +"استخدم عقدة جسيمات-ÙˆØدة-المعالجة-المركزية-ثنائية-البÙعد (CPUParticles2D) بدلاً " +"من ذلك. يمكنك استخدام خيار \"التØويل إلى CPUParticles\" لهذا الغرض." #: scene/2d/particles_2d.cpp scene/3d/particles.cpp msgid "" "A material to process the particles is not assigned, so no behavior is " "imprinted." msgstr "" +"لا يوجد مادة (material) لمعالجة الجسيمات ØŒ لذلك لا يتم طبع او عمل أي سلوك." #: scene/2d/particles_2d.cpp msgid "" "Particles2D animation requires the usage of a CanvasItemMaterial with " "\"Particles Animation\" enabled." msgstr "" +"تتطلب الرسوم المتØركة للجسيمات-ثنائية-البÙعد (Particles2D) استخدام لوØØ©-مادة-" +"العنصر (CanvasItemMaterial) مع تمكين \"الرسوم المتØركة للجسيمات\"." #: scene/2d/path_2d.cpp msgid "PathFollow2D only works when set as a child of a Path2D node." msgstr "" +"لا يعمل اتباع-المسار-ثنائي-البÙعد (PathFollow2D) إلا عند جعل عقدة مسار-ثنائي-" +"البÙعد (Path2D) تابعًا له." #: scene/2d/physics_body_2d.cpp msgid "" @@ -12352,10 +12321,14 @@ msgid "" "by the physics engine when running.\n" "Change the size in children collision shapes instead." msgstr "" +"تغييرات الØجم للجسم-صلب-ثنائي-البÙعد (RigidBody2D) (ÙÙŠ أوضاع الشخصيات أو " +"الأوضاع الصلبة) سيتم تجاوزها بواسطة Ù…Øرك الÙيزياء عند التشغيل.\n" +"قم بتغيير الØجم ÙÙŠ أشكال تصادم التابعين له بدلاً من ذلك." #: scene/2d/remote_transform_2d.cpp msgid "Path property must point to a valid Node2D node to work." msgstr "" +"يجب أن تشير خاصية المسار إلى عÙقدة-ثنائية-البÙعد (Node2D) صالØØ© لكي تعمل." #: scene/2d/skeleton_2d.cpp msgid "This Bone2D chain should end at a Skeleton2D node." @@ -12366,11 +12339,15 @@ msgstr "" #: scene/2d/skeleton_2d.cpp msgid "A Bone2D only works with a Skeleton2D or another Bone2D as parent node." msgstr "" +"يعمل عظم-ثنائي-البÙعد (Bone2D) Ùقط مع هيكلية-ثنائية-البÙعد (Skeleton2D) أو " +"Bone2D آخر كعقدة رئيسية." #: scene/2d/skeleton_2d.cpp msgid "" "This bone lacks a proper REST pose. Go to the Skeleton2D node and set one." msgstr "" +"هذا العظم ÙŠÙتقر إلى وضع الراØØ© المناسب. انتقل إلى عقدة هيكلية ثنائية " +"البÙعد(Skeleton2D) وقم بتعيين واØدة." #: scene/2d/tile_map.cpp msgid "" @@ -12378,40 +12355,56 @@ msgid "" "to. Please use it as a child of Area2D, StaticBody2D, RigidBody2D, " "KinematicBody2D, etc. to give them a shape." msgstr "" +"ÙŠØتاج خريطة-البلاط (TileMap) مع تÙعيل خاصية إستخدام الأصل (Use Parent) إلى " +"ان يكون تابعًا لكائن-تصادمي-ثنائي-البÙعد (CollisionObject2D) لإعطاء الأشكال. " +"يرجى استخدامه كتابع Ù„Øيز-ثنائي-البÙعد(ÙArea2D)ØŒ جسم-ثابت-ثنائي-البÙعد " +"(StaticBody2D)ØŒ جسم-صلب-ثنائي-البÙعد (RigidBody2D)ØŒ أو جسم-متØرك-ثنائي-البÙعد " +"(KinematicBody2D)ØŒ وما إلى ذلك لمنØهم شكلاً." #: scene/2d/visibility_notifier_2d.cpp msgid "" "VisibilityEnabler2D works best when used with the edited scene root directly " "as parent." msgstr "" +"يعمل Ù…ÙÙ…ÙŽÙƒÙÙ†-الرؤية-ثنائي-البÙعد (VisibilityEnabler2D) بشكل Ø£Ùضل عند استخدامه مع " +"المشهد الرئيس الذي تم تØريره مباشرةً باعتباره الأصل." #: scene/3d/arvr_nodes.cpp msgid "ARVRCamera must have an ARVROrigin node as its parent." -msgstr "" +msgstr "يجب أن تØتوي ARVRCamera على عقدة ARVROrigin كأصل لها." #: scene/3d/arvr_nodes.cpp msgid "ARVRController must have an ARVROrigin node as its parent." -msgstr "" +msgstr "يجب أن تØتوي ARVRController على عقدة ARVROrigin كأصل لها." #: scene/3d/arvr_nodes.cpp msgid "" "The controller ID must not be 0 or this controller won't be bound to an " "actual controller." msgstr "" +"يجب ألا يكون معر٠وØدة التØكم تساوي 0 أو لن تكون ÙˆØدة التØكم هذه مقيدة بوØدة " +"تØكم Ùعلية." #: scene/3d/arvr_nodes.cpp msgid "ARVRAnchor must have an ARVROrigin node as its parent." -msgstr "" +msgstr "يجب أن ÙŠØتوي ARVRController على عقدة ARVROrigin كأصل له." #: scene/3d/arvr_nodes.cpp msgid "" "The anchor ID must not be 0 or this anchor won't be bound to an actual " "anchor." msgstr "" +"يجب ألا يكون معر٠الإرتكاز (The anchor) يساوي 0 أو لن يكون هذا الإرتكاز مقيد " +"بإرتكاز ÙÙعلي." #: scene/3d/arvr_nodes.cpp msgid "ARVROrigin requires an ARVRCamera child node." msgstr "" +"ÙŠØتاج خريطة-البلاط (TileMap) مع تÙعيل خاصية إستخدام الأصل (Use Parent) إلى " +"ان يكون تابعًا لكائن-تصادمي-ثنائي-البÙعد (CollisionObject2D) لإعطاء الأشكال. " +"يرجى استخدامه كتابع Ù„Øيز-ثنائي-البÙعد(ÙArea2D)ØŒ جسم-ثابت-ثنائي-البÙعد " +"(StaticBody2D)ØŒ جسم-صلب-ثنائي-البÙعد (RigidBody2D)ØŒ أو جسم-متØرك-ثنائي-البÙعد " +"(KinematicBody2D)ØŒ وما إلى ذلك لمنØهم شكلاً." #: scene/3d/baked_lightmap.cpp msgid "%d%%" @@ -12423,19 +12416,19 @@ msgstr "(الوقت المتبقي: %d:%02d ثانية)" #: scene/3d/baked_lightmap.cpp msgid "Plotting Meshes: " -msgstr "" +msgstr "تخطيط المجسمات: " #: scene/3d/baked_lightmap.cpp msgid "Plotting Lights:" -msgstr "" +msgstr "تخطيط الإضاءات:" #: scene/3d/baked_lightmap.cpp scene/3d/gi_probe.cpp msgid "Finishing Plot" -msgstr "" +msgstr "الانتهاء من التخطيط" #: scene/3d/baked_lightmap.cpp msgid "Lighting Meshes: " -msgstr "" +msgstr "إضاءة المجسمات: " #: scene/3d/collision_object.cpp msgid "" @@ -12443,6 +12436,8 @@ msgid "" "Consider adding a CollisionShape or CollisionPolygon as a child to define " "its shape." msgstr "" +"هذه العقدة ليس لها شكل، لذلك لا يمكن أن تصطدم أو تتÙاعل مع الكائنات الأخرى.\n" +"ضع ÙÙŠ الإعتبار إضاÙØ© شكل تصادم أو مضلع تصادم كتابع لتعري٠شكله." #: scene/3d/collision_polygon.cpp msgid "" @@ -12450,6 +12445,10 @@ msgid "" "CollisionObject derived node. Please only use it as a child of Area, " "StaticBody, RigidBody, KinematicBody, etc. to give them a shape." msgstr "" +"يعمل مضلع التصادم (CollisionPolygon) Ùقط على توÙير شكل تصادم لعقدة كائن " +"التصادم (CollisionObject) المشتقة. ÙŠÙرجى استخدامه Ùقط كتابع Ù„Øيز (Area)ØŒ جسم " +"ثابت (StaticBody)ØŒ جسم صلب (StaticBody)ØŒ أو جسم Øركي (KinematicBody)ØŒ وما " +"إلى ذلك لمنØهم شكلاً." #: scene/3d/collision_polygon.cpp msgid "An empty CollisionPolygon has no effect on collision." @@ -12461,46 +12460,58 @@ msgid "" "derived node. Please only use it as a child of Area, StaticBody, RigidBody, " "KinematicBody, etc. to give them a shape." msgstr "" +"يعمل شكل التصادم (CollisionPolygon) Ùقط على توÙير شكل تصادم لعقدة كائن " +"التصادم (CollisionObject) المشتقة. ÙŠÙرجى استخدامه Ùقط كتابع Ù„Øيز (Area)ØŒ جسم " +"ثابت (StaticBody)ØŒ جسم صلب (StaticBody)ØŒ أو جسم Øركي (KinematicBody)ØŒ وما " +"إلى ذلك لمنØهم شكلاً." #: scene/3d/collision_shape.cpp -#, fuzzy msgid "" "A shape must be provided for CollisionShape to function. Please create a " "shape resource for it." msgstr "" -"يجب تزويد ال CollisionShape2D بإØدى الأشكال (من نوع Shape2D) لتعمل بالشكل " -"المطلوب. الرجاء تكوين Ùˆ ضبط الشكل لها اولا!" +"يجب توÙير شكل لـ CollisionShape2D بإØدى الأشكال (من نوع Shape2D) لتعمل " +"بالشكل المطلوب. الرجاء تكوين Ùˆ ضبط الشكل لها." #: scene/3d/collision_shape.cpp msgid "" "Plane shapes don't work well and will be removed in future versions. Please " "don't use them." msgstr "" +"لا تعمل أشكال التبويت (Plane shapes) بشكل جيد وسيتم إزالتها ÙÙŠ الإصدارات " +"المستقبلية. من Ùضلك لا تستخدمها." #: scene/3d/collision_shape.cpp msgid "" "ConcavePolygonShape doesn't support RigidBody in another mode than static." msgstr "" +"الشكل المضلع المÙقعر (ConcavePolygonShape) لا يدعم الجسم الصلب (RigidBody) ÙÙŠ " +"أي وضع غير الوضع الثابت." #: scene/3d/cpu_particles.cpp msgid "Nothing is visible because no mesh has been assigned." -msgstr "" +msgstr "لا شيء مرئي لأنه لم يتم تعيين أي مجسم." #: scene/3d/cpu_particles.cpp msgid "" "CPUParticles animation requires the usage of a SpatialMaterial whose " "Billboard Mode is set to \"Particle Billboard\"." msgstr "" +"تتطلب الرسوم المتØركة لجسيمات ÙˆØدة المعالجة المركزية( CPUParticles) استخدام " +"مادة مكانية (SpatialMaterial) التي تم ضبط وضع اللوØØ© (Billboard Mode) الخاص " +"بها على \"لوØØ© الجسيمات\"." #: scene/3d/gi_probe.cpp msgid "Plotting Meshes" -msgstr "" +msgstr "تخطيط المجسمات" #: scene/3d/gi_probe.cpp msgid "" "GIProbes are not supported by the GLES2 video driver.\n" "Use a BakedLightmap instead." msgstr "" +"GIProbes لا يدعم برنامج تشغيل الÙيديو GLES2.\n" +"استخدم BakedLightmap بدلاً من ذلك." #: scene/3d/light.cpp msgid "A SpotLight with an angle wider than 90 degrees cannot cast shadows." @@ -12509,12 +12520,15 @@ msgstr "بقعة الضوء بزاوية أكبر من 90 درجة لا يمكن #: scene/3d/navigation_mesh.cpp msgid "A NavigationMesh resource must be set or created for this node to work." msgstr "" +"يجب تعيين مصدر مجسم-التنقل (NavigationMesh) أو إنشاؤه Øتى تعمل هذه العقدة." #: scene/3d/navigation_mesh.cpp msgid "" "NavigationMeshInstance must be a child or grandchild to a Navigation node. " "It only provides navigation data." msgstr "" +"يجب أن يكون نموذج-مجسم-التنقل (NavigationMeshInstance) تابعًا أو ØÙيدًا لعقدة " +"التنقل (Navigation node). انه يوÙر Ùقط بيانات التنقل." #: scene/3d/particles.cpp msgid "" @@ -12522,17 +12536,23 @@ msgid "" "Use the CPUParticles node instead. You can use the \"Convert to CPUParticles" "\" option for this purpose." msgstr "" +"الجسيمات القائمة على ÙˆØدة معالجة الرسومات (GPU-based particles) لا تدعم " +"برنامج تشغيل الÙيديو GLES2 .\n" +"استخدم عقدة CPUParticles بدلاً من ذلك. يمكنك استخدام خيار \"التØويل إلى " +"CPUParticles\" لهذا الغرض." #: scene/3d/particles.cpp msgid "" "Nothing is visible because meshes have not been assigned to draw passes." -msgstr "" +msgstr "لا يوجد شيء مرئي لأن المجسمات لم يتم تعيين لها رسم التمريرات." #: scene/3d/particles.cpp msgid "" "Particles animation requires the usage of a SpatialMaterial whose Billboard " "Mode is set to \"Particle Billboard\"." msgstr "" +"تتطلب الرسوم المتØركة للجسيمات استخدام مادة مكانية (SpatialMaterial) التي تم " +"ضبط وضع اللوØØ© (Billboard Mode) الخاص بها على \"لوØØ© الجسيمات\"." #: scene/3d/path.cpp msgid "PathFollow only works when set as a child of a Path node." @@ -12543,6 +12563,8 @@ msgid "" "PathFollow's ROTATION_ORIENTED requires \"Up Vector\" to be enabled in its " "parent Path's Curve resource." msgstr "" +"يتطلب ROTATION_ORIENTED الخاص بأتباع-المسار (PathFollow) تمكين \"Up Vector\" " +"ÙÙŠ مصدر منØنى مسار الأصل (Parent Path's)." #: scene/3d/physics_body.cpp msgid "" @@ -12550,16 +12572,21 @@ msgid "" "by the physics engine when running.\n" "Change the size in children collision shapes instead." msgstr "" +"تغير Øجم الجسم الصلب (RigidBody) (ÙÙŠ الشخصية أو الأوضاع الصلبة) سيتم تجاوزها " +"بواسطة Ù…Øرك الÙيزياء عند التشغيل.\n" +"قم بتغيير الØجم ÙÙŠ أشكال تصادم الأتباع (Children) بدلاً من ذلك." #: scene/3d/remote_transform.cpp msgid "" "The \"Remote Path\" property must point to a valid Spatial or Spatial-" "derived node to work." msgstr "" +"يجب أن تشير خاصية \"المسار البعيد\" إلى عقدة مكانية أو مشتقة مكانية صالØØ© " +"لكي تعمل." #: scene/3d/soft_body.cpp msgid "This body will be ignored until you set a mesh." -msgstr "سيتم تجاهل هذا الجسم Øتى تضع تØدد سطØاً mesh." +msgstr "سيتم تجاهل هذا الجسم Øتى تضع تØدد له مجسمًا." #: scene/3d/soft_body.cpp msgid "" @@ -12567,42 +12594,52 @@ msgid "" "running.\n" "Change the size in children collision shapes instead." msgstr "" +"تغير Øجم الجسم الناعم (SoftBody) سيتم تجاوزها بواسطة Ù…Øرك الÙيزياء عند " +"التشغيل.\n" +"قم بتغيير الØجم ÙÙŠ أشكال تصادم الأتباع (Children) بدلاً من ذلك." #: scene/3d/sprite_3d.cpp -#, fuzzy msgid "" "A SpriteFrames resource must be created or set in the \"Frames\" property in " "order for AnimatedSprite3D to display frames." msgstr "" -"ليتم إظهار الأطر (اللقطات) ÙÙŠ الAnimatedSprite (النقوش المتØركة), يجب تكوين " -"مصدر لها من نوع SpriteFrames Ùˆ ضبط خاصية الFrames (الأطر) بها." +"يجب إنشاء مصدر إطارات الرسم (SpriteFrames) أو تعيينه ÙÙŠ خاصية \"الإطارات\" " +"Øتى يتمكن الرسوم المتØركة للرسم ثلاثي الÙعد (AnimatedSprite3D) من عرض " +"الإطارات." #: scene/3d/vehicle_body.cpp msgid "" "VehicleWheel serves to provide a wheel system to a VehicleBody. Please use " "it as a child of a VehicleBody." msgstr "" +"تعمل عجلة المركبة (VehicleWheel) على توÙير نظام عجلات لجسم " +"المركبة(VehicleBody). يرجى استخدامه كتابع لجسم المركبة." #: scene/3d/world_environment.cpp msgid "" "WorldEnvironment requires its \"Environment\" property to contain an " "Environment to have a visible effect." msgstr "" +"تتطلب بيئة-العالم (WorldEnvironment) خاصية\"البيئة\" الخاصة بها لاØتواء بيئة " +"ليكون لها تأثير مرئي." #: scene/3d/world_environment.cpp msgid "" "Only one WorldEnvironment is allowed per scene (or set of instanced scenes)." -msgstr "" +msgstr "ÙŠÙØ³Ù…Ø Ùقط ببيئة عالمية واØدة لكل مشهد (أو مجموعة من المشاهد المتواÙقة)." #: scene/3d/world_environment.cpp msgid "" "This WorldEnvironment is ignored. Either add a Camera (for 3D scenes) or set " "this environment's Background Mode to Canvas (for 2D scenes)." msgstr "" +"يتم تجاهل هذه البيئة العالمية. إما أن تضي٠كاميرا (للمشاهد ثلاثية البÙعد) أو " +"اضبط وضع الخلÙية لهذه البيئة على لوØØ© (Canvas) (للمشاهد ثنائية البÙعد)." #: scene/animation/animation_blend_tree.cpp msgid "On BlendTree node '%s', animation not found: '%s'" msgstr "" +"ÙÙŠ عقدة خليط-الشجرة (BlendTree) '%s'ØŒ لم يتم العثور على الرسوم المتØركة:'%s '" #: scene/animation/animation_blend_tree.cpp msgid "Animation not found: '%s'" @@ -12679,12 +12716,18 @@ msgid "" "children placement behavior.\n" "If you don't intend to add a script, use a plain Control node instead." msgstr "" +"لا تخدم الØاوية ÙÙŠ Øد ذاتها أي غرض ما لم يقم النص البرمجي بتكوين سلوك وضع " +"الأتباع الخاص به .\n" +"إذا كنت لا تنوي إضاÙØ© نص برمجي ØŒ Ùاستخدم عقدة تØكم عادية بدلاً من ذلك." #: scene/gui/control.cpp 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 "" +"لن يتم عرض أداة Ø§Ù„ØªÙ„Ù…ÙŠØ Ø£Ø«Ù†Ø§Ø¡ تعيين عامل تصÙية الÙأره الخاص بعنصر التØكم, تم " +"وضعه على \"تجاهل\". Ù„ØÙ„ هذه المشكلة ØŒ اضبط تصÙية الÙأره على \"إيقاÙ\" أو " +"\"تمرير\"." #: scene/gui/dialogs.cpp msgid "Alert!" @@ -12700,10 +12743,13 @@ msgid "" "functions. Making them visible for editing is fine, but they will hide upon " "running." msgstr "" +"ستختÙÙŠ النواÙØ° المنبثقة اÙتراضيًا ما لم تقم باستدعاء popup() أو أي من وظائ٠" +"popup(). من الجيد جعلها مرئية للتØرير ØŒ لكنها ستختÙÙŠ عند التشغيل." #: scene/gui/range.cpp msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0." msgstr "" +"إذا تم تÙعيل الـ\"Exp Edit\" يجب على ان يكون \"Min Value\" اعلى من صÙر." #: scene/gui/scroll_container.cpp msgid "" @@ -12711,6 +12757,9 @@ msgid "" "Use a container as child (VBox, HBox, etc.), or a Control and set the custom " "minimum size manually." msgstr "" +"تم تصميم ScrollContainer للعمل مع عنصر تØكم تابع واØد.\n" +"استخدم Øاوية كتابع (VBox ØŒ HBox ØŒ إلخ) ØŒ أو عنصر تØكم واضبط الØد الأدنى " +"المخصص للØجم يدويًا." #: scene/gui/tree.cpp msgid "(Other)" @@ -12721,6 +12770,8 @@ msgid "" "Default Environment as specified in Project Settings (Rendering -> " "Environment -> Default Environment) could not be loaded." msgstr "" +"تعذر تØميل البيئة الاÙتراضية كما هو Ù…Øدد ÙÙŠ إعدادات المشروع (التقديم -> " +"البيئة -> البيئة الاÙتراضية)." #: scene/main/viewport.cpp msgid "" @@ -12729,6 +12780,9 @@ msgid "" "obtain a size. Otherwise, make it a RenderTarget and assign its internal " "texture to some node for display." msgstr "" +"لم يتم تعيين منÙØ° العرض هذا كهد٠عرض. إذا كنت تنوي عرض Ù…Øتوياته مباشرة على " +"الشاشة ØŒ اجعله تابعًا لعنصر تØكم Øتى يتمكن من الØصول على الØجم. خلا٠ذلك ØŒ " +"اجعلها RenderTarget وقم بتعيين نسيجها الداخلي لبعض العقد لعرضها." #: scene/main/viewport.cpp msgid "Viewport size must be greater than 0 to render anything." diff --git a/editor/translations/bg.po b/editor/translations/bg.po index b0378d612c..c327d96e57 100644 --- a/editor/translations/bg.po +++ b/editor/translations/bg.po @@ -1097,6 +1097,9 @@ msgstr "ОÑнователи на проекта" msgid "Lead Developer" msgstr "Главен разработчик" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Ръководител на проекта " @@ -1118,6 +1121,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9643,6 +9654,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Управление на проектите" diff --git a/editor/translations/bn.po b/editor/translations/bn.po index 5fdcfb385b..dd713b6b81 100644 --- a/editor/translations/bn.po +++ b/editor/translations/bn.po @@ -1193,6 +1193,9 @@ msgstr "পà§à¦°à¦œà§‡à¦•à§à¦Ÿ ফাউনà§à¦¡à¦¾à¦°" msgid "Lead Developer" msgstr "মূল ডেà¦à§‡à¦²à¦ªà¦¾à¦°" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp #, fuzzy msgid "Project Manager " @@ -1215,6 +1218,16 @@ msgid "Gold Sponsors" msgstr "গোলà§à¦¡ সà§à¦ªà¦¨à¦¸à¦°" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "সিলà¦à¦¾à¦° ডোনার" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "বà§à¦°à§‹à¦žà§à¦œ ডোনার" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "মিনি সà§à¦ªà¦¨à¦¸à¦°" @@ -10518,6 +10531,7 @@ msgstr "" "বিদà§à¦¯à¦®à¦¾à¦¨ Godot পà§à¦°à¦œà§‡à¦•à§à¦Ÿà§‡à¦° খোà¦à¦œà§‡ আপনি %s ফোলà§à¦¡à¦¾à¦°à¦¸à¦®à§‚হ সà§à¦•à§à¦¯à¦¾à¦¨ করতে যাচà§à¦›à§‡à¦¨à¥¤ আপনি কি " "সà§à¦¨à¦¿à¦¶à§à¦šà¦¿à¦¤?" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "পà§à¦°à¦œà§‡à¦•à§à¦Ÿ মà§à¦¯à¦¾à¦¨à§‡à¦œà¦¾à¦°" diff --git a/editor/translations/ca.po b/editor/translations/ca.po index 359aea8184..feb0f8fea4 100644 --- a/editor/translations/ca.po +++ b/editor/translations/ca.po @@ -1127,6 +1127,9 @@ msgstr "Fundadors del Projecte" msgid "Lead Developer" msgstr "Desenvolupador Principal" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Gestor del Projecte " @@ -1148,6 +1151,16 @@ msgid "Gold Sponsors" msgstr "Patrocinadors Gold" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Donants Silver" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Donants Bronze" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Patrocinadors" @@ -10136,6 +10149,7 @@ msgstr "" "existents?\n" "Això pot trigar una estona." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Gestor del Projecte" diff --git a/editor/translations/cs.po b/editor/translations/cs.po index 0d2ae15065..f6bb57006a 100644 --- a/editor/translations/cs.po +++ b/editor/translations/cs.po @@ -25,8 +25,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-11 14:04+0000\n" -"Last-Translator: Daniel KřÞ <Daniel.kriz@protonmail.com>\n" +"PO-Revision-Date: 2020-08-16 03:50+0000\n" +"Last-Translator: ZbynÄ›k <zbynek.fiala@gmail.com>\n" "Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/" "cs/>\n" "Language: cs\n" @@ -1133,6 +1133,9 @@ msgstr "Zakladatelé projektu" msgid "Lead Developer" msgstr "Vedoucà vývojář" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Správce projektu " @@ -1154,6 +1157,16 @@ msgid "Gold Sponsors" msgstr "Zlatà sponzoÅ™i" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "StÅ™Ãbrnà dárci" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronzovà dárci" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Malà sponzoÅ™i" @@ -1622,7 +1635,7 @@ msgstr "Editor skriptů" #: editor/editor_feature_profile.cpp msgid "Asset Library" -msgstr "OtevÅ™Ãt knihovnu assetů" +msgstr "Knihovna zdrojů (AssetLib)" #: editor/editor_feature_profile.cpp msgid "Scene Tree Editing" @@ -9872,6 +9885,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Správce projektů" diff --git a/editor/translations/da.po b/editor/translations/da.po index da54615917..6925853253 100644 --- a/editor/translations/da.po +++ b/editor/translations/da.po @@ -1168,6 +1168,9 @@ msgstr "Projekt grundlæggere" msgid "Lead Developer" msgstr "Ledende Udvikler" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projektleder " @@ -1189,6 +1192,16 @@ msgid "Gold Sponsors" msgstr "Guld Sponsorer" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Sølv Donorer" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronze Donorer" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsorer" @@ -10109,9 +10122,10 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" -msgstr "Projektleder" +msgstr "Projekt Manager" #: editor/project_manager.cpp #, fuzzy diff --git a/editor/translations/de.po b/editor/translations/de.po index 081dfb8e4f..3d9af3cdd4 100644 --- a/editor/translations/de.po +++ b/editor/translations/de.po @@ -55,12 +55,15 @@ # Günther Bohn <ciscouser@gmx.de>, 2020. # Tom Wor <mail@tomwor.com>, 2020. # Bjarne Hiller <bjarne.hiller@gmail.com>, 2020. +# Dirk Federmann <weblategodot@dirkfedermann.de>, 2020. +# Helmut Hirtes <helmut.h@gmx.de>, 2020. +# Michal695 <michalek.jedrzejak@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-05 16:58+0000\n" -"Last-Translator: Bjarne Hiller <bjarne.hiller@gmail.com>\n" +"PO-Revision-Date: 2020-08-28 13:09+0000\n" +"Last-Translator: Michal695 <michalek.jedrzejak@gmail.com>\n" "Language-Team: German <https://hosted.weblate.org/projects/godot-engine/" "godot/de/>\n" "Language: de\n" @@ -68,7 +71,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.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -77,13 +80,13 @@ msgstr "Ungültiger Argument-Typ in convert(), TYPE_*-Konstanten benötigt." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "Zeichenkette der Länge 1 erwartet (exakt ein Symbol)." +msgstr "Zeichenkette der Länge 1 erwartet (exakt ein Zeichen)." #: 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 "Nicht genügend Bytes zum Dekodieren oder ungültiges Format." +msgstr "Nicht genügend Bytes zur Dekodierung oder ungültiges Format." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" @@ -1173,9 +1176,12 @@ msgstr "Projektgründer" msgid "Lead Developer" msgstr "Hauptentwickler" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Projektverwaltung " +msgstr "Projektleiter " #: editor/editor_about.cpp msgid "Developers" @@ -1194,6 +1200,16 @@ msgid "Gold Sponsors" msgstr "Gold-Sponsoren" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Silber-Unterstützer" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronze-Unterstützer" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini-Sponsoren" @@ -1660,11 +1676,11 @@ msgstr "3D-Editor" #: editor/editor_feature_profile.cpp msgid "Script Editor" -msgstr "Skripteditor" +msgstr "Skript Editor" #: editor/editor_feature_profile.cpp msgid "Asset Library" -msgstr "Nutzerinhaltesammlung" +msgstr "Bestandsbibliothek" #: editor/editor_feature_profile.cpp msgid "Scene Tree Editing" @@ -3011,7 +3027,7 @@ msgstr "Projekt abspielen." #: editor/editor_node.cpp msgid "Play" -msgstr "Starten" +msgstr "Abspielen" #: editor/editor_node.cpp msgid "Pause the scene execution for debugging." @@ -3031,7 +3047,7 @@ msgstr "Spiele die bearbeitete Szene." #: editor/editor_node.cpp msgid "Play Scene" -msgstr "Szene starten" +msgstr "Szene abspielen" #: editor/editor_node.cpp msgid "Play custom scene" @@ -3039,7 +3055,7 @@ msgstr "Spiele angepasste Szene" #: editor/editor_node.cpp msgid "Play Custom Scene" -msgstr "Spiele angepasste Szene" +msgstr "Angepasste Szene abspielen" #: editor/editor_node.cpp msgid "Changing the video driver requires restarting the editor." @@ -3256,7 +3272,7 @@ msgstr "Gesamt" #: editor/editor_profiler.cpp msgid "Self" -msgstr "Eigenanteil" +msgstr "Selbst" #: editor/editor_profiler.cpp msgid "Frame #:" @@ -5695,7 +5711,7 @@ msgstr "Pose kopieren" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Pose" -msgstr "Pose zurücksetzen" +msgstr "Pose/Stellung löschen" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Multiply grid step by 2" @@ -6833,7 +6849,7 @@ msgstr "Schiebe hoch" #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Down" -msgstr "Schiebe herunter" +msgstr "Schiebe runter" #: editor/plugins/script_editor_plugin.cpp msgid "Next script" @@ -6878,7 +6894,7 @@ msgstr "Vorwärts im Verlauf" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Theme" -msgstr "Theme" +msgstr "Designvorlagen (Thema)" #: editor/plugins/script_editor_plugin.cpp msgid "Import Theme..." @@ -7110,7 +7126,7 @@ msgstr "Symbol vervollständigen" #: editor/plugins/script_text_editor.cpp msgid "Evaluate Selection" -msgstr "Auswahl auswerten" +msgstr "Springe zum vorigen Haltepunkt" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" @@ -9398,9 +9414,9 @@ msgid "" "Returns falloff based on the dot product of surface normal and view " "direction of camera (pass associated inputs to it)." msgstr "" -"Gibt den Fresnelabfall abgeleitet aus dem Skalarprodukt aus " -"Oberflächennormalenvektor und Kamerablickrichtung zurück (zugeordnete " -"Eingänge müssen übergeben werden)." +"Gibt den Abfall basierend auf dem Punktprodukt der Oberflächennormalen und " +"der Blickrichtung der Kamera zurück (übergeben Sie die zugehörigen Eingaben " +"an diese)." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" @@ -9972,6 +9988,7 @@ msgstr "" "Sollen wirklich %s Ordner nach Godot-Projekten durchsucht werden?\n" "Dies kann eine Weile dauern." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Projektverwaltung" @@ -10323,7 +10340,7 @@ msgstr "Umleitungen nach Lokalisierung:" #: editor/project_settings_editor.cpp msgid "Locale" -msgstr "Lokalisierung" +msgstr "Gebietsschema" #: editor/project_settings_editor.cpp msgid "Locales Filter" @@ -10756,7 +10773,7 @@ msgstr "Unter-Ressourcen" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" -msgstr "Leere Vererbung" +msgstr "Löse Vererbung" #: editor/scene_tree_dock.cpp msgid "Editable Children" @@ -10845,7 +10862,7 @@ msgstr "Lokal" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance? (No Undo!)" -msgstr "Vererbung wirklich leeren? (Lässt sich nicht rückgängig machen!)" +msgstr "Vererbung wirklich lösen? (Lässt sich nicht rückgängig machen!)" #: editor/scene_tree_editor.cpp msgid "Toggle Visible" @@ -11926,7 +11943,7 @@ msgstr "" #: modules/visual_script/visual_script_editor.cpp msgid "Delete Selected" -msgstr "Ausgewähltes löschen" +msgstr "Auswahl löschen" #: modules/visual_script/visual_script_editor.cpp msgid "Find Node Type" @@ -11942,7 +11959,7 @@ msgstr "Nodes trennen" #: modules/visual_script/visual_script_editor.cpp msgid "Make Function" -msgstr "Funktion bauen" +msgstr "Funktion erstellen" #: modules/visual_script/visual_script_editor.cpp msgid "Refresh Graph" diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot index 87dca17afd..e544f254cd 100644 --- a/editor/translations/editor.pot +++ b/editor/translations/editor.pot @@ -1080,6 +1080,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1101,6 +1104,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9461,6 +9472,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/el.po b/editor/translations/el.po index 7c2a202767..34ca85d1bd 100644 --- a/editor/translations/el.po +++ b/editor/translations/el.po @@ -1126,6 +1126,9 @@ msgstr "ΙδÏÏ…Ï„ÎÏ‚ του ÎÏγου" msgid "Lead Developer" msgstr "Επικεφαλής Ï€ÏογÏαμματιστής" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "ΔιαχειÏιστής ÎÏγων " @@ -1147,6 +1150,16 @@ msgid "Gold Sponsors" msgstr "ΧÏυσοί ΧοÏυγοί" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "ΑÏγυÏοί ΔωÏητÎÏ‚" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Χάλκινοι ΔωÏητÎÏ‚" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "ΜικÏοί ΧοÏηγοί" @@ -9924,6 +9937,7 @@ msgstr "" "ΘÎλετε να σαÏώσετε %s φακÎλους για υπαÏκτά ÎÏγα Godot;\n" "Αυτό μποÏεί να πάÏει κάποια ÏŽÏα." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "ΔιαχειÏιστής" diff --git a/editor/translations/eo.po b/editor/translations/eo.po index e740ea7d7a..8595625d56 100644 --- a/editor/translations/eo.po +++ b/editor/translations/eo.po @@ -1119,6 +1119,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1140,6 +1143,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9610,6 +9621,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/es.po b/editor/translations/es.po index 172ce58604..9092ba4566 100644 --- a/editor/translations/es.po +++ b/editor/translations/es.po @@ -1172,9 +1172,12 @@ msgstr "Fundadores del Proyecto" msgid "Lead Developer" msgstr "Desarrollador Principal" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Administrador del Proyecto " +msgstr "Gestor del Proyecto " #: editor/editor_about.cpp msgid "Developers" @@ -1193,6 +1196,16 @@ msgid "Gold Sponsors" msgstr "Patrocinadores Oro" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Donantes Plata" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Donantes Bronce" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Patrocinadores" @@ -9965,6 +9978,7 @@ msgstr "" "existentes?\n" "Esto puede tardar un poco." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Administrador de Proyectos" diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po index f2c72ce1be..d9255df906 100644 --- a/editor/translations/es_AR.po +++ b/editor/translations/es_AR.po @@ -1133,6 +1133,9 @@ msgstr "Fundadores del Proyecto" msgid "Lead Developer" msgstr "Desarrollador Principal" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Gestor de Proyectos " @@ -1154,6 +1157,16 @@ msgid "Gold Sponsors" msgstr "Sponsor Oro" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Donantes Plata" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Donantes Bronce" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsors" @@ -9916,6 +9929,7 @@ msgstr "" "existentes?\n" "PodrÃa demorar un rato." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Gestor de Proyectos" diff --git a/editor/translations/et.po b/editor/translations/et.po index 504de558d5..d3e7c9e930 100644 --- a/editor/translations/et.po +++ b/editor/translations/et.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2020-08-11 14:04+0000\n" +"PO-Revision-Date: 2020-09-01 10:38+0000\n" "Last-Translator: StReef <streef.gtx@gmail.com>\n" "Language-Team: Estonian <https://hosted.weblate.org/projects/godot-engine/" "godot/et/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -799,7 +799,7 @@ msgstr "" #: editor/connections_dialog.cpp msgid "Advanced" -msgstr "" +msgstr "Täpsem" #: editor/connections_dialog.cpp msgid "Deferred" @@ -912,23 +912,23 @@ msgstr "" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp msgid "Favorites:" -msgstr "" +msgstr "Lemmikud:" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp msgid "Recent:" -msgstr "" +msgstr "Hiljutised:" #: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp #: editor/property_selector.cpp editor/quick_open.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" -msgstr "" +msgstr "Otsi:" #: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp #: editor/property_selector.cpp editor/quick_open.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" -msgstr "" +msgstr "Vasted:" #: editor/create_dialog.cpp editor/editor_plugin_settings.cpp #: editor/plugin_config_dialog.cpp @@ -936,7 +936,7 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Description:" -msgstr "" +msgstr "Kirjeldus:" #: editor/dependency_editor.cpp msgid "Search Replacement For:" @@ -1059,7 +1059,7 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp #: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" -msgstr "" +msgstr "Kustuta" #: editor/dependency_editor.cpp msgid "Owns" @@ -1079,7 +1079,7 @@ msgstr "" #: editor/editor_about.cpp msgid "Thanks from the Godot community!" -msgstr "Tänu Godot kogukonnale!" +msgstr "Suur tänu Godot kogukonnalt!" #: editor/editor_about.cpp msgid "Godot Engine contributors" @@ -1093,6 +1093,9 @@ msgstr "Projekti asutajad" msgid "Lead Developer" msgstr "Juhtiv arendaja" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projekti juht " @@ -1114,6 +1117,16 @@ msgid "Gold Sponsors" msgstr "Kuldsponsorid" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Hõbennetajad" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Pronksannetajad" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Väikesponsorid" @@ -1148,14 +1161,18 @@ msgid "" "is an exhaustive list of all such third-party components with their " "respective copyright statements and license terms." msgstr "" +"Godot mängumootor tugineb mitmetele kolmandate osapoolte tasuta ja avatud " +"lähtekoodiga teekidele, mis kõik on kooskõlas MIT-litsentsi tingimustega. " +"Järgnev on kõigi selliste kolmandate osapoolte komponentide täielik loetelu " +"koos vastavate autoriõiguste avalduste ja litsentsitingimustega." #: editor/editor_about.cpp msgid "All Components" -msgstr "" +msgstr "Kõik komponendid" #: editor/editor_about.cpp msgid "Components" -msgstr "" +msgstr "Komponendid" #: editor/editor_about.cpp msgid "Licenses" @@ -1204,7 +1221,7 @@ msgstr "" #: editor/editor_audio_buses.cpp msgid "Speakers" -msgstr "" +msgstr "Heliväljundi" #: editor/editor_audio_buses.cpp msgid "Add Effect" @@ -1269,7 +1286,7 @@ msgstr "" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Duplicate" -msgstr "" +msgstr "Duplikeeri" #: editor/editor_audio_buses.cpp msgid "Reset Volume" @@ -2287,15 +2304,15 @@ msgstr "" #: editor/editor_node.cpp msgid "Quick Open..." -msgstr "" +msgstr "Ava kiiresti..." #: editor/editor_node.cpp msgid "Quick Open Scene..." -msgstr "" +msgstr "Ava kiiresti stseen..." #: editor/editor_node.cpp msgid "Quick Open Script..." -msgstr "" +msgstr "Ava kiiresti skript..." #: editor/editor_node.cpp msgid "Save & Close" @@ -2423,22 +2440,28 @@ msgstr "" #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "" +msgstr "Lisa-skripti ei olnud võimalik laadida teelt: '%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." msgstr "" +"Lisa-skripti ei olnud võimalik laadida teelt: '%s'. Tundub, et koodis on " +"viga, palun kontrolli süntaksi." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." msgstr "" +"Lisa-skripti ei olnud võimalik laadida teelt: '%s'. Baastüüp ei ole " +"EditorPlugin." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." msgstr "" +"Lisa-skripti ei olnud võimalik laadida teelt: '%s'. Skript ei ole tööriista " +"režiimis." #: editor/editor_node.cpp msgid "" @@ -2609,7 +2632,7 @@ msgstr "Salvesta kõik stseenid" #: editor/editor_node.cpp msgid "Convert To..." -msgstr "" +msgstr "Teisenda..." #: editor/editor_node.cpp msgid "MeshLibrary..." @@ -2827,7 +2850,7 @@ msgstr "Teavita veast" #: editor/editor_node.cpp msgid "Send Docs Feedback" -msgstr "Saada dokumentatsioonide tagasisede" +msgstr "Saada dokumentatsioonide tagasiside" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" @@ -2971,7 +2994,7 @@ msgstr "" #: editor/editor_node.cpp msgid "Load Errors" -msgstr "" +msgstr "Laadimisvead" #: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp msgid "Select" @@ -3027,36 +3050,36 @@ msgstr "" #: editor/editor_plugin_settings.cpp msgid "Installed Plugins:" -msgstr "" +msgstr "Paigaldatud pistikprogrammid:" #: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp msgid "Update" -msgstr "" +msgstr "Uuenda" #: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Version:" -msgstr "" +msgstr "Versioon:" #: editor/editor_plugin_settings.cpp editor/plugin_config_dialog.cpp msgid "Author:" -msgstr "" +msgstr "Autor:" #: editor/editor_plugin_settings.cpp msgid "Status:" -msgstr "" +msgstr "Olek:" #: editor/editor_plugin_settings.cpp msgid "Edit:" -msgstr "" +msgstr "Muuda:" #: editor/editor_profiler.cpp msgid "Measure:" -msgstr "" +msgstr "Mõõda:" #: editor/editor_profiler.cpp msgid "Frame Time (sec)" -msgstr "" +msgstr "Kaadri aeg (sek)" #: editor/editor_profiler.cpp msgid "Average Time (sec)" @@ -3064,7 +3087,7 @@ msgstr "" #: editor/editor_profiler.cpp msgid "Frame %" -msgstr "" +msgstr "Kaadri %" #: editor/editor_profiler.cpp msgid "Physics Frame %" @@ -3080,15 +3103,15 @@ msgstr "" #: editor/editor_profiler.cpp msgid "Frame #:" -msgstr "" +msgstr "Kaader nr:" #: editor/editor_profiler.cpp msgid "Time" -msgstr "" +msgstr "Aeg" #: editor/editor_profiler.cpp msgid "Calls" -msgstr "" +msgstr "Kutsungid" #: editor/editor_properties.cpp msgid "Edit Text:" @@ -3140,15 +3163,15 @@ msgstr "" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "Pick a Viewport" -msgstr "" +msgstr "Vali vaateaken" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "New Script" -msgstr "" +msgstr "Uus skript" #: editor/editor_properties.cpp editor/scene_tree_dock.cpp msgid "Extend Script" -msgstr "" +msgstr "Laienda skripti" #: editor/editor_properties.cpp editor/property_editor.cpp msgid "New %s" @@ -3199,7 +3222,7 @@ msgstr "" #: editor/editor_properties_array_dict.cpp msgid "New Value:" -msgstr "" +msgstr "Uus väärtus:" #: editor/editor_properties_array_dict.cpp msgid "Add Key/Value Pair" @@ -3428,7 +3451,7 @@ msgstr "" #: editor/export_template_manager.cpp msgid "Current Version:" -msgstr "" +msgstr "Praegune versioon:" #: editor/export_template_manager.cpp msgid "Installed Versions:" @@ -3540,7 +3563,7 @@ msgstr "" #: editor/filesystem_dock.cpp msgid "Add to Favorites" -msgstr "" +msgstr "Lisa lemmikutesse" #: editor/filesystem_dock.cpp msgid "Remove from Favorites" @@ -3548,45 +3571,45 @@ msgstr "" #: editor/filesystem_dock.cpp msgid "Edit Dependencies..." -msgstr "" +msgstr "Redigeeri sõltuvusi..." #: editor/filesystem_dock.cpp msgid "View Owners..." -msgstr "" +msgstr "Kuva omanikud..." #: editor/filesystem_dock.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Rename..." -msgstr "" +msgstr "Muuda nime..." #: editor/filesystem_dock.cpp msgid "Duplicate..." -msgstr "" +msgstr "Duplikeeri..." #: editor/filesystem_dock.cpp msgid "Move To..." -msgstr "" +msgstr "Teisalda..." #: editor/filesystem_dock.cpp msgid "New Scene..." -msgstr "" +msgstr "Uus stseen..." #: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp msgid "New Script..." -msgstr "" +msgstr "Uus skript..." #: editor/filesystem_dock.cpp msgid "New Resource..." -msgstr "" +msgstr "Uus ressurss..." #: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp #: editor/script_editor_debugger.cpp msgid "Expand All" -msgstr "" +msgstr "Laienda kõik" #: editor/filesystem_dock.cpp editor/plugins/visual_shader_editor_plugin.cpp #: editor/script_editor_debugger.cpp msgid "Collapse All" -msgstr "" +msgstr "Ahenda kõik" #: editor/filesystem_dock.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp @@ -3597,11 +3620,11 @@ msgstr "Nimeta ümber" #: editor/filesystem_dock.cpp msgid "Previous Folder/File" -msgstr "" +msgstr "Eelmine kaust/fail" #: editor/filesystem_dock.cpp msgid "Next Folder/File" -msgstr "" +msgstr "Järgmine kaust/fail" #: editor/filesystem_dock.cpp msgid "Re-Scan Filesystem" @@ -3609,7 +3632,7 @@ msgstr "" #: editor/filesystem_dock.cpp msgid "Toggle Split Mode" -msgstr "" +msgstr "Lülita jagamisrežiim sisse/välja" #: editor/filesystem_dock.cpp msgid "Search files" @@ -3639,7 +3662,7 @@ msgstr "Loo stseen" #: editor/filesystem_dock.cpp editor/plugins/script_editor_plugin.cpp msgid "Create Script" -msgstr "" +msgstr "Loo skript" #: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp msgid "Find in Files" @@ -3954,7 +3977,7 @@ msgstr "" #: editor/plugin_config_dialog.cpp msgid "Edit a Plugin" -msgstr "" +msgstr "Pistikprogrammi muutmine" #: editor/plugin_config_dialog.cpp msgid "Create a Plugin" @@ -3962,7 +3985,7 @@ msgstr "" #: editor/plugin_config_dialog.cpp msgid "Plugin Name:" -msgstr "" +msgstr "Pistikprogrammi nimi:" #: editor/plugin_config_dialog.cpp msgid "Subfolder:" @@ -3970,11 +3993,11 @@ msgstr "" #: editor/plugin_config_dialog.cpp editor/script_create_dialog.cpp msgid "Language:" -msgstr "" +msgstr "Keel:" #: editor/plugin_config_dialog.cpp msgid "Script Name:" -msgstr "" +msgstr "Skripti nimi:" #: editor/plugin_config_dialog.cpp msgid "Activate now?" @@ -4214,7 +4237,7 @@ msgstr "" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" -msgstr "" +msgstr "Kustuta sõlm(ed)" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Toggle Filter On/Off" @@ -4379,7 +4402,7 @@ msgstr "Animatsiooni tööriistad" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation" -msgstr "" +msgstr "Animatsioon" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Edit Transitions..." @@ -4443,7 +4466,7 @@ msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Include Gizmos (3D)" -msgstr "" +msgstr "Kaasa vidinad (3D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Pin AnimationPlayer" @@ -4715,7 +4738,7 @@ msgstr "" #: editor/plugins/asset_library_editor_plugin.cpp msgid "View Files" -msgstr "" +msgstr "Kuva failid" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connection error, please try again." @@ -4875,7 +4898,7 @@ msgstr "" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Plugins..." -msgstr "" +msgstr "Pistikprogrammid..." #: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp msgid "Sort:" @@ -4934,7 +4957,7 @@ msgstr "" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/rename_dialog.cpp msgid "Preview" -msgstr "" +msgstr "Eelvaade" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" @@ -5349,7 +5372,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "View" -msgstr "" +msgstr "Kuva" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Always Show Grid" @@ -5373,7 +5396,7 @@ msgstr "" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Viewport" -msgstr "" +msgstr "Kuva vaateaken" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Group And Lock Icons" @@ -6392,7 +6415,7 @@ msgstr "" #: editor/scene_tree_editor.cpp editor/script_editor_debugger.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Type:" -msgstr "" +msgstr "Tüüp:" #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/scene_tree_dock.cpp editor/scene_tree_editor.cpp @@ -6530,21 +6553,21 @@ msgstr "" #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Up" -msgstr "" +msgstr "Liiguta üles" #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/script_text_editor.cpp editor/scene_tree_dock.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Move Down" -msgstr "" +msgstr "Liiguta allapoole" #: editor/plugins/script_editor_plugin.cpp msgid "Next script" -msgstr "" +msgstr "Järgmine skript" #: editor/plugins/script_editor_plugin.cpp msgid "Previous script" -msgstr "" +msgstr "Eelmine skript" #: editor/plugins/script_editor_plugin.cpp msgid "File" @@ -6617,12 +6640,12 @@ msgstr "" #: editor/plugins/script_editor_plugin.cpp editor/script_editor_debugger.cpp msgid "Break" -msgstr "" +msgstr "Paus" #: editor/plugins/script_editor_plugin.cpp editor/project_manager.cpp #: editor/script_editor_debugger.cpp msgid "Continue" -msgstr "" +msgstr "Jätka" #: editor/plugins/script_editor_plugin.cpp msgid "Keep Debugger Open" @@ -7095,7 +7118,7 @@ msgstr "Kuva keskkond" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Gizmos" -msgstr "" +msgstr "Kuva vidinad" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Information" @@ -7262,44 +7285,44 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "1 Viewport" -msgstr "" +msgstr "1 vaateaken" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports" -msgstr "" +msgstr "2 vaateakent" #: editor/plugins/spatial_editor_plugin.cpp msgid "2 Viewports (Alt)" -msgstr "" +msgstr "2 vaateakent (alt)" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports" -msgstr "" +msgstr "3 vaateakent" #: editor/plugins/spatial_editor_plugin.cpp msgid "3 Viewports (Alt)" -msgstr "" +msgstr "3 vaateakent (alt)" #: editor/plugins/spatial_editor_plugin.cpp msgid "4 Viewports" -msgstr "" +msgstr "4 vaateakent" #: editor/plugins/spatial_editor_plugin.cpp msgid "Gizmos" -msgstr "" +msgstr "Vidinad" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Origin" -msgstr "" +msgstr "Kuva lähtekoht" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Grid" -msgstr "" +msgstr "Kuva ruudustik" #: editor/plugins/spatial_editor_plugin.cpp #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Settings..." -msgstr "" +msgstr "Sätted..." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" @@ -7319,7 +7342,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" -msgstr "" +msgstr "Vaateakna sätted" #: editor/plugins/spatial_editor_plugin.cpp msgid "Perspective FOV (deg.):" @@ -7475,7 +7498,7 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Unable to load images" -msgstr "" +msgstr "Pilte ei saa laadida" #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "ERROR: Couldn't load frame resource!" @@ -7748,7 +7771,7 @@ msgstr "" #: editor/plugins/theme_editor_plugin.cpp msgid "Data Type:" -msgstr "" +msgstr "Andmetüüp:" #: editor/plugins/theme_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp @@ -7876,7 +7899,7 @@ msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Merge from Scene" -msgstr "" +msgstr "Liida stseenist" #: editor/plugins/tile_set_editor_plugin.cpp msgid "New Single Tile" @@ -8247,7 +8270,7 @@ msgstr "" #: editor/plugins/version_control_editor_plugin.cpp #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Status" -msgstr "" +msgstr "Olek" #: editor/plugins/version_control_editor_plugin.cpp msgid "View file diffs before committing them to the latest version" @@ -9119,7 +9142,7 @@ msgstr "" #: editor/project_export.cpp editor/project_settings_editor.cpp msgid "Add..." -msgstr "" +msgstr "Lisa..." #: editor/project_export.cpp msgid "" @@ -9193,7 +9216,7 @@ msgstr "" #: editor/project_export.cpp msgid "Script" -msgstr "" +msgstr "Skript" #: editor/project_export.cpp msgid "Script Export Mode:" @@ -9492,6 +9515,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "projektihaldur" @@ -9807,15 +9831,15 @@ msgstr "" #: editor/project_settings_editor.cpp msgid "Localization" -msgstr "" +msgstr "Tõlked" #: editor/project_settings_editor.cpp msgid "Translations" -msgstr "" +msgstr "Tõlked" #: editor/project_settings_editor.cpp msgid "Translations:" -msgstr "" +msgstr "Tõlked:" #: editor/project_settings_editor.cpp msgid "Remaps" @@ -9859,7 +9883,7 @@ msgstr "" #: editor/project_settings_editor.cpp msgid "Plugins" -msgstr "" +msgstr "Pistikprogrammid" #: editor/property_editor.cpp msgid "Preset..." @@ -9935,7 +9959,7 @@ msgstr "" #: editor/rename_dialog.cpp msgid "Advanced Options" -msgstr "" +msgstr "Täpsemad sätted" #: editor/rename_dialog.cpp msgid "Substitute" @@ -10218,7 +10242,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Attach Script" -msgstr "" +msgstr "Manusta skript" #: editor/scene_tree_dock.cpp msgid "Remove Node(s)" @@ -10244,7 +10268,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Sub-Resources" -msgstr "" +msgstr "Alamressursid" #: editor/scene_tree_dock.cpp msgid "Clear Inheritance" @@ -10260,7 +10284,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Open Documentation" -msgstr "" +msgstr "Ava dokumentatsioon" #: editor/scene_tree_dock.cpp msgid "" @@ -10275,11 +10299,11 @@ msgstr "Lisa alamsõlm" #: editor/scene_tree_dock.cpp msgid "Expand/Collapse All" -msgstr "" +msgstr "Laienda/ahenda kõik" #: editor/scene_tree_dock.cpp msgid "Change Type" -msgstr "" +msgstr "Muuda tüüpi" #: editor/scene_tree_dock.cpp msgid "Reparent to New Node" @@ -10287,7 +10311,7 @@ msgstr "" #: editor/scene_tree_dock.cpp msgid "Make Scene Root" -msgstr "" +msgstr "Tee stseeni juurikaks" #: editor/scene_tree_dock.cpp msgid "Merge From Scene" @@ -10295,11 +10319,11 @@ msgstr "" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Save Branch as Scene" -msgstr "" +msgstr "Salvesta filiaal stseenina" #: editor/scene_tree_dock.cpp editor/script_editor_debugger.cpp msgid "Copy Node Path" -msgstr "" +msgstr "Kopeeri sõlme tee" #: editor/scene_tree_dock.cpp msgid "Delete (No Confirm)" @@ -10477,7 +10501,7 @@ msgstr "" #: editor/script_create_dialog.cpp msgid "Open Script" -msgstr "" +msgstr "Ava skript" #: editor/script_create_dialog.cpp msgid "File exists, it will be reused." @@ -10583,7 +10607,7 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Errors" -msgstr "" +msgstr "Vead" #: editor/script_editor_debugger.cpp msgid "Child process connected." @@ -10591,11 +10615,11 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Copy Error" -msgstr "" +msgstr "Kopeeri viga" #: editor/script_editor_debugger.cpp msgid "Video RAM" -msgstr "" +msgstr "Videomälu" #: editor/script_editor_debugger.cpp msgid "Skip Breakpoints" @@ -10611,7 +10635,7 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Stack Frames" -msgstr "" +msgstr "Virnakaadrid" #: editor/script_editor_debugger.cpp msgid "Profiler" @@ -10623,15 +10647,15 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Monitor" -msgstr "" +msgstr "Jälgija" #: editor/script_editor_debugger.cpp msgid "Value" -msgstr "" +msgstr "Väärtus" #: editor/script_editor_debugger.cpp msgid "Monitors" -msgstr "" +msgstr "Jälgijad" #: editor/script_editor_debugger.cpp msgid "Pick one or more items from the list to display the graph." @@ -10639,7 +10663,7 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "List of Video Memory Usage by Resource:" -msgstr "" +msgstr "Videomälu kasutamise loetelu ressursside kaupa:" #: editor/script_editor_debugger.cpp msgid "Total:" @@ -10651,7 +10675,7 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Resource Path" -msgstr "" +msgstr "Ressursi tee" #: editor/script_editor_debugger.cpp msgid "Type" @@ -10659,15 +10683,15 @@ msgstr "" #: editor/script_editor_debugger.cpp msgid "Format" -msgstr "" +msgstr "Formaat" #: editor/script_editor_debugger.cpp msgid "Usage" -msgstr "" +msgstr "Kasutus" #: editor/script_editor_debugger.cpp msgid "Misc" -msgstr "" +msgstr "Muud" #: editor/script_editor_debugger.cpp msgid "Clicked Control:" @@ -10686,8 +10710,9 @@ msgid "Set From Tree" msgstr "" #: editor/script_editor_debugger.cpp +#, fuzzy msgid "Export measures as CSV" -msgstr "" +msgstr "Ekspordi mõõtmed/meetmed CSV-vormingus" #: editor/settings_config_dialog.cpp msgid "Erase Shortcut" @@ -10831,11 +10856,11 @@ msgstr "" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Library" -msgstr "" +msgstr "Teek" #: modules/gdnative/gdnative_library_singleton_editor.cpp msgid "Libraries: " -msgstr "" +msgstr "Teegid: " #: modules/gdnative/register_types.cpp msgid "GDNative" diff --git a/editor/translations/eu.po b/editor/translations/eu.po index 906a258f32..8042403f9d 100644 --- a/editor/translations/eu.po +++ b/editor/translations/eu.po @@ -1090,6 +1090,9 @@ msgstr "Proiektuaren sortzaileak" msgid "Lead Developer" msgstr "Garatzaile nagusia" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Proiektu-kudeatzailea " @@ -1111,6 +1114,16 @@ msgid "Gold Sponsors" msgstr "Urrezko babesleak" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Zilarrezko emaileak" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Brontzezko emaileak" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini babesleak" @@ -9481,6 +9494,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/extract.py b/editor/translations/extract.py index 02ed65131f..93124ec30c 100755 --- a/editor/translations/extract.py +++ b/editor/translations/extract.py @@ -49,28 +49,27 @@ msgstr "" "Report-Msgid-Bugs-To: https://github.com/godotengine/godot\\n" "MIME-Version: 1.0\\n" "Content-Type: text/plain; charset=UTF-8\\n" -"Content-Transfer-Encoding: 8-bit\\n" +"Content-Transfer-Encoding: 8-bit\\n"\n """ def _write_message(msgctx, msg, msg_plural, location): global main_po - main_po += "\n#: " + location + "\n" + main_po += "#: " + location + "\n" if msgctx != "": main_po += 'msgctxt "' + msgctx + '"\n' main_po += 'msgid "' + msg + '"\n' if msg_plural != "": main_po += 'msgid_plural "' + msg_plural + '"\n' main_po += 'msgstr[0] ""\n' - main_po += 'msgstr[1] ""\n' + main_po += 'msgstr[1] ""\n\n' else: - main_po += 'msgstr ""\n' + main_po += 'msgstr ""\n\n' def _add_additional_location(msgctx, msg, location): global main_po - # Add additional location to previous occurrence - msg_pos = -1 + # Add additional location to previous occurrence. if msgctx != "": msg_pos = main_po.find('\nmsgctxt "' + msgctx + '"\nmsgid "' + msg + '"') else: @@ -81,18 +80,137 @@ def _add_additional_location(msgctx, msg, location): main_po = main_po[:msg_pos] + " " + location + main_po[msg_pos:] +def _write_translator_comment(msgctx, msg, translator_comment): + if translator_comment == "": + return + + global main_po + if msgctx != "": + msg_pos = main_po.find('\nmsgctxt "' + msgctx + '"\nmsgid "' + msg + '"') + else: + msg_pos = main_po.find('\nmsgid "' + msg + '"') + + # If it's a new message, just append comment to the end of PO file. + if msg_pos == -1: + main_po += _format_translator_comment(translator_comment, True) + return + + # Find position just before location. Translator comment will be added there. + translator_comment_pos = main_po.rfind("\n\n#", 0, msg_pos) + 2 + if translator_comment_pos - 2 == -1: + print("translator_comment_pos not found") + return + + # Check if a previous translator comment already exists. If so, merge them together. + if main_po.find("TRANSLATORS:", translator_comment_pos, msg_pos) != -1: + translator_comment_pos = main_po.find("\n#:", translator_comment_pos, msg_pos) + 1 + if translator_comment_pos == 0: + print('translator_comment_pos after "TRANSLATORS:" not found') + return + main_po = ( + main_po[:translator_comment_pos] + + _format_translator_comment(translator_comment, False) + + main_po[translator_comment_pos:] + ) + return + + main_po = ( + main_po[:translator_comment_pos] + + _format_translator_comment(translator_comment, True) + + main_po[translator_comment_pos:] + ) + + +def _format_translator_comment(comment, new): + if not comment: + return "" + + comment_lines = comment.split("\n") + + formatted_comment = "" + if not new: + for comment in comment_lines: + formatted_comment += "#. " + comment.strip() + "\n" + return formatted_comment + + formatted_comment = "#. TRANSLATORS: " + for i in range(len(comment_lines)): + if i == 0: + formatted_comment += comment_lines[i].strip() + "\n" + else: + formatted_comment += "#. " + comment_lines[i].strip() + "\n" + return formatted_comment + + +def _is_block_translator_comment(translator_line): + line = translator_line.strip() + if line.find("//") == 0: + return False + else: + return True + + +def _extract_translator_comment(line, is_block_translator_comment): + line = line.strip() + reached_end = False + extracted_comment = "" + + start = line.find("TRANSLATORS:") + if start == -1: + start = 0 + else: + start += len("TRANSLATORS:") + + if is_block_translator_comment: + # If '*/' is found, then it's the end. + if line.rfind("*/") != -1: + extracted_comment = line[start : line.rfind("*/")] + reached_end = True + else: + extracted_comment = line[start:] + else: + # If beginning is not '//', then it's the end. + if line.find("//") != 0: + reached_end = True + else: + start = 2 if start == 0 else start + extracted_comment = line[start:] + + return (not reached_end, extracted_comment) + + def process_file(f, fname): global main_po, unique_str, unique_loc + patterns = ['RTR("', 'TTR("', 'TTRC("', 'TTRN("', 'RTRN("'] + l = f.readline() lc = 1 + reading_translator_comment = False + is_block_translator_comment = False + translator_comment = "" + while l: - patterns = ['RTR("', 'TTR("', 'TTRC("', 'TTRN("', 'RTRN("'] + # Detect translator comments. + if not reading_translator_comment and l.find("TRANSLATORS:") != -1: + reading_translator_comment = True + is_block_translator_comment = _is_block_translator_comment(l) + translator_comment = "" + + # Gather translator comments. It will be gathered for the next translation function. + if reading_translator_comment: + reading_translator_comment, extracted_comment = _extract_translator_comment(l, is_block_translator_comment) + if extracted_comment != "": + translator_comment += extracted_comment + "\n" + if not reading_translator_comment: + translator_comment = translator_comment[:-1] # Remove extra \n at the end. + idx = 0 pos = 0 - while pos >= 0: + + while not reading_translator_comment and pos >= 0: # Loop until a pattern is found. If not, next line. pos = l.find(patterns[idx], pos) if pos == -1: @@ -140,6 +258,10 @@ def process_file(f, fname): if line_nb: location += ":" + str(lc) + # Write translator comment. + _write_translator_comment(msgctx, msg, translator_comment) + translator_comment = "" + if msgctx != "": # If it's a new context or a new message within an existing context, then write new msgid. # Else add location to existing msgid. @@ -160,6 +282,7 @@ def process_file(f, fname): elif not location in unique_loc[msg]: _add_additional_location(msgctx, msg, location) unique_loc[msg].append(location) + l = f.readline() lc += 1 diff --git a/editor/translations/fa.po b/editor/translations/fa.po index dc7ae9ec69..dee4ae4030 100644 --- a/editor/translations/fa.po +++ b/editor/translations/fa.po @@ -1120,6 +1120,9 @@ msgstr "بنیان‌گذاران پروژه" msgid "Lead Developer" msgstr "توسعه‌دهنده‌ی اصلی" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "مدیر پروژه " @@ -1141,6 +1144,16 @@ msgid "Gold Sponsors" msgstr "Øامیان طلایی (درجه Û²)" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "اهداکنندگان نقره‌ای" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "اهداکنندگان برنزی" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "اسپانسر‌های Ú©ÙˆÚ†Ú©" @@ -9931,6 +9944,7 @@ msgstr "" "شما درخواست بررسی پوشه های s٪‌ برای پیدا کردن پروژه های گودات را داده اید. " "آیا انجام این عمل را تایید Ù…ÛŒ کنید؟‌" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "مدیر پروژه" diff --git a/editor/translations/fi.po b/editor/translations/fi.po index 124ae4f2e0..bc8d755714 100644 --- a/editor/translations/fi.po +++ b/editor/translations/fi.po @@ -15,7 +15,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-05 16:58+0000\n" +"PO-Revision-Date: 2020-09-05 09:37+0000\n" "Last-Translator: Tapani Niemi <tapani.niemi@kapsi.fi>\n" "Language-Team: Finnish <https://hosted.weblate.org/projects/godot-engine/" "godot/fi/>\n" @@ -24,7 +24,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1117,6 +1117,9 @@ msgstr "Projektin perustajat" msgid "Lead Developer" msgstr "Pääkehittäjä" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projektipäällikkö " @@ -1138,6 +1141,14 @@ msgid "Gold Sponsors" msgstr "Kultasponsorit" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "Hopeasponsorit" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "Pronssisponsorit" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Minisponsorit" @@ -9862,6 +9873,7 @@ msgstr "" "Haluatko varmasti etsiä %s kansiosta olemassa olevia Godot-projekteja?\n" "Tämä saattaa kestää hetken." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Projektinhallinta" diff --git a/editor/translations/fil.po b/editor/translations/fil.po index 490d9d92ec..697692ac9c 100644 --- a/editor/translations/fil.po +++ b/editor/translations/fil.po @@ -5,11 +5,12 @@ # Marco Santos <enum.scima@gmail.com>, 2019. # Amado Wilkins <epicalert68@gmail.com>, 2019. # Bakainkorp <Ryan.Bautista86@myhunter.cuny.edu>, 2019. +# Jethro Parker <lionbearjet@hotmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" -"PO-Revision-Date: 2019-12-21 08:37+0000\n" -"Last-Translator: Bakainkorp <Ryan.Bautista86@myhunter.cuny.edu>\n" +"PO-Revision-Date: 2020-08-14 03:56+0000\n" +"Last-Translator: Jethro Parker <lionbearjet@hotmail.com>\n" "Language-Team: Filipino <https://hosted.weblate.org/projects/godot-engine/" "godot/fil/>\n" "Language: fil\n" @@ -17,7 +18,7 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=n != 1 && n != 2 && n != 3 && (n % 10 == 4 " "|| n % 10 == 6 || n % 10 == 9);\n" -"X-Generator: Weblate 3.10\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 @@ -28,7 +29,7 @@ msgstr "" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "" +msgstr "Nanghihingi ng string na may habang 1 (character)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp @@ -185,12 +186,12 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Change Animation Length" -msgstr "" +msgstr "Ibahin ang haba ng Animation" #: editor/animation_track_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Change Animation Loop" -msgstr "" +msgstr "Ibahin ang ulit ng Animation" #: editor/animation_track_editor.cpp msgid "Property Track" @@ -218,44 +219,44 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "Animation length (frames)" -msgstr "" +msgstr "Haba ng animation (frames)" #: editor/animation_track_editor.cpp msgid "Animation length (seconds)" -msgstr "" +msgstr "Haba ng animation (segundo)" #: editor/animation_track_editor.cpp msgid "Add Track" -msgstr "" +msgstr "Magdagdag ng Track" #: editor/animation_track_editor.cpp msgid "Animation Looping" -msgstr "" +msgstr "Pagulit ng Animation" #: editor/animation_track_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Functions:" -msgstr "" +msgstr "Functions:" #: editor/animation_track_editor.cpp msgid "Audio Clips:" -msgstr "" +msgstr "Mga clip ng tunog:" #: editor/animation_track_editor.cpp msgid "Anim Clips:" -msgstr "" +msgstr "Mga clip ng Anim:" #: editor/animation_track_editor.cpp msgid "Change Track Path" -msgstr "" +msgstr "Ibahin ang landas ng Track" #: editor/animation_track_editor.cpp msgid "Toggle this track on/off." -msgstr "" +msgstr "Ilipat sa on/off ang track na ito." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" -msgstr "" +msgstr "Baguhin ang Mode (Kung paano na-set ang property)" #: editor/animation_track_editor.cpp msgid "Interpolation Mode" @@ -1093,6 +1094,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1114,6 +1118,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -1893,7 +1905,7 @@ msgstr "" #: editor/editor_help.cpp msgid "Description" -msgstr "" +msgstr "Paglalarawan" #: editor/editor_help.cpp msgid "Online Tutorials" @@ -2816,11 +2828,11 @@ msgstr "" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" -msgstr "" +msgstr "Komunidad" #: editor/editor_node.cpp msgid "About" -msgstr "" +msgstr "Tungkol" #: editor/editor_node.cpp msgid "Play the project." @@ -9485,6 +9497,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/fr.po b/editor/translations/fr.po index 9bb04cb2b0..d3ec3b7719 100644 --- a/editor/translations/fr.po +++ b/editor/translations/fr.po @@ -79,8 +79,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-01 11:14+0000\n" -"Last-Translator: Pierre Caye <pierrecaye@laposte.net>\n" +"PO-Revision-Date: 2020-09-08 13:44+0200\n" +"Last-Translator: Nathan <bonnemainsnathan@gmail.com>\n" "Language-Team: French <https://hosted.weblate.org/projects/godot-engine/" "godot/fr/>\n" "Language: fr\n" @@ -88,7 +88,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.2-dev\n" +"X-Generator: Poedit 2.4.1\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -136,7 +136,7 @@ msgstr "Lors de l’appel à '%s' :" #: core/ustring.cpp msgid "B" -msgstr "Octet" +msgstr "o" #: core/ustring.cpp msgid "KiB" @@ -1196,9 +1196,12 @@ msgstr "Fondateurs du projet" msgid "Lead Developer" msgstr "Développeur principal" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Gestionnaire de projets " +msgstr "Chef de projet " #: editor/editor_about.cpp msgid "Developers" @@ -1217,6 +1220,14 @@ msgid "Gold Sponsors" msgstr "Sponsors Or" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "Sponsors Argent" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "Sponsors Bronze" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsors" @@ -8580,7 +8591,7 @@ msgstr "Système de contrôle de version" #: editor/plugins/version_control_editor_plugin.cpp msgid "Initialize" -msgstr "initialiser" +msgstr "Initialiser" #: editor/plugins/version_control_editor_plugin.cpp msgid "Staging area" @@ -10017,6 +10028,7 @@ msgstr "" "Godot existants ?\n" "Cela pourrait prendre un moment." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Gestionnaire de projets" diff --git a/editor/translations/ga.po b/editor/translations/ga.po index a496566c2e..d3733ca614 100644 --- a/editor/translations/ga.po +++ b/editor/translations/ga.po @@ -1086,6 +1086,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1107,6 +1110,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9481,6 +9492,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/he.po b/editor/translations/he.po index 0f9a19c842..2661ed39ff 100644 --- a/editor/translations/he.po +++ b/editor/translations/he.po @@ -15,11 +15,12 @@ # Anonymous <noreply@weblate.org>, 2020. # Daniel Kariv <danielkariv98@gmail.com>, 2020. # Ziv D <wizdavid@gmail.com>, 2020. +# yariv benj <yariv4400@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-11 14:04+0000\n" +"PO-Revision-Date: 2020-09-08 11:40+0000\n" "Last-Translator: Ziv D <wizdavid@gmail.com>\n" "Language-Team: Hebrew <https://hosted.weblate.org/projects/godot-engine/" "godot/he/>\n" @@ -29,16 +30,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && " "n % 10 == 0) ? 2 : 3));\n" -"X-Generator: Weblate 4.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "×ž×©×ª× ×” סוג ×œ× ×—×•×§×™ ×œ×¤×•× ×§×¦×™×™×ª convert()‎, יש להשתמש בקבועי TYPE_*‎." +msgstr "סוג ×ž×©×ª× ×” ×œ× ×—×•×§×™ ×œ×¤×•× ×§×¦×™×™×ª convert()‎, יש להשתמש בקבועי TYPE_*‎." #: 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 @@ -52,7 +53,7 @@ msgstr "קלט שגוי %I (×œ× ×”×•×¢×‘×¨) בתוך הביטוי" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "×œ× × ×™×ª×Ÿ להשתמש ב־self כיוון שהמופע ×”×•× ×פס (null - ×œ× ×”×•×¢×‘×¨)" +msgstr "'self' ×œ× × ×™×ª×Ÿ לשימוש ×›×™ המופע ×”×™× ×• 'null' ( ×œ× ×”×•×¢×‘×¨)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." @@ -64,7 +65,7 @@ msgstr "×©× ×ž×פיין ×”××™× ×“×§×¡ מסוג %s עבור בסיס %s שגו #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" -msgstr "×©× ××™× ×“×§×¡ ×œ× ×ª×§×™×Ÿ '%s' לסוג בסיס '%s'" +msgstr "×©× ××™× ×“×§×¡ ×œ× ×ª×§×™×Ÿ '%s' לסוג בסיס %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" @@ -76,7 +77,7 @@ msgstr "בקרי××” ל־‚%s’:" #: core/ustring.cpp msgid "B" -msgstr "ב׳" +msgstr "B" #: core/ustring.cpp msgid "KiB" @@ -124,15 +125,15 @@ msgstr "ערך:" #: editor/animation_bezier_editor.cpp msgid "Insert Key Here" -msgstr "×”×›× ×¡ מפתח ×›×ן" +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" @@ -267,7 +268,7 @@ 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)" @@ -336,7 +337,6 @@ msgid "Delete Key(s)" msgstr "מחיקת מפתח(ות)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Change Animation Update Mode" msgstr "×©×™× ×•×™ מצב עדכון ×”× ×¤×©×”" @@ -373,7 +373,6 @@ msgid "Create" msgstr "יצירה" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Insert" msgstr "הוסף ×”× ×¤×©×”" @@ -400,9 +399,8 @@ msgid "Change Animation Step" msgstr "× ×™×§×•×™ ×”×”× ×¤×©×”" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Rearrange Tracks" -msgstr "סידור רצועות" +msgstr "סדר רצועות מחדש" #: editor/animation_track_editor.cpp msgid "Transform tracks only apply to Spatial-based nodes." @@ -478,9 +476,8 @@ msgid "Anim Move Keys" msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Clipboard is empty" -msgstr "לוח גזירי המש××‘×™× ×¨×™×§!" +msgstr "לוח העתקה ריק" #: editor/animation_track_editor.cpp #, fuzzy @@ -541,7 +538,7 @@ msgstr "" #: editor/animation_track_editor.cpp msgid "FPS" -msgstr "" +msgstr "FPS" #: editor/animation_track_editor.cpp editor/editor_properties.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -665,7 +662,7 @@ msgstr "הגדרת ×ž×¢×‘×¨×•× ×™× ×ל:" #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Copy" -msgstr "העתקה" +msgstr "העתק" #: editor/animation_track_editor.cpp #, fuzzy @@ -703,7 +700,7 @@ msgstr "מעבר לשורה" #: editor/code_editor.cpp msgid "Line Number:" -msgstr "מספר השורה:" +msgstr "שורה מספר:" #: editor/code_editor.cpp msgid "%d replaced." @@ -711,7 +708,7 @@ msgstr "%d הוחלף." #: editor/code_editor.cpp editor/editor_help.cpp msgid "%d match." -msgstr "%d הת×מות." +msgstr "%d הת×מה." #: editor/code_editor.cpp editor/editor_help.cpp msgid "%d matches." @@ -727,7 +724,7 @@ msgstr "×ž×™×œ×™× ×©×œ×ž×•×ª" #: editor/code_editor.cpp editor/rename_dialog.cpp msgid "Replace" -msgstr "להחליף" +msgstr "החלף" #: editor/code_editor.cpp msgid "Replace All" @@ -934,9 +931,8 @@ msgid "Edit..." msgstr "עריכה..." #: editor/connections_dialog.cpp -#, fuzzy msgid "Go To Method" -msgstr "שיטות" +msgstr "מעבר למתודה" #: editor/create_dialog.cpp msgid "Change %s Type" @@ -1127,7 +1123,7 @@ msgstr "תודה רבה מקהילת Godot!" #: editor/editor_about.cpp msgid "Godot Engine contributors" -msgstr "×ž×ª× ×“×‘×™ ×ž× ×•×¢ Godot" +msgstr "×ž×ª× ×“×‘×™ ×ž× ×•×¢ גודו" #: editor/editor_about.cpp msgid "Project Founders" @@ -1137,6 +1133,9 @@ msgstr "מקימי המיז×" msgid "Lead Developer" msgstr "×ž×¤×ª×—×™× ×¨×שיי×" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "×ž× ×”×œ ×”×ž×™×–× " @@ -1158,6 +1157,16 @@ msgid "Gold Sponsors" msgstr "×ž×ž×ž× ×™ זהב" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "×ª×•×¨×ž×™× ×‘×“×¨×’×ª כסף" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "×ª×•×¨×ž×™× ×‘×“×¨×’×ª ×רד" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "×ž×ž×ž× ×™× ×–×¢×™×¨×™×" @@ -1212,9 +1221,8 @@ msgid "Error opening package file, not in ZIP format." msgstr "פתיחת קובץ החבילה × ×›×©×œ×”, ×”×ž×‘× ×” ××™× ×• zip." #: editor/editor_asset_installer.cpp -#, fuzzy msgid "%s (Already Exists)" -msgstr "הפעולה ‚%s’ כבר קיימת!" +msgstr "%s (כבר קיי×)" #: editor/editor_asset_installer.cpp msgid "Uncompressing Assets" @@ -1801,13 +1809,11 @@ msgid "Copy Path" msgstr "העתקת × ×ª×™×‘" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp -#, fuzzy msgid "Open in File Manager" -msgstr "הצגה ×‘×ž× ×”×œ הקבצי×" +msgstr "פתיחה ×‘×ž× ×”×œ הקבצי×" #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/project_manager.cpp -#, fuzzy msgid "Show in File Manager" msgstr "הצגה ×‘×ž× ×”×œ הקבצי×" @@ -1857,39 +1863,39 @@ msgstr "שמירת קובץ" #: editor/editor_file_dialog.cpp msgid "Go Back" -msgstr "חזרה ×חורה" +msgstr "מעבר ×חורה" #: editor/editor_file_dialog.cpp msgid "Go Forward" -msgstr "התקדמות קדימה" +msgstr "מעבר קדימה" #: editor/editor_file_dialog.cpp msgid "Go Up" -msgstr "עלייה למעלה" +msgstr "מעבר מעלה" #: editor/editor_file_dialog.cpp msgid "Toggle Hidden Files" -msgstr "החלפת מצב תצוגה ×œ×§×‘×¦×™× ×ž×•×¡×ª×¨×™×" +msgstr "הצג/הסתר ×§×‘×¦×™× ×ž×•×¡×ª×¨×™×" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "החלפת מצב מועדפי×" +msgstr "הוספת/ביטול מועדף" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "החלפת מצב" +msgstr "×©×™× ×•×™ מצב" #: editor/editor_file_dialog.cpp msgid "Focus Path" -msgstr "התמקדות על × ×ª×™×‘" +msgstr "מיקוד × ×ª×™×‘" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" -msgstr "העברת מועדף למעלה" +msgstr "העברת מועדף מעלה" #: editor/editor_file_dialog.cpp msgid "Move Favorite Down" -msgstr "העברת מועדף למטה" +msgstr "העברת מועדף מטה" #: editor/editor_file_dialog.cpp msgid "Go to previous folder." @@ -1900,18 +1906,16 @@ msgid "Go to next folder." msgstr "מעבר לתיקיה הב××”." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp -#, fuzzy msgid "Go to parent folder." -msgstr "מעבר לתיקייה שמעל" +msgstr "מעבר לתיקיית העל." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Refresh files." msgstr "×¨×¢× ×Ÿ קבצי×." #: editor/editor_file_dialog.cpp -#, fuzzy msgid "(Un)favorite current folder." -msgstr "×œ× × ×™×ª×Ÿ ליצור תיקייה." +msgstr "(בטל) העדפת תיקייה × ×•×›×—×™×ª." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Toggle the visibility of hidden files." @@ -1951,11 +1955,11 @@ msgstr "סריקת מקורות" msgid "" "There are multiple importers for different types pointing to file %s, import " "aborted" -msgstr "" +msgstr "יש מספר מייב××™× ×œ×¡×•×’×™× ×©×•× ×™× ×”×ž×¦×‘×™×¢×™× ×œ×§×•×‘×¥ %s, ×”×™×™×‘×•× ×‘×•×˜×œ" #: editor/editor_file_system.cpp msgid "(Re)Importing Assets" -msgstr "" +msgstr "×™×™×‘×•× ×ž×©××‘×™× (מחדש)" #: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Top" @@ -1975,14 +1979,12 @@ msgid "Inherited by:" msgstr "מוריש ×ל:" #: editor/editor_help.cpp -#, fuzzy msgid "Description" -msgstr "תי×ור:" +msgstr "תי×ור" #: editor/editor_help.cpp -#, fuzzy msgid "Online Tutorials" -msgstr "×ž×¡×ž×›×™× ×ž×§×•×•× ×™×" +msgstr "הדרכות ×ž×§×•×•× ×•×ª" #: editor/editor_help.cpp msgid "Properties" @@ -1990,21 +1992,19 @@ msgstr "מ××¤×™×™× ×™×" #: editor/editor_help.cpp msgid "override:" -msgstr "" +msgstr "דריסה:" #: editor/editor_help.cpp -#, fuzzy msgid "default:" -msgstr "×˜×¢×™× ×ª בררת המחדל" +msgstr "ברירת מחדל:" #: editor/editor_help.cpp msgid "Methods" -msgstr "שיטות" +msgstr "מתודות" #: editor/editor_help.cpp -#, fuzzy msgid "Theme Properties" -msgstr "מ××¤×™×™× ×™×" +msgstr "מ××¤×™×™× ×™ ערכת עיצוב" #: editor/editor_help.cpp msgid "Enumerations" @@ -2015,31 +2015,32 @@ msgid "Constants" msgstr "קבועי×" #: editor/editor_help.cpp -#, fuzzy msgid "Property Descriptions" -msgstr "תי×ור המ×פיין:" +msgstr "תי×ורי מ××¤×™×™× ×™×" #: editor/editor_help.cpp -#, fuzzy msgid "(value)" -msgstr "ערך:" +msgstr "(ערך)" #: editor/editor_help.cpp msgid "" "There is currently no description for this property. Please help us by " "[color=$color][url=$url]contributing one[/url][/color]!" msgstr "" +"כרגע ×ין תי×ור למ×פיין ×–×”. בבקשה עזור ×œ× ×• על-ידי [/color][/url]כתיבת " +"תי×ור[url=$url][color=$color]!" #: editor/editor_help.cpp -#, fuzzy msgid "Method Descriptions" -msgstr "תי×ור השיטה:" +msgstr "תי×ורי מתודות" #: editor/editor_help.cpp msgid "" "There is currently no description for this method. Please help us by [color=" "$color][url=$url]contributing one[/url][/color]!" msgstr "" +"כרגע ×ין תי×ור למתודה זו. בבקשה עזור ×œ× ×• על-ידי [/url][/color]כתיבת תי×ור " +"[color=$color][url=$url]!" #: editor/editor_help_search.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp @@ -2051,99 +2052,84 @@ msgid "Case Sensitive" msgstr "תלוי רישיות" #: editor/editor_help_search.cpp -#, fuzzy msgid "Show Hierarchy" -msgstr "חיפוש" +msgstr "הצג היררכיה" #: editor/editor_help_search.cpp -#, fuzzy msgid "Display All" -msgstr "הצגה × ×•×¨×ž×œ×™×ª" +msgstr "הצג הכל" #: editor/editor_help_search.cpp -#, fuzzy msgid "Classes Only" -msgstr "מחלקות" +msgstr "מחלקות בלבד" #: editor/editor_help_search.cpp -#, fuzzy msgid "Methods Only" -msgstr "שיטות" +msgstr "מתודות בלבד" #: editor/editor_help_search.cpp -#, fuzzy msgid "Signals Only" -msgstr "×ותות" +msgstr "×ותות בלבד" #: editor/editor_help_search.cpp -#, fuzzy msgid "Constants Only" -msgstr "קבועי×" +msgstr "×§×‘×•×¢×™× ×‘×œ×‘×“" #: editor/editor_help_search.cpp -#, fuzzy msgid "Properties Only" -msgstr "מ××¤×™×™× ×™×" +msgstr "מ××¤×™×™× ×™× ×‘×œ×‘×“" #: editor/editor_help_search.cpp -#, fuzzy msgid "Theme Properties Only" -msgstr "מ××¤×™×™× ×™×" +msgstr "מ××¤×™×™× ×™ ערכת עיצוב בלבד" #: editor/editor_help_search.cpp -#, fuzzy msgid "Member Type" -msgstr "חברי×" +msgstr "סוג שדה" #: editor/editor_help_search.cpp -#, fuzzy msgid "Class" -msgstr "מחלקה:" +msgstr "מחלקה" #: editor/editor_help_search.cpp -#, fuzzy msgid "Method" -msgstr "שיטות" +msgstr "מתודה" #: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Signal" -msgstr "×ותות" +msgstr "×ות" #: editor/editor_help_search.cpp editor/plugins/theme_editor_plugin.cpp msgid "Constant" msgstr "קבוע" #: editor/editor_help_search.cpp -#, fuzzy msgid "Property" -msgstr "מ××¤×™×™× ×™×" +msgstr "מ×פיין" #: editor/editor_help_search.cpp -#, fuzzy msgid "Theme Property" -msgstr "מ××¤×™×™× ×™×" +msgstr "מ×פיין ערכת עיצוב" #: editor/editor_inspector.cpp editor/project_settings_editor.cpp msgid "Property:" -msgstr "" +msgstr "מ×פיין:" #: editor/editor_inspector.cpp msgid "Set" -msgstr "" +msgstr "קבע" #: editor/editor_inspector.cpp msgid "Set Multiple:" -msgstr "" +msgstr "קביעה מרובה:" #: editor/editor_log.cpp msgid "Output:" msgstr "פלט:" #: editor/editor_log.cpp editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Copy Selection" -msgstr "הסרת הבחירה" +msgstr "העתקת בחירה" #: editor/editor_log.cpp editor/editor_network_profiler.cpp #: editor/editor_profiler.cpp editor/editor_properties.cpp @@ -2153,11 +2139,11 @@ msgstr "הסרת הבחירה" #: modules/gdnative/gdnative_library_editor_plugin.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Clear" -msgstr "מחיקה" +msgstr "× ×™×§×•×™" #: editor/editor_log.cpp msgid "Clear Output" -msgstr "מחיקת הפלט" +msgstr "× ×™×§×•×™ פלט" #: editor/editor_network_profiler.cpp editor/editor_node.cpp #: editor/editor_profiler.cpp @@ -2167,20 +2153,19 @@ msgstr "עצירה" #: editor/editor_network_profiler.cpp editor/editor_profiler.cpp #: editor/plugins/animation_state_machine_editor.cpp editor/rename_dialog.cpp msgid "Start" -msgstr "" +msgstr "התחלה" #: editor/editor_network_profiler.cpp msgid "%s/s" -msgstr "" +msgstr "%s ×œ×©× ×™×™×”" #: editor/editor_network_profiler.cpp -#, fuzzy msgid "Down" msgstr "הורדה" #: editor/editor_network_profiler.cpp msgid "Up" -msgstr "" +msgstr "העל××”" #: editor/editor_network_profiler.cpp editor/editor_node.cpp msgid "Node" @@ -2188,32 +2173,32 @@ msgstr "מפרק" #: editor/editor_network_profiler.cpp msgid "Incoming RPC" -msgstr "" +msgstr "RPC × ×›× ×¡" #: editor/editor_network_profiler.cpp msgid "Incoming RSET" -msgstr "" +msgstr "RSET × ×›× ×¡" #: editor/editor_network_profiler.cpp msgid "Outgoing RPC" -msgstr "" +msgstr "RPC יוצ×" #: editor/editor_network_profiler.cpp msgid "Outgoing RSET" -msgstr "" +msgstr "RSET יוצ×" #: editor/editor_node.cpp editor/project_manager.cpp msgid "New Window" -msgstr "" +msgstr "חלון חדש" #: editor/editor_node.cpp msgid "Imported resources can't be saved." -msgstr "" +msgstr "מש××‘×™× ×ž×™×•×‘××™× ×œ× × ×©×ž×¨×•." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: scene/gui/dialogs.cpp msgid "OK" -msgstr "" +msgstr "×ישור" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" @@ -2224,6 +2209,7 @@ msgid "" "This resource can't be saved because it does not belong to the edited scene. " "Make it unique first." msgstr "" +"המש×ב ×œ× ×™×›×•×œ להישמר ×ž×¤× ×™ ש××™× ×• שייך ×œ×¡×¦× ×” ×©× ×¢×¨×›×”, הפוך ×ותו ×§×•×“× ×œ×™×™×—×•×“×™." #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." @@ -2235,7 +2221,7 @@ msgstr "×œ× × ×™×ª×Ÿ לפתוח קובץ לכתיבה:" #: editor/editor_node.cpp msgid "Requested file format unknown:" -msgstr "×ª×‘× ×™×ª הקובץ המבוקשת ×œ× ×™×“×•×¢×”:" +msgstr "סוג הקובץ המבוקש ×œ× ×™×“×•×¢:" #: editor/editor_node.cpp msgid "Error while saving." @@ -2243,27 +2229,27 @@ msgstr "שגי××” בעת השמירה." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Can't open '%s'. The file could have been moved or deleted." -msgstr "" +msgstr "×œ× ×™×›×•×œ לפתוח ×ת 's%'. יכול להיות שהקובץ הועבר ×ו × ×ž×—×§." #: editor/editor_node.cpp msgid "Error while parsing '%s'." -msgstr "×”×¤×¢× ×•×— של ‚%s’ × ×›×©×œ." +msgstr "שגי××” ×‘×¤×¢× ×•×— 's%'." #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." -msgstr "סוף הקובץ בלתי צפוי ‚%s’." +msgstr "סוף קובץ בלתי צפוי '%s'." #: editor/editor_node.cpp msgid "Missing '%s' or its dependencies." -msgstr "" +msgstr "חסר 's%' ×ו תלות שלו." #: editor/editor_node.cpp msgid "Error while loading '%s'." -msgstr "×”×˜×¢×™× ×” של ‚%s’ × ×›×©×œ×”." +msgstr "שגי××” ×‘×˜×¢×™× ×ª 's%'." #: editor/editor_node.cpp msgid "Saving Scene" -msgstr "×”×¡×¦× ×” × ×©×ž×¨×ª" +msgstr "שומר ×¡×¦× ×”" #: editor/editor_node.cpp msgid "Analyzing" @@ -2271,7 +2257,7 @@ msgstr "מתבצע × ×™×ª×•×—" #: editor/editor_node.cpp msgid "Creating Thumbnail" -msgstr "× ×•×¦×¨×ª ×ª×ž×•× ×” ממוזערת" +msgstr "יצירת ×ª×ž×•× ×” ממוזערת" #: editor/editor_node.cpp msgid "This operation can't be done without a tree root." @@ -2282,34 +2268,34 @@ msgid "" "This scene can't be saved because there is a cyclic instancing inclusion.\n" "Please resolve it and then attempt to save again." msgstr "" +"×¡×¦× ×” זו ×œ× ×™×›×•×œ×” להישמר ×ž×¤× ×™ שיש הכללת מופע מעגלית.\n" +"בבקשה פתור ×–×ת ו××– × ×¡×” לשמור שוב." #: editor/editor_node.cpp msgid "" "Couldn't save scene. Likely dependencies (instances or inheritance) couldn't " "be satisfied." -msgstr "" -"×œ× × ×™×ª×Ÿ לשמור ×ת ×”×¡×¦× ×”. כפי ×”× ×¨××” עקב תלויות (×ž×•×¤×¢×™× ×ו ירושות) ש××™× ×Ÿ " -"מסופקות." +msgstr "×œ× × ×™×ª×Ÿ לשמור ×ת ×”×¡×¦× ×”. ×›× ×¨××” עקב תלות (מופע ×ו ירושה) ×©×œ× ×ž×¡×•×¤×§×ª." #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "Can't overwrite scene that is still open!" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ להחליף ×¡×¦× ×” שעדיין פתוחה!" #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לטעון ×ת MeshLibrary למיזוג!" #: editor/editor_node.cpp msgid "Error saving MeshLibrary!" -msgstr "" +msgstr "שגי××” בשמירת MeshLibrary!" #: editor/editor_node.cpp msgid "Can't load TileSet for merging!" -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לטעון TileSet למיזוג!" #: editor/editor_node.cpp msgid "Error saving TileSet!" -msgstr "" +msgstr "שגי××” בשמירת TileSet!" #: editor/editor_node.cpp msgid "Error trying to save layout!" @@ -2317,7 +2303,7 @@ msgstr "שמירת הפריסה × ×›×©×œ×”!" #: editor/editor_node.cpp msgid "Default editor layout overridden." -msgstr "בררת המחדל של פריסת העורך שוכתבה." +msgstr "ברירת המחדל של עורך הפריסה × ×“×¨×¡×”." #: editor/editor_node.cpp msgid "Layout name not found!" @@ -2325,7 +2311,7 @@ msgstr "×©× ×”×¤×¨×™×¡×” ×œ× × ×ž×¦×!" #: editor/editor_node.cpp msgid "Restored default layout to base settings." -msgstr "פריסת בררת המחדל שוחזרה להגדרות הבסיס." +msgstr "פריסת ברירת המחדל שוחזרה להגדרות הבסיס." #: editor/editor_node.cpp msgid "" @@ -2333,20 +2319,24 @@ msgid "" "Please read the documentation relevant to importing scenes to better " "understand this workflow." msgstr "" +"מש×ב ×–×” שייך ×œ×¡×¦× ×” שיוב××” ×•×œ× × ×™×ª×Ÿ לעריכה.\n" +"בבקשה קר×/×™ ×ת התיעוד הקשור ×œ×™×™×‘×•× ×¡×¦× ×•×ª כדי להבין טוב יותר ×ת שיטת עבודה." #: editor/editor_node.cpp msgid "" "This resource belongs to a scene that was instanced or inherited.\n" "Changes to it won't be kept when saving the current scene." msgstr "" +"מש×ב ×–×” שייך ×œ×¡×¦× ×” ×©× ×•×¦×¨ לה מופע ×ו שעברה ירושה.\n" +"×©×™× ×•×™×™× ×‘×ž×©×ב ×œ× ×™×™×©×ž×¨×• בשמירת ×”×¡×¦×™× ×” ×”× ×•×›×—×™×ª." #: editor/editor_node.cpp msgid "" "This resource was imported, so it's not editable. Change its settings in the " "import panel and then re-import." msgstr "" -"מש×ב ×–×” עבר יבו×, לכן ×ין ×פשרות לערוך ×ותו. יש ×œ×©× ×•×ª ×ת ההגדרות שלו ×‘×—×œ×•× ×™×ª " -"×”×™×™×‘×•× ×•××– ×œ×™×™×‘× ×©×•×‘." +"מש×ב ×–×” ×ž×™×•×‘× ×•×ין ×פשרות לערוך ×ותו. יש ×œ×©× ×•×ª ×ת הגדרותיו בחלון ×”×™×™×‘×•× " +"×•×œ×™×™×‘× ×ž×—×“×©." #: editor/editor_node.cpp msgid "" @@ -2355,6 +2345,9 @@ msgid "" "Please read the documentation relevant to importing scenes to better " "understand this workflow." msgstr "" +"×¡×¦× ×” זו מיוב×ת, כל ×©×™× ×•×™ בה ×œ× ×™×™×©×ž×¨.\n" +"יצירת מופע ×ו ירושה ת×פשר לעשות בה ×©×™× ×•×™×™×.\n" +"בבקשה קר×/×™ ×ת התיעוד הקשור ×œ×™×™×‘×•× ×¡×¦× ×•×ª כדי להבין טוב יותר ×ת שיטת העבודה." #: editor/editor_node.cpp msgid "" @@ -2362,6 +2355,8 @@ msgid "" "Please read the documentation relevant to debugging to better understand " "this workflow." msgstr "" +"זהו ×ובייקט מרוחק לכן ×©×™× ×•×™×™× ×‘×• ×œ× ×™×™×©×ž×¨×•.\n" +"בבקשה קר×/×™ ×ת התיועד הקשור ×œ× ×™×¤×•×™ שגי×ות כדי להבין טוב יותר ×ת שיטת העבודה." #: editor/editor_node.cpp msgid "There is no defined scene to run." @@ -2380,9 +2375,8 @@ msgid "Open Base Scene" msgstr "פתיחת ×¡×¦× ×ª בסיס" #: editor/editor_node.cpp -#, fuzzy msgid "Quick Open..." -msgstr "פתיחת ×¡×¦× ×” מהירה…" +msgstr "פתיחה מהירה…" #: editor/editor_node.cpp msgid "Quick Open Scene..." @@ -2398,16 +2392,15 @@ msgstr "שמירה וסגירה" #: editor/editor_node.cpp msgid "Save changes to '%s' before closing?" -msgstr "לשמור ×ת ×”×©×™× ×•×™×™× ×œÖ¾â€š%s’ ×œ×¤× ×™ הסגירה?" +msgstr "לשמור ×ת ×”×©×™× ×•×™×™× ×œÖ¾'%s' ×œ×¤× ×™ הסגירה?" #: editor/editor_node.cpp -#, fuzzy msgid "Saved %s modified resource(s)." -msgstr "×˜×¢×™× ×ª המש×ב × ×›×©×œ×”." +msgstr "× ×©×ž×¨×• %s מש××‘×™× ×©×”×©×ª× ×•." #: editor/editor_node.cpp msgid "A root node is required to save the scene." -msgstr "" +msgstr "מפרק עליון דרוש כדי לשמור ×ת ×”×¡×¦×™× ×”." #: editor/editor_node.cpp msgid "Save Scene As..." @@ -2431,7 +2424,7 @@ msgstr "×œ× × ×™×ª×Ÿ לבצע פעולה זו ×œ×œ× ×¡×¦× ×”." #: editor/editor_node.cpp msgid "Export Mesh Library" -msgstr "" +msgstr "×™×™×¦×•× Mesh Library" #: editor/editor_node.cpp msgid "This operation can't be done without a root node." @@ -2439,7 +2432,7 @@ msgstr "×œ× × ×™×ª×Ÿ לבצע פעולה זו ×œ×œ× ×ž×¤×¨×§ עליון." #: editor/editor_node.cpp msgid "Export Tile Set" -msgstr "" +msgstr "×™×™×¦×•× Tile Set" #: editor/editor_node.cpp msgid "This operation can't be done without a selected node." @@ -2454,19 +2447,20 @@ msgid "Can't reload a scene that was never saved." msgstr "×œ× × ×™×ª×Ÿ ×œ×¨×¢× ×Ÿ ×¡×¦× ×” ×©×ž×¢×•×œ× ×œ× × ×©×ž×¨×”." #: editor/editor_node.cpp -#, fuzzy msgid "Reload Saved Scene" -msgstr "שמירת ×¡×¦× ×”" +msgstr "×˜×¢×™× ×” מחדש של ×¡×¦×™× ×” שמורה" #: editor/editor_node.cpp 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..." -msgstr "" +msgstr "הפעלה מהירה של ×”×¡×¦× ×”..." #: editor/editor_node.cpp msgid "Quit" @@ -2509,56 +2503,61 @@ msgid "Close Scene" msgstr "סגירת ×¡×¦× ×”" #: editor/editor_node.cpp -#, fuzzy msgid "Reopen Closed Scene" -msgstr "סגירת ×¡×¦× ×”" +msgstr "פתיחה מחדש של ×¡×¦× ×” סגורה" #: editor/editor_node.cpp msgid "Unable to enable addon plugin at: '%s' parsing of config failed." -msgstr "×œ× × ×™×ª×Ÿ לפתוח ×ת תוסף ההרחבות תחת: ‚%s’ ×¤×¢× ×•×— ההגדרות × ×›×©×œ." +msgstr "×œ× × ×™×ª×Ÿ לפתוח ×ת תוסף ההרחבות ×‘× ×ª×™×‘: '%s' ×¤×¢× ×•×— ההגדרות × ×›×©×œ." #: editor/editor_node.cpp msgid "Unable to find script field for addon plugin at: 'res://addons/%s'." -msgstr "×œ× × ×™×ª×Ÿ ×œ×ž×¦×•× ×©×“×” סקריפט עבור תוסף הרחבה תחת ‚res://addons/%s’." +msgstr "×œ× × ×™×ª×Ÿ ×œ×ž×¦×•× ×©×“×” סקריפט עבור תוסף הרחבה ×‘× ×ª×™×‘ 'res://addons/%s'." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s'." -msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž×”× ×ª×™×‘: ‚%s’." +msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž× ×ª×™×‘: '%s'." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' There seems to be an error in " "the code, please check the syntax." msgstr "" +"×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž× ×ª×™×‘: '%s' × ×¨××” שיש שגי××” בקוד, ×× × ×‘×“×•×§ ×ת " +"התחביר." #: editor/editor_node.cpp msgid "" "Unable to load addon script from path: '%s' Base type is not EditorPlugin." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž× ×ª×™×‘: '%s' סוג הבסיס ××™× ×• EditorPlugin." #: editor/editor_node.cpp msgid "Unable to load addon script from path: '%s' Script is not in tool mode." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ לטעון סקריפט הרחבה ×ž× ×ª×™×‘: '%s' סקריפט ××™× ×• מוגדר ככלי (tool)." #: editor/editor_node.cpp msgid "" "Scene '%s' was automatically imported, so it can't be modified.\n" "To make changes to it, a new inherited scene can be created." msgstr "" +"×”×¡×¦×™× ×” '%s' יוב××” ב×ופן ×וטומטי ו×ין ×פשרות ×œ×©× ×•×ª ×ותה.\n" +"כדי לבצע בה ×©×™× ×•×™×™×, × ×™×ª×Ÿ ליצור ×¡×¦×™× ×” חדשה בירושה." #: editor/editor_node.cpp msgid "" "Error loading scene, it must be inside the project path. Use 'Import' to " "open the scene, then save it inside the project path." msgstr "" +"שגי××” ×‘×˜×¢×™× ×ª ×”×¡×¦× ×”, ×”×™× ×—×™×™×‘×ª להיות בתוך × ×ª×™×‘ המיז×. השתמש ב'ייבו×' כדי " +"לפתוח ×ת ×”×¡×¦×™× ×”, ו××– שמור ×ותה ×‘× ×ª×™×‘ המיז×." #: editor/editor_node.cpp msgid "Scene '%s' has broken dependencies:" -msgstr "" +msgstr "×œ×¡×¦×™× ×” '%s' יש תלות חסרה:" #: editor/editor_node.cpp msgid "Clear Recent Scenes" -msgstr "" +msgstr "× ×§×” ×¡×¦×™× ×•×ª ××—×¨×•× ×•×ª" #: editor/editor_node.cpp msgid "" @@ -2566,6 +2565,8 @@ msgid "" "You can change it later in \"Project Settings\" under the 'application' " "category." msgstr "" +"×œ× ×”×•×’×“×¨×” ×¡×¦× ×” ר×שית, לבחור ×חת?\n" +"×פשר ×œ×©× ×•×ª ×–×ת מ×וחר יותר ב-\"הגדרות מיז×\" תחת הקטגוריה 'יישו×'." #: editor/editor_node.cpp msgid "" @@ -2573,6 +2574,8 @@ msgid "" "You can change it later in \"Project Settings\" under the 'application' " "category." msgstr "" +"×”×¡×¦×™× ×” ×©× ×‘×—×¨×” '%s' ×œ× ×§×™×™×ž×ª, לבחור ×¡×¦× ×” קיימת?\n" +"×פשר ×œ×©× ×•×ª ×–×ת מ×וחר יותר ב\"הגדרות מיז×\" תחת הקטגוריה 'יישו×'." #: editor/editor_node.cpp msgid "" @@ -2580,81 +2583,78 @@ msgid "" "You can change it later in \"Project Settings\" under the 'application' " "category." msgstr "" +"×”×¡×¦×™× ×” ×©× ×‘×—×¨×” '%s' ××™× ×” קובץ ×¡×¦×™× ×”, לבחור קובץ ×¡×¦×™× ×” ×חר?\n" +"×פשר ×œ×©× ×•×ª ×–×ת מ×וחר יותר ב-\"הגדרות מיז×\" תחת הקטגוריה 'יישו×'." #: editor/editor_node.cpp msgid "Save Layout" -msgstr "" +msgstr "שמירת פריסה" #: editor/editor_node.cpp msgid "Delete Layout" -msgstr "" +msgstr "מחיקת פריסה" #: editor/editor_node.cpp editor/import_dock.cpp #: editor/script_create_dialog.cpp msgid "Default" -msgstr "" +msgstr "בחירת מחדל" #: editor/editor_node.cpp editor/editor_properties.cpp #: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp -#, fuzzy msgid "Show in FileSystem" -msgstr "הצגה במערכת הקבצי×" +msgstr "הצגה בחלון הקבצי×" #: editor/editor_node.cpp -#, fuzzy msgid "Play This Scene" -msgstr "× ×’×™× ×ª ×”×¡×¦× ×”" +msgstr "הרצת ×”×¡×¦× ×”" #: editor/editor_node.cpp -#, fuzzy msgid "Close Tab" -msgstr "לסגור ×œ×©×•× ×™×•×ª ×חרות" +msgstr "סגירת ×œ×©×•× ×™×ª" #: editor/editor_node.cpp -#, fuzzy msgid "Undo Close Tab" -msgstr "לסגור ×œ×©×•× ×™×•×ª ×חרות" +msgstr "ביטול סגירת ×œ×©×•× ×™×ª" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Close Other Tabs" -msgstr "לסגור ×œ×©×•× ×™×•×ª ×חרות" +msgstr "סגירת ×œ×©×•× ×™×•×ª ×חרות" #: editor/editor_node.cpp msgid "Close Tabs to the Right" -msgstr "" +msgstr "סגירת ×œ×©×•× ×™×•×ª מימין" #: editor/editor_node.cpp -#, fuzzy msgid "Close All Tabs" -msgstr "לסגור הכול" +msgstr "סגירת כל ×”×œ×©×•× ×™×•×ª" #: editor/editor_node.cpp msgid "Switch Scene Tab" -msgstr "" +msgstr "החלפת ×œ×©×•× ×™×ª ×¡×¦× ×”" #: editor/editor_node.cpp msgid "%d more files or folders" -msgstr "" +msgstr "%d ×§×‘×¦×™× ×ו תיקיות × ×•×¡×¤×™×" #: editor/editor_node.cpp msgid "%d more folders" -msgstr "" +msgstr "%d תיקיות × ×•×¡×¤×•×ª" #: editor/editor_node.cpp msgid "%d more files" -msgstr "" +msgstr "%d ×§×‘×¦×™× × ×•×¡×¤×™×" #: editor/editor_node.cpp msgid "Dock Position" -msgstr "" +msgstr "×ž×™×§×•× ×”×¤× ×œ" #: editor/editor_node.cpp msgid "Distraction Free Mode" -msgstr "" +msgstr "מצב ×œ×œ× ×”×¡×—×•×ª דעת" #: editor/editor_node.cpp msgid "Toggle distraction-free mode." -msgstr "" +msgstr "הפעל/בטל מצב ×œ×œ× ×”×¡×—×•×ª דעת." #: editor/editor_node.cpp msgid "Add a new scene." @@ -2666,12 +2666,11 @@ msgstr "×¡×¦× ×”" #: editor/editor_node.cpp msgid "Go to previously opened scene." -msgstr "מעבר ×œ×¡×¦× ×” ×©× ×¤×ª×—×” ×§×•×“× ×œ×›×Ÿ." +msgstr "מעבר ×œ×¡×¦× ×” הקודמת." #: editor/editor_node.cpp -#, fuzzy msgid "Copy Text" -msgstr "העתקת × ×ª×™×‘" +msgstr "העתקת טקסט" #: editor/editor_node.cpp msgid "Next tab" @@ -2683,7 +2682,7 @@ msgstr "×”×œ×©×•× ×™×ª הקודמת" #: editor/editor_node.cpp msgid "Filter Files..." -msgstr "" +msgstr "×¡× ×Ÿ קבצי×..." #: editor/editor_node.cpp msgid "Operations with scene files." @@ -2710,7 +2709,6 @@ msgid "Save Scene" msgstr "שמירת ×¡×¦× ×”" #: editor/editor_node.cpp -#, fuzzy msgid "Save All Scenes" msgstr "שמירת כל ×”×¡×¦× ×•×ª" @@ -2720,11 +2718,11 @@ msgstr "המרה ×ל…" #: editor/editor_node.cpp msgid "MeshLibrary..." -msgstr "" +msgstr "MeshLibrary..." #: editor/editor_node.cpp msgid "TileSet..." -msgstr "" +msgstr "TileSet..." #: editor/editor_node.cpp editor/plugins/script_text_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp @@ -2750,17 +2748,16 @@ msgid "Project Settings..." msgstr "הגדרות מיז×..." #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp -#, fuzzy msgid "Version Control" -msgstr "גרסה:" +msgstr "בקרת גירס×ות" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Set Up Version Control" -msgstr "" +msgstr "קביעת בקרת גירס×ות" #: editor/editor_node.cpp msgid "Shut Down Version Control" -msgstr "" +msgstr "סגור בקרת גירס×ות" #: editor/editor_node.cpp msgid "Export..." @@ -2768,7 +2765,7 @@ msgstr "ייצו×..." #: editor/editor_node.cpp msgid "Install Android Build Template..." -msgstr "" +msgstr "×”×ª×§× ×ª ×ª×‘× ×™×ª ×‘× ×™×™×” ל×× ×“×¨×•×יד..." #: editor/editor_node.cpp msgid "Open Project Data Folder" @@ -2784,7 +2781,7 @@ msgstr "סייר מש××‘×™× ×™×ª×•×ž×™× ..." #: editor/editor_node.cpp msgid "Quit to Project List" -msgstr "יצי××” לרשימת המיזמי×" +msgstr "יצי××” לרשימת מיזמי×" #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: editor/project_export.cpp @@ -2816,16 +2813,22 @@ msgid "" "On Android, deploy will use the USB cable for faster performance. This " "option speeds up testing for games with a large footprint." msgstr "" +"×›×שר ×פשרות זו מופעלת, ×™×™×¦×•× ×ו פריסה יפיקו קובץ הפעלה ×ž×™× ×™×ž×œ×™.\n" +"מערכת ×”×§×‘×¦×™× ×ª×¡×•×¤×§ ×ž×”×ž×™×–× ×¢×œ ידי העורך ברשת.\n" +"ב×× ×“×¨×•×יד, הפריסה תשתמש בכבל USB ×œ×‘×™×¦×•×¢×™× ×ž×”×™×¨×™× ×™×•×ª×¨. ×פשרות זו מזרזת בדיקה " +"של ×ž×©×—×§×™× ×¢× ×§×•×‘×¥ הרצה גדול." #: editor/editor_node.cpp msgid "Visible Collision Shapes" -msgstr "" +msgstr "צורות ×”×ª× ×’×©×•×ª גלויי×" #: editor/editor_node.cpp msgid "" "Collision shapes and raycast nodes (for 2D and 3D) will be visible on the " "running game if this option is turned on." msgstr "" +"צורות ×”×ª× ×’×©×•×™×•×ª ומפרקי ×§×¨× ×™×™× (עבור דו ותלת מימד) יהיו ×’×œ×•×™×™× ×‘×”×¨×¦×ª המשחק ×× " +"×פשרות ×–×ת מופעלת." #: editor/editor_node.cpp msgid "Visible Navigation" @@ -2835,7 +2838,7 @@ msgstr "× ×™×•×•×˜ גלוי" msgid "" "Navigation meshes and polygons will be visible on the running game if this " "option is turned on." -msgstr "" +msgstr "רשתות × ×™×•×•×˜ ×•×ž×¦×•×œ×¢×™× ×™×”×™×• ×’×œ×•×™×™× ×‘×”×¨×¦×ª המשחק ×× ×פשרות ×–×ת מופעלת." #: editor/editor_node.cpp msgid "Sync Scene Changes" @@ -2848,6 +2851,8 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" +"×›×שר ×פשרות זו מופעלת, כל ×”×©×™× ×•×™×™× ×©×™×‘×•×¦×¢×• ×‘×¡×¦× ×” בעורך יוצגו בהרצת המשחק.\n" +"בשימוש ×¢× ×ž×›×©×™×¨ מרוחק, מערכת ×§×‘×¦×™× ×‘×¨×©×ª (NFS) תהיה יעילה יותר ." #: editor/editor_node.cpp msgid "Sync Script Changes" @@ -2860,6 +2865,8 @@ msgid "" "When used remotely on a device, this is more efficient with network " "filesystem." msgstr "" +"×›×שר ×פשרות זו מופעלת, כל סקריפט ×©× ×©×ž×¨ יטען מחדש בהרצת המשחק.\n" +"בשימוש ×¢× ×ž×›×©×™×¨ מרוחק, מערכת ×§×‘×¦×™× ×‘×¨×©×ª (NFS) תהיה יעילה יותר ." #: editor/editor_node.cpp editor/script_create_dialog.cpp msgid "Editor" @@ -2874,46 +2881,40 @@ msgid "Editor Layout" msgstr "פריסת עורך" #: editor/editor_node.cpp -#, fuzzy msgid "Take Screenshot" -msgstr "שמירת ×¡×¦× ×”" +msgstr "שמירת ×¦×™×œ×•× ×ž×¡×š" #: editor/editor_node.cpp -#, fuzzy msgid "Screenshots are stored in the Editor Data/Settings Folder." -msgstr "הגדרות עורך" +msgstr "צילומי מסך × ×©×ž×¨×™× ×‘×ª×™×§×™×™×ª × ×ª×•× ×™/הגדרות העורך." #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "×›× ×™×¡×” ×ל/יצי××” ממסך מל×" +msgstr "הפעלת/ביטול מסך מל×" #: editor/editor_node.cpp -#, fuzzy msgid "Toggle System Console" -msgstr "החלפת מצב" +msgstr "הפעלת/ביטול מסוף מערכת" #: editor/editor_node.cpp msgid "Open Editor Data/Settings Folder" -msgstr "פתח תיקיית × ×ª×•× ×™×/הגדרות של העורך" +msgstr "פתיחת תיקיית × ×ª×•× ×™/הגדרות העורך" #: editor/editor_node.cpp msgid "Open Editor Data Folder" -msgstr "" +msgstr "פתיחת תיקיית × ×ª×•× ×™ העורך" #: editor/editor_node.cpp -#, fuzzy msgid "Open Editor Settings Folder" -msgstr "הגדרות עורך" +msgstr "פתיחת תיקיית הגדרות העורך" #: editor/editor_node.cpp -#, fuzzy msgid "Manage Editor Features..." -msgstr "× ×™×”×•×œ ×ª×‘× ×™×•×ª ייצו×" +msgstr "× ×™×”×•×œ ×ª×›×•× ×•×ª העורך..." #: editor/editor_node.cpp -#, fuzzy msgid "Manage Export Templates..." -msgstr "× ×™×”×•×œ ×ª×‘× ×™×•×ª ייצו×" +msgstr "× ×™×”×•×œ ×ª×‘× ×™×•×ª ייצו×..." #: editor/editor_node.cpp editor/plugins/shader_editor_plugin.cpp msgid "Help" @@ -2938,13 +2939,12 @@ msgid "Q&A" msgstr "ש×לות ותשובות × ×¤×•×¦×•×ª" #: editor/editor_node.cpp -#, fuzzy msgid "Report a Bug" -msgstr "×™×™×‘×•× ×ž×—×“×©" +msgstr "דיווח על תקלה (ב××’)" #: editor/editor_node.cpp msgid "Send Docs Feedback" -msgstr "" +msgstr "שליחת משוב על התיעוד" #: editor/editor_node.cpp editor/plugins/asset_library_editor_plugin.cpp msgid "Community" @@ -2952,19 +2952,19 @@ msgstr "קהילה" #: editor/editor_node.cpp msgid "About" -msgstr "על" +msgstr "על ×ודות" #: editor/editor_node.cpp msgid "Play the project." -msgstr "× ×’×™× ×ª המיז×…" +msgstr "הרצת המיז×." #: editor/editor_node.cpp msgid "Play" -msgstr "× ×’×™× ×”" +msgstr "הרצה" #: editor/editor_node.cpp msgid "Pause the scene execution for debugging." -msgstr "" +msgstr "הפסקת הרצת ×”×¡×¦× ×” ×œ× ×™×¤×•×™ שגי×ות." #: editor/editor_node.cpp msgid "Pause Scene" @@ -2976,49 +2976,44 @@ msgstr "עצירת ×”×¡×¦× ×”." #: editor/editor_node.cpp msgid "Play the edited scene." -msgstr "× ×’×™× ×ª ×”×¡×¦× ×” ×©× ×¢×¨×›×”." +msgstr "הרצת ×”×¡×¦× ×” ×©× ×¢×¨×›×”." #: editor/editor_node.cpp msgid "Play Scene" -msgstr "× ×’×™× ×ª ×”×¡×¦× ×”" +msgstr "הרצת ×”×¡×¦× ×”" #: editor/editor_node.cpp msgid "Play custom scene" -msgstr "× ×’×™× ×ª ×¡×¦× ×” מות×מת ×ישית" +msgstr "הרצת ×¡×¦× ×” מות×מת ×ישית" #: editor/editor_node.cpp msgid "Play Custom Scene" -msgstr "× ×’×™× ×ª ×¡×¦× ×” בהת×מה ×ישית" +msgstr "הרצת ×¡×¦× ×” בהת×מה ×ישית" #: editor/editor_node.cpp msgid "Changing the video driver requires restarting the editor." -msgstr "" +msgstr "×©×™× ×•×™ ×ž× ×”×œ התקן הוויד×ו דורש הפעלת העורך מחדש." #: editor/editor_node.cpp editor/project_settings_editor.cpp #: editor/settings_config_dialog.cpp -#, fuzzy msgid "Save & Restart" -msgstr "לשמור ולצ×ת" +msgstr "שמירה והפעלה מחדש" #: editor/editor_node.cpp -#, fuzzy msgid "Spins when the editor window redraws." -msgstr "מסתובב ×›×שר חלון העורך מצויר מחדש!" +msgstr "מסתובב ×›×שר חלון העורך מצויר מחדש." #: editor/editor_node.cpp -#, fuzzy msgid "Update Continuously" -msgstr "מתמשך" +msgstr "עדכון רציף" #: editor/editor_node.cpp -#, fuzzy msgid "Update When Changed" -msgstr "עדכון ×©×™× ×•×™×™×" +msgstr "עדכון בעת ×©×™× ×•×™" #: editor/editor_node.cpp -#, fuzzy msgid "Hide Update Spinner" -msgstr "השבתת שבשבת עדכון" +msgstr "הסתרת מחוון העדכון" #: editor/editor_node.cpp msgid "FileSystem" @@ -3029,9 +3024,8 @@ msgid "Inspector" msgstr "חוקר" #: editor/editor_node.cpp -#, fuzzy msgid "Expand Bottom Panel" -msgstr "להרחיב הכול" +msgstr "הרחבת פ×× ×œ תחתון" #: editor/editor_node.cpp msgid "Output" @@ -3043,12 +3037,11 @@ msgstr "×œ× ×œ×©×ž×•×¨" #: editor/editor_node.cpp msgid "Android build template is missing, please install relevant templates." -msgstr "" +msgstr "חסרה ×ª×‘× ×™×ª ×‘× ×™×™×” ל×× ×“×¨×•×יד, × × ×œ×”×ª×§×™×Ÿ ×ª×‘× ×™×•×ª ×¨×œ×•×•× ×˜×™×•×ª." #: editor/editor_node.cpp -#, fuzzy msgid "Manage Templates" -msgstr "× ×™×”×•×œ ×ª×‘× ×™×•×ª ייצו×" +msgstr "× ×™×”×•×œ ×ª×‘× ×™×•×ª" #: editor/editor_node.cpp msgid "" @@ -3060,6 +3053,12 @@ msgid "" "the \"Use Custom Build\" option should be enabled in the Android export " "preset." msgstr "" +"פעולה זו תגדיר ×ת ×”×ž×™×–× ×©×œ×š ×œ×‘× ×™×™×ª ×× ×“×¨×•×יד מות×מת ×ישית על ידי ×”×ª×§× ×ª ×ª×‘× ×™×ª " +"המקור ל- \"res://android/build\".\n" +"ל×חר מכן ×פשר להחיל ×©×™× ×•×™×™× ×•×œ×‘× ×•×ª APK מות×× ×ישית ×‘×™×™×¦×•× (הוספת מודולי×, " +"×©×™× ×•×™ AndroidManifest.xml, וכו').\n" +"כדי לערוך ×‘× ×™×™×” מות×מת ×ישית ×‘×ž×§×•× ×©×™×ž×•×© ×‘×ª×‘× ×™×ª קיימת, יש ל×פשר ×ת \"השתמש " +"×‘×‘× ×™×” מות×מת ×ישית\" בהגדרות ×”×™×™×¦×•× ×œ×× ×“×¨×•×יד." #: editor/editor_node.cpp msgid "" @@ -3127,9 +3126,8 @@ msgid "Open the previous Editor" msgstr "פתיחת העורך הקוד×" #: editor/editor_node.h -#, fuzzy msgid "Warning!" -msgstr "×זהרות" +msgstr "×זהרה!" #: editor/editor_path.cpp msgid "No sub-resources found." @@ -3596,9 +3594,8 @@ msgid "Download Templates" msgstr "הורדת ×ª×‘× ×™×•×ª" #: editor/export_template_manager.cpp -#, fuzzy msgid "Select mirror from list: (Shift+Click: Open in Browser)" -msgstr "בחירת ×תר מר××” מהרשימה: " +msgstr "בחר ×תר חלופי מהרשימה: (Shift+Click: פתיחה בדפדפן)" #: editor/filesystem_dock.cpp #, fuzzy @@ -3663,9 +3660,8 @@ msgid "Duplicating folder:" msgstr "תיקייה משוכפלת:" #: editor/filesystem_dock.cpp -#, fuzzy msgid "New Inherited Scene" -msgstr "×¡×¦× ×” חדשה בירושה…" +msgstr "×¡×¦× ×” חדשה יורשת" #: editor/filesystem_dock.cpp #, fuzzy @@ -3800,9 +3796,8 @@ msgid "Create Script" msgstr "יצירת סקריפט" #: editor/find_in_files.cpp editor/plugins/script_editor_plugin.cpp -#, fuzzy msgid "Find in Files" -msgstr "×יתור…" +msgstr "×יתור בקבצי×" #: editor/find_in_files.cpp #, fuzzy @@ -3869,9 +3864,8 @@ msgid "Remove from Group" msgstr "הסרה מקבוצה" #: editor/groups_editor.cpp -#, fuzzy msgid "Group name already exists." -msgstr "הפעולה ‚%s’ כבר קיימת!" +msgstr "×©× ×”×§×‘×•×¦×” כבר קיי×." #: editor/groups_editor.cpp #, fuzzy @@ -4064,9 +4058,8 @@ msgid "Copy Params" msgstr "העתקת ×ž×©×ª× ×™×" #: editor/inspector_dock.cpp -#, fuzzy msgid "Edit Resource Clipboard" -msgstr "לוח גזירי המש××‘×™× ×¨×™×§!" +msgstr "ערוך לוח העתקת מש×בי×" #: editor/inspector_dock.cpp msgid "Copy Resource" @@ -4308,9 +4301,8 @@ msgid "Open Animation Node" msgstr "×©× ×”× ×¤×©×” חדשה:" #: editor/plugins/animation_blend_space_2d_editor.cpp -#, fuzzy msgid "Triangle already exists." -msgstr "הפעולה ‚%s’ כבר קיימת!" +msgstr "המשולש כבר קיי×." #: editor/plugins/animation_blend_space_2d_editor.cpp #, fuzzy @@ -4365,14 +4357,13 @@ msgid "Blend:" msgstr "" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Parameter Changed" -msgstr "×©×™× ×•×™×™ חומרי×" +msgstr "×ž×©×ª× ×” ×”×©×ª× ×”" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Edit Filters" -msgstr "" +msgstr "עריכת ×ž×¡× × ×™×" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Output node can't be added to the blend tree." @@ -4405,15 +4396,14 @@ msgid "Nodes Disconnected" msgstr "×ž× ×•×ª×§" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Set Animation" -msgstr "×©× ×”× ×¤×©×” חדשה:" +msgstr "קביעת ×”× ×¤×©×”" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp #, fuzzy msgid "Delete Node" -msgstr "מחיקת שורה" +msgstr "מחק מפרק" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/scene_tree_dock.cpp @@ -4508,9 +4498,8 @@ msgid "Remove Animation" msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Invalid animation name!" -msgstr "×©× ×©×’×•×™." +msgstr "×©× ×”× ×¤×©×” ×œ× ×—×•×§×™!" #: editor/plugins/animation_player_editor_plugin.cpp #, fuzzy @@ -4539,14 +4528,12 @@ msgid "Duplicate Animation" msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "No animation to copy!" -msgstr "תקריב ×”× ×¤×©×”." +msgstr "×ין ×”× ×¤×©×” להעתקה!" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "No animation resource on clipboard!" -msgstr "×œ× ×‘× ×ª×™×‘ המש×ב." +msgstr "×ין מש×ב ×”× ×¤×©×” בלוח ההעתקה!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Pasted Animation" @@ -4557,9 +4544,8 @@ msgid "Paste Animation" msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "No animation to edit!" -msgstr "×©× ×”× ×¤×©×” חדשה:" +msgstr "×ין ×”× ×¤×©×” לעריכה!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from current pos. (A)" @@ -4702,9 +4688,8 @@ msgid "Move Node" msgstr "מצב ×”×–×–×” (W)" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition exists!" -msgstr "מעברון" +msgstr "המעברון קיי×!" #: editor/plugins/animation_state_machine_editor.cpp #, fuzzy @@ -6473,7 +6458,7 @@ msgstr "הזזת × ×§×•×“×”" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "" "The skeleton property of the Polygon2D does not point to a Skeleton2D node" -msgstr "" +msgstr "מ×פיין 'skeleton' של Polygon2D ××™× ×• מצביע על מפרק Skeleton2D" #: editor/plugins/polygon_2d_editor_plugin.cpp #, fuzzy @@ -6648,9 +6633,8 @@ msgid "Show Grid" msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp -#, fuzzy msgid "Configure Grid:" -msgstr "הגדרת הצמדה…" +msgstr "הגדר רשת:" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid Offset X:" @@ -7038,9 +7022,8 @@ msgid "Line" msgstr "שורה:" #: editor/plugins/script_text_editor.cpp -#, fuzzy msgid "Go to Function" -msgstr "מעבר ×œ×¤×•× ×§×¦×™×”â€¦" +msgstr "עבור ×œ×¤×•× ×§×¦×™×”" #: editor/plugins/script_text_editor.cpp msgid "Only resources from filesystem can be dropped." @@ -8841,9 +8824,8 @@ msgid "Create Shader Node" msgstr "יצירת תיקייה" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color function." -msgstr "מעבר ×œ×¤×•× ×§×¦×™×”â€¦" +msgstr "×¤×•× ×§×¦×™×™×ª צבע." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Color operator." @@ -9333,9 +9315,8 @@ msgid "Transform uniform." msgstr "התמרה" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Vector function." -msgstr "מעבר ×œ×¤×•× ×§×¦×™×”â€¦" +msgstr "×¤×•× ×§×¦×™×” וקטורית." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Vector operator." @@ -9983,6 +9964,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "×ž× ×”×œ המיזמי×" @@ -10061,9 +10043,8 @@ msgid "" msgstr "" #: editor/project_settings_editor.cpp -#, fuzzy msgid "An action with the name '%s' already exists." -msgstr "הפעולה ‚%s’ כבר קיימת!" +msgstr "פעולה ×¢× ×”×©× '%s' כבר קיימת." #: editor/project_settings_editor.cpp msgid "Rename Input Action Event" @@ -10657,7 +10638,6 @@ msgid "Delete %d nodes and any children?" msgstr "מחיקת שורה" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes?" msgstr "מחק %d מפרקי×?" @@ -10953,19 +10933,16 @@ msgid "Select a Node" msgstr "" #: editor/script_create_dialog.cpp -#, fuzzy msgid "Path is empty." -msgstr "לוח גזירי המש××‘×™× ×¨×™×§!" +msgstr "×”× ×ª×™×‘ ריק." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Filename is empty." -msgstr "לוח גזירי המש××‘×™× ×¨×™×§!" +msgstr "×©× ×”×§×•×‘×¥ ריק." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Path is not local." -msgstr "×”× ×ª×™×‘ ×œ× ×ž×•×‘×™×œ מפרק!" +msgstr "×”× ×ª×™×‘ ××™× ×• מקומי." #: editor/script_create_dialog.cpp #, fuzzy @@ -11063,9 +11040,8 @@ msgid "Will load an existing script file." msgstr "×˜×¢×™× ×ª פריסת ×פיקי שמע." #: editor/script_create_dialog.cpp -#, fuzzy msgid "Script file already exists." -msgstr "הפעולה ‚%s’ כבר קיימת!" +msgstr "קובץ סקריפט כבר קיי×." #: editor/script_create_dialog.cpp msgid "" @@ -11642,334 +11618,324 @@ msgid "Done!" msgstr "" #: modules/visual_script/visual_script.cpp +#, fuzzy msgid "" "A node yielded without working memory, please read the docs on how to yield " "properly!" msgstr "" +"מפרק ביצע yield ×œ×œ× ×–×™×›×¨×•×Ÿ עבודה, ×× × ×§×¨× ×ת התיעוד על ×יך לעשות yield כר×וי!" #: modules/visual_script/visual_script.cpp msgid "" "Node yielded, but did not return a function state in the first working " "memory." -msgstr "" +msgstr "המפרק ביצע yield, ×בל ×œ× ×”×—×–×™×¨ ×ת מצב ×”×¤×•× ×§×¦×™×” בזיכרון העבודה הר×שון." #: modules/visual_script/visual_script.cpp msgid "" "Return value must be assigned to first element of node working memory! Fix " "your node please." msgstr "" +"יש להקצות ×ת הערך המוחזר ל××œ×ž× ×˜ הר×שון של זיכרון עבודה של המפרק! יש לתקן ×ת " +"המפרק בבקשה." #: modules/visual_script/visual_script.cpp msgid "Node returned an invalid sequence output: " -msgstr "" +msgstr "מפרק החזיר פלט סדר (sequence) ×œ× ×—×•×§×™: " #: modules/visual_script/visual_script.cpp msgid "Found sequence bit but not the node in the stack, report bug!" -msgstr "" +msgstr "סיבית הסדר (sequence bit) × ×ž×¦××” ×בל המפרק ×œ× ×‘×ž×—×¡× ×™×ª, דווח על שגי××”!" #: modules/visual_script/visual_script.cpp msgid "Stack overflow with stack depth: " -msgstr "" +msgstr "גלישת ×ž×—×¡× ×™×ª ×¢× ×¢×•×ž×§ ×ž×—×¡× ×™×ª: " #: modules/visual_script/visual_script_editor.cpp msgid "Change Signal Arguments" -msgstr "" +msgstr "×©×™× ×•×™ ××¨×’×•×ž× ×˜×™× ×©×œ ×ות" #: modules/visual_script/visual_script_editor.cpp msgid "Change Argument Type" -msgstr "" +msgstr "×©×™× ×•×™ סוג ××¨×’×•×ž× ×˜" #: modules/visual_script/visual_script_editor.cpp msgid "Change Argument name" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ××¨×’×•×ž× ×˜" #: modules/visual_script/visual_script_editor.cpp msgid "Set Variable Default Value" -msgstr "" +msgstr "קביעת ערך ברירת מחדל של ×ž×©×ª× ×”" #: modules/visual_script/visual_script_editor.cpp msgid "Set Variable Type" -msgstr "" +msgstr "קביעת סוג ×ž×©×ª× ×”" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Input Port" -msgstr "מועדפי×:" +msgstr "הוספת פורט ×›× ×™×¡×”" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Output Port" -msgstr "מועדפי×:" +msgstr "הוספת פורט יצי××”" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Override an existing built-in function." -msgstr "×©× ×©×’×•×™. ×œ× ×™×›×•×œ לחפוף ×œ×©× ×¡×•×’ ×ž×•×‘× ×” קיי×." +msgstr "דריסה של ×¤×•× ×§×¦×™×” ×ž×•×‘× ×ª קיימת." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new function." -msgstr "יצירת %s חדש" +msgstr "יצירת ×¤×•× ×§×¦×™×” חדשה." #: modules/visual_script/visual_script_editor.cpp msgid "Variables:" -msgstr "" +msgstr "×ž×©×ª× ×™×:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new variable." -msgstr "יצירת %s חדש" +msgstr "יצירת ×ž×©×ª× ×” חדש." #: modules/visual_script/visual_script_editor.cpp msgid "Signals:" msgstr "×ותות:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create a new signal." -msgstr "יצירת מצולע" +msgstr "יצירת ×ות חדש." #: modules/visual_script/visual_script_editor.cpp msgid "Name is not a valid identifier:" -msgstr "" +msgstr "×”×©× ××™× ×• מזהה חוקי:" #: modules/visual_script/visual_script_editor.cpp msgid "Name already in use by another func/var/signal:" -msgstr "" +msgstr "×”×©× ×›×‘×¨ בשימוש של ×¤×•× ×§×¦×™×”/×ž×©×ª× ×”/×ות ×חר:" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Function" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×¤×•× ×§×¦×™×”" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Variable" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×ž×©×ª× ×”" #: modules/visual_script/visual_script_editor.cpp msgid "Rename Signal" -msgstr "" +msgstr "×©×™× ×•×™ ×©× ×ות" #: modules/visual_script/visual_script_editor.cpp msgid "Add Function" -msgstr "" +msgstr "הוספת ×¤×•× ×§×¦×™×”" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Delete input port" -msgstr "הסרת × ×§×•×“×” ×‘× ×ª×™×‘" +msgstr "מחיקת פורט ×›× ×™×¡×”" #: modules/visual_script/visual_script_editor.cpp msgid "Add Variable" -msgstr "" +msgstr "הוספת ×ž×©×ª× ×”" #: modules/visual_script/visual_script_editor.cpp msgid "Add Signal" -msgstr "" +msgstr "הוספת ×ות" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove Input Port" -msgstr "הסרת × ×§×•×“×” ×‘× ×ª×™×‘" +msgstr "הסרת פורט ×›× ×™×¡×”" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Remove Output Port" -msgstr "הסרת × ×§×•×“×” ×‘× ×ª×™×‘" +msgstr "הסרת פורט יצי××”" #: modules/visual_script/visual_script_editor.cpp msgid "Change Expression" -msgstr "" +msgstr "×©×™× ×•×™ ביטוי" #: modules/visual_script/visual_script_editor.cpp msgid "Remove VisualScript Nodes" -msgstr "" +msgstr "הסרת מפרקי VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Duplicate VisualScript Nodes" -msgstr "" +msgstr "שכפול מפרקי VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"החזק ×ת %s כדי להוסיף Getter. החזק ×ת מקש Shift כדי להוסיף חתימה ×’× ×¨×™×ª." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature." msgstr "" +"החזק ×ת מקש Ctrl כדי להוסיף Getter. החזק ×ת מקש Shift כדי להוסיף חתימה ×’× ×¨×™×ª." #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a simple reference to the node." -msgstr "" +msgstr "החזק ×ת %s כדי להוסיף ×”×¤× ×™×” פשוטה למפרק." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a simple reference to the node." -msgstr "" +msgstr "החזק ×ת מקש Ctrl כדי להוסיף ×”×¤× ×™×” פשוטה למפרק." #: modules/visual_script/visual_script_editor.cpp msgid "Hold %s to drop a Variable Setter." -msgstr "" +msgstr "החזק ×ת %s כדי להוסיף Setter ×œ×ž×©×ª× ×”." #: modules/visual_script/visual_script_editor.cpp msgid "Hold Ctrl to drop a Variable Setter." -msgstr "" +msgstr "החזק ×ת מקש Ctrl כדי להוסיף  Setter ×œ×ž×©×ª× ×”." #: modules/visual_script/visual_script_editor.cpp msgid "Add Preload Node" -msgstr "" +msgstr "הוספת מפרק ×§×“× ×˜×¢×™× ×”" #: modules/visual_script/visual_script_editor.cpp msgid "Add Node(s) From Tree" -msgstr "" +msgstr "הוספת מפרק/×™× ×ž×”×¢×¥" #: modules/visual_script/visual_script_editor.cpp msgid "" "Can't drop properties because script '%s' is not used in this scene.\n" "Drop holding 'Shift' to just copy the signature." msgstr "" +"×œ× × ×™×ª×Ÿ להוסיף מ××¤×™×™× ×™× ×›×™ סקריפט '%s' ×œ× ×‘×©×™×ž×•×© ×‘×¡×¦× ×” זו.\n" +"החזקת 'Shift' בזמן הוספה תעתיק רק ×ת החתימה." #: modules/visual_script/visual_script_editor.cpp msgid "Add Getter Property" -msgstr "" +msgstr "הוספת מ×פיין ל-Getter" #: modules/visual_script/visual_script_editor.cpp msgid "Add Setter Property" -msgstr "" +msgstr "הוספת מ×פיין ל-Setter" #: modules/visual_script/visual_script_editor.cpp msgid "Change Base Type" -msgstr "" +msgstr "×©×™× ×•×™ סוג בסיס" #: modules/visual_script/visual_script_editor.cpp msgid "Move Node(s)" -msgstr "" +msgstr "הזזת מפרק(×™×)" #: modules/visual_script/visual_script_editor.cpp msgid "Remove VisualScript Node" -msgstr "" +msgstr "הסרת מפרק VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Connect Nodes" -msgstr "" +msgstr "חיבור מפרקי×" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Disconnect Nodes" -msgstr "×ž× ×•×ª×§" +msgstr "× ×™×ª×•×§ מפרקי×" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Connect Node Data" -msgstr "התחברות למפרק:" +msgstr "קישור × ×ª×•× ×™ ‫מפרק" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Connect Node Sequence" -msgstr "התחברות למפרק:" +msgstr "קישור Sequence של מפרק" #: modules/visual_script/visual_script_editor.cpp msgid "Script already has function '%s'" -msgstr "" +msgstr "לסקריפט יש כבר ×¤×•× ×§×¦×™×” '%s'" #: modules/visual_script/visual_script_editor.cpp msgid "Change Input Value" -msgstr "" +msgstr "×©×™× ×•×™ ערך × ×§×œ×˜" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Resize Comment" -msgstr "החלפת מצב הערה" +msgstr "×©×™× ×•×™ גודל הערה" #: modules/visual_script/visual_script_editor.cpp msgid "Can't copy the function node." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ להעתיק ×ת ×¤×•× ×§×¦×™×ª המפרק." #: modules/visual_script/visual_script_editor.cpp msgid "Clipboard is empty!" -msgstr "" +msgstr "לוח העתקה ריק!" #: modules/visual_script/visual_script_editor.cpp msgid "Paste VisualScript Nodes" -msgstr "" +msgstr "הדבקת מפרקי VisualScript" #: modules/visual_script/visual_script_editor.cpp msgid "Can't create function with a function node." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ ליצור ×¤×•× ×§×¦×™×” ×¢× ×¤×•× ×§×¦×™×ª המפרק." #: modules/visual_script/visual_script_editor.cpp msgid "Can't create function of nodes from nodes of multiple functions." -msgstr "" +msgstr "×œ× × ×™×ª×Ÿ ליצור ×¤×•× ×§×¦×™×” של ×ž×¤×¨×§×™× ×ž×ž×¤×¨×§×™× ×©×œ ×¤×•× ×§×¦×™×•×ª מרובות." #: modules/visual_script/visual_script_editor.cpp msgid "Select at least one node with sequence port." -msgstr "" +msgstr "בחר מפרק ×חד לפחות ×¢× ×›× ×™×¡×” רציפה (Sequence)." #: modules/visual_script/visual_script_editor.cpp msgid "Try to only have one sequence input in selection." -msgstr "" +msgstr "יש ×œ× ×¡×•×ª בחירה של רק ×›× ×™×¡×” רציפה ×חת." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Create Function" -msgstr "יצירת %s חדש" +msgstr "יצירת ×¤×•× ×§×¦×™×”" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Function" -msgstr "" +msgstr "הסרת ×¤×•× ×§×¦×™×”" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Variable" -msgstr "" +msgstr "הסרת ×ž×©×ª× ×”" #: modules/visual_script/visual_script_editor.cpp msgid "Editing Variable:" -msgstr "" +msgstr "עריכת ×ž×©×ª× ×”:" #: modules/visual_script/visual_script_editor.cpp msgid "Remove Signal" -msgstr "" +msgstr "הסרת ×ות" #: modules/visual_script/visual_script_editor.cpp msgid "Editing Signal:" -msgstr "" +msgstr "עריכת ×ות:" #: modules/visual_script/visual_script_editor.cpp msgid "Make Tool:" -msgstr "" +msgstr "יצירת כלי:" #: modules/visual_script/visual_script_editor.cpp msgid "Members:" -msgstr "חברי×:" +msgstr "שדות:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Change Base Type:" -msgstr "×©×™× ×•×™ ערך בררת המחדל" +msgstr "×©×™× ×•×™ סוג הבסיס:" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Nodes..." -msgstr "הזזת × ×§×•×“×”" +msgstr "הוספת מפרקי×..." #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Function..." -msgstr "מעבר ×œ×¤×•× ×§×¦×™×”â€¦" +msgstr "הוספת ×¤×•× ×§×¦×™×”â€¦" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "function_name" -msgstr "×¤×•× ×§×¦×™×•×ª:" +msgstr "ש×_×¤×•× ×§×¦×™×”" #: modules/visual_script/visual_script_editor.cpp msgid "Select or create a function to edit its graph." -msgstr "" +msgstr "יש לבחור ×ו ליצור ×¤×•× ×§×¦×™×” לעריכת ×”×ª×¨×©×™× ×©×œ×”." #: modules/visual_script/visual_script_editor.cpp msgid "Delete Selected" -msgstr "" +msgstr "מחיקת ×”× ×‘×—×¨" #: modules/visual_script/visual_script_editor.cpp msgid "Find Node Type" -msgstr "×יתור סוג מפרק" +msgstr "×יתור סוג המפרק" #: modules/visual_script/visual_script_editor.cpp msgid "Copy Nodes" @@ -11980,19 +11946,16 @@ msgid "Cut Nodes" msgstr "גזירת מפרקי×" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Make Function" -msgstr "×¤×•× ×§×¦×™×•×ª:" +msgstr "יצירת ×¤×•× ×§×¦×™×”" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Refresh Graph" -msgstr "×¨×¢× ×•×Ÿ" +msgstr "×¨×¢× ×•×Ÿ תרשי×" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Edit Member" -msgstr "חברי×" +msgstr "עריכת שדה" #: modules/visual_script/visual_script_flow_control.cpp msgid "Input type not iterable: " @@ -12000,11 +11963,11 @@ msgstr "סוג הקלט ×œ× ×–×ž×™×Ÿ למחזוריות: " #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid" -msgstr "" +msgstr "×יטרטור הפך ×œ×œ× ×—×•×§×™" #: modules/visual_script/visual_script_flow_control.cpp msgid "Iterator became invalid: " -msgstr "" +msgstr "×יטרטור הפך ×œ×œ× ×—×•×§×™: " #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name." @@ -12020,7 +11983,7 @@ msgstr "×”× ×ª×™×‘ ×œ× ×ž×•×‘×™×œ מפרק!" #: modules/visual_script/visual_script_func_nodes.cpp msgid "Invalid index property name '%s' in node %s." -msgstr "" +msgstr "×©× ×ž×פיין ××™× ×“×§×¡ ×œ× ×—×•×§×™ '%s' במפרק %s." #: modules/visual_script/visual_script_nodes.cpp msgid ": Invalid argument of type: " @@ -12047,43 +12010,43 @@ msgid "" "Invalid return value from _step(), must be integer (seq out), or string " "(error)." msgstr "" +"ערך מוחזר ×œ× ×—×•×§×™ מ-_step(), חייב להיות מספר ×©×œ× (seq out) ×ו מחרוזת (שגי××”)." #: modules/visual_script/visual_script_property_selector.cpp -#, fuzzy msgid "Search VisualScript" -msgstr "חיפוש בעזרה" +msgstr "חיפוש VisualScript" #: modules/visual_script/visual_script_property_selector.cpp msgid "Get %s" -msgstr "" +msgstr "קבלת %s" #: modules/visual_script/visual_script_property_selector.cpp msgid "Set %s" -msgstr "" +msgstr "קביעת %s" #: platform/android/export/export.cpp msgid "Package name is missing." -msgstr "" +msgstr "×©× ×”×—×‘×™×œ×” חסר." #: platform/android/export/export.cpp msgid "Package segments must be of non-zero length." -msgstr "" +msgstr "מקטעי החבילה ×—×™×™×‘×™× ×œ×”×™×•×ª ב×ורך ש××™× ×• ×פס." #: platform/android/export/export.cpp msgid "The character '%s' is not allowed in Android application package names." -msgstr "" +msgstr "התו '%s' ××™× ×• מותר בשמות חבילת ×™×™×©×•× ×× ×“×¨×•×יד." #: platform/android/export/export.cpp msgid "A digit cannot be the first character in a package segment." -msgstr "" +msgstr "ספרה ××™× ×” יכולה להיות התו הר×שון במקטע חבילה." #: platform/android/export/export.cpp msgid "The character '%s' cannot be the first character in a package segment." -msgstr "" +msgstr "התו '%s' ××™× ×• יכול להיות התו הר×שון במקטע חבילה." #: platform/android/export/export.cpp msgid "The package must have at least one '.' separator." -msgstr "" +msgstr "החבילה חייבת לכלול לפחות מפריד '.' ×חד." #: platform/android/export/export.cpp msgid "Select device from the list" @@ -12091,121 +12054,135 @@ msgstr "× × ×œ×‘×—×•×¨ התקן מהרשימה" #: platform/android/export/export.cpp msgid "ADB executable not configured in the Editor Settings." -msgstr "" +msgstr "קובץ ההפעלה של ADB ×œ× × ×§×‘×¢ בהגדרות העורך." #: platform/android/export/export.cpp msgid "OpenJDK jarsigner not configured in the Editor Settings." -msgstr "" +msgstr "OpenJDK jarsigner ×œ× × ×§×‘×¢ בהגדרות העורך." #: platform/android/export/export.cpp msgid "Debug keystore not configured in the Editor Settings nor in the preset." -msgstr "" +msgstr "מפתח ×œ× ×™×¤×•×™ שגי×ות ×œ× × ×§×‘×¢ בהגדרות העורך ×•×œ× ×‘×”×’×“×¨×•×ª הייצו×." #: platform/android/export/export.cpp 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." msgstr "" +"×‘× ×™×™×” מות×מת ×ישית דורשת × ×ª×™×‘ חוקי של ערכת פיתוח ל×× ×“×¨×•×יד בהגדרות העורך." #: platform/android/export/export.cpp msgid "Invalid Android SDK path for custom build in Editor Settings." msgstr "" +"× ×ª×™×‘ ×œ× ×—×•×§×™ לערכת פיתוח ×× ×“×¨×•×יד עבור ×‘× ×™×™×” מות×מת ×ישית בהגדרות העורך." #: platform/android/export/export.cpp msgid "" "Android build template not installed in the project. Install it from the " "Project menu." -msgstr "" +msgstr "×ª×‘× ×™×ª ×‘× ×™×™×” ל×× ×“×¨×•×יד ×œ× ×ž×•×ª×§× ×ª בפרוייקט. ×”×”×ª×§× ×” ×”×™× ×ž×ª×¤×¨×™×˜ המיז×." #: platform/android/export/export.cpp msgid "Invalid public key for APK expansion." -msgstr "" +msgstr "מפתח ציבורי ×œ× ×—×•×§×™ להרחבת APK." #: platform/android/export/export.cpp -#, fuzzy msgid "Invalid package name:" -msgstr "×©× ×©×’×•×™." +msgstr "×©× ×—×‘×™×œ×” ×œ× ×—×•×§×™:" #: platform/android/export/export.cpp msgid "" "Invalid \"GodotPaymentV3\" module included in the \"android/modules\" " "project setting (changed in Godot 3.2.2).\n" msgstr "" +"מודול \"GodotPaymentV3\" ×œ× ×—×•×§×™ × ×ž×¦× ×‘×”×’×“×¨×ª ×”×ž×™×–× ×‘-\"×× ×“×¨×•×יד/מודולי×" +"\" (×©×™× ×•×™ בגודו 3.2.2).\n" #: platform/android/export/export.cpp msgid "\"Use Custom Build\" must be enabled to use the plugins." -msgstr "" +msgstr "חובה ל×פשר ״שימוש ×‘×‘× ×™×” מות×מת ×ישית״ כדי להשתמש בתוספי×." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Degrees Of Freedom\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR" "\"." -msgstr "" +msgstr "\"דרגות של חופש\" תקף רק ×›×שר \"מצב Xr\" ×”×•× \"Oculus Mobile VR\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Hand Tracking\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." -msgstr "" +msgstr "\"Hand Tracking\" תקף רק ×›×שר \"מצב Xr\" ×”×•× \"Oculus Mobile VR\"." #: platform/android/export/export.cpp +#, fuzzy msgid "" "\"Focus Awareness\" is only valid when \"Xr Mode\" is \"Oculus Mobile VR\"." -msgstr "" +msgstr "\"Focus Awareness\" תקף רק ×›×שר \"מצב Xr\" ×”×•× \"Oculus Mobile VR\"." #: 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 "" +"×ž× ×¡×” ×œ×‘× ×•×ª ×ž×ª×‘× ×™×ª מות×מת ×ישית, ×ך ×œ× ×§×™×™× ×ž×™×“×¢ על גירסת ×”×‘× ×™×”. × × ×œ×”×ª×§×™×Ÿ " +"מחדש מתפריט 'Project'." #: platform/android/export/export.cpp +#, fuzzy msgid "" "Android build version mismatch:\n" " Template installed: %s\n" " Godot Version: %s\n" "Please reinstall Android build template from 'Project' menu." msgstr "" +"חוסר הת×מה בגירסת ×× ×“×¨×•×יד:\n" +" ×ª×‘× ×™×ª ×”×•×ª×§× ×”: %s\n" +" גרסת גודו: %s\n" +"× × ×œ×”×ª×§×™×Ÿ מחדש ×ת ×ª×‘× ×™×ª ×‘× ×™×™×ª ×× ×“×¨×•×יד מתפריט 'Project'." #: platform/android/export/export.cpp msgid "Building Android Project (gradle)" -msgstr "" +msgstr "×‘× ×™×™×ª ×ž×™×–× ×× ×“×¨×•×יד (gradle)" #: platform/android/export/export.cpp msgid "" "Building of Android project failed, check output for the error.\n" "Alternatively visit docs.godotengine.org for Android build documentation." msgstr "" +"×‘× ×™×™×ª ×ž×™×–× ×× ×“×¨×•×יד × ×›×©×œ×”, × ×™×ª×Ÿ לבדוק ×ת הפלט ל×יתור השגי××”.\n" +"לחלופין, ×§×™×™× ×‘- docs.godotengine.org תיעוד ×œ×‘× ×™×™×ª ×× ×“×¨×•×יד." #: platform/android/export/export.cpp msgid "No build apk generated at: " -msgstr "" +msgstr "×œ× × ×•×¦×¨ apk ב: " #: platform/iphone/export/export.cpp msgid "Identifier is missing." -msgstr "" +msgstr "מזהה חסר." #: platform/iphone/export/export.cpp msgid "The character '%s' is not allowed in Identifier." -msgstr "" +msgstr "התו '%s' ××™× ×• מותר במזהה." #: platform/iphone/export/export.cpp msgid "App Store Team ID not specified - cannot configure the project." -msgstr "" +msgstr "×œ× ×¦×•×™×Ÿ App Store Team ID - ×œ× × ×™×ª×Ÿ להגדיר ×ת המיז×." #: platform/iphone/export/export.cpp -#, fuzzy msgid "Invalid Identifier:" -msgstr "גודל הגופן שגוי." +msgstr "מזהה ×œ× ×—×•×§×™:" #: platform/iphone/export/export.cpp msgid "Required icon is not specified in the preset." -msgstr "" +msgstr "סמליל × ×“×¨×© ××™× ×• מוגדר בהגדרות יצו×." #: platform/javascript/export/export.cpp msgid "Stop HTTP Server" -msgstr "" +msgstr "עצירת שרת HTTP" #: platform/javascript/export/export.cpp msgid "Run in Browser" @@ -12240,74 +12217,74 @@ msgid "Using default boot splash image." msgstr "× ×¢×©×” שימוש ×‘×ª×ž×•× ×ª הפתיח כבררת מחדל." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package short name." -msgstr "×©× ×©×’×•×™." +msgstr "×©× ×§×¦×¨ של חבילה ×œ× ×—×•×§×™." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package unique name." -msgstr "×©× ×©×’×•×™." +msgstr "×©× ×™×—×•×“×™ של חבילה ×œ× ×—×•×§×™." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid package publisher display name." -msgstr "×©× ×©×’×•×™." +msgstr "×©× ×ª×¦×•×’×” של ×ž×¤×¨×¡× ×”×—×‘×™×œ×” ×œ× ×—×•×§×™." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid product GUID." -msgstr "×©× ×©×’×•×™." +msgstr "GUID מוצר ×œ× ×—×•×§×™." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid publisher GUID." -msgstr "× ×ª×™×‘ שגוי." +msgstr "GUID ×ž×¤×¨×¡× ×œ× ×—×•×§×™." #: platform/uwp/export/export.cpp -#, fuzzy msgid "Invalid background color." -msgstr "×©× ×©×’×•×™." +msgstr "צבע רקע ×œ× ×—×•×§×™." #: platform/uwp/export/export.cpp msgid "Invalid Store Logo image dimensions (should be 50x50)." -msgstr "" +msgstr "מידות ×ª×ž×•× ×ª לוגו ×—× ×•×ª ×œ× ×—×•×§×™×•×ª (צריכות להיות 50x50)." #: platform/uwp/export/export.cpp msgid "Invalid square 44x44 logo image dimensions (should be 44x44)." -msgstr "" +msgstr "מידות ×ª×ž×•× ×ª לוגו מרובעות 44x44 ×œ× ×—×•×§×™×•×ª (צריכות להיות 44x44)." #: platform/uwp/export/export.cpp msgid "Invalid square 71x71 logo image dimensions (should be 71x71)." -msgstr "" +msgstr "מידות ×ª×ž×•× ×ª לוגו מרובעות 71x71 ×œ× ×—×•×§×™×•×ª (צריכות להיות 71x71)." #: platform/uwp/export/export.cpp msgid "Invalid square 150x150 logo image dimensions (should be 150x150)." msgstr "" +"מידות ×ª×ž×•× ×ª לוגו מרובעות בגודל 150x150 ×œ× ×—×•×§×™×•×ª (צריכות להיות 150x150)." #: platform/uwp/export/export.cpp msgid "Invalid square 310x310 logo image dimensions (should be 310x310)." msgstr "" +"מידות ×ª×ž×•× ×ª לוגו מרובעות בגודל 310x310 ××™× ×Ÿ חוקיות (צריכות להיות 310x310)." #: platform/uwp/export/export.cpp msgid "Invalid wide 310x150 logo image dimensions (should be 310x150)." -msgstr "" +msgstr "מידות ×ª×ž×•× ×ª לוגו רחבה 310x150 ×œ× ×—×•×§×™×•×ª (צריכות להיות 310x150)." #: platform/uwp/export/export.cpp msgid "Invalid splash screen image dimensions (should be 620x300)." -msgstr "" +msgstr "מידות ×ª×ž×•× ×ª פתיח ×œ× ×—×•×§×™×•×ª (צריכות להיות 620x300)." #: scene/2d/animated_sprite.cpp msgid "" "A SpriteFrames resource must be created or set in the \"Frames\" property in " "order for AnimatedSprite to display frames." msgstr "" +"יש ליצור ×ו להגדיר מש×ב SpriteFrames במ×פיין \"Frames\" כדי ש- " +"AnimatedSprite יציג ×ª×ž×•× ×™×•×ª." #: scene/2d/canvas_modulate.cpp msgid "" "Only one visible CanvasModulate is allowed per scene (or set of instanced " "scenes). The first created one will work, while the rest will be ignored." msgstr "" +"מותר רק CanvasModulate גלוי ×חד לכל ×¡×¦× ×” (×ו סט מופעי ×¡×¦×™× ×•×ª). הר×שון ×©× ×•×¦×¨ " +"יעבוד, ו×ילו הש×ר ל×." #: scene/2d/collision_object_2d.cpp msgid "" @@ -12315,6 +12292,9 @@ msgid "" "Consider adding a CollisionShape2D or CollisionPolygon2D as a child to " "define its shape." msgstr "" +"למפרק ×–×” ×ין צורה ולכן ×”×•× ×œ× ×™×›×•×œ ×œ×”×ª× ×’×© ×ו ×œ×§×™×™× ××™× ×˜×¨×קציה ×¢× ××•×‘×™×™×§×˜×™× " +"×חרי×.\n" +"הוספת CollisionShape2D ×ו CollisionPolygon2D כילד תגדיר ×ת צורתו." #: scene/2d/collision_polygon_2d.cpp msgid "" @@ -12322,6 +12302,9 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" +"CollisionPolygon2D משמש רק להספקת צורת ×”×ª× ×’×©×•×ª למפרק היורש מ-" +"CollisionObject2D. השימוש בו ×”×•× ×¨×§ כילד של Area2D, StaticBody2D, " +"RigidBody2D, KinematicBody2D וכו'." #: scene/2d/collision_polygon_2d.cpp msgid "An empty CollisionPolygon2D has no effect on collision." @@ -12333,18 +12316,23 @@ msgid "" "CollisionObject2D derived node. Please only use it as a child of Area2D, " "StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape." msgstr "" +"CollisionShape2D משמש רק להספקת צורת ×”×ª× ×’×©×•×ª למפרק היורש מ-" +"CollisionObject2D. השימוש בו ×”×•× ×¨×§ כילד של Area2D, StaticBody2D, " +"RigidBody2D, KinematicBody2D וכו'." #: scene/2d/collision_shape_2d.cpp msgid "" "A shape must be provided for CollisionShape2D to function. Please create a " "shape resource for it!" -msgstr "" +msgstr "יש לספק צורה כדי ש-CollisionShape2D יתפקד. יש ליצור מש×ב צורה עבורו!" #: scene/2d/collision_shape_2d.cpp msgid "" "Polygon-based shapes are not meant be used nor edited directly through the " "CollisionShape2D node. Please use the CollisionPolygon2D node instead." msgstr "" +"צורות מבוססות מצולע ××™× ×Ÿ מיועדות לשימוש ×ו לעריכה ישירות דרך מפרק " +"CollisionShape2D. ×‘×ž×§×•× ×–×ת יש להשתמש במפרק מסוג CollisionPolygon2D." #: scene/2d/cpu_particles_2d.cpp msgid "" diff --git a/editor/translations/hi.po b/editor/translations/hi.po index 70d7a4d6b3..0704292af5 100644 --- a/editor/translations/hi.po +++ b/editor/translations/hi.po @@ -1115,6 +1115,9 @@ msgstr "परियोजना के संसà¥à¤¥à¤¾à¤ªà¤•" msgid "Lead Developer" msgstr "पà¥à¤°à¤®à¥à¤– डेवलपर" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "परियोजना पà¥à¤°à¤¬à¤‚धक " @@ -1136,6 +1139,16 @@ msgid "Gold Sponsors" msgstr "गोलà¥à¤¡ पà¥à¤°à¤¾à¤¯à¥‹à¤œà¤•" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "रजत दाताओं" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "कांसà¥à¤¯ दाताओं" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "मिनी पà¥à¤°à¤¾à¤¯à¥‹à¤œà¤•" @@ -9675,6 +9688,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "पà¥à¤°à¥‹à¤œà¥‡à¤•à¥à¤Ÿ मैनेजर" diff --git a/editor/translations/hr.po b/editor/translations/hr.po index a515a912b0..e4ea6d0a1a 100644 --- a/editor/translations/hr.po +++ b/editor/translations/hr.po @@ -1102,6 +1102,9 @@ msgstr "OsnivaÄi projekta" msgid "Lead Developer" msgstr "Glavni razvijatelj" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projektni menadžer " @@ -1123,6 +1126,16 @@ msgid "Gold Sponsors" msgstr "Zlatni sponzori" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Srebrni donatori" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "BronÄani donatori" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini sponzori" @@ -9529,6 +9542,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/hu.po b/editor/translations/hu.po index c6828cc7d3..59a6e0ad25 100644 --- a/editor/translations/hu.po +++ b/editor/translations/hu.po @@ -11,12 +11,13 @@ # Máté Lugosi <mate.lugosi@gmail.com>, 2019. # sztrovacsek <magadeve@gmail.com>, 2019. # Ãcs Zoltán <acszoltan111@gmail.com>, 2020. +# cefrebevalo <szmarci711@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-11 14:04+0000\n" -"Last-Translator: Ãcs Zoltán <acszoltan111@gmail.com>\n" +"PO-Revision-Date: 2020-09-05 09:37+0000\n" +"Last-Translator: cefrebevalo <szmarci711@gmail.com>\n" "Language-Team: Hungarian <https://hosted.weblate.org/projects/godot-engine/" "godot/hu/>\n" "Language: hu\n" @@ -24,7 +25,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -33,9 +34,8 @@ msgstr "" "Érvénytelen tÃpus argumentum a convert()-hez használjon TYPE_* konstansokat." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp -#, fuzzy msgid "Expected a string of length 1 (a character)." -msgstr "Egy karakter hosszúságú string-et várt." +msgstr "A várt string egy karakter hosszú." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp @@ -64,10 +64,8 @@ msgid "Invalid named index '%s' for base type %s" msgstr "Érvénytelen nevezett index '%s' %s alaptÃpushoz" #: core/math/expression.cpp -#, fuzzy msgid "Invalid arguments to construct '%s'" msgstr "" -"Érvénytelen tÃpus argumentum a convert()-hez használjon TYPE_* konstansokat." #: core/math/expression.cpp msgid "On call to '%s':" @@ -204,14 +202,12 @@ msgid "Change Animation Loop" msgstr "Animációs ciklus változtatása" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Property Track" -msgstr "Tulajdonság Követés" +msgstr "Tulajdonságkövetés" #: editor/animation_track_editor.cpp -#, fuzzy msgid "3D Transform Track" -msgstr "UV Térkép Transzformálása" +msgstr "" #: editor/animation_track_editor.cpp msgid "Call Method Track" @@ -226,9 +222,8 @@ msgid "Audio Playback Track" msgstr "Hang lejátszás követése" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Animation Playback Track" -msgstr "Animáció lejátszásának leállÃtása. (S)" +msgstr "" #: editor/animation_track_editor.cpp msgid "Animation length (frames)" @@ -239,9 +234,8 @@ msgid "Animation length (seconds)" msgstr "Animáció hossza (másodpercben)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add Track" -msgstr "Animáció nyomvonal hozzáadás" +msgstr "Nyomvonal hozzáadása" #: editor/animation_track_editor.cpp msgid "Animation Looping" @@ -261,9 +255,8 @@ msgid "Anim Clips:" msgstr "" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Change Track Path" -msgstr "Tömb Értékének Megváltoztatása" +msgstr "" #: editor/animation_track_editor.cpp msgid "Toggle this track on/off." @@ -1167,6 +1160,9 @@ msgstr "Projekt AlapÃtói" msgid "Lead Developer" msgstr "VezetÅ‘ FejlesztÅ‘" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projekt KezelÅ‘ " @@ -1188,6 +1184,16 @@ msgid "Gold Sponsors" msgstr "Arany Szponzorok" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Ezüst Adományozók" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronz Adományozók" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Szponzorok" @@ -10218,6 +10224,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "ProjektkezelÅ‘" diff --git a/editor/translations/id.po b/editor/translations/id.po index cf4bd738fa..9bd5244ee5 100644 --- a/editor/translations/id.po +++ b/editor/translations/id.po @@ -20,7 +20,7 @@ # Alphin Albukhari <alphinalbukhari5@gmail.com>, 2019. # I Dewa Agung Adhinata <agungnata2003@gmail.com>, 2019. # herri siagian <herry.it.2007@gmail.com>, 2019. -# MonsterGila <fikrirazor@outlook.co.id>, 2019. +# MonsterGila <fikrirazor@outlook.co.id>, 2019, 2020. # Modeus Darksono <garuga17@gmail.com>, 2019. # Akhmad Zulfikar <azuldegratz@gmail.com>, 2020. # Ade Fikri Malihuddin <ade.fm97@gmail.com>, 2020. @@ -31,8 +31,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-06 04:41+0000\n" -"Last-Translator: yusuf afandi <afandi.yusuf.04@gmail.com>\n" +"PO-Revision-Date: 2020-08-12 08:00+0000\n" +"Last-Translator: MonsterGila <fikrirazor@outlook.co.id>\n" "Language-Team: Indonesian <https://hosted.weblate.org/projects/godot-engine/" "godot/id/>\n" "Language: id\n" @@ -1139,6 +1139,9 @@ msgstr "Penemu Proyek" msgid "Lead Developer" msgstr "Pengembang Utama" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Manajer Proyek " @@ -1160,6 +1163,16 @@ msgid "Gold Sponsors" msgstr "Sponsor Emas" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Donatur Perak" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Donatur Perunggu" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Sponsor Mini" @@ -2435,10 +2448,13 @@ msgid "Reload Saved Scene" msgstr "Simpan Skena" #: editor/editor_node.cpp +#, fuzzy msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Skena saat ini mempunyai perubahan yang belum tersimpan.\n" +"Tetap muat ulang skena yang tersimpan? Aksi ini tidak dapat dibatalkan." #: editor/editor_node.cpp msgid "Quick Run Scene..." @@ -9884,6 +9900,7 @@ msgstr "" "Apakah Anda yakin untuk memindai %s folder untuk proyek Godot yang ada?\n" "Ini bisa memakan waktu yang lama." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Manajer Proyek" @@ -10683,11 +10700,14 @@ msgid "Open Documentation" msgstr "Buka Dokumentasi" #: 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 "" +"Tidak dapat melampirkan skrip: tidak ada bahasa yang terdaftar.\n" +"Ini mungkin karena editor ini dibuat dengan semua modul bahasa dinonaktifkan." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -12240,10 +12260,14 @@ msgstr "" "ciptakan resource shape untuknya!" #: scene/2d/collision_shape_2d.cpp +#, fuzzy msgid "" "Polygon-based shapes are not meant be used nor edited directly through the " "CollisionShape2D node. Please use the CollisionPolygon2D node instead." msgstr "" +"Bentuk Polygon-based tidak dimaksudkan untuk digunakan atau diedit secara " +"langsung melalui node CollisionShape2D. Silakan gunakan node " +"CollisionPolygon2D sebagai gantinya." #: scene/2d/cpu_particles_2d.cpp msgid "" @@ -12429,8 +12453,9 @@ msgid "Finishing Plot" msgstr "Menyelesaikan Pemetaan" #: scene/3d/baked_lightmap.cpp +#, fuzzy msgid "Lighting Meshes: " -msgstr "" +msgstr "Lighting Meshes: " #: scene/3d/collision_object.cpp msgid "" @@ -12485,8 +12510,9 @@ msgid "" msgstr "" #: scene/3d/cpu_particles.cpp +#, fuzzy msgid "Nothing is visible because no mesh has been assigned." -msgstr "" +msgstr "Tidak ada yang tampak karena tidak ada mesh yang ditetapkan." #: scene/3d/cpu_particles.cpp msgid "" diff --git a/editor/translations/is.po b/editor/translations/is.po index d53a9d609d..7b4ed6415b 100644 --- a/editor/translations/is.po +++ b/editor/translations/is.po @@ -1122,6 +1122,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Verkefna Stjóri " @@ -1143,6 +1146,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9587,6 +9598,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Verkefna Stjóri" diff --git a/editor/translations/it.po b/editor/translations/it.po index b2dac5ae0e..ba09df0418 100644 --- a/editor/translations/it.po +++ b/editor/translations/it.po @@ -54,12 +54,13 @@ # Lorenzo Asolan <brixiumx@gmail.com>, 2020. # Lorenzo Cerqua <lorenzocerqua@tutanota.com>, 2020. # Federico Manzella <ferdiu.manzella@gmail.com>, 2020. +# Ziv D <wizdavid@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-05 16:58+0000\n" -"Last-Translator: Lorenzo Cerqua <lorenzocerqua@tutanota.com>\n" +"PO-Revision-Date: 2020-09-08 11:40+0000\n" +"Last-Translator: Micila Micillotto <micillotto@gmail.com>\n" "Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/" "godot/it/>\n" "Language: it\n" @@ -67,7 +68,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1167,6 +1168,9 @@ msgstr "Fondatori del progetto" msgid "Lead Developer" msgstr "Sviluppatore principale" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Gestore progetto " @@ -1188,6 +1192,14 @@ msgid "Gold Sponsors" msgstr "Sponsor oro" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "Sponsor Argento" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "Sponsor Bronzo" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Sponsor mini" @@ -1758,7 +1770,7 @@ msgstr "Nuovo" #: editor/editor_feature_profile.cpp editor/editor_node.cpp #: editor/project_manager.cpp msgid "Import" -msgstr "Importa" +msgstr "Importare" #: editor/editor_feature_profile.cpp editor/project_export.cpp msgid "Export" @@ -4800,7 +4812,7 @@ msgstr "Modalità Gioco:" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "AnimationTree" -msgstr "AnimazioneAlbero" +msgstr "AnimationTree" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "New name:" @@ -9970,6 +9982,7 @@ msgstr "" "esistenti?\n" "Per questo potrebbe volerci un pò." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Gestore dei progetti" @@ -12058,7 +12071,7 @@ msgstr "" #: platform/android/export/export.cpp msgid "Release keystore incorrectly configured in the export preset." msgstr "" -"Debug keystore non configurato correttamente nel preset di esportazione." +"Release keystore non configurato correttamente nel preset di esportazione." #: platform/android/export/export.cpp msgid "Custom build requires a valid Android SDK path in Editor Settings." @@ -12191,9 +12204,8 @@ msgid "Run in Browser" msgstr "Esegui nel Browser" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Run exported HTML in the system's default browser." -msgstr "Esegui HTML esportato all'interno del browser di sistema predefinito." +msgstr "Esegui il codice HTML esportato nel browser di sistema predefinito." #: platform/javascript/export/export.cpp msgid "Could not write file:" @@ -12216,9 +12228,8 @@ msgid "Could not read boot splash image file:" msgstr "Impossibile leggere il file immagine di avvio splash:" #: platform/javascript/export/export.cpp -#, fuzzy msgid "Using default boot splash image." -msgstr "Utilizzando l'immagine di splash di avvio predefinita." +msgstr "Utilizzando l'immagine splash predefinita." #: platform/uwp/export/export.cpp msgid "Invalid package short name." diff --git a/editor/translations/ja.po b/editor/translations/ja.po index e0a1d4d909..bdab275f0f 100644 --- a/editor/translations/ja.po +++ b/editor/translations/ja.po @@ -36,7 +36,7 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-11 14:04+0000\n" +"PO-Revision-Date: 2020-08-28 13:09+0000\n" "Last-Translator: Wataru Onuki <bettawat@yahoo.co.jp>\n" "Language-Team: Japanese <https://hosted.weblate.org/projects/godot-engine/" "godot/ja/>\n" @@ -45,7 +45,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.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1143,6 +1143,9 @@ msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆå‰µå§‹è€…" msgid "Lead Developer" msgstr "開発リーダー" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼ " @@ -1164,6 +1167,16 @@ msgid "Gold Sponsors" msgstr "ゴールドスãƒãƒ³ã‚µãƒ¼" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "シルãƒãƒ¼ãƒ‰ãƒŠãƒ¼" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "ブãƒãƒ³ã‚ºãƒ‰ãƒŠãƒ¼" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "ミニスãƒãƒ³ã‚µãƒ¼" @@ -2751,11 +2764,11 @@ msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚³ãƒ³ãƒˆãƒãƒ¼ãƒ«" #: editor/editor_node.cpp editor/plugins/version_control_editor_plugin.cpp msgid "Set Up Version Control" -msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã®ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—" +msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚’セットアップ" #: editor/editor_node.cpp msgid "Shut Down Version Control" -msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã®çµ‚了" +msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç®¡ç†ã‚’終了" #: editor/editor_node.cpp msgid "Export..." @@ -2894,11 +2907,11 @@ msgstr "スクリーンショットã¯Editor Data / Settingsフォルダã«ä¿å #: editor/editor_node.cpp msgid "Toggle Fullscreen" -msgstr "フルスクリーンã®æœ‰åŠ¹åŒ– / 無効化" +msgstr "フルスクリーンを有効化 / 無効化" #: editor/editor_node.cpp msgid "Toggle System Console" -msgstr "システムコンソールã®æœ‰åŠ¹åŒ– / 無効化" +msgstr "システムコンソールを有効化 / 無効化" #: editor/editor_node.cpp msgid "Open Editor Data/Settings Folder" @@ -7011,11 +7024,11 @@ msgstr "å³ã‚¤ãƒ³ãƒ‡ãƒ³ãƒˆ" #: editor/plugins/script_text_editor.cpp msgid "Toggle Comment" -msgstr "コメントã®åˆ‡ã‚Šæ›¿ãˆ" +msgstr "コメントアウト / 解除" #: editor/plugins/script_text_editor.cpp msgid "Fold/Unfold Line" -msgstr "行を折りãŸãŸã‚€ / 展開ã™ã‚‹" +msgstr "行を折りãŸãŸã‚€ / 展開" #: editor/plugins/script_text_editor.cpp msgid "Fold All Lines" @@ -7023,7 +7036,7 @@ msgstr "ã™ã¹ã¦ã®è¡Œã‚’折りãŸãŸã‚€" #: editor/plugins/script_text_editor.cpp msgid "Unfold All Lines" -msgstr "ã™ã¹ã¦ã®è¡Œã‚’展開ã™ã‚‹" +msgstr "ã™ã¹ã¦ã®è¡Œã‚’展開" #: editor/plugins/script_text_editor.cpp msgid "Clone Down" @@ -7035,7 +7048,7 @@ msgstr "シンボルを補完" #: editor/plugins/script_text_editor.cpp msgid "Evaluate Selection" -msgstr "é¸æŠžç¯„囲を評価ã™ã‚‹" +msgstr "é¸æŠžç¯„囲を評価" #: editor/plugins/script_text_editor.cpp msgid "Trim Trailing Whitespace" @@ -9873,6 +9886,7 @@ msgstr "" "æ—¢å˜ã®Godotプãƒã‚¸ã‚§ã‚¯ãƒˆã®%sフォルダをスã‚ャンã—ã¾ã™ã‹?\n" "ã“ã‚Œã«ã¯ã—ã°ã‚‰ã時間ãŒã‹ã‹ã‚Šã¾ã™ã€‚" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "プãƒã‚¸ã‚§ã‚¯ãƒˆãƒžãƒãƒ¼ã‚¸ãƒ£ãƒ¼" diff --git a/editor/translations/ka.po b/editor/translations/ka.po index 1bfd23080b..7ec9bbd88a 100644 --- a/editor/translations/ka.po +++ b/editor/translations/ka.po @@ -1164,6 +1164,9 @@ msgstr "პრáƒáƒ”ქტის დáƒáƒ›áƒ¤áƒ£áƒ«áƒœáƒ”ბლები" msgid "Lead Developer" msgstr "მთáƒáƒ•áƒáƒ ი დეველáƒáƒžáƒ”რი" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "პრáƒáƒ”ქტის მენეჯერი. " @@ -1185,6 +1188,16 @@ msgid "Gold Sponsors" msgstr "áƒáƒ¥áƒ áƒáƒ¡ სპáƒáƒœáƒ¡áƒáƒ ები" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "ვერცხლის დáƒáƒœáƒáƒ¢áƒáƒ ები" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "ბრინჯáƒáƒáƒ¡ დáƒáƒœáƒáƒ¢áƒáƒ ები" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "მინი სპáƒáƒœáƒ¡áƒáƒ ები" @@ -9783,6 +9796,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/ko.po b/editor/translations/ko.po index 9b19450d58..83853be57c 100644 --- a/editor/translations/ko.po +++ b/editor/translations/ko.po @@ -1129,6 +1129,9 @@ msgstr "프로ì 트 창립ìž" msgid "Lead Developer" msgstr "리드 개발ìž" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "프로ì 트 ë§¤ë‹ˆì € " @@ -1150,6 +1153,16 @@ msgid "Gold Sponsors" msgstr "골드 스í°ì„œ" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "실버 기부ìž" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "ë¸Œë¡ ì¦ˆ 기부ìž" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "미니 스í°ì„œ" @@ -9802,6 +9815,7 @@ msgstr "" "Godot 프로ì 트를 확ì¸í•˜ê¸° 위해 %s í´ë”를 ìŠ¤ìº”í• ê¹Œìš”?\n" "ì‹œê°„ì´ ê±¸ë¦´ 수 있습니다." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "프로ì 트 ë§¤ë‹ˆì €" diff --git a/editor/translations/lt.po b/editor/translations/lt.po index 4d3884d5f8..01d9abae70 100644 --- a/editor/translations/lt.po +++ b/editor/translations/lt.po @@ -1127,6 +1127,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1148,6 +1151,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9762,6 +9773,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/lv.po b/editor/translations/lv.po index 2612b441c6..43bcc6beb0 100644 --- a/editor/translations/lv.po +++ b/editor/translations/lv.po @@ -1119,6 +1119,9 @@ msgstr "Projekta DibinÄtÄji" msgid "Lead Developer" msgstr "Galvenais IzstrÄdÄtÄjs" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projekta Menedžeris " @@ -1140,6 +1143,16 @@ msgid "Gold Sponsors" msgstr "Zelta Sponsori" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Sudraba Donors" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronzas Donors" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsori" @@ -9576,6 +9589,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/mi.po b/editor/translations/mi.po index 07a3bdae3c..8f922c0f43 100644 --- a/editor/translations/mi.po +++ b/editor/translations/mi.po @@ -1078,6 +1078,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1099,6 +1102,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9459,6 +9470,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/ml.po b/editor/translations/ml.po index aa7844d7ab..458429641d 100644 --- a/editor/translations/ml.po +++ b/editor/translations/ml.po @@ -1088,6 +1088,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1109,6 +1112,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9475,6 +9486,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/mr.po b/editor/translations/mr.po index 043d7e643e..dc88f027c0 100644 --- a/editor/translations/mr.po +++ b/editor/translations/mr.po @@ -1085,6 +1085,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1106,6 +1109,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9466,6 +9477,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/ms.po b/editor/translations/ms.po index ad70f291ca..b25e23a674 100644 --- a/editor/translations/ms.po +++ b/editor/translations/ms.po @@ -7,13 +7,14 @@ # Syaz Amirin <amirin123z@gmail.com>, 2018. # Nafis Ibrahim <thepreciousnafis@gmail.com>, 2018. # Muhammad Hazim bin Hafizalshah <muhammadhazimhafizalshah@gmail.com>, 2020. +# keviinx <keviinx@yahoo.com>, 2020. +# Keviindran Ramachandran <keviinx@yahoo.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-01-27 07:10+0000\n" -"Last-Translator: Muhammad Hazim bin Hafizalshah " -"<muhammadhazimhafizalshah@gmail.com>\n" +"PO-Revision-Date: 2020-09-08 11:40+0000\n" +"Last-Translator: Keviindran Ramachandran <keviinx@yahoo.com>\n" "Language-Team: Malay <https://hosted.weblate.org/projects/godot-engine/godot/" "ms/>\n" "Language: ms\n" @@ -21,119 +22,118 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.11-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "" +msgstr "Argumen jenis tidak sah untuk convert(), guna pemalar TYPE_*." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "" +msgstr "Menjangkakan rentetan dengan panjang 1 (satu watak)." #: 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 "Bait tidak mencukupi untuk menyahkod bait, atau format tidak sah." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "" +msgstr "Input %i tidak sah (tidak lulus) dalam ungkapan" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" -msgstr "" +msgstr "self tidak boleh digunakan kerana instance adalah null (tidak lulus)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." -msgstr "" +msgstr "Operan tidak sah untuk pengendali %s, %s dan %s." #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" -msgstr "" +msgstr "Indeks tidak sah untuk jenis %s untuk jenis asa %s" #: core/math/expression.cpp msgid "Invalid named index '%s' for base type %s" -msgstr "" +msgstr "Indeks bernama tidak sah '%s' untuk jenis asa %s" #: core/math/expression.cpp msgid "Invalid arguments to construct '%s'" -msgstr "" +msgstr "Argumen tidak sah untuk binaan '%s'" #: core/math/expression.cpp msgid "On call to '%s':" -msgstr "" +msgstr "Atas panggilan ke '%s':" #: core/ustring.cpp msgid "B" -msgstr "" +msgstr "B" #: core/ustring.cpp msgid "KiB" -msgstr "" +msgstr "KiB" #: core/ustring.cpp msgid "MiB" -msgstr "" +msgstr "MiB" #: core/ustring.cpp msgid "GiB" -msgstr "" +msgstr "GiB" #: core/ustring.cpp msgid "TiB" -msgstr "" +msgstr "TiB" #: core/ustring.cpp msgid "PiB" -msgstr "" +msgstr "PiB" #: core/ustring.cpp msgid "EiB" -msgstr "" +msgstr "EiB" #: editor/animation_bezier_editor.cpp msgid "Free" -msgstr "" +msgstr "Bebas" #: editor/animation_bezier_editor.cpp msgid "Balanced" -msgstr "" +msgstr "Seimbang" #: editor/animation_bezier_editor.cpp msgid "Mirror" -msgstr "" +msgstr "Cermin" #: editor/animation_bezier_editor.cpp editor/editor_profiler.cpp msgid "Time:" -msgstr "" +msgstr "Masa:" #: editor/animation_bezier_editor.cpp msgid "Value:" -msgstr "" +msgstr "Nilai:" #: editor/animation_bezier_editor.cpp msgid "Insert Key Here" -msgstr "" +msgstr "Masukkan Kunci di Sini" #: editor/animation_bezier_editor.cpp -#, fuzzy msgid "Duplicate Selected Key(s)" -msgstr "Anim Menduakan Kunci" +msgstr "Gandakan Kunci Terpilih" #: editor/animation_bezier_editor.cpp msgid "Delete Selected Key(s)" -msgstr "" +msgstr "Padam Kunci Terpilih" #: editor/animation_bezier_editor.cpp msgid "Add Bezier Point" -msgstr "" +msgstr "Tambah Titik Bezier" #: editor/animation_bezier_editor.cpp msgid "Move Bezier Points" -msgstr "" +msgstr "Pindah Titik-titik Bezier" #: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp msgid "Anim Duplicate Keys" @@ -141,10 +141,9 @@ msgstr "Anim Menduakan Kunci" #: editor/animation_bezier_editor.cpp editor/animation_track_editor.cpp msgid "Anim Delete Keys" -msgstr "" +msgstr "Anim Padam Kunci" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Change Keyframe Time" msgstr "Anim Ubah Masa Keyframe" @@ -154,7 +153,7 @@ msgstr "Anim Ubah Peralihan" #: editor/animation_track_editor.cpp msgid "Anim Change Transform" -msgstr "Anim Ubah Penukaran" +msgstr "Anim Ubah Perubahan" #: editor/animation_track_editor.cpp msgid "Anim Change Keyframe Value" @@ -165,200 +164,192 @@ msgid "Anim Change Call" msgstr "Anim Ubah Panggilan" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Keyframe Time" -msgstr "Anim Ubah Masa Keyframe" +msgstr "Anim Ubah Pelbagai Masa Keyframe" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Transition" -msgstr "Anim Ubah Peralihan" +msgstr "Anim Ubah Pelbagai Peralihan" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Transform" -msgstr "Anim Ubah Penukaran" +msgstr "Anim Ubah Pelbagai Penukaran" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Keyframe Value" -msgstr "Anim Ubah Nilai Keyframe" +msgstr "Anim Ubah Pelbagai Nilai Keyframe" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Anim Multi Change Call" -msgstr "Anim Ubah Panggilan" +msgstr "Anim Ubah Pelbagai Panggilan" #: editor/animation_track_editor.cpp msgid "Change Animation Length" -msgstr "" +msgstr "Ubah Panjang Animasi" #: editor/animation_track_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Change Animation Loop" -msgstr "" +msgstr "Ubah Gelung Animasi" #: editor/animation_track_editor.cpp msgid "Property Track" -msgstr "" +msgstr "Trek Sifat" #: editor/animation_track_editor.cpp msgid "3D Transform Track" -msgstr "" +msgstr "Trek Transformasi 3D" #: editor/animation_track_editor.cpp msgid "Call Method Track" -msgstr "" +msgstr "Trek Panggilan Kaedah" #: editor/animation_track_editor.cpp msgid "Bezier Curve Track" -msgstr "" +msgstr "Trek Lengkung Bezier" #: editor/animation_track_editor.cpp msgid "Audio Playback Track" -msgstr "" +msgstr "Trek Main balik Audio" #: editor/animation_track_editor.cpp msgid "Animation Playback Track" -msgstr "" +msgstr "Trek Main Balik Animasi" #: editor/animation_track_editor.cpp msgid "Animation length (frames)" -msgstr "" +msgstr "Panjang animasi (bingkai)" #: editor/animation_track_editor.cpp msgid "Animation length (seconds)" -msgstr "" +msgstr "Panjang animasi (saat)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add Track" -msgstr "Anim Tambah Trek" +msgstr "Tambah Trek" #: editor/animation_track_editor.cpp msgid "Animation Looping" -msgstr "" +msgstr "Gelung Animasi" #: editor/animation_track_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Functions:" -msgstr "" +msgstr "Fungsi:" #: editor/animation_track_editor.cpp msgid "Audio Clips:" -msgstr "" +msgstr "Klip Audio:" #: editor/animation_track_editor.cpp msgid "Anim Clips:" -msgstr "" +msgstr "Klip Anim:" #: editor/animation_track_editor.cpp msgid "Change Track Path" -msgstr "" +msgstr "Tukar Laluan Trek" #: editor/animation_track_editor.cpp msgid "Toggle this track on/off." -msgstr "" +msgstr "Hidupkan / matikan trek ini." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" -msgstr "" +msgstr "Kemas kini Mod (Bagaimana sifat ini ditetapkan)" #: editor/animation_track_editor.cpp msgid "Interpolation Mode" -msgstr "" +msgstr "Mod Interpolasi" #: editor/animation_track_editor.cpp msgid "Loop Wrap Mode (Interpolate end with beginning on loop)" -msgstr "" +msgstr "Mod Gelung Balut (Interpolat hujung dengan permulaan pada gelung)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Remove this track." -msgstr "Buang Trek Anim" +msgstr "Keluarkan trek ini." #: editor/animation_track_editor.cpp msgid "Time (s): " -msgstr "" +msgstr "Masa (s): " #: editor/animation_track_editor.cpp msgid "Toggle Track Enabled" -msgstr "" +msgstr "Togol Trek Diaktifkan" #: editor/animation_track_editor.cpp msgid "Continuous" -msgstr "" +msgstr "Berterusan" #: editor/animation_track_editor.cpp msgid "Discrete" -msgstr "" +msgstr "Diskret" #: editor/animation_track_editor.cpp msgid "Trigger" -msgstr "" +msgstr "Pencetus" #: editor/animation_track_editor.cpp msgid "Capture" -msgstr "" +msgstr "Tangkap" #: editor/animation_track_editor.cpp msgid "Nearest" -msgstr "" +msgstr "Terdekat" #: editor/animation_track_editor.cpp editor/plugins/curve_editor_plugin.cpp #: editor/property_editor.cpp msgid "Linear" -msgstr "" +msgstr "Linear" #: editor/animation_track_editor.cpp msgid "Cubic" -msgstr "" +msgstr "Kubik" #: editor/animation_track_editor.cpp msgid "Clamp Loop Interp" -msgstr "" +msgstr "Kepit Gelung Interp" #: editor/animation_track_editor.cpp msgid "Wrap Loop Interp" -msgstr "" +msgstr "Balut Gelung Interp" #: editor/animation_track_editor.cpp #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key" -msgstr "" +msgstr "Masukkan Kunci" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Duplicate Key(s)" -msgstr "Anim Menduakan Kunci" +msgstr "Menduakan Kunci" #: editor/animation_track_editor.cpp msgid "Delete Key(s)" -msgstr "" +msgstr "Padam Kunci" #: editor/animation_track_editor.cpp msgid "Change Animation Update Mode" -msgstr "" +msgstr "Mod Tukar Kemas Kini Animasi" #: editor/animation_track_editor.cpp msgid "Change Animation Interpolation Mode" -msgstr "" +msgstr "Tukar Mod Interpolasi Animasi" #: editor/animation_track_editor.cpp msgid "Change Animation Loop Mode" -msgstr "" +msgstr "Tukar Mod Gelung Animasi" #: editor/animation_track_editor.cpp msgid "Remove Anim Track" -msgstr "Buang Trek Anim" +msgstr "Keluarkan Trek Anim" #: editor/animation_track_editor.cpp msgid "Create NEW track for %s and insert key?" -msgstr "" +msgstr "Cipta trek BARU untuk %s dan masukkan kunci?" #: editor/animation_track_editor.cpp msgid "Create %d NEW tracks and insert keys?" -msgstr "" +msgstr "Cipta %d BARU trek dan masukkan kunci?" #: editor/animation_track_editor.cpp editor/create_dialog.cpp #: editor/editor_audio_buses.cpp editor/editor_feature_profile.cpp @@ -370,40 +361,39 @@ msgstr "" #: editor/script_create_dialog.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Create" -msgstr "" +msgstr "Cipta" #: editor/animation_track_editor.cpp msgid "Anim Insert" -msgstr "" +msgstr "Masukkan Anim" #: editor/animation_track_editor.cpp msgid "AnimationPlayer can't animate itself, only other players." -msgstr "" +msgstr "AnimationPlayer tidak animasikan dirinya sendiri, hanya pemain lain." #: editor/animation_track_editor.cpp msgid "Anim Create & Insert" -msgstr "" +msgstr "Anim Cipta & Masukkan" #: editor/animation_track_editor.cpp msgid "Anim Insert Track & Key" -msgstr "" +msgstr "Anim Masukkan Trek & Kunci" #: editor/animation_track_editor.cpp msgid "Anim Insert Key" -msgstr "" +msgstr "Anim Masukkan Kunci" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Change Animation Step" -msgstr "Anim Ubah Peralihan" +msgstr "Tukar Langkah Animasi" #: editor/animation_track_editor.cpp msgid "Rearrange Tracks" -msgstr "" +msgstr "Susun semula Trek" #: editor/animation_track_editor.cpp msgid "Transform tracks only apply to Spatial-based nodes." -msgstr "" +msgstr "Transformasi trek hanya berlaku kepada nod berasaskan Spatial." #: editor/animation_track_editor.cpp msgid "" @@ -412,78 +402,82 @@ msgid "" "-AudioStreamPlayer2D\n" "-AudioStreamPlayer3D" msgstr "" +"Trek audio hanya boleh ditujukan kepada nod jenis:\n" +"-AudioStreamPlayer\n" +"-AudioStreamPlayer2D\n" +"-AudioStreamPlayer3D" #: editor/animation_track_editor.cpp msgid "Animation tracks can only point to AnimationPlayer nodes." -msgstr "" +msgstr "Trek animasi hanya dapat ditujukan kepada nod AnimationPlayer." #: editor/animation_track_editor.cpp msgid "An animation player can't animate itself, only other players." msgstr "" +"Pemain animasi tidak boleh animasikan dirinya sendiri, hanya pemain lain." #: editor/animation_track_editor.cpp msgid "Not possible to add a new track without a root" -msgstr "" +msgstr "Tidak boleh menambah trek baru tanpa satu akar" #: editor/animation_track_editor.cpp msgid "Invalid track for Bezier (no suitable sub-properties)" -msgstr "" +msgstr "Trek tidak sah untuk Bezier (tiada sub-sifat yang sesuai)" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add Bezier Track" -msgstr "Anim Tambah Trek" +msgstr "Tambah Trek Bezier" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a key." -msgstr "" +msgstr "Laluan trek tidak sah, maka tidak boleh menambahkan kunci." #: editor/animation_track_editor.cpp msgid "Track is not of type Spatial, can't insert key" -msgstr "" +msgstr "Trek bukan jenis Spatial, tidak boleh memasukkan kunci" #: editor/animation_track_editor.cpp msgid "Add Transform Track Key" -msgstr "" +msgstr "Tambah Kunci Trek Transformasi" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add Track Key" -msgstr "Anim Tambah Trek" +msgstr "Tambah Kunci Trek" #: editor/animation_track_editor.cpp msgid "Track path is invalid, so can't add a method key." -msgstr "" +msgstr "Laluan trek tidak sah, maka tidak boleh menambahkan kunci kaedah." #: editor/animation_track_editor.cpp -#, fuzzy msgid "Add Method Track Key" -msgstr "Anim Tambah Trek" +msgstr "Tambah Kunci Trek Kaedah" #: editor/animation_track_editor.cpp msgid "Method not found in object: " -msgstr "" +msgstr "Kaedah tidak ditemui dalam objek: " #: editor/animation_track_editor.cpp msgid "Anim Move Keys" -msgstr "" +msgstr "Kunci Gerak Anim" #: editor/animation_track_editor.cpp msgid "Clipboard is empty" -msgstr "" +msgstr "Papan klip kosong" #: editor/animation_track_editor.cpp msgid "Paste Tracks" -msgstr "" +msgstr "Tampal Trek" #: editor/animation_track_editor.cpp msgid "Anim Scale Keys" -msgstr "" +msgstr "Kunci Skala Anim" #: editor/animation_track_editor.cpp msgid "" "This option does not work for Bezier editing, as it's only a single track." msgstr "" +"Pilihan ini tidak berfungsi untuk pengeditan Bezier, kerana ia hanya satu " +"trek." #: editor/animation_track_editor.cpp msgid "" @@ -497,38 +491,47 @@ msgid "" "Alternatively, use an import preset that imports animations to separate " "files." msgstr "" +"Animasi ini tergolong dalam adegan yang diimport, maka perubahan untuk trek " +"yang diimport tidak akan disimpan.\n" +"\n" +"Untuk memberikan keupayaan untuk menambah trek tersuai, navigasi ke tetapan " +"import adegan dan tetapkan\n" +"\"Animasi > Simpanan\" ke \"Fail\", aktifkan \"Animasi > Simpan Trek Tersuai" +"\", kemudian import semula.\n" +"Sebagai alternatif, gunakan pratetap import yang mengimportkan animasi untuk " +"memisahkan fail." #: editor/animation_track_editor.cpp msgid "Warning: Editing imported animation" -msgstr "" +msgstr "Amaran: Mengedit animasi yang diimport" #: editor/animation_track_editor.cpp msgid "Select an AnimationPlayer node to create and edit animations." -msgstr "" +msgstr "Pilih nod AnimationPlayer untuk mencipta dan mengedit animasi." #: editor/animation_track_editor.cpp msgid "Only show tracks from nodes selected in tree." -msgstr "" +msgstr "Hanya tunjukkan trek dari nod yang dipilih di pokok." #: editor/animation_track_editor.cpp msgid "Group tracks by node or display them as plain list." -msgstr "" +msgstr "Kumpulkan trek mengikut nod atau memaparkannya sebagai senarai biasa." #: editor/animation_track_editor.cpp msgid "Snap:" -msgstr "" +msgstr "Tangkap:" #: editor/animation_track_editor.cpp msgid "Animation step value." -msgstr "" +msgstr "Nilai langkah animasi." #: editor/animation_track_editor.cpp msgid "Seconds" -msgstr "" +msgstr "Saat" #: editor/animation_track_editor.cpp msgid "FPS" -msgstr "" +msgstr "FPS" #: editor/animation_track_editor.cpp editor/editor_properties.cpp #: editor/plugins/polygon_2d_editor_plugin.cpp @@ -538,108 +541,107 @@ msgstr "" #: editor/project_settings_editor.cpp editor/property_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Edit" -msgstr "" +msgstr "Edit" #: editor/animation_track_editor.cpp msgid "Animation properties." -msgstr "" +msgstr "Sifat animasi." #: editor/animation_track_editor.cpp msgid "Copy Tracks" -msgstr "" +msgstr "Salin Trek" #: editor/animation_track_editor.cpp msgid "Scale Selection" -msgstr "" +msgstr "Pemilihan Skala" #: editor/animation_track_editor.cpp msgid "Scale From Cursor" -msgstr "" +msgstr "Skala Dari Kursor" #: editor/animation_track_editor.cpp modules/gridmap/grid_map_editor_plugin.cpp msgid "Duplicate Selection" -msgstr "" +msgstr "Menduakan Pilihan" #: editor/animation_track_editor.cpp msgid "Duplicate Transposed" -msgstr "" +msgstr "Menduakan Pindahan" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Delete Selection" -msgstr "Semua Pilihan" +msgstr "Padam Pilihan" #: editor/animation_track_editor.cpp msgid "Go to Next Step" -msgstr "" +msgstr "Pergi ke Langkah Seterusnya" #: editor/animation_track_editor.cpp msgid "Go to Previous Step" -msgstr "" +msgstr "Pergi ke Langkah Sebelumnya" #: editor/animation_track_editor.cpp msgid "Optimize Animation" -msgstr "" +msgstr "Optimumkan Animasi" #: editor/animation_track_editor.cpp msgid "Clean-Up Animation" -msgstr "" +msgstr "Bersihkan Animasi" #: editor/animation_track_editor.cpp msgid "Pick the node that will be animated:" -msgstr "" +msgstr "Pilih nod yang akan dianimasikan:" #: editor/animation_track_editor.cpp msgid "Use Bezier Curves" -msgstr "" +msgstr "Guna Lengkung Bezier" #: editor/animation_track_editor.cpp msgid "Anim. Optimizer" -msgstr "" +msgstr "Pengoptimum Anim." #: editor/animation_track_editor.cpp msgid "Max. Linear Error:" -msgstr "" +msgstr "Max. Ralat Linear:" #: editor/animation_track_editor.cpp msgid "Max. Angular Error:" -msgstr "" +msgstr "Max. Ralat Sudut:" #: editor/animation_track_editor.cpp msgid "Max Optimizable Angle:" -msgstr "" +msgstr "Sudut Maksimum yang Boleh Dioptimumkan:" #: editor/animation_track_editor.cpp msgid "Optimize" -msgstr "" +msgstr "Mengoptimumkan" #: editor/animation_track_editor.cpp msgid "Remove invalid keys" -msgstr "" +msgstr "Keluarkan kunci yang tidak sah" #: editor/animation_track_editor.cpp msgid "Remove unresolved and empty tracks" -msgstr "" +msgstr "Keluarkan trek yang tidak boleh diselesaikan dan kosong" #: editor/animation_track_editor.cpp msgid "Clean-up all animations" -msgstr "" +msgstr "Bersihkan semua animasi" #: editor/animation_track_editor.cpp msgid "Clean-Up Animation(s) (NO UNDO!)" -msgstr "" +msgstr "Bersihkan Animasi (TIDAK BOLEH BUAT ASAL!)" #: editor/animation_track_editor.cpp msgid "Clean-Up" -msgstr "" +msgstr "Bersihkan" #: editor/animation_track_editor.cpp msgid "Scale Ratio:" -msgstr "" +msgstr "Nisbah Skala:" #: editor/animation_track_editor.cpp msgid "Select Tracks to Copy" -msgstr "" +msgstr "Pilih Trek untuk Disalin" #: editor/animation_track_editor.cpp editor/editor_log.cpp #: editor/editor_properties.cpp @@ -648,146 +650,146 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp #: scene/gui/line_edit.cpp scene/gui/text_edit.cpp msgid "Copy" -msgstr "" +msgstr "Salin" #: editor/animation_track_editor.cpp -#, fuzzy msgid "Select All/None" -msgstr "Semua Pilihan" +msgstr "Pilih Semua/Tiada" #: editor/animation_track_editor_plugins.cpp -#, fuzzy msgid "Add Audio Track Clip" -msgstr "Anim Tambah Trek" +msgstr "Tambah Klip Trek Audio" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip Start Offset" -msgstr "" +msgstr "Tukar Klip Trek Audio Mula Offset" #: editor/animation_track_editor_plugins.cpp msgid "Change Audio Track Clip End Offset" -msgstr "" +msgstr "Tukar Klip Audio Trek Hujung Offset" #: editor/array_property_edit.cpp msgid "Resize Array" -msgstr "" +msgstr "Ubah saiz Array" #: editor/array_property_edit.cpp msgid "Change Array Value Type" -msgstr "" +msgstr "Tukar Jenis Nilai Array" #: editor/array_property_edit.cpp msgid "Change Array Value" -msgstr "" +msgstr "Tukar Nilai Array" #: editor/code_editor.cpp msgid "Go to Line" -msgstr "" +msgstr "Pergi ke Baris" #: editor/code_editor.cpp msgid "Line Number:" -msgstr "" +msgstr "Nombor Baris:" #: editor/code_editor.cpp msgid "%d replaced." -msgstr "" +msgstr "%d telah diganti." #: editor/code_editor.cpp editor/editor_help.cpp msgid "%d match." -msgstr "" +msgstr "%d padan." #: editor/code_editor.cpp editor/editor_help.cpp msgid "%d matches." -msgstr "" +msgstr "%d padan." #: editor/code_editor.cpp editor/find_in_files.cpp msgid "Match Case" -msgstr "" +msgstr "Kes Padan" #: editor/code_editor.cpp editor/find_in_files.cpp msgid "Whole Words" -msgstr "" +msgstr "Seluruh Perkataan" #: editor/code_editor.cpp editor/rename_dialog.cpp msgid "Replace" -msgstr "" +msgstr "Ganti" #: editor/code_editor.cpp msgid "Replace All" -msgstr "" +msgstr "Ganti Semua" #: editor/code_editor.cpp msgid "Selection Only" -msgstr "" +msgstr "Pilihan Sahaja" #: editor/code_editor.cpp editor/plugins/script_text_editor.cpp #: editor/plugins/text_editor.cpp msgid "Standard" -msgstr "" +msgstr "Piawai" #: editor/code_editor.cpp editor/plugins/script_editor_plugin.cpp msgid "Toggle Scripts Panel" -msgstr "" +msgstr "Togol Panel Skrip" #: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp msgid "Zoom In" -msgstr "" +msgstr "Zum Masuk" #: editor/code_editor.cpp editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp msgid "Zoom Out" -msgstr "" +msgstr "Zum Keluar" #: editor/code_editor.cpp msgid "Reset Zoom" -msgstr "" +msgstr "Set Semula Zum" #: editor/code_editor.cpp msgid "Warnings" -msgstr "" +msgstr "Amaran" #: editor/code_editor.cpp msgid "Line and column numbers." -msgstr "" +msgstr "Nombor baris dan lajur." #: editor/connections_dialog.cpp msgid "Method in target node must be specified." -msgstr "" +msgstr "Kaedah dalam nod sasaran mesti ditentukan." #: editor/connections_dialog.cpp msgid "Method name must be a valid identifier." -msgstr "" +msgstr "Nama kaedah mestilah pengecam yang sah." #: editor/connections_dialog.cpp msgid "" "Target method not found. Specify a valid method or attach a script to the " "target node." msgstr "" +"Kaedah sasaran tidak dijumpai. Tentukan kaedah yang sah atau lampirkan skrip " +"ke nod sasaran." #: editor/connections_dialog.cpp msgid "Connect to Node:" -msgstr "" +msgstr "Sambung ke Nod:" #: editor/connections_dialog.cpp msgid "Connect to Script:" -msgstr "" +msgstr "Sambung ke Skrip:" #: editor/connections_dialog.cpp msgid "From Signal:" -msgstr "" +msgstr "Dari Isyarat:" #: editor/connections_dialog.cpp msgid "Scene does not contain any script." -msgstr "" +msgstr "Adegan tidak mengandungi sebarang skrip." #: editor/connections_dialog.cpp editor/editor_autoload_settings.cpp #: editor/groups_editor.cpp editor/plugins/item_list_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp editor/project_settings_editor.cpp msgid "Add" -msgstr "" +msgstr "Tambah" #: editor/connections_dialog.cpp editor/dependency_editor.cpp #: editor/editor_feature_profile.cpp editor/groups_editor.cpp @@ -798,44 +800,46 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp editor/project_manager.cpp #: editor/project_settings_editor.cpp msgid "Remove" -msgstr "" +msgstr "Keluarkan" #: editor/connections_dialog.cpp msgid "Add Extra Call Argument:" -msgstr "" +msgstr "Tambah Hujah Panggilan Tambahan:" #: editor/connections_dialog.cpp msgid "Extra Call Arguments:" -msgstr "" +msgstr "Hujah Panggilan Tambahan:" #: editor/connections_dialog.cpp msgid "Receiver Method:" -msgstr "" +msgstr "Kaedah Penerima:" #: editor/connections_dialog.cpp msgid "Advanced" -msgstr "" +msgstr "Lanjutan" #: editor/connections_dialog.cpp msgid "Deferred" -msgstr "" +msgstr "Ditangguhkan" #: editor/connections_dialog.cpp msgid "" "Defers the signal, storing it in a queue and only firing it at idle time." msgstr "" +"Mencegah isyarat, menyimpannya dalam barisan dan hanya menyalakannya pada " +"waktu terbiar." #: editor/connections_dialog.cpp msgid "Oneshot" -msgstr "" +msgstr "Oneshot" #: editor/connections_dialog.cpp msgid "Disconnects the signal after its first emission." -msgstr "" +msgstr "Putuskan isyarat selepas pelepasan pertama." #: editor/connections_dialog.cpp msgid "Cannot connect signal" -msgstr "" +msgstr "Tidak dapat menyambungkan isyarat" #: editor/connections_dialog.cpp editor/dependency_editor.cpp #: editor/export_template_manager.cpp editor/groups_editor.cpp @@ -849,101 +853,104 @@ msgstr "" #: editor/run_settings_dialog.cpp editor/settings_config_dialog.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Close" -msgstr "" +msgstr "Tutup" #: editor/connections_dialog.cpp msgid "Connect" -msgstr "" +msgstr "Sambung" #: editor/connections_dialog.cpp msgid "Signal:" -msgstr "" +msgstr "Isyarat:" #: editor/connections_dialog.cpp msgid "Connect '%s' to '%s'" -msgstr "" +msgstr "Sambungkan '% s' ke '% s'" #: editor/connections_dialog.cpp msgid "Disconnect '%s' from '%s'" -msgstr "" +msgstr "Putuskan sambungan '% s' dari '% s'" #: editor/connections_dialog.cpp msgid "Disconnect all from signal: '%s'" -msgstr "" +msgstr "Putuskan semua sambungan dari isyarat: '% s'" #: editor/connections_dialog.cpp msgid "Connect..." -msgstr "" +msgstr "Sambung ..." #: editor/connections_dialog.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Disconnect" -msgstr "" +msgstr "Putuskan sambungan" #: editor/connections_dialog.cpp msgid "Connect a Signal to a Method" -msgstr "" +msgstr "Sambungkan Isyarat ke Kaedah" #: editor/connections_dialog.cpp msgid "Edit Connection:" -msgstr "" +msgstr "Edit Sambungan:" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from the \"%s\" signal?" msgstr "" +"Adakah anda pasti anda mahu mengeluarkan semua sambungan dari isyarat \"% s" +"\"?" #: editor/connections_dialog.cpp editor/editor_help.cpp editor/node_dock.cpp msgid "Signals" -msgstr "" +msgstr "Isyarat" #: editor/connections_dialog.cpp msgid "Are you sure you want to remove all connections from this signal?" msgstr "" +"Adakah anda pasti anda mahu mengeluarkan semua sambungan dari isyarat ini?" #: editor/connections_dialog.cpp msgid "Disconnect All" -msgstr "" +msgstr "Putuskan Semua" #: editor/connections_dialog.cpp msgid "Edit..." -msgstr "" +msgstr "Edit..." #: editor/connections_dialog.cpp msgid "Go To Method" -msgstr "" +msgstr "Pergi ke Kaedah" #: editor/create_dialog.cpp msgid "Change %s Type" -msgstr "" +msgstr "Ubah Jenis %s" #: editor/create_dialog.cpp editor/project_settings_editor.cpp msgid "Change" -msgstr "" +msgstr "Ubah" #: editor/create_dialog.cpp msgid "Create New %s" -msgstr "" +msgstr "Cipta %s Baru" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp msgid "Favorites:" -msgstr "" +msgstr "Kegemaran:" #: editor/create_dialog.cpp editor/editor_file_dialog.cpp msgid "Recent:" -msgstr "" +msgstr "Terkini:" #: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp #: editor/property_selector.cpp editor/quick_open.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Search:" -msgstr "" +msgstr "Cari:" #: editor/create_dialog.cpp editor/plugins/script_editor_plugin.cpp #: editor/property_selector.cpp editor/quick_open.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Matches:" -msgstr "" +msgstr "Padanan:" #: editor/create_dialog.cpp editor/editor_plugin_settings.cpp #: editor/plugin_config_dialog.cpp @@ -951,57 +958,61 @@ msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp editor/property_selector.cpp #: modules/visual_script/visual_script_property_selector.cpp msgid "Description:" -msgstr "" +msgstr "Keterangan:" #: editor/dependency_editor.cpp msgid "Search Replacement For:" -msgstr "" +msgstr "Cari Penggantian Untuk:" #: editor/dependency_editor.cpp msgid "Dependencies For:" -msgstr "" +msgstr "Kebergantungan Untuk:" #: editor/dependency_editor.cpp msgid "" "Scene '%s' is currently being edited.\n" "Changes will only take effect when reloaded." msgstr "" +"Adegan '% s' kini sedang diedit.\n" +"Perubahan hanya akan berlaku apabila dimuat semula." #: editor/dependency_editor.cpp msgid "" "Resource '%s' is in use.\n" "Changes will only take effect when reloaded." msgstr "" +"Sumber '% s' sedang digunakan.\n" +"Perubahan hanya akan berlaku apabila dimuat semula." #: editor/dependency_editor.cpp #: modules/gdnative/gdnative_library_editor_plugin.cpp msgid "Dependencies" -msgstr "" +msgstr "Kebergantungan" #: editor/dependency_editor.cpp msgid "Resource" -msgstr "" +msgstr "Sumber" #: editor/dependency_editor.cpp editor/editor_autoload_settings.cpp #: editor/project_manager.cpp editor/project_settings_editor.cpp msgid "Path" -msgstr "" +msgstr "Laluan" #: editor/dependency_editor.cpp msgid "Dependencies:" -msgstr "" +msgstr "Kebergantungan:" #: editor/dependency_editor.cpp msgid "Fix Broken" -msgstr "" +msgstr "Perbaiki Pecah" #: editor/dependency_editor.cpp msgid "Dependency Editor" -msgstr "" +msgstr "Editor Ketergantungan" #: editor/dependency_editor.cpp msgid "Search Replacement Resource:" -msgstr "" +msgstr "Cari Penggantian Sumber:" #: editor/dependency_editor.cpp editor/editor_file_dialog.cpp #: editor/editor_help_search.cpp editor/editor_node.cpp @@ -1011,15 +1022,15 @@ msgstr "" #: modules/visual_script/visual_script_property_selector.cpp #: scene/gui/file_dialog.cpp msgid "Open" -msgstr "" +msgstr "Buka" #: editor/dependency_editor.cpp msgid "Owners Of:" -msgstr "" +msgstr "Pemilik:" #: editor/dependency_editor.cpp msgid "Remove selected files from the project? (Can't be restored)" -msgstr "" +msgstr "Alih keluar fail terpilih dari projek? (Tidak dapat dipulihkan)" #: editor/dependency_editor.cpp msgid "" @@ -1027,46 +1038,49 @@ msgid "" "work.\n" "Remove them anyway? (no undo)" msgstr "" +"Fail yang akan dikeluarkan diperlukan oleh sumber lain agar dapat " +"berfungsi.\n" +"Masih mahu keluarkan fail tersebut? (tidak boleh buat asal)" #: editor/dependency_editor.cpp msgid "Cannot remove:" -msgstr "" +msgstr "Tidak boleh dialih keluar:" #: editor/dependency_editor.cpp msgid "Error loading:" -msgstr "" +msgstr "Ralat memuatkan:" #: editor/dependency_editor.cpp msgid "Load failed due to missing dependencies:" -msgstr "" +msgstr "Gagal memuat kerana kebergantungan hilang:" #: editor/dependency_editor.cpp editor/editor_node.cpp msgid "Open Anyway" -msgstr "" +msgstr "Buka Bagaimanapun" #: editor/dependency_editor.cpp msgid "Which action should be taken?" -msgstr "" +msgstr "Tindakan apa yang harus diambil?" #: editor/dependency_editor.cpp msgid "Fix Dependencies" -msgstr "" +msgstr "Perbaiki Kebergantungan" #: editor/dependency_editor.cpp msgid "Errors loading!" -msgstr "" +msgstr "Ralat memuatkan!" #: editor/dependency_editor.cpp msgid "Permanently delete %d item(s)? (No undo!)" -msgstr "" +msgstr "Padamkan objek %d secara kekal? (Tidak boleh dibuat asal!)" #: editor/dependency_editor.cpp msgid "Show Dependencies" -msgstr "" +msgstr "Tunjuk Kebergantungan" #: editor/dependency_editor.cpp msgid "Orphan Resource Explorer" -msgstr "" +msgstr "Penjelajah Sumber Yatim" #: editor/dependency_editor.cpp editor/editor_audio_buses.cpp #: editor/editor_file_dialog.cpp editor/editor_node.cpp @@ -1074,79 +1088,92 @@ msgstr "" #: editor/plugins/sprite_frames_editor_plugin.cpp editor/project_export.cpp #: editor/project_settings_editor.cpp editor/scene_tree_dock.cpp msgid "Delete" -msgstr "" +msgstr "Padam" #: editor/dependency_editor.cpp msgid "Owns" -msgstr "" +msgstr "Memiliki" #: editor/dependency_editor.cpp msgid "Resources Without Explicit Ownership:" -msgstr "" +msgstr "Sumber Tanpa Hak Milik Eksplisit:" #: editor/dictionary_property_edit.cpp msgid "Change Dictionary Key" -msgstr "" +msgstr "Tukar Kunci Kamus" #: editor/dictionary_property_edit.cpp msgid "Change Dictionary Value" -msgstr "" +msgstr "Tukar Nilai Kamus" #: editor/editor_about.cpp msgid "Thanks from the Godot community!" -msgstr "" +msgstr "Terima kasih dari komuniti Godot!" #: editor/editor_about.cpp msgid "Godot Engine contributors" -msgstr "" +msgstr "Penyumbang Enjin Godot" #: editor/editor_about.cpp msgid "Project Founders" -msgstr "" +msgstr "Pengasas Projek" #: editor/editor_about.cpp msgid "Lead Developer" -msgstr "" +msgstr "Pemaju Utama" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " -msgstr "" +msgstr "Pengurus Projek " #: editor/editor_about.cpp msgid "Developers" -msgstr "" +msgstr "Pemaju" #: editor/editor_about.cpp msgid "Authors" -msgstr "" +msgstr "Pengarang" #: editor/editor_about.cpp msgid "Platinum Sponsors" -msgstr "" +msgstr "Penaja Platinum" #: editor/editor_about.cpp msgid "Gold Sponsors" -msgstr "" +msgstr "Penaja Emas" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Penderma Perak" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Penderma Gangsa" #: editor/editor_about.cpp msgid "Mini Sponsors" -msgstr "" +msgstr "Penaja Mini" #: editor/editor_about.cpp msgid "Gold Donors" -msgstr "" +msgstr "Penderma Emas" #: editor/editor_about.cpp msgid "Silver Donors" -msgstr "" +msgstr "Penderma Perak" #: editor/editor_about.cpp msgid "Bronze Donors" -msgstr "" +msgstr "Penderma Gangsa" #: editor/editor_about.cpp msgid "Donors" -msgstr "" +msgstr "Penderma" #: editor/editor_about.cpp msgid "License" @@ -1154,7 +1181,7 @@ msgstr "Lesen" #: editor/editor_about.cpp msgid "Third-party Licenses" -msgstr "" +msgstr "Lesen Pihak Ketiga" #: editor/editor_about.cpp msgid "" @@ -1163,389 +1190,398 @@ msgid "" "is an exhaustive list of all such third-party components with their " "respective copyright statements and license terms." msgstr "" +"Enjin Godot bergantung kepada beberapa perpustakaan sumber terbuka dan bebas " +"pihak ketiga, semuanya serasi dengan syarat-syarat lesen MITnya. Berikut " +"adalah senarai lengkap semua komponen pihak ketiga tersebut dengan " +"pernyataan hak cipta dan syarat lesen masing-masing." #: editor/editor_about.cpp msgid "All Components" -msgstr "" +msgstr "Semua Komponen" #: editor/editor_about.cpp msgid "Components" -msgstr "" +msgstr "Komponen" #: editor/editor_about.cpp msgid "Licenses" -msgstr "" +msgstr "Lesen" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Error opening package file, not in ZIP format." -msgstr "" +msgstr "Ralat semasa membuka fail pakej, bukan dalam format ZIP." #: editor/editor_asset_installer.cpp msgid "%s (Already Exists)" -msgstr "" +msgstr "%s (Sudah Wujud)" #: editor/editor_asset_installer.cpp msgid "Uncompressing Assets" -msgstr "" +msgstr "Nyahmampatkan Aset" #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "The following files failed extraction from package:" -msgstr "" +msgstr "Fail berikut gagal diekstrak dari pakej:" #: editor/editor_asset_installer.cpp msgid "And %s more files." -msgstr "" +msgstr "Dan sebanyak %s fail." #: editor/editor_asset_installer.cpp editor/project_manager.cpp msgid "Package installed successfully!" -msgstr "" +msgstr "Pakej berjaya dipasang!" #: editor/editor_asset_installer.cpp #: editor/plugins/asset_library_editor_plugin.cpp msgid "Success!" -msgstr "" +msgstr "Berjaya!" #: editor/editor_asset_installer.cpp msgid "Package Contents:" -msgstr "" +msgstr "Kandungan Pakej:" #: editor/editor_asset_installer.cpp editor/editor_node.cpp msgid "Install" -msgstr "" +msgstr "Pasang" #: editor/editor_asset_installer.cpp msgid "Package Installer" -msgstr "" +msgstr "Pemasang Pakej" #: editor/editor_audio_buses.cpp msgid "Speakers" -msgstr "" +msgstr "Pembesar suara" #: editor/editor_audio_buses.cpp msgid "Add Effect" -msgstr "" +msgstr "Tambah Kesan" #: editor/editor_audio_buses.cpp msgid "Rename Audio Bus" -msgstr "" +msgstr "Namakan Semula Bas Audio" #: editor/editor_audio_buses.cpp msgid "Change Audio Bus Volume" -msgstr "" +msgstr "Tukar Kelantangan Bas Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" -msgstr "" +msgstr "Togol Bas Audio Solo" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Mute" -msgstr "" +msgstr "Togol Senyap Bas Audio" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Bypass Effects" -msgstr "" +msgstr "Togol Kesan Pintasan Bas Audio" #: editor/editor_audio_buses.cpp msgid "Select Audio Bus Send" -msgstr "" +msgstr "Pilih Hantar Bas Audio" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus Effect" -msgstr "" +msgstr "Tambah Kesan Bas Audio" #: editor/editor_audio_buses.cpp msgid "Move Bus Effect" -msgstr "" +msgstr "Alih Kesan Bas" #: editor/editor_audio_buses.cpp msgid "Delete Bus Effect" -msgstr "" +msgstr "Padam Kesan Bas" #: editor/editor_audio_buses.cpp msgid "Drag & drop to rearrange." -msgstr "" +msgstr "Seret & lepas untuk menyusun semula." #: editor/editor_audio_buses.cpp msgid "Solo" -msgstr "" +msgstr "Solo" #: editor/editor_audio_buses.cpp msgid "Mute" -msgstr "" +msgstr "Bisu" #: editor/editor_audio_buses.cpp msgid "Bypass" -msgstr "" +msgstr "Pintas" #: editor/editor_audio_buses.cpp msgid "Bus options" -msgstr "" +msgstr "Pilihan bas" #: editor/editor_audio_buses.cpp editor/filesystem_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Duplicate" -msgstr "" +msgstr "Pendua" #: editor/editor_audio_buses.cpp msgid "Reset Volume" -msgstr "" +msgstr "Tetapkan Semula Kelantangan" #: editor/editor_audio_buses.cpp msgid "Delete Effect" -msgstr "" +msgstr "Padam Kesan" #: editor/editor_audio_buses.cpp msgid "Audio" -msgstr "" +msgstr "Audio" #: editor/editor_audio_buses.cpp msgid "Add Audio Bus" -msgstr "" +msgstr "Tambah Bas Audio" #: editor/editor_audio_buses.cpp msgid "Master bus can't be deleted!" -msgstr "" +msgstr "Bas induk tidak boleh dipadamkan!" #: editor/editor_audio_buses.cpp msgid "Delete Audio Bus" -msgstr "" +msgstr "Padam Bas Audio" #: editor/editor_audio_buses.cpp msgid "Duplicate Audio Bus" -msgstr "" +msgstr "Pendua Bas Audio" #: editor/editor_audio_buses.cpp msgid "Reset Bus Volume" -msgstr "" +msgstr "Tetapkan Semula Kelantangan Bas" #: editor/editor_audio_buses.cpp msgid "Move Audio Bus" -msgstr "" +msgstr "Pindah Bas Audio" #: editor/editor_audio_buses.cpp msgid "Save Audio Bus Layout As..." -msgstr "" +msgstr "Simpan Susun Atur Bas Audio Sebagai..." #: editor/editor_audio_buses.cpp msgid "Location for New Layout..." -msgstr "" +msgstr "Lokasi untuk Susun Atur Baru..." #: editor/editor_audio_buses.cpp msgid "Open Audio Bus Layout" -msgstr "" +msgstr "Buka Susun Atur Bas Audio" #: editor/editor_audio_buses.cpp msgid "There is no '%s' file." -msgstr "" +msgstr "Tiada fail '%s'." #: editor/editor_audio_buses.cpp editor/plugins/canvas_item_editor_plugin.cpp msgid "Layout" -msgstr "" +msgstr "Susun atur" #: editor/editor_audio_buses.cpp msgid "Invalid file, not an audio bus layout." -msgstr "" +msgstr "Fail tidak sah, bukan susun atur bas audio." #: editor/editor_audio_buses.cpp msgid "Error saving file: %s" -msgstr "" +msgstr "Ralat semasa menyimpan fail: %s" #: editor/editor_audio_buses.cpp msgid "Add Bus" -msgstr "" +msgstr "Tambah Bas" #: editor/editor_audio_buses.cpp msgid "Add a new Audio Bus to this layout." -msgstr "" +msgstr "Tambah Bas Audio baru ke susun atur ini." #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp #: editor/script_create_dialog.cpp msgid "Load" -msgstr "" +msgstr "Memuatkan" #: editor/editor_audio_buses.cpp msgid "Load an existing Bus Layout." -msgstr "" +msgstr "Muatkan Susun Atur Bas yang sedia ada." #: editor/editor_audio_buses.cpp msgid "Save As" -msgstr "" +msgstr "Simpan sebagai" #: editor/editor_audio_buses.cpp msgid "Save this Bus Layout to a file." -msgstr "" +msgstr "Simpan Susun Atur Bas ini ke fail." #: editor/editor_audio_buses.cpp editor/import_dock.cpp msgid "Load Default" -msgstr "" +msgstr "Muatkan Lalai" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "" +msgstr "Muatkan Susun Atur Bas lalai." #: editor/editor_audio_buses.cpp msgid "Create a new Bus Layout." -msgstr "" +msgstr "Cipta Susun Atur Bas baru." #: editor/editor_autoload_settings.cpp msgid "Invalid name." -msgstr "" +msgstr "Nama tidak sah." #: editor/editor_autoload_settings.cpp msgid "Valid characters:" -msgstr "" +msgstr "Watak yang sah:" #: editor/editor_autoload_settings.cpp msgid "Must not collide with an existing engine class name." -msgstr "" +msgstr "Tidak boleh bertembung dengan nama kelas engin yang telah wujud." #: editor/editor_autoload_settings.cpp msgid "Must not collide with an existing built-in type name." msgstr "" +"Tidak boleh bertembung dengan nama jenis terbina dalam yang telah wujud." #: editor/editor_autoload_settings.cpp msgid "Must not collide with an existing global constant name." -msgstr "" +msgstr "Tidak boleh bertembung dengan nama pemalar global yang telah wujud." #: editor/editor_autoload_settings.cpp msgid "Keyword cannot be used as an autoload name." -msgstr "" +msgstr "Kata kunci tidak boleh digunakan sebagai nama autoload." #: editor/editor_autoload_settings.cpp msgid "Autoload '%s' already exists!" -msgstr "" +msgstr "Autoload '%s' sudah wujud!" #: editor/editor_autoload_settings.cpp msgid "Rename Autoload" -msgstr "" +msgstr "Namakan Semula Autoload" #: editor/editor_autoload_settings.cpp msgid "Toggle AutoLoad Globals" -msgstr "" +msgstr "Togol Global Autoload" #: editor/editor_autoload_settings.cpp msgid "Move Autoload" -msgstr "" +msgstr "Pindah Autoload" #: editor/editor_autoload_settings.cpp msgid "Remove Autoload" -msgstr "" +msgstr "Keluarkan Autoload" #: editor/editor_autoload_settings.cpp editor/editor_plugin_settings.cpp msgid "Enable" -msgstr "" +msgstr "Aktifkan" #: editor/editor_autoload_settings.cpp msgid "Rearrange Autoloads" -msgstr "" +msgstr "Susun Semula Autoload" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "Tidak boleh menambahkan autoload:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" -msgstr "" +msgstr "Tambah AutoLoad" #: editor/editor_autoload_settings.cpp editor/editor_file_dialog.cpp #: editor/editor_plugin_settings.cpp #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/script_create_dialog.cpp scene/gui/file_dialog.cpp msgid "Path:" -msgstr "" +msgstr "Laluan:" #: editor/editor_autoload_settings.cpp msgid "Node Name:" -msgstr "" +msgstr "Nama Nod:" #: editor/editor_autoload_settings.cpp editor/editor_help_search.cpp #: editor/editor_profiler.cpp editor/project_manager.cpp #: editor/settings_config_dialog.cpp msgid "Name" -msgstr "" +msgstr "Nama" #: editor/editor_autoload_settings.cpp msgid "Singleton" -msgstr "" +msgstr "Singleton" #: editor/editor_data.cpp editor/inspector_dock.cpp msgid "Paste Params" -msgstr "" +msgstr "Tampal Param" #: editor/editor_data.cpp msgid "Updating Scene" -msgstr "" +msgstr "Mengemaskini Adegan" #: editor/editor_data.cpp msgid "Storing local changes..." -msgstr "" +msgstr "Menyimpan perubahan tempatan..." #: editor/editor_data.cpp msgid "Updating scene..." -msgstr "" +msgstr "Mengemaskini adegan..." #: editor/editor_data.cpp editor/editor_properties.cpp msgid "[empty]" -msgstr "" +msgstr "[kosong]" #: editor/editor_data.cpp msgid "[unsaved]" -msgstr "" +msgstr "[tidak disimpan]" #: editor/editor_dir_dialog.cpp msgid "Please select a base directory first." -msgstr "" +msgstr "Sila pilih direktori asas terlebih dahulu." #: editor/editor_dir_dialog.cpp msgid "Choose a Directory" -msgstr "" +msgstr "Pilih Direktori" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp editor/project_manager.cpp #: scene/gui/file_dialog.cpp msgid "Create Folder" -msgstr "" +msgstr "Cipta Folder" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/editor_plugin_settings.cpp editor/filesystem_dock.cpp #: editor/plugins/theme_editor_plugin.cpp editor/project_export.cpp #: modules/visual_script/visual_script_editor.cpp scene/gui/file_dialog.cpp msgid "Name:" -msgstr "" +msgstr "Nama:" #: editor/editor_dir_dialog.cpp editor/editor_file_dialog.cpp #: editor/filesystem_dock.cpp scene/gui/file_dialog.cpp msgid "Could not create folder." -msgstr "" +msgstr "Tidak dapat mencipta folder." #: editor/editor_dir_dialog.cpp msgid "Choose" -msgstr "" +msgstr "Pilih" #: editor/editor_export.cpp msgid "Storing File:" -msgstr "" +msgstr "Menyimpan Fail:" #: editor/editor_export.cpp msgid "No export template found at the expected path:" -msgstr "" +msgstr "Tiada templat eksport ditemui di laluan yang dijangkakan:" #: editor/editor_export.cpp msgid "Packing" -msgstr "" +msgstr "Pembungkusan" #: editor/editor_export.cpp msgid "" "Target platform requires 'ETC' texture compression for GLES2. Enable 'Import " "Etc' in Project Settings." msgstr "" +"Platform sasaran memerlukan pemampatan tekstur 'ETC' untuk GLES2. Aktifkan " +"'Import Etc' dalam Tetapan Projek." #: editor/editor_export.cpp msgid "" "Target platform requires 'ETC2' texture compression for GLES3. Enable " "'Import Etc 2' in Project Settings." msgstr "" +"Platform sasaran memerlukan pemampatan tekstur 'ETC2' untuk GLES3. Aktifkan " +"'Import Etc 2' dalam Tetapan Projek." #: editor/editor_export.cpp msgid "" @@ -1554,508 +1590,519 @@ msgid "" "Enable 'Import Etc' in Project Settings, or disable 'Driver Fallback " "Enabled'." msgstr "" +"Platform sasaran memerlukan pemampatan tekstur 'ETC' untuk sandaran pemandu " +"ke GLES2.\n" +"Aktifkan 'Import Etc' dalam Tetapan Projek, atau nyahaktifkan 'Driver " +"Fallback Enabled'." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp msgid "Custom debug template not found." -msgstr "" +msgstr "Templat nyahpepijat tersuai tidak dijumpai." #: editor/editor_export.cpp platform/android/export/export.cpp #: platform/iphone/export/export.cpp platform/javascript/export/export.cpp #: platform/osx/export/export.cpp platform/uwp/export/export.cpp msgid "Custom release template not found." -msgstr "" +msgstr "Templat pelepasan tersuai tidak dijumpai." #: editor/editor_export.cpp platform/javascript/export/export.cpp msgid "Template file not found:" -msgstr "" +msgstr "Fail templat tidak dijumpai:" #: editor/editor_export.cpp msgid "On 32-bit exports the embedded PCK cannot be bigger than 4 GiB." msgstr "" +"Pada eksport 32-bit PCK terbenam tidak boleh lebih besar daripada 4 GiB." #: editor/editor_feature_profile.cpp msgid "3D Editor" -msgstr "" +msgstr "Editor 3D" #: editor/editor_feature_profile.cpp msgid "Script Editor" -msgstr "" +msgstr "Editor Skrip" #: editor/editor_feature_profile.cpp msgid "Asset Library" -msgstr "" +msgstr "Perpustakaan Aset" #: editor/editor_feature_profile.cpp msgid "Scene Tree Editing" -msgstr "" +msgstr "Penyuntingan Pokok Adegan" #: editor/editor_feature_profile.cpp msgid "Import Dock" -msgstr "" +msgstr "Import Dok" #: editor/editor_feature_profile.cpp msgid "Node Dock" -msgstr "" +msgstr "Dok nod" #: editor/editor_feature_profile.cpp msgid "FileSystem and Import Docks" -msgstr "" +msgstr "Sistem Fail dan Dok Import" #: editor/editor_feature_profile.cpp msgid "Erase profile '%s'? (no undo)" -msgstr "" +msgstr "Padamkan profil '%s'? (tidak boleh buat asal)" #: editor/editor_feature_profile.cpp msgid "Profile must be a valid filename and must not contain '.'" -msgstr "" +msgstr "Profil mestilah nama fail yang sah dan tidak boleh mengandungi '.'" #: editor/editor_feature_profile.cpp msgid "Profile with this name already exists." -msgstr "" +msgstr "Profil dengan nama ini sudah wujud." #: editor/editor_feature_profile.cpp msgid "(Editor Disabled, Properties Disabled)" -msgstr "" +msgstr "(Editor Dinyahaktifkan, Ciri-ciri Dinyahaktifkan)" #: editor/editor_feature_profile.cpp msgid "(Properties Disabled)" -msgstr "" +msgstr "(Ciri-ciri dinyahaktif)" #: editor/editor_feature_profile.cpp -#, fuzzy msgid "(Editor Disabled)" -msgstr "Tidak Aktif" +msgstr "(Editor Dinyahaktif)" #: editor/editor_feature_profile.cpp msgid "Class Options:" -msgstr "" +msgstr "Pilihan Kelas:" #: editor/editor_feature_profile.cpp msgid "Enable Contextual Editor" -msgstr "" +msgstr "Aktifkan Editor Kontekstual" #: editor/editor_feature_profile.cpp msgid "Enabled Properties:" -msgstr "" +msgstr "Ciri-ciri Diaktifkan:" #: editor/editor_feature_profile.cpp msgid "Enabled Features:" -msgstr "" +msgstr "Ciri Diaktifkan:" #: editor/editor_feature_profile.cpp msgid "Enabled Classes:" -msgstr "" +msgstr "Kelas Diaktifkan:" #: editor/editor_feature_profile.cpp msgid "File '%s' format is invalid, import aborted." -msgstr "" +msgstr "Format fail '%s' tidak sah, import dibatalkan." #: editor/editor_feature_profile.cpp msgid "" "Profile '%s' already exists. Remove it first before importing, import " "aborted." msgstr "" +"Profil '%s' sudah wujud. Keluarkannya terlebih dahulu sebelum mengimport, " +"import dibatalkan." #: editor/editor_feature_profile.cpp msgid "Error saving profile to path: '%s'." -msgstr "" +msgstr "Ralat menyimpan profil ke laluan: '%s'." #: editor/editor_feature_profile.cpp msgid "Unset" -msgstr "" +msgstr "Nyahtetap" #: editor/editor_feature_profile.cpp msgid "Current Profile:" -msgstr "" +msgstr "Profil Semasa:" #: editor/editor_feature_profile.cpp msgid "Make Current" -msgstr "" +msgstr "Buat Semasa" #: editor/editor_feature_profile.cpp #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/version_control_editor_plugin.cpp msgid "New" -msgstr "" +msgstr "Baru" #: editor/editor_feature_profile.cpp editor/editor_node.cpp #: editor/project_manager.cpp msgid "Import" -msgstr "" +msgstr "Import" #: editor/editor_feature_profile.cpp editor/project_export.cpp msgid "Export" -msgstr "" +msgstr "Eksport" #: editor/editor_feature_profile.cpp msgid "Available Profiles:" -msgstr "" +msgstr "Profil yang ada:" #: editor/editor_feature_profile.cpp msgid "Class Options" -msgstr "" +msgstr "Pilihan Kelas" #: editor/editor_feature_profile.cpp msgid "New profile name:" -msgstr "" +msgstr "Nama profil baru:" #: editor/editor_feature_profile.cpp msgid "Erase Profile" -msgstr "" +msgstr "Padam Profil" #: editor/editor_feature_profile.cpp msgid "Godot Feature Profile" -msgstr "" +msgstr "Profil Ciri Godot" #: editor/editor_feature_profile.cpp msgid "Import Profile(s)" -msgstr "" +msgstr "Import Profil" #: editor/editor_feature_profile.cpp msgid "Export Profile" -msgstr "" +msgstr "Eksport Profil" #: editor/editor_feature_profile.cpp msgid "Manage Editor Feature Profiles" -msgstr "" +msgstr "Urus Profil Ciri Editor" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select Current Folder" -msgstr "" +msgstr "Pilih Folder Semasa" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "File Exists, Overwrite?" -msgstr "" +msgstr "Fail Wujud, Tulis Ganti?" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Select This Folder" -msgstr "" +msgstr "Pilih Folder Ini" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Copy Path" -msgstr "" +msgstr "Salin Laluan" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "Open in File Manager" -msgstr "" +msgstr "Buka dalam Pengurus Fail" #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/filesystem_dock.cpp editor/project_manager.cpp msgid "Show in File Manager" -msgstr "" +msgstr "Tunjukkan dalam Pengurus Fail" #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "New Folder..." -msgstr "" +msgstr "Folder Baru..." #: editor/editor_file_dialog.cpp editor/find_in_files.cpp #: editor/plugins/version_control_editor_plugin.cpp msgid "Refresh" -msgstr "" +msgstr "Muat Semula" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Recognized" -msgstr "" +msgstr "Semua Dikenali" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "All Files (*)" -msgstr "" +msgstr "Semua Fail (*)" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a File" -msgstr "" +msgstr "Buka Fail" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open File(s)" -msgstr "" +msgstr "Buka Fail" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a Directory" -msgstr "" +msgstr "Buka Direktori" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Open a File or Directory" -msgstr "" +msgstr "Buka Fail atau Direktori" #: editor/editor_file_dialog.cpp editor/editor_node.cpp #: editor/editor_properties.cpp editor/inspector_dock.cpp #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/script_editor_plugin.cpp scene/gui/file_dialog.cpp msgid "Save" -msgstr "" +msgstr "Simpan" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Save a File" -msgstr "" +msgstr "Simpan Fail" #: editor/editor_file_dialog.cpp msgid "Go Back" -msgstr "" +msgstr "Pergi Balik" #: editor/editor_file_dialog.cpp msgid "Go Forward" -msgstr "" +msgstr "Pergi ke Hadapan" #: editor/editor_file_dialog.cpp msgid "Go Up" -msgstr "" +msgstr "Pergi Atas" #: editor/editor_file_dialog.cpp msgid "Toggle Hidden Files" -msgstr "" +msgstr "Togol Fail Tersembunyi" #: editor/editor_file_dialog.cpp msgid "Toggle Favorite" -msgstr "" +msgstr "Togol Kegemaran" #: editor/editor_file_dialog.cpp msgid "Toggle Mode" -msgstr "" +msgstr "Togol Mod" #: editor/editor_file_dialog.cpp msgid "Focus Path" -msgstr "" +msgstr "Laluan Fokus" #: editor/editor_file_dialog.cpp msgid "Move Favorite Up" -msgstr "" +msgstr "Pindah Kegemaran ke Atas" #: editor/editor_file_dialog.cpp msgid "Move Favorite Down" -msgstr "" +msgstr "Pindah Kegemaran ke Bawah" #: editor/editor_file_dialog.cpp msgid "Go to previous folder." -msgstr "" +msgstr "Pergi ke folder sebelumnya." #: editor/editor_file_dialog.cpp msgid "Go to next folder." -msgstr "" +msgstr "Pergi ke folder seterusnya." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Go to parent folder." -msgstr "" +msgstr "Pergi ke folder induk." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Refresh files." -msgstr "" +msgstr "Muat semula fail." #: editor/editor_file_dialog.cpp msgid "(Un)favorite current folder." -msgstr "" +msgstr "(Nyah)kegemaran folder semasa." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Toggle the visibility of hidden files." -msgstr "" +msgstr "Togol keterlihatan fail tersembunyi." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "View items as a grid of thumbnails." -msgstr "" +msgstr "Lihat barang sebagai grid gambar kecil." #: editor/editor_file_dialog.cpp editor/filesystem_dock.cpp msgid "View items as a list." -msgstr "" +msgstr "Lihat barang sebagai senarai." #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Directories & Files:" -msgstr "" +msgstr "Direktori & Fail:" #: editor/editor_file_dialog.cpp editor/plugins/sprite_editor_plugin.cpp #: editor/plugins/style_box_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Preview:" -msgstr "" +msgstr "Pratonton:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "File:" -msgstr "" +msgstr "Fail:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "Must use a valid extension." -msgstr "" +msgstr "Mesti menggunakan sambungan yang sah." #: editor/editor_file_system.cpp msgid "ScanSources" -msgstr "" +msgstr "Sumber Imbas" #: editor/editor_file_system.cpp msgid "" "There are multiple importers for different types pointing to file %s, import " "aborted" msgstr "" +"Terdapat beberapa pengimport untuk pelbagai jenis yang menunjukkan ke fail " +"%s, import dibatalkan" #: editor/editor_file_system.cpp msgid "(Re)Importing Assets" -msgstr "" +msgstr "Mengimport (Semula) Aset" #: editor/editor_help.cpp editor/plugins/spatial_editor_plugin.cpp msgid "Top" -msgstr "" +msgstr "Atas" #: editor/editor_help.cpp msgid "Class:" -msgstr "" +msgstr "Kelas:" #: editor/editor_help.cpp editor/scene_tree_editor.cpp #: editor/script_create_dialog.cpp msgid "Inherits:" -msgstr "" +msgstr "Mewarisi:" #: editor/editor_help.cpp msgid "Inherited by:" -msgstr "" +msgstr "Diwarisi oleh:" #: editor/editor_help.cpp msgid "Description" -msgstr "" +msgstr "Keterangan" #: editor/editor_help.cpp msgid "Online Tutorials" -msgstr "" +msgstr "Tutorial Dalam Talian" #: editor/editor_help.cpp msgid "Properties" -msgstr "" +msgstr "Sifat" #: editor/editor_help.cpp msgid "override:" -msgstr "" +msgstr "ganti:" #: editor/editor_help.cpp msgid "default:" -msgstr "" +msgstr "lalai:" #: editor/editor_help.cpp msgid "Methods" -msgstr "" +msgstr "Kaedah" #: editor/editor_help.cpp msgid "Theme Properties" -msgstr "" +msgstr "Sifat Tema" #: editor/editor_help.cpp msgid "Enumerations" -msgstr "" +msgstr "Penghitungan" #: editor/editor_help.cpp msgid "Constants" -msgstr "" +msgstr "Pemalar" #: editor/editor_help.cpp msgid "Property Descriptions" -msgstr "" +msgstr "Penerangan Sifat" #: editor/editor_help.cpp msgid "(value)" -msgstr "" +msgstr "(nilai)" #: editor/editor_help.cpp msgid "" "There is currently no description for this property. Please help us by " "[color=$color][url=$url]contributing one[/url][/color]!" msgstr "" +"Tiada keterangan untuk sifat ini. Tolong bantu kami dengan [color=$color]" +"[url=$url]menyumbang satu[/url][/color]!" #: editor/editor_help.cpp msgid "Method Descriptions" -msgstr "" +msgstr "Penerangan Kaedah" #: editor/editor_help.cpp msgid "" "There is currently no description for this method. Please help us by [color=" "$color][url=$url]contributing one[/url][/color]!" msgstr "" +"Tiada keterangan untuk kaedah ini. Tolong bantu kami dengan [color=$color]" +"[url=$url]menyumbang satu[/url][/color]!" #: editor/editor_help_search.cpp editor/editor_node.cpp #: editor/plugins/script_editor_plugin.cpp msgid "Search Help" -msgstr "" +msgstr "Cari Bantuan" #: editor/editor_help_search.cpp msgid "Case Sensitive" -msgstr "" +msgstr "Kesensitifan Huruf" #: editor/editor_help_search.cpp msgid "Show Hierarchy" -msgstr "" +msgstr "Tunjuk Hierarki" #: editor/editor_help_search.cpp msgid "Display All" -msgstr "" +msgstr "Paparkan Semua" #: editor/editor_help_search.cpp msgid "Classes Only" -msgstr "" +msgstr "Kelas Sahaja" #: editor/editor_help_search.cpp msgid "Methods Only" -msgstr "" +msgstr "Kaedah Sahaja" #: editor/editor_help_search.cpp msgid "Signals Only" -msgstr "" +msgstr "Isyarat Sahaja" #: editor/editor_help_search.cpp msgid "Constants Only" -msgstr "" +msgstr "Pemalar Sahaja" #: editor/editor_help_search.cpp msgid "Properties Only" -msgstr "" +msgstr "Sifat Sahaja" #: editor/editor_help_search.cpp msgid "Theme Properties Only" -msgstr "" +msgstr "Sifat Tema Sahaja" #: editor/editor_help_search.cpp msgid "Member Type" -msgstr "" +msgstr "Jenis Ahli" #: editor/editor_help_search.cpp msgid "Class" -msgstr "" +msgstr "Kelas" #: editor/editor_help_search.cpp msgid "Method" -msgstr "" +msgstr "Kaedah" #: editor/editor_help_search.cpp editor/plugins/script_text_editor.cpp msgid "Signal" -msgstr "" +msgstr "Isyarat" #: editor/editor_help_search.cpp editor/plugins/theme_editor_plugin.cpp msgid "Constant" -msgstr "" +msgstr "Pemalar" #: editor/editor_help_search.cpp msgid "Property" -msgstr "" +msgstr "Sifat" #: editor/editor_help_search.cpp msgid "Theme Property" -msgstr "" +msgstr "Sifat Tema" #: editor/editor_inspector.cpp editor/project_settings_editor.cpp msgid "Property:" -msgstr "" +msgstr "Sifat:" #: editor/editor_inspector.cpp msgid "Set" -msgstr "" +msgstr "Tetapkan" #: editor/editor_inspector.cpp msgid "Set Multiple:" -msgstr "" +msgstr "Tetapkan Pelbagai:" #: editor/editor_log.cpp msgid "Output:" -msgstr "" +msgstr "Keluaran:" #: editor/editor_log.cpp editor/plugins/tile_map_editor_plugin.cpp -#, fuzzy msgid "Copy Selection" -msgstr "Semua Pilihan" +msgstr "Salin Pilihan" #: editor/editor_log.cpp editor/editor_network_profiler.cpp #: editor/editor_profiler.cpp editor/editor_properties.cpp @@ -2065,176 +2112,184 @@ msgstr "Semua Pilihan" #: modules/gdnative/gdnative_library_editor_plugin.cpp scene/gui/line_edit.cpp #: scene/gui/text_edit.cpp msgid "Clear" -msgstr "" +msgstr "Kosongkan" #: editor/editor_log.cpp msgid "Clear Output" -msgstr "" +msgstr "Kosongkan Keluaran" #: editor/editor_network_profiler.cpp editor/editor_node.cpp #: editor/editor_profiler.cpp msgid "Stop" -msgstr "" +msgstr "Hentikan" #: editor/editor_network_profiler.cpp editor/editor_profiler.cpp #: editor/plugins/animation_state_machine_editor.cpp editor/rename_dialog.cpp msgid "Start" -msgstr "" +msgstr "Mulakan" #: editor/editor_network_profiler.cpp msgid "%s/s" -msgstr "" +msgstr "%s/s" #: editor/editor_network_profiler.cpp msgid "Down" -msgstr "" +msgstr "Bawah" #: editor/editor_network_profiler.cpp msgid "Up" -msgstr "" +msgstr "Atas" #: editor/editor_network_profiler.cpp editor/editor_node.cpp msgid "Node" -msgstr "" +msgstr "Nod" #: editor/editor_network_profiler.cpp msgid "Incoming RPC" -msgstr "" +msgstr "RPC masuk" #: editor/editor_network_profiler.cpp msgid "Incoming RSET" -msgstr "" +msgstr "RSET masuk" #: editor/editor_network_profiler.cpp msgid "Outgoing RPC" -msgstr "" +msgstr "RPC Keluar" #: editor/editor_network_profiler.cpp msgid "Outgoing RSET" -msgstr "" +msgstr "RSET Keluar" #: editor/editor_node.cpp editor/project_manager.cpp msgid "New Window" -msgstr "" +msgstr "Tetingkap Baru" #: editor/editor_node.cpp msgid "Imported resources can't be saved." -msgstr "" +msgstr "Sumber yang diimport tidak dapat disimpan." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp #: scene/gui/dialogs.cpp msgid "OK" -msgstr "" +msgstr "OK" #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Error saving resource!" -msgstr "" +msgstr "Ralat semasa menyimpan sumber!" #: editor/editor_node.cpp msgid "" "This resource can't be saved because it does not belong to the edited scene. " "Make it unique first." msgstr "" +"Sumber ini tidak dapat disimpan kerana tidak tergolong dalam adegan yang " +"diedit. Jadikannya unik terlebih dahulu." #: editor/editor_node.cpp editor/plugins/animation_player_editor_plugin.cpp msgid "Save Resource As..." -msgstr "" +msgstr "Simpan Sumber Sebagai..." #: editor/editor_node.cpp msgid "Can't open file for writing:" -msgstr "" +msgstr "Tidak dapat membuka fail untuk ditulis:" #: editor/editor_node.cpp msgid "Requested file format unknown:" -msgstr "" +msgstr "Format fail yang diminta tidak diketahui:" #: editor/editor_node.cpp msgid "Error while saving." -msgstr "" +msgstr "Ralat semasa menyimpan." #: editor/editor_node.cpp editor/plugins/script_editor_plugin.cpp msgid "Can't open '%s'. The file could have been moved or deleted." msgstr "" +"Tidak dapat membuka '% s'. Fail mungkin telah dipindahkan atau dipadam." #: editor/editor_node.cpp msgid "Error while parsing '%s'." -msgstr "" +msgstr "Ralat semasa menghuraikan '%s'." #: editor/editor_node.cpp msgid "Unexpected end of file '%s'." -msgstr "" +msgstr "Penghujung fail '%s' tidak dijangka." #: editor/editor_node.cpp msgid "Missing '%s' or its dependencies." -msgstr "" +msgstr "Hilang '%s' atau kebergantungannya." #: editor/editor_node.cpp msgid "Error while loading '%s'." -msgstr "" +msgstr "Ralat semasa memuatkan '%s'." #: editor/editor_node.cpp msgid "Saving Scene" -msgstr "" +msgstr "Menyimpan Adegan" #: editor/editor_node.cpp msgid "Analyzing" -msgstr "" +msgstr "Menganalisis" #: editor/editor_node.cpp msgid "Creating Thumbnail" -msgstr "" +msgstr "Mencipta Gambar Kecil" #: editor/editor_node.cpp msgid "This operation can't be done without a tree root." -msgstr "" +msgstr "Operasi ini tidak boleh dilakukan tanpa akar pokok." #: editor/editor_node.cpp msgid "" "This scene can't be saved because there is a cyclic instancing inclusion.\n" "Please resolve it and then attempt to save again." msgstr "" +"Adegan ini tidak dapat disimpan kerana terdapat penyertaan yang berbentuk " +"siklik.\n" +"Sila selesaikan dan kemudian cuba simpan semula." #: editor/editor_node.cpp msgid "" "Couldn't save scene. Likely dependencies (instances or inheritance) couldn't " "be satisfied." msgstr "" +"Tidak dapat menyimpan adegan. Kemungkinan kebergantungan (instance atau " +"warisan) tidak dapat dipenuhi." #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "Can't overwrite scene that is still open!" -msgstr "" +msgstr "Tidak boleh tulis ganti adegan yang masih terbuka!" #: editor/editor_node.cpp msgid "Can't load MeshLibrary for merging!" -msgstr "" +msgstr "Tidak dapat memuatkan MeshLibrary untuk penggabungan!" #: editor/editor_node.cpp msgid "Error saving MeshLibrary!" -msgstr "" +msgstr "Ralat menyimpan MeshLibrary!" #: editor/editor_node.cpp msgid "Can't load TileSet for merging!" -msgstr "" +msgstr "Tidak boleh memuatkan TileSet untuk penggabungan!" #: editor/editor_node.cpp msgid "Error saving TileSet!" -msgstr "" +msgstr "Ralat semasa menyimpan TileSet!" #: editor/editor_node.cpp msgid "Error trying to save layout!" -msgstr "" +msgstr "Ralat semasa menyimpan susun atur!" #: editor/editor_node.cpp msgid "Default editor layout overridden." -msgstr "" +msgstr "Susun atur lalai telah diganti." #: editor/editor_node.cpp msgid "Layout name not found!" -msgstr "" +msgstr "Nama susun atur tidak dijumpai!" #: editor/editor_node.cpp msgid "Restored default layout to base settings." -msgstr "" +msgstr "Tata letak lalai telah dipulihkan ke tetapan asas." #: editor/editor_node.cpp msgid "" @@ -2242,18 +2297,26 @@ msgid "" "Please read the documentation relevant to importing scenes to better " "understand this workflow." msgstr "" +"Sumber ini tergolong dalam adegan yang diimport, maka ia tidak dapat " +"diedit.\n" +"Sila baca dokumentasi yang berkaitan dengan pengimportan adegan untuk lebih " +"memahami aliran kerja ini." #: editor/editor_node.cpp msgid "" "This resource belongs to a scene that was instanced or inherited.\n" "Changes to it won't be kept when saving the current scene." msgstr "" +"Sumber ini tergolong dalam adegan yang di-instance atau diwarisi.\n" +"Perubahan tidak akan disimpan semasa menyimpan adegan semasa." #: editor/editor_node.cpp msgid "" "This resource was imported, so it's not editable. Change its settings in the " "import panel and then re-import." msgstr "" +"Sumber ini telah diimport, maka ia tidak dapat diedit. Ubah tetapannya di " +"panel import dan kemudian import semula." #: editor/editor_node.cpp msgid "" @@ -2262,6 +2325,10 @@ msgid "" "Please read the documentation relevant to importing scenes to better " "understand this workflow." msgstr "" +"Adegan ini telah diimport, maka perubahan kepada ia tidak akan disimpan.\n" +"Instance-kan ia atau mewarisi akan membenarkan perubahan dibuat padanya.\n" +"Sila baca dokumentasi yang berkaitan dengan pengimportan adegan untuk lebih " +"memahami aliran kerja ini." #: editor/editor_node.cpp msgid "" @@ -2269,108 +2336,114 @@ msgid "" "Please read the documentation relevant to debugging to better understand " "this workflow." msgstr "" +"Ini adalah objek terpencil, maka perubahan padanya tidak akan disimpan.\n" +"Sila baca dokumentasi yang berkaitan dengan penyahpepijatan untuk lebih " +"memahami aliran kerja ini." #: editor/editor_node.cpp msgid "There is no defined scene to run." -msgstr "" +msgstr "Tiada adegan yang didefinisikan untuk dijalankan." #: editor/editor_node.cpp msgid "Could not start subprocess!" -msgstr "" +msgstr "Tidak dapat memulakan subproses!" #: editor/editor_node.cpp editor/filesystem_dock.cpp msgid "Open Scene" -msgstr "" +msgstr "Buka Adegan" #: editor/editor_node.cpp msgid "Open Base Scene" -msgstr "" +msgstr "Buka Adegan Asas" #: editor/editor_node.cpp msgid "Quick Open..." -msgstr "" +msgstr "Buka Cepat..." #: editor/editor_node.cpp msgid "Quick Open Scene..." -msgstr "" +msgstr "Buka Cepat Adegan..." #: editor/editor_node.cpp msgid "Quick Open Script..." -msgstr "" +msgstr "Buka Cepat Skrip..." #: editor/editor_node.cpp msgid "Save & Close" -msgstr "" +msgstr "Simpan & Tutup" #: editor/editor_node.cpp msgid "Save changes to '%s' before closing?" -msgstr "" +msgstr "Simpan perubahan pada '%s' sebelum menutup?" #: editor/editor_node.cpp msgid "Saved %s modified resource(s)." -msgstr "" +msgstr "Sumber %s yang diubahsuai telah disimpan." #: editor/editor_node.cpp msgid "A root node is required to save the scene." -msgstr "" +msgstr "Nod akar diperlukan untuk menyimpan adegan." #: editor/editor_node.cpp msgid "Save Scene As..." -msgstr "" +msgstr "Simpan Adegan Sebagai..." #: editor/editor_node.cpp msgid "No" -msgstr "" +msgstr "Tidak" #: editor/editor_node.cpp msgid "Yes" -msgstr "" +msgstr "Ya" #: editor/editor_node.cpp msgid "This scene has never been saved. Save before running?" -msgstr "" +msgstr "Adegan ini tidak pernah disimpan. Simpan sebelum menjalankan?" #: editor/editor_node.cpp editor/scene_tree_dock.cpp msgid "This operation can't be done without a scene." -msgstr "" +msgstr "Operasi ini tidak boleh dilakukan tanpa adegan." #: editor/editor_node.cpp msgid "Export Mesh Library" -msgstr "" +msgstr "Eksport Perpustakaan Mesh" #: editor/editor_node.cpp msgid "This operation can't be done without a root node." -msgstr "" +msgstr "Operasi ini tidak boleh dilakukan tanpa nod akar." #: editor/editor_node.cpp msgid "Export Tile Set" -msgstr "" +msgstr "Eksport Tile Set" #: editor/editor_node.cpp msgid "This operation can't be done without a selected node." -msgstr "" +msgstr "Operasi ini tidak dapat dilakukan tanpa nod terpilih." #: editor/editor_node.cpp msgid "Current scene not saved. Open anyway?" -msgstr "" +msgstr "Adegan semasa tidak disimpan. Masih buka?" #: editor/editor_node.cpp msgid "Can't reload a scene that was never saved." -msgstr "" +msgstr "Tidak dapat memuatkan semula adegan yang tidak pernah disimpan." #: editor/editor_node.cpp msgid "Reload Saved Scene" -msgstr "" +msgstr "Muatkan semula Adegan yang Disimpan" #: editor/editor_node.cpp msgid "" "The current scene has unsaved changes.\n" "Reload the saved scene anyway? This action cannot be undone." msgstr "" +"Adegan semasa mempunyai perubahan yang belum disimpan.\n" +"Masih muat semula adegan yang telah disimpan? Tindakan ini tidak boleh " +"dibuat asal." #: editor/editor_node.cpp msgid "Quick Run Scene..." -msgstr "" +msgstr "Jalan Cepat Adegan..." #: editor/editor_node.cpp msgid "Quit" @@ -2758,9 +2831,8 @@ msgid "Editor" msgstr "" #: editor/editor_node.cpp -#, fuzzy msgid "Editor Settings..." -msgstr "Set Peralihan ke:" +msgstr "Tetapan Editor..." #: editor/editor_node.cpp msgid "Editor Layout" @@ -4064,9 +4136,8 @@ msgstr "" #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp -#, fuzzy msgid "Add Animation Point" -msgstr "Set Peralihan ke:" +msgstr "Tambah Titik Animasi" #: editor/plugins/animation_blend_space_1d_editor.cpp msgid "Remove BlendSpace1D Point" @@ -4209,9 +4280,8 @@ msgid "Nodes Disconnected" msgstr "" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Set Animation" -msgstr "Set Peralihan ke:" +msgstr "Tetapkan Animasi" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp @@ -4391,9 +4461,8 @@ msgid "Animation" msgstr "" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Edit Transitions..." -msgstr "Set Peralihan ke:" +msgstr "Sunting Peralihan..." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Open in Inspector" @@ -4491,14 +4560,12 @@ msgid "Move Node" msgstr "" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition exists!" -msgstr "Set Peralihan ke:" +msgstr "Peralihan wujud!" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Add Transition" -msgstr "Set Peralihan ke:" +msgstr "Tambah Peralihan" #: editor/plugins/animation_state_machine_editor.cpp #: modules/visual_script/visual_script_editor.cpp @@ -4538,9 +4605,8 @@ msgid "Node Removed" msgstr "" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition Removed" -msgstr "Set Peralihan ke:" +msgstr "Peralihan Dikeluarkan" #: editor/plugins/animation_state_machine_editor.cpp msgid "Set Start Node (Autoplay)" @@ -4574,9 +4640,8 @@ msgid "Set the end animation. This is useful for sub-transitions." msgstr "" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition: " -msgstr "Set Peralihan ke:" +msgstr "Peralihan: " #: editor/plugins/animation_state_machine_editor.cpp msgid "Play Mode:" @@ -5621,9 +5686,8 @@ msgid "Load Curve Preset" msgstr "" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Add Point" -msgstr "Set Peralihan ke:" +msgstr "Tambah Titik" #: editor/plugins/curve_editor_plugin.cpp #, fuzzy @@ -8065,9 +8129,8 @@ msgid "" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Delete selected Rect." -msgstr "Semua Pilihan" +msgstr "Padam Rect yang dipilih." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8076,9 +8139,8 @@ msgid "" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "Delete polygon." -msgstr "Semua Pilihan" +msgstr "Padam poligon." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8477,9 +8539,8 @@ msgid "Color constant." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Color uniform." -msgstr "Anim Ubah Penukaran" +msgstr "Warna seragam." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the boolean result of the %s comparison between two parameters." @@ -8822,9 +8883,8 @@ msgid "Scalar constant." msgstr "" #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Scalar uniform." -msgstr "Anim Ubah Penukaran" +msgstr "Seragam skalar." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Perform the cubic texture lookup." @@ -9532,6 +9592,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" @@ -10177,14 +10238,12 @@ msgid "Make node as Root" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes and any children?" -msgstr "Semua Pilihan" +msgstr "Padamkan nod %d dan mana-mana kanak-kanak?" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes?" -msgstr "Semua Pilihan" +msgstr "Padam nod %d?" #: editor/scene_tree_dock.cpp msgid "Delete the root node \"%s\"?" @@ -10195,9 +10254,8 @@ msgid "Delete node \"%s\" and its children?" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete node \"%s\"?" -msgstr "Semua Pilihan" +msgstr "Padam nod \"%s\"?" #: editor/scene_tree_dock.cpp msgid "Can not perform with the root node." @@ -11172,9 +11230,8 @@ msgid "Set Variable Type" msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Input Port" -msgstr "Set Peralihan ke:" +msgstr "Tambah Port Input" #: modules/visual_script/visual_script_editor.cpp msgid "Add Output Port" @@ -11419,9 +11476,8 @@ msgid "Add Nodes..." msgstr "" #: modules/visual_script/visual_script_editor.cpp -#, fuzzy msgid "Add Function..." -msgstr "Semua Pilihan" +msgstr "Tambah fungsi..." #: modules/visual_script/visual_script_editor.cpp msgid "function_name" diff --git a/editor/translations/nb.po b/editor/translations/nb.po index dbad564d9a..a31504e186 100644 --- a/editor/translations/nb.po +++ b/editor/translations/nb.po @@ -1178,6 +1178,9 @@ msgstr "Prosjektgrunnleggere" msgid "Lead Developer" msgstr "Utviklingsleder" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Prosjektstyring " @@ -1199,6 +1202,16 @@ msgid "Gold Sponsors" msgstr "Gullsponsorer" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Sølvdonorer" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronsedonorer" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Minisponsorer" @@ -10302,6 +10315,7 @@ msgstr "" "Godotprosjekter.\n" "Det kan ta en stund." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Prosjektstyring" diff --git a/editor/translations/nl.po b/editor/translations/nl.po index 7f111ad901..1dabe25c73 100644 --- a/editor/translations/nl.po +++ b/editor/translations/nl.po @@ -47,8 +47,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-04 08:58+0000\n" -"Last-Translator: marnicq van loon <marnicqvanloon@gmail.com>\n" +"PO-Revision-Date: 2020-08-28 13:09+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" "Language: nl\n" @@ -56,7 +56,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.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1160,6 +1160,9 @@ msgstr "Projectoprichters" msgid "Lead Developer" msgstr "Hoofdontwikkelaar" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Projectbeheer " @@ -1181,6 +1184,16 @@ msgid "Gold Sponsors" msgstr "Gouden Sponsors" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Zilveren Donors" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronzen Donors" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsoren" @@ -7361,7 +7374,7 @@ msgstr "Bekijk Omgeving" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Gizmos" -msgstr "Bekijk Gizmos" +msgstr "Toon Gizmos" #: editor/plugins/spatial_editor_plugin.cpp msgid "View Information" @@ -7450,9 +7463,9 @@ msgid "" msgstr "" "Klik om te wisselen tussen zichtbaarheidsweergaven.\n" "\n" -"Open oog: handvat is zichtbaar.\n" -"Gesloten oog: handvat is verborgen.\n" -"Half open oog: handvat is ook zichtbaar door ondoorzichtige oppervlaktes." +"Open oog: Gizmo is zichtbaar.\n" +"Gesloten oog: Gizmo is verborgen.\n" +"Half open oog: Gizmo is ook zichtbaar door ondoorzichtige oppervlaktes." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -7640,7 +7653,7 @@ msgstr "Post" #: editor/plugins/spatial_editor_plugin.cpp msgid "Nameless gizmo" -msgstr "Naamloos apparaat" +msgstr "Naamloze gizmo" #: editor/plugins/sprite_editor_plugin.cpp msgid "Create Mesh2D" @@ -9932,6 +9945,7 @@ msgstr "" "Wil je %s mappen doorzoeken naar bestaande Godot projecten?\n" "Dit kan een tijdje duren." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Projectbeheer" @@ -10596,9 +10610,8 @@ msgid "Make node as Root" msgstr "Knoop tot wortelknoop maken" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes and any children?" -msgstr "Verwijder knoop \"%s\" en zijn kinderen?" +msgstr "%d knopen en hun (eventuele) kinderen verwijderen?" #: editor/scene_tree_dock.cpp msgid "Delete %d nodes?" diff --git a/editor/translations/or.po b/editor/translations/or.po index 5859fe6b0a..220638494d 100644 --- a/editor/translations/or.po +++ b/editor/translations/or.po @@ -1084,6 +1084,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1105,6 +1108,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9465,6 +9476,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/pl.po b/editor/translations/pl.po index d7ff515b05..dd93a0ec83 100644 --- a/editor/translations/pl.po +++ b/editor/translations/pl.po @@ -41,12 +41,13 @@ # Jan LigudziÅ„ski <jan.ligudzinski@gmail.com>, 2020. # Adam Jagoda <kontakt@lukasz.xyz>, 2020. # Filip Glura <mcmr.slendy@gmail.com>, 2020. +# Roman Skiba <romanskiba0@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-31 03:47+0000\n" -"Last-Translator: Tomek <kobewi4e@gmail.com>\n" +"PO-Revision-Date: 2020-09-01 18:42+0000\n" +"Last-Translator: Roman Skiba <romanskiba0@gmail.com>\n" "Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/" "godot/pl/>\n" "Language: pl\n" @@ -55,7 +56,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.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1151,6 +1152,9 @@ msgstr "ZaÅ‚ożyciele projektu" msgid "Lead Developer" msgstr "Deweloper naczelny" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Menedżer projektu " @@ -1172,6 +1176,16 @@ msgid "Gold Sponsors" msgstr "ZÅ‚oci sponsorzy" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Srebrni darczyÅ„cy" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "BrÄ…zowi darczyÅ„cy" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini-sponsorzy" @@ -9539,7 +9553,7 @@ msgstr "Plik paczki" #: editor/project_export.cpp msgid "Features" -msgstr "FunkcjonalnoÅ›ci" +msgstr "Funkcje" #: editor/project_export.cpp msgid "Custom (comma-separated):" @@ -9898,6 +9912,7 @@ msgstr "" "projektów Godota?\n" "To może chwilÄ™ zająć." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Menedżer projektów" diff --git a/editor/translations/pr.po b/editor/translations/pr.po index bf2d3ef0ad..9640ed40f1 100644 --- a/editor/translations/pr.po +++ b/editor/translations/pr.po @@ -1127,6 +1127,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1148,6 +1151,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9789,6 +9800,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po index 6c035decd5..3e9e709aab 100644 --- a/editor/translations/pt_BR.po +++ b/editor/translations/pt_BR.po @@ -1209,9 +1209,12 @@ msgstr "Fundadores do Projeto" msgid "Lead Developer" msgstr "Desenvolvedor-chefe" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Gerenciador de Projetos " +msgstr "Gerente do Projeto " #: editor/editor_about.cpp msgid "Developers" @@ -1230,6 +1233,16 @@ msgid "Gold Sponsors" msgstr "Patrocinadores Ouro" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Doadores Prata" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Doadores Bronze" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Patrocinadores Mini" @@ -9966,6 +9979,7 @@ msgstr "" "existentes?\n" "Isso pode levar algum tempo." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Gerenciador de Projetos" diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po index b9d6c82ff0..63c82c84ba 100644 --- a/editor/translations/pt_PT.po +++ b/editor/translations/pt_PT.po @@ -13,15 +13,15 @@ # Rueben Stevens <supercell03@gmail.com>, 2017. # SARDON <fabio3_Santos@hotmail.com>, 2017. # Vinicius Gonçalves <viniciusgoncalves21@gmail.com>, 2017. -# ssantos <ssantos@web.de>, 2018, 2019. +# ssantos <ssantos@web.de>, 2018, 2019, 2020. # Gonçalo Dinis Guerreiro João <goncalojoao205@gmail.com>, 2019. # Manuela Silva <mmsrs@sky.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-31 03:47+0000\n" -"Last-Translator: João Lopes <linux-man@hotmail.com>\n" +"PO-Revision-Date: 2020-08-16 15:25+0000\n" +"Last-Translator: ssantos <ssantos@web.de>\n" "Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/" "godot-engine/godot/pt_PT/>\n" "Language: pt_PT\n" @@ -1037,7 +1037,7 @@ msgstr "Proprietários de:" #: editor/dependency_editor.cpp msgid "Remove selected files from the project? (Can't be restored)" -msgstr "Remover arquivos selecionados do Projeto? (Sem desfazer)" +msgstr "Remover ficheiros selecionados do Projeto? (Sem desfazer)" #: editor/dependency_editor.cpp msgid "" @@ -1045,7 +1045,7 @@ msgid "" "work.\n" "Remove them anyway? (no undo)" msgstr "" -"Os arquivos a serem removidos são necessários para que outros recursos " +"Os ficheiros a serem removidos são necessários para que outros recursos " "funcionem.\n" "Remover mesmo assim? (sem anular)" @@ -1129,6 +1129,9 @@ msgstr "Fundadores do Projeto" msgid "Lead Developer" msgstr "Desenvolvedor-chefe" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Gestor de Projeto " @@ -1150,6 +1153,16 @@ msgid "Gold Sponsors" msgstr "Patrocinadores Gold" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Doadores Silver" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Doadores Bronze" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Patrocinadores Mini" @@ -1403,11 +1416,11 @@ msgstr "Guardar este Modelo de Barramento para um ficheiro." #: editor/editor_audio_buses.cpp editor/import_dock.cpp msgid "Load Default" -msgstr "Carregar Padrão" +msgstr "Carregar Predefinição" #: editor/editor_audio_buses.cpp msgid "Load the default Bus Layout." -msgstr "Carregar o Modelo padrão de barramento." +msgstr "Carregar o Modelo predefinido de barramento." #: editor/editor_audio_buses.cpp msgid "Create a new Bus Layout." @@ -1551,7 +1564,7 @@ msgstr "Escolha" #: editor/editor_export.cpp msgid "Storing File:" -msgstr "Arquivo de Armazenamento:" +msgstr "Armazenar o Ficheiro:" #: editor/editor_export.cpp msgid "No export template found at the expected path:" @@ -1962,7 +1975,7 @@ msgstr "Sobrepõe:" #: editor/editor_help.cpp msgid "default:" -msgstr "Padrão:" +msgstr "predefinição:" #: editor/editor_help.cpp msgid "Methods" @@ -2273,7 +2286,7 @@ msgstr "Erro ao tentar guardar o Modelo!" #: editor/editor_node.cpp msgid "Default editor layout overridden." -msgstr "O Modelo do Editor padrão foi substituÃdo." +msgstr "O modelo do editor predefinido foi substituÃdo." #: editor/editor_node.cpp msgid "Layout name not found!" @@ -2281,7 +2294,7 @@ msgstr "Nome do Modelo não encontrado!" #: editor/editor_node.cpp msgid "Restored default layout to base settings." -msgstr "Modelo padrão restaurado para as configurações base." +msgstr "Modelo predefinido restaurado para as configurações base." #: editor/editor_node.cpp msgid "" @@ -2582,7 +2595,7 @@ msgstr "Apagar Modelo" #: editor/editor_node.cpp editor/import_dock.cpp #: editor/script_create_dialog.cpp msgid "Default" -msgstr "Padrão" +msgstr "Predefinição" #: editor/editor_node.cpp editor/editor_properties.cpp #: editor/plugins/script_editor_plugin.cpp editor/property_editor.cpp @@ -2840,7 +2853,7 @@ msgid "" msgstr "" "Com esta opção ativa, alterações da cena no editor serão replicadas no jogo " "em execução.\n" -"Quando usada num dispositivo remoto, é mais eficiente com um sistema de " +"Quando usada num aparelho remoto, é mais eficiente com um sistema de " "ficheiros em rede." #: editor/editor_node.cpp @@ -2856,7 +2869,7 @@ msgid "" msgstr "" "Com esta opção ativa, qualquer Script guardado será recarregado no jogo em " "execução.\n" -"Quando usada num dispositivo remoto, é mais eficiente com um Sistema de " +"Quando usada num aparelho remoto, é mais eficiente com um Sistema de " "Ficheiros em rede." #: editor/editor_node.cpp editor/script_create_dialog.cpp @@ -3464,8 +3477,9 @@ msgid "" "No download links found for this version. Direct download is only available " "for official releases." msgstr "" -"Não foram encontrados ligações para download para esta versão. Download " -"direto está apenas disponÃvel para os lançamentos oficiais." +"Não foram encontrados ligações para descarregar para esta versão. " +"Descarregamentos diretos estão disponÃveis apenas para os lançamentos " +"oficiais." #: editor/export_template_manager.cpp #: editor/plugins/asset_library_editor_plugin.cpp @@ -3981,11 +3995,11 @@ msgstr "%d Ficheiros" #: editor/import_dock.cpp msgid "Set as Default for '%s'" -msgstr "Definir como Padrão para '%s'" +msgstr "Definir como Predefinição para '%s'" #: editor/import_dock.cpp msgid "Clear Default for '%s'" -msgstr "Limpar Padrão para '%s'" +msgstr "Limpar Predefinição para '%s'" #: editor/import_dock.cpp msgid "Import As:" @@ -5658,7 +5672,7 @@ msgstr "Erro a instanciar cena de %s" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Default Type" -msgstr "Mudar Tipo Padrão" +msgstr "Mudar Predefinição de Tipo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -8577,7 +8591,7 @@ msgstr "Definir Nome do Uniform" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Set Input Default Port" -msgstr "Definir Porta de Entrada Padrão" +msgstr "Definir Porta de Entrada Predefinida" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add Node to Visual Shader" @@ -9306,7 +9320,7 @@ msgid "" "constants." msgstr "" "Expressão personalizada em Linguagem Godot Shader, colocada sobre o shader " -"resultante. Pode colocar várias definições de função e chamá-las depois nas " +"resultante. Pode pôr várias definições de função e chamá-las depois nas " "Expressões. Também pode declarar variantes, uniformes e constantes." #: editor/plugins/visual_shader_editor_plugin.cpp @@ -9864,6 +9878,7 @@ msgstr "" "Pretende pesquisar %s pastas por projetos Godot existentes?\n" "Pode demorar um pouco." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Gestor de Projetos" @@ -9965,11 +9980,11 @@ msgstr "Adicionar evento ação de entrada" #: editor/project_settings_editor.cpp msgid "All Devices" -msgstr "Todos os Dispositivos" +msgstr "Todos os Aparelhos" #: editor/project_settings_editor.cpp msgid "Device" -msgstr "Dispositivo" +msgstr "Aparelho" #: editor/project_settings_editor.cpp editor/settings_config_dialog.cpp msgid "Press a Key..." @@ -10181,7 +10196,7 @@ msgstr "Zona morta" #: editor/project_settings_editor.cpp msgid "Device:" -msgstr "Dispositivo:" +msgstr "Aparelho:" #: editor/project_settings_editor.cpp msgid "Index:" @@ -10425,11 +10440,11 @@ msgstr "No carácter %s" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent Node" -msgstr "Recolocar Nó" +msgstr "Repôr Nó" #: editor/reparent_dialog.cpp msgid "Reparent Location (Select new Parent):" -msgstr "Recolocar localização (selecionar novo Parente):" +msgstr "Repôr localização (selecionar novo Parente):" #: editor/reparent_dialog.cpp msgid "Keep Global Transform" @@ -10437,7 +10452,7 @@ msgstr "Manter transformação global" #: editor/reparent_dialog.cpp editor/scene_tree_dock.cpp msgid "Reparent" -msgstr "Recolocar" +msgstr "Repôr" #: editor/run_settings_dialog.cpp msgid "Run Mode:" @@ -10562,7 +10577,7 @@ msgid "" "reverted to their default." msgstr "" "Desativar \"editable_instance\" irá reverter todas as propriedades do nó " -"para os seus valores padrão." +"para os seus valores predefinição." #: editor/scene_tree_dock.cpp msgid "" @@ -10570,7 +10585,8 @@ msgid "" "cause all properties of the node to be reverted to their default." msgstr "" "Ativar \"Carregar como Espaço Reservado\" vai desativar \"Filhos Editáveis\" " -"e fazer com que todas as propriedades do nó revertam para valores padrão." +"e fazer com que todas as propriedades do nó revertam para valores " +"predefinidos." #: editor/scene_tree_dock.cpp msgid "Make Local" @@ -10680,7 +10696,7 @@ msgstr "Mudar tipo" #: editor/scene_tree_dock.cpp msgid "Reparent to New Node" -msgstr "Recolocar o Novo Nó" +msgstr "Repôr o Novo Nó" #: editor/scene_tree_dock.cpp msgid "Make Scene Root" @@ -11539,7 +11555,7 @@ msgstr "Mudar nome do argumento" #: modules/visual_script/visual_script_editor.cpp msgid "Set Variable Default Value" -msgstr "Definir Valor Padrão da Variável" +msgstr "Definir Valor Predefinido da Variável" #: modules/visual_script/visual_script_editor.cpp msgid "Set Variable Type" @@ -11931,7 +11947,7 @@ msgstr "O pacote deve ter pelo menos um separador '.'." #: platform/android/export/export.cpp msgid "Select device from the list" -msgstr "Selecionar dispositivo da lista" +msgstr "Selecionar aparelho da lista" #: platform/android/export/export.cpp msgid "ADB executable not configured in the Editor Settings." @@ -12083,7 +12099,7 @@ msgstr "Executar no Navegador" #: platform/javascript/export/export.cpp msgid "Run exported HTML in the system's default browser." -msgstr "Executar HTML exportado no Navegador padrão do sistema." +msgstr "Executar HTML exportado no navegador predefinido do sistema." #: platform/javascript/export/export.cpp msgid "Could not write file:" @@ -12107,7 +12123,7 @@ msgstr "Não consigo ler ficheiro de imagem do ecrã de inicialização:" #: platform/javascript/export/export.cpp msgid "Using default boot splash image." -msgstr "A usar imagem padrão de inicialização." +msgstr "A usar imagem de inicialização predefinida." #: platform/uwp/export/export.cpp msgid "Invalid package short name." @@ -12333,7 +12349,7 @@ msgstr "" #: scene/2d/skeleton_2d.cpp msgid "This Bone2D chain should end at a Skeleton2D node." -msgstr "Esta corrente de Bone2D deve terminar em um nó Skeleton2D." +msgstr "Esta corrente de Bone2D deve terminar num nó Skeleton2D." #: scene/2d/skeleton_2d.cpp msgid "A Bone2D only works with a Skeleton2D or another Bone2D as parent node." @@ -12754,7 +12770,7 @@ msgid "" "Default Environment as specified in Project Settings (Rendering -> " "Environment -> Default Environment) could not be loaded." msgstr "" -"Ambiente Padrão especificado em Configuração do Projeto (Rendering -> " +"Ambiente predefinido especificado em Configuração do Projeto (Rendering -> " "Environment -> Default Environment) não pode ser carregado." #: scene/main/viewport.cpp diff --git a/editor/translations/ro.po b/editor/translations/ro.po index 29487392f8..5a8c083d54 100644 --- a/editor/translations/ro.po +++ b/editor/translations/ro.po @@ -1126,6 +1126,9 @@ msgstr "Fondatorii Proiectului" msgid "Lead Developer" msgstr "Dezvoltator Principal" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Manager de Proiect " @@ -1147,6 +1150,16 @@ msgid "Gold Sponsors" msgstr "Sponsori Aur" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Donatori de Argint" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Donatori de Bronz" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsori" @@ -9912,6 +9925,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/ru.po b/editor/translations/ru.po index 7b12d8195c..9e0ecb8e8d 100644 --- a/editor/translations/ru.po +++ b/editor/translations/ru.po @@ -85,12 +85,14 @@ # kyanukovich <ianu0001@algonquinlive.com>, 2020. # Ron788 <ustinov200511@gmail.com>, 2020. # Daniel <dan.ef1999@gmail.com>, 2020. +# NeoLan Qu <it.bulla@mail.ru>, 2020. +# Nikita Epifanov <nikgreens@protonmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-01 11:14+0000\n" -"Last-Translator: Daniel <dan.ef1999@gmail.com>\n" +"PO-Revision-Date: 2020-09-08 11:40+0000\n" +"Last-Translator: Nikita Epifanov <nikgreens@protonmail.com>\n" "Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/" "godot/ru/>\n" "Language: ru\n" @@ -99,7 +101,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1197,6 +1199,9 @@ msgstr "ОÑнователи Проекта" msgid "Lead Developer" msgstr "Ведущий разработчик" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Менеджер проектов " @@ -1218,6 +1223,14 @@ msgid "Gold Sponsors" msgstr "Золотые ÑпонÑоры" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "СеребрÑные ÑпонÑоры" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "Бронзовые ÑпонÑоры" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Мини ÑпонÑоры" @@ -8952,7 +8965,7 @@ msgstr "Возвращает обратный гиперболичеÑкий Ñ‚Ð #: editor/plugins/visual_shader_editor_plugin.cpp msgid "" "Finds the nearest integer that is greater than or equal to the parameter." -msgstr "ВычиÑлÑет ближайшее целое чиÑло, большее или равное аргументу." +msgstr "Ðаходит ближайшее целое, которое больше или равно параметра." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Constrains a value to lie between two further values." @@ -8960,11 +8973,11 @@ msgstr "Удерживает значение в пределах двух Ð´Ñ€Ñ #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the cosine of the parameter." -msgstr "Возвращает коÑÐ¸Ð½ÑƒÑ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°." +msgstr "Возвращает коÑÐ¸Ð½ÑƒÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the hyperbolic cosine of the parameter." -msgstr "Возвращает гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°." +msgstr "Возвращает гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð°." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Converts a quantity in radians to degrees." @@ -8980,7 +8993,7 @@ msgstr "ÐкÑпонента Ñ Ð¾Ñнованием 2." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest integer less than or equal to the parameter." -msgstr "ВычиÑлÑет ближайшее целое, меньшее или равное аргументу." +msgstr "Ðаходит ближайшее целое, меньшее или равное аргументу." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Computes the fractional part of the argument." @@ -8988,7 +9001,7 @@ msgstr "ВычиÑлÑет дробную чаÑÑ‚ÑŒ аргумента." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Returns the inverse of the square root of the parameter." -msgstr "Возвращает обратный корень из аргумента." +msgstr "Возвращает обратный квадратный корень из аргумента." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Natural logarithm." @@ -9033,11 +9046,11 @@ msgstr "1.0 / ÑкалÑÑ€" #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest integer to the parameter." -msgstr "ВычиÑлÑет ближайшее целое чиÑло." +msgstr "Ðаходит ближайшее к параметру целое чиÑло." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Finds the nearest even integer to the parameter." -msgstr "ВычиÑлÑет ближайшее чётное чиÑло." +msgstr "Ðаходит ближайшее чётное чиÑло к параметру." #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Clamps the value between 0.0 and 1.0." @@ -9939,6 +9952,7 @@ msgstr "" "Ð’Ñ‹ дейÑтвительно хотите поиÑкать ÑущеÑтвующие проекты Godot в %s папках?\n" "Ðто может занÑÑ‚ÑŒ много времени." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Менеджер проектов" diff --git a/editor/translations/si.po b/editor/translations/si.po index c8b0a57cbe..6db6ba355a 100644 --- a/editor/translations/si.po +++ b/editor/translations/si.po @@ -1107,6 +1107,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1128,6 +1131,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9542,6 +9553,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/sk.po b/editor/translations/sk.po index 59cd8da671..7a5bd57c4c 100644 --- a/editor/translations/sk.po +++ b/editor/translations/sk.po @@ -14,7 +14,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-09-08 11:40+0000\n" "Last-Translator: Richard Urban <redasuio1@gmail.com>\n" "Language-Team: Slovak <https://hosted.weblate.org/projects/godot-engine/" "godot/sk/>\n" @@ -23,7 +23,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.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -32,7 +32,7 @@ msgstr "Chybný argument convert(), použite TYPE_* konÅ¡tanty." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "dĺžka oÄakávaného stringu 1 (pÃsmeno)" +msgstr "dĺžka oÄakávaného stringu 1 (pÃsmeno)." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/mono/glue/gd_glue.cpp @@ -42,7 +42,7 @@ msgstr "Nedostatok bajtov na dekódovanie, alebo chybný formát." #: core/math/expression.cpp msgid "Invalid input %i (not passed) in expression" -msgstr "Neplatný vstup %i (nepreÅ¡lo) vo výraze" +msgstr "Nesprávny vstup(input) %i (neschválený) v požiadavke" #: core/math/expression.cpp msgid "self can't be used because instance is null (not passed)" @@ -98,7 +98,7 @@ msgstr "EiB" #: editor/animation_bezier_editor.cpp msgid "Free" -msgstr "zadarmo" +msgstr "Voľný" #: editor/animation_bezier_editor.cpp msgid "Balanced" @@ -118,7 +118,7 @@ msgstr "Hodnota:" #: editor/animation_bezier_editor.cpp msgid "Insert Key Here" -msgstr "Sem Vložte KľúÄ" +msgstr "Tu vložiÅ¥ kľúÄ" #: editor/animation_bezier_editor.cpp msgid "Duplicate Selected Key(s)" @@ -130,7 +130,7 @@ msgstr "ZmazaÅ¥ oznaÄené kľúÄ(e)" #: editor/animation_bezier_editor.cpp msgid "Add Bezier Point" -msgstr "PridaÅ¥ Bezierov bod" +msgstr "PridaÅ¥ Bezier bod" #: editor/animation_bezier_editor.cpp msgid "Move Bezier Points" @@ -191,7 +191,7 @@ msgstr "ZmeniÅ¥ Dĺžku Animácie (Change Animation Length)" #: editor/animation_track_editor.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Change Animation Loop" -msgstr "ZmeniÅ¥ opakovanie Animácie (Change Animation Loop)" +msgstr "ZmeniÅ¥ Opakovanie Animácie" #: editor/animation_track_editor.cpp msgid "Property Track" @@ -256,7 +256,7 @@ msgstr "Zapnúť/Vypnúť tento track." #: editor/animation_track_editor.cpp msgid "Update Mode (How this property is set)" -msgstr "Update Mode (ako je nastavená táto možnosÅ¥)" +msgstr "Update Mode (Tak ako je táto možnosÅ¥ nastavená)" #: editor/animation_track_editor.cpp msgid "Interpolation Mode" @@ -517,7 +517,7 @@ msgstr "Zoskupte track-y pomocou node-u alebo ich zobrazte ako plain list." #: editor/animation_track_editor.cpp msgid "Snap:" -msgstr "Snap:" +msgstr "PrichytiÅ¥:" #: editor/animation_track_editor.cpp msgid "Animation step value." @@ -756,9 +756,8 @@ 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á." +msgstr "Meno Metódy musà byÅ¥ Å¡pecifikované." #: editor/connections_dialog.cpp msgid "" @@ -1115,6 +1114,9 @@ msgstr "Zakladatelia Projektu" msgid "Lead Developer" msgstr "Vedúci Vývojár" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Manažér Projektu " @@ -1136,6 +1138,14 @@ msgid "Gold Sponsors" msgstr "Zlatý Sponzori" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "Strieborný Sponzori" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "Bronzový Sponzori" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Malý Sponzori" @@ -1886,7 +1896,7 @@ msgstr "PrieÄinky a Súbory:" #: editor/plugins/style_box_editor_plugin.cpp #: editor/plugins/theme_editor_plugin.cpp msgid "Preview:" -msgstr "Ako to bude vyzeraÅ¥:" +msgstr "PredzobraziÅ¥:" #: editor/editor_file_dialog.cpp scene/gui/file_dialog.cpp msgid "File:" @@ -2782,9 +2792,9 @@ msgid "" msgstr "" "KeÄ bude povolená táto možnosÅ¥, export alebo deploy vyprodukujú menej \n" "súboru executable.\n" -"Filesystém bude z projektu poskytovaný editorom v sieti. Na Androide, pre " -"deploy budete potrebovaÅ¥ USB kábel \n" -"rýchlejÅ¡Ã výkon. Táto možnosÅ¥ zrýchľuje proces testovania." +"Filesystém bude z projektu poskytovaný editorom v sieti.\n" +"Na Androide, predeploy budete potrebovaÅ¥ USB kábel pre rýchlejÅ¡Ã výkon. Táto " +"možnosÅ¥ zrýchľuje proces testovania." #: editor/editor_node.cpp msgid "Visible Collision Shapes" @@ -3053,19 +3063,19 @@ msgstr "ImportovaÅ¥ Å ablóny Zo ZIP File-u" #: editor/editor_node.cpp msgid "Template Package" -msgstr "BalÃÄek Å ablón" +msgstr "BalÃk Å ablón" #: editor/editor_node.cpp msgid "Export Library" -msgstr "ExportovaÅ¥ Library" +msgstr "ExportovaÅ¥ Knižnicu" #: editor/editor_node.cpp msgid "Merge With Existing" -msgstr "SpojiÅ¥ Z Existujúcim" +msgstr "ZlúÄiÅ¥ s existujúcim" #: editor/editor_node.cpp msgid "Open & Run a Script" -msgstr "OtvoriÅ¥ & SpustiÅ¥ Script" +msgstr "OtvoriÅ¥ a vykonaÅ¥ skript" #: editor/editor_node.cpp msgid "New Inherited" @@ -3105,7 +3115,7 @@ msgstr "OtvoriÅ¥ predchádzajúci Editor" #: editor/editor_node.h msgid "Warning!" -msgstr "Varovanie!" +msgstr "Upozornenie!" #: editor/editor_path.cpp msgid "No sub-resources found." @@ -3113,7 +3123,7 @@ msgstr "NenaÅ¡li sa žiadne \"sub-resources\"." #: editor/editor_plugin.cpp msgid "Creating Mesh Previews" -msgstr "Vytváranie Zobrazenia \"Mesh-u\"" +msgstr "Vytváranie Predzobrazenia Mesh-u" #: editor/editor_plugin.cpp msgid "Thumbnail..." @@ -4223,7 +4233,7 @@ msgstr "Vyberte a premiestnite body, vytvorte body z RMB." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp msgid "Enable snap and show grid." -msgstr "PovoliÅ¥ snap a show grid." +msgstr "PovoliÅ¥ prichytenie a zobraziÅ¥ mriežku." #: editor/plugins/animation_blend_space_1d_editor.cpp #: editor/plugins/animation_blend_space_2d_editor.cpp @@ -4253,118 +4263,117 @@ msgstr "PridaÅ¥ TrojuholnÃk" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Change BlendSpace2D Limits" -msgstr "" +msgstr "ZmeniÅ¥ Limity BlendSpace2D" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Change BlendSpace2D Labels" -msgstr "" +msgstr "ZmeniÅ¥ Label BlendSpace2D" #: editor/plugins/animation_blend_space_2d_editor.cpp -#, fuzzy msgid "Remove BlendSpace2D Point" -msgstr "VÅ¡etky vybrané" +msgstr "VymazaÅ¥ BlendSpace2D Bod" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Remove BlendSpace2D Triangle" -msgstr "" +msgstr "VymazaÅ¥ BlendSpace2D TrojuholnÃk" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "BlendSpace2D does not belong to an AnimationTree node." -msgstr "" +msgstr "BlendSpace2D nepatrà ku AnimationTree node." #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "No triangles exist, so no blending can take place." msgstr "" +"Neexistujú žiadne trojuholnÃky, takže si nemôže zabraÅ¥ miesto žiadny " +"blending." #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Toggle Auto Triangles" -msgstr "" +msgstr "Prepnúť Automatické TrojuholnÃky" #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Create triangles by connecting points." -msgstr "" +msgstr "VytvoriÅ¥ trojuholnÃky spájanÃm bodov." #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Erase points and triangles." -msgstr "" +msgstr "VymazaÅ¥ body a trojuholnÃky." #: editor/plugins/animation_blend_space_2d_editor.cpp msgid "Generate blend triangles automatically (instead of manually)" -msgstr "" +msgstr "VygenerovaÅ¥ blend trojuholnÃky Automaticky (nie manuálne)" #: editor/plugins/animation_blend_space_2d_editor.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend:" -msgstr "" +msgstr "Blend:" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Parameter Changed" -msgstr "" +msgstr "Parameter sa Zmenil" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp -#, fuzzy msgid "Edit Filters" -msgstr "Súbor:" +msgstr "UpraviÅ¥ Filtre" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Output node can't be added to the blend tree." -msgstr "" +msgstr "Nemôžete pridaÅ¥ output node do blend tree." #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Add Node to BlendTree" -msgstr "" +msgstr "PridaÅ¥ Node do BlendTree" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Node Moved" -msgstr "" +msgstr "Node sa pohol" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Unable to connect, port may be in use or connection may be invalid." -msgstr "" +msgstr "Nepodarilo sa pripojiÅ¥, port sa možno použÃva alebo je neplatný." #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Nodes Connected" -msgstr "" +msgstr "Node-y Spojené" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Nodes Disconnected" -msgstr "" +msgstr "Node-y Odpojené" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Set Animation" -msgstr "Popis:" +msgstr "NastaviÅ¥ Animáciu" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp -#, fuzzy msgid "Delete Node" -msgstr "VÅ¡etky vybrané" +msgstr "ZmazaÅ¥ Node" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/scene_tree_dock.cpp msgid "Delete Node(s)" -msgstr "" +msgstr "ZmazaÅ¥ Node(y)" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Toggle Filter On/Off" -msgstr "" +msgstr "Zapnúť/Vypnúť Filter" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Change Filter" -msgstr "" +msgstr "ZmeniÅ¥ Filter" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "No animation player set, so unable to retrieve track names." msgstr "" +"Nieje nastavený AnimaÄný PrehrávaÄ, takže sa nepodarilo zÃskaÅ¥ mená trackov." #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Player path set is invalid, so unable to retrieve track names." -msgstr "" +msgstr "Cesta prehrávaÄa je neplatná, takže sa nepodarilo zÃskaÅ¥ mená trackov." #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/root_motion_editor_plugin.cpp @@ -4372,312 +4381,302 @@ msgid "" "Animation player has no valid root node path, so unable to retrieve track " "names." msgstr "" +"AnimaÄný PrehrávaÄ nemá žiadny platnú root node cestu, takže sa nepodarilo " +"zistiÅ¥ mená trackov." #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Anim Clips" -msgstr "Klipy Animácie:" +msgstr "Klipy Animácie" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Audio Clips" -msgstr "Zvukové Klipy:" +msgstr "Zvukové Klipy" #: editor/plugins/animation_blend_tree_editor_plugin.cpp -#, fuzzy msgid "Functions" -msgstr "Funkcie:" +msgstr "Funkcie" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/animation_state_machine_editor.cpp msgid "Node Renamed" -msgstr "" +msgstr "Node Premenovaný" #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp msgid "Add Node..." -msgstr "" +msgstr "PridaÅ¥ Node..." #: editor/plugins/animation_blend_tree_editor_plugin.cpp #: editor/plugins/root_motion_editor_plugin.cpp -#, fuzzy msgid "Edit Filtered Tracks:" -msgstr "Súbor:" +msgstr "UpraviÅ¥ Filtrované Tracky:" #: editor/plugins/animation_blend_tree_editor_plugin.cpp msgid "Enable Filtering" -msgstr "" +msgstr "PovoliÅ¥ Filtrovanie" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Toggle Autoplay" -msgstr "" +msgstr "Prepnúť Autoplay" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Animation Name:" -msgstr "" +msgstr "Nové Meno Animácie:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "New Anim" -msgstr "" +msgstr "Nová Animácia" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Change Animation Name:" -msgstr "" +msgstr "ZmeniÅ¥ Meno Animácie:" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Delete Animation?" -msgstr "" +msgstr "Naozaj chcete vymazaÅ¥ Animáciu?" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Remove Animation" -msgstr "" +msgstr "VymazaÅ¥ Animáciu" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Invalid animation name!" -msgstr "" +msgstr "Meno animácie je Vadné!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation name already exists!" -msgstr "" +msgstr "Toto meno Animácie už existuje!" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp msgid "Rename Animation" -msgstr "" +msgstr "PremenovaÅ¥ Animáciu" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Next Changed" -msgstr "" +msgstr "Blend sa ÄŽalej Zmenil" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Change Blend Time" -msgstr "" +msgstr "ZmeniÅ¥ Blend Time" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Load Animation" -msgstr "" +msgstr "NaÄÃtaÅ¥ Animáciu" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Duplicate Animation" -msgstr "" +msgstr "DuplikovaÅ¥ Animáciu" #: editor/plugins/animation_player_editor_plugin.cpp msgid "No animation to copy!" -msgstr "" +msgstr "Žiadne animácie na skopÃrovanie!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "No animation resource on clipboard!" -msgstr "" +msgstr "Žiadny zroj animácie v clipboard!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Pasted Animation" -msgstr "" +msgstr "Prilepená Animácia" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Paste Animation" -msgstr "" +msgstr "PrilepiÅ¥ Animáciu" #: editor/plugins/animation_player_editor_plugin.cpp msgid "No animation to edit!" -msgstr "" +msgstr "Žiadna animácia na úpravu!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from current pos. (A)" -msgstr "" +msgstr "SpusÅ¥iÅ¥ vybranú animáciu odzadu z aktuálnej pozÃcie. (A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation backwards from end. (Shift+A)" -msgstr "" +msgstr "SpustiÅ¥ vybranú animáciu odzadu z konca. (Shift+A)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Stop animation playback. (S)" -msgstr "" +msgstr "ZastaviÅ¥ playback animácie. (S)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from start. (Shift+D)" -msgstr "" +msgstr "SpustiÅ¥ vybranú animáciu od zaÄiatku. (Shift+D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Play selected animation from current pos. (D)" -msgstr "" +msgstr "SpustiÅ¥ vybranú animáciu z aktuálnej pozÃcie. (D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation position (in seconds)." -msgstr "" +msgstr "PozÃcia Animácie (v sekundách)." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Scale animation playback globally for the node." -msgstr "" +msgstr "ZväÄÅ¡iÅ¥ playback animácie globálne pre node." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Tools" -msgstr "" +msgstr "AnimaÄné Náradie" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation" msgstr "Animácie" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Edit Transitions..." -msgstr "Prechody" +msgstr "UpraviÅ¥ Prechody..." #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Open in Inspector" -msgstr "Otvorit prieÄinok" +msgstr "Otvorit v InÅ¡pektor-ovi" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Display list of animations in player." -msgstr "" +msgstr "ZobraziÅ¥ list animácii v prehrávaÄi." #: editor/plugins/animation_player_editor_plugin.cpp msgid "Autoplay on Load" -msgstr "" +msgstr "Autoplay pri NaÄÃtanÃ" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Enable Onion Skinning" -msgstr "" +msgstr "PovoliÅ¥ Onion Skinning" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Onion Skinning Options" -msgstr "" +msgstr "Onion Skinning Možnosti" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Directions" -msgstr "Popis:" +msgstr "Smery" #: editor/plugins/animation_player_editor_plugin.cpp -#, fuzzy msgid "Past" -msgstr "VložiÅ¥" +msgstr "MinulosÅ¥" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Future" -msgstr "" +msgstr "BudúcnosÅ¥" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Depth" -msgstr "" +msgstr "Hĺbka" #: editor/plugins/animation_player_editor_plugin.cpp msgid "1 step" -msgstr "" +msgstr "1 krok" #: editor/plugins/animation_player_editor_plugin.cpp msgid "2 steps" -msgstr "" +msgstr "2 kroky" #: editor/plugins/animation_player_editor_plugin.cpp msgid "3 steps" -msgstr "" +msgstr "3 kroky" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Differences Only" -msgstr "" +msgstr "Iba OdliÅ¡nosti" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Force White Modulate" -msgstr "" +msgstr "Force White Modulate" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Include Gizmos (3D)" -msgstr "" +msgstr "Zahŕňa Gizmos (3D)" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Pin AnimationPlayer" -msgstr "" +msgstr "Pripnúť PrehrávaÄ Animácie" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Create New Animation" -msgstr "" +msgstr "VytvoriÅ¥ Novú Animáciu" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Animation Name:" -msgstr "" +msgstr "Meno Animácie:" #: editor/plugins/animation_player_editor_plugin.cpp #: editor/plugins/resource_preloader_editor_plugin.cpp #: editor/plugins/script_editor_plugin.cpp #: editor/plugins/sprite_frames_editor_plugin.cpp editor/property_editor.cpp msgid "Error!" -msgstr "" +msgstr "Chyba!" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Blend Times:" -msgstr "" +msgstr "Blend Times:" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Next (Auto Queue):" -msgstr "" +msgstr "ÄŽalej (Automatický Rad):" #: editor/plugins/animation_player_editor_plugin.cpp msgid "Cross-Animation Blend Times" -msgstr "" +msgstr "Cross-Animation Blend Times" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Move Node" -msgstr "VložiÅ¥" +msgstr "PremiestniÅ¥ Node" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition exists!" -msgstr "Prechody" +msgstr "Prechod existuje!" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Add Transition" -msgstr "Prechody" +msgstr "PridaÅ¥ Prechod" #: editor/plugins/animation_state_machine_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Add Node" -msgstr "" +msgstr "PridaÅ¥ Node" #: editor/plugins/animation_state_machine_editor.cpp msgid "End" -msgstr "" +msgstr "Koniec" #: editor/plugins/animation_state_machine_editor.cpp msgid "Immediate" -msgstr "" +msgstr "Okamžite" #: editor/plugins/animation_state_machine_editor.cpp msgid "Sync" -msgstr "" +msgstr "Synchronizácia" #: editor/plugins/animation_state_machine_editor.cpp msgid "At End" -msgstr "" +msgstr "Na Konci" #: editor/plugins/animation_state_machine_editor.cpp msgid "Travel" -msgstr "" +msgstr "CestovaÅ¥" #: editor/plugins/animation_state_machine_editor.cpp msgid "Start and end nodes are needed for a sub-transition." -msgstr "" +msgstr "Pre sub-prechod je potrebné zaÄaÅ¥ a skonÄiÅ¥ node-y." #: editor/plugins/animation_state_machine_editor.cpp msgid "No playback resource set at path: %s." -msgstr "" +msgstr "Nieje nastavený žiadny zdrojový playback ako cesta: %s." #: editor/plugins/animation_state_machine_editor.cpp msgid "Node Removed" -msgstr "" +msgstr "Node Zmazaný" #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition Removed" -msgstr "Prechody" +msgstr "Prechod Vymazaný" #: editor/plugins/animation_state_machine_editor.cpp msgid "Set Start Node (Autoplay)" -msgstr "" +msgstr "NastaviÅ¥ ZaÄiatoÄný Node (Autoplay)" #: editor/plugins/animation_state_machine_editor.cpp msgid "" @@ -4685,363 +4684,356 @@ msgid "" "RMB to add new nodes.\n" "Shift+LMB to create connections." msgstr "" +"VybraÅ¥ a premiestniÅ¥ node-y.\n" +"PravÃm tlaÄÃtkom myÅ¡i pridáte node-y.\n" +"Shift+Lavé tlaÄÃko myÅ¡i vytvoriÅ¥ pripojenie." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Create new nodes." -msgstr "VytvoriÅ¥ adresár" +msgstr "VytvoriÅ¥ Nové Node-y." #: editor/plugins/animation_state_machine_editor.cpp msgid "Connect nodes." -msgstr "" +msgstr "SpojiÅ¥ Node-y." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Remove selected node or transition." -msgstr "OdstrániÅ¥ výber" +msgstr "VymazaÅ¥ oznaÄený node alebo prechod." #: editor/plugins/animation_state_machine_editor.cpp msgid "Toggle autoplay this animation on start, restart or seek to zero." msgstr "" +"Prepnúť autoplay na tejto animácii pri Å¡tarte, reÅ¡tarte alebo seek to zero." #: editor/plugins/animation_state_machine_editor.cpp msgid "Set the end animation. This is useful for sub-transitions." -msgstr "" +msgstr "NastaviÅ¥ koniec animácie. Toto je užitoÄné pre sub-prechody." #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Transition: " -msgstr "Prechody" +msgstr "Prechody: " #: editor/plugins/animation_state_machine_editor.cpp -#, fuzzy msgid "Play Mode:" -msgstr "Cesta k Node:" +msgstr "PrehraÅ¥ Mód:" #: editor/plugins/animation_tree_editor_plugin.cpp #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "AnimationTree" -msgstr "" +msgstr "AnimaÄnýStrom" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "New name:" -msgstr "" +msgstr "Nové Meno:" #: editor/plugins/animation_tree_player_editor_plugin.cpp #: editor/plugins/multimesh_editor_plugin.cpp msgid "Scale:" -msgstr "" +msgstr "VeľkosÅ¥:" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Fade In (s):" -msgstr "" +msgstr "Miznutie do (s):" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Fade Out (s):" -msgstr "" +msgstr "Miznutie Von (s):" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend" -msgstr "" +msgstr "Blend" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Mix" -msgstr "" +msgstr "Mix" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Auto Restart:" -msgstr "" +msgstr "Auto ReÅ¡tart:" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Restart (s):" -msgstr "" +msgstr "ReÅ¡tart (s):" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Random Restart (s):" -msgstr "" +msgstr "Náhodný ReÅ¡tart (s):" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Start!" -msgstr "" +msgstr "Å tart!" #: editor/plugins/animation_tree_player_editor_plugin.cpp #: editor/plugins/multimesh_editor_plugin.cpp msgid "Amount:" -msgstr "" +msgstr "Množstvo:" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend 0:" -msgstr "" +msgstr "Blend 0:" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend 1:" -msgstr "" +msgstr "Blend 1:" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "X-Fade Time (s):" -msgstr "" +msgstr "ÄŒas X-Miznutia (s):" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Current:" -msgstr "" +msgstr "Aktuálny:" #: editor/plugins/animation_tree_player_editor_plugin.cpp #: editor/plugins/visual_shader_editor_plugin.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Add Input" -msgstr "" +msgstr "PridaÅ¥ Vstup" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Clear Auto-Advance" -msgstr "" +msgstr "ÄŒistý Auto-Advance" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Set Auto-Advance" -msgstr "" +msgstr "NastaviÅ¥ Auto-Advance" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Delete Input" -msgstr "" +msgstr "ZmazaÅ¥ Vstup" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Animation tree is valid." -msgstr "" +msgstr "AnimaÄný Strom je platný." #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Animation tree is invalid." -msgstr "" +msgstr "AnimaÄný Strom je neplatný." #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Animation Node" -msgstr "" +msgstr "AnimaÄný Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "OneShot Node" -msgstr "" +msgstr "OneShot Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Mix Node" -msgstr "" +msgstr "Mix Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend2 Node" -msgstr "" +msgstr "Blend2 Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend3 Node" -msgstr "" +msgstr "Blend3 Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Blend4 Node" -msgstr "" +msgstr "Blend4 Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "TimeScale Node" -msgstr "" +msgstr "TimeScale Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "TimeSeek Node" -msgstr "" +msgstr "TimeSeek Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Transition Node" -msgstr "" +msgstr "Prechodový Node" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Import Animations..." -msgstr "" +msgstr "ImportovaÅ¥ Animácie..." #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Edit Node Filters" -msgstr "" +msgstr "NastaviÅ¥ Node Filtre" #: editor/plugins/animation_tree_player_editor_plugin.cpp msgid "Filters..." -msgstr "" +msgstr "Filtre..." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Contents:" -msgstr "KonÅ¡tanty:" +msgstr "Obsah:" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "View Files" -msgstr "Súbor:" +msgstr "ZobraziÅ¥ Súbory" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Connection error, please try again." -msgstr "" +msgstr "Chyba pripojenia, prosÃm skúste znovu." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't connect to host:" -msgstr "" +msgstr "Nepodarilo sa pripojiÅ¥ k host:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "No response from host:" -msgstr "" +msgstr "Žiadna odozva od host-a:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Can't resolve hostname:" -msgstr "" +msgstr "Nepodarilo sa rozlúštiÅ¥ hostove meno:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed, return code:" -msgstr "" +msgstr "ŽiadosÅ¥ zlyhala, spätný kód:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed." -msgstr "" +msgstr "ŽiadosÅ¥ zlyhala." #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Cannot save response to:" -msgstr "Nemôžete odstrániÅ¥:" +msgstr "Nepodarilo sa uložiÅ¥ odpoveÄ do:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Write error." -msgstr "" +msgstr "Chyba pÃsania." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed, too many redirects" -msgstr "" +msgstr "ŽiadosÅ¥ zlyhala, prÃliÅ¡ veľa presmerovanÃ" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Redirect loop." -msgstr "" +msgstr "Presmerovacà loop." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Request failed, timeout" -msgstr "" +msgstr "ŽiadosÅ¥ zlyhala, Äas vyprÅ¡al" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Timeout." -msgstr "ÄŒas:" +msgstr "ÄŒas vyprÅ¡al." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Bad download hash, assuming file has been tampered with." -msgstr "" +msgstr "Zlý download hash, za predpokladu že bolo narábané so súborom." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Expected:" -msgstr "" +msgstr "OÄakávané:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Got:" -msgstr "" +msgstr "Má:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Failed sha256 hash check" -msgstr "" +msgstr "Zlyhalo sha256 hash check" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Asset Download Error:" -msgstr "" +msgstr "Zlyhalo SÅ¥ahovanie Prostriedku:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Downloading (%s / %s)..." -msgstr "" +msgstr "SÅ¥ahovanie (%s / %s)..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Downloading..." -msgstr "" +msgstr "SÅ¥ahovanie..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Resolving..." -msgstr "" +msgstr "RieÅ¡i sa..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Error making request" -msgstr "" +msgstr "Pri vytváranà žiadosÅ¥i nastala chyba" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Idle" -msgstr "" +msgstr "Idle" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "Install..." -msgstr "InÅ¡talovaÅ¥" +msgstr "InÅ¡talovaÅ¥..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Retry" -msgstr "" +msgstr "SkúsiÅ¥ znova" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download Error" -msgstr "" +msgstr "Chyba SÅ¥ahovania" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Download for this asset is already in progress!" -msgstr "" +msgstr "SÅ¥ahovanie tohoto prostriedku už prebieha!" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Recently Updated" -msgstr "" +msgstr "Nedávno VylepÅ¡ené" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Least Recently Updated" -msgstr "" +msgstr "Za Poslednú Dobu Najmenej Aktualizované" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Name (A-Z)" -msgstr "" +msgstr "Meno (A-Z)" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Name (Z-A)" -msgstr "" +msgstr "Meno (Z-A)" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "License (A-Z)" -msgstr "Licencia" +msgstr "Licencia (A-Z)" #: editor/plugins/asset_library_editor_plugin.cpp -#, fuzzy msgid "License (Z-A)" -msgstr "Licencia" +msgstr "Licencia (Z-A)" #: editor/plugins/asset_library_editor_plugin.cpp msgid "First" -msgstr "" +msgstr "Prvý" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Previous" -msgstr "" +msgstr "Minulý" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Next" -msgstr "" +msgstr "ÄŽalÅ¡Ã" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Last" -msgstr "" +msgstr "Posledný" #: editor/plugins/asset_library_editor_plugin.cpp msgid "All" -msgstr "" +msgstr "VÅ¡etky" #: editor/plugins/asset_library_editor_plugin.cpp msgid "No results for \"%s\"." -msgstr "" +msgstr "Žiadne výsledky pre \"%s\"." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Import..." -msgstr "" +msgstr "Import..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Plugins..." -msgstr "" +msgstr "Pluginy..." #: editor/plugins/asset_library_editor_plugin.cpp editor/project_manager.cpp msgid "Sort:" -msgstr "" +msgstr "ZoradiÅ¥:" #: editor/plugins/asset_library_editor_plugin.cpp #: editor/project_settings_editor.cpp msgid "Category:" -msgstr "" +msgstr "Kategória:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Site:" @@ -5049,23 +5041,23 @@ msgstr "Stránka:" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Support" -msgstr "" +msgstr "Podpora" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Official" -msgstr "" +msgstr "Oficiálne" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Testing" -msgstr "" +msgstr "Testovanie" #: editor/plugins/asset_library_editor_plugin.cpp msgid "Loading..." -msgstr "" +msgstr "NaÄitávanie..." #: editor/plugins/asset_library_editor_plugin.cpp msgid "Assets ZIP File" -msgstr "" +msgstr "Prostriedky Súboru ZIP" #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" @@ -5073,216 +5065,215 @@ msgid "" "Save your scene (for images to be saved in the same dir), or pick a save " "path from the BakedLightmap properties." msgstr "" +"Nedá sa urÄiÅ¥ cesta pre uloženie lightmap obrázkov.\n" +"Uložte svoju scénu (Aby sa obrázky na to isté miesto), alebo vyberte cestu " +"na uloženie so BakedLightmap vlastnostÃ." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "" "No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake " "Light' flag is on." msgstr "" +"Žiadne mesh-e na bake. Uistite sa že obsahujú UV2 channel a je na ňom 'Bake " +"Light' vlajka." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Failed creating lightmap images, make sure path is writable." msgstr "" +"Nepodarilo sa vytvoriÅ¥ lightmap obrázok, uistite sa že Äi je cesta " +"zapisovateľná." #: editor/plugins/baked_lightmap_editor_plugin.cpp msgid "Bake Lightmaps" -msgstr "" +msgstr "Bake Lightmaps" #: editor/plugins/camera_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/rename_dialog.cpp msgid "Preview" -msgstr "" +msgstr "PredzobraziÅ¥" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Configure Snap" -msgstr "" +msgstr "KonfigurovaÅ¥ Prichytenie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Grid Offset:" -msgstr "" +msgstr "Odchýlka Mriežky:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Grid Step:" -msgstr "" +msgstr "Krok Mriežky:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Primary Line Every:" -msgstr "" +msgstr "VÅ¡etky Primary Line:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "steps" -msgstr "" +msgstr "kroky" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Offset:" -msgstr "" +msgstr "Odchýlka Rotácie:" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation Step:" -msgstr "" +msgstr "Krok Rotácie:" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Scale Step:" -msgstr "ZmeniÅ¥ veľkosÅ¥ výberu" +msgstr "Krok Veľkosti:" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move Vertical Guide" -msgstr "Popis:" +msgstr "Presunúť Vertikálny Návod" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Create Vertical Guide" -msgstr "Popis:" +msgstr "VytvoriÅ¥ Vertikálny Návod" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Remove Vertical Guide" -msgstr "VÅ¡etky vybrané" +msgstr "VymazaÅ¥ Vertikálny Návod" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move Horizontal Guide" -msgstr "VÅ¡etky vybrané" +msgstr "Presunúť Horizontálny Návod" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Create Horizontal Guide" -msgstr "Popis:" +msgstr "VytvoriÅ¥ Horizontálny Návod" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Remove Horizontal Guide" -msgstr "VÅ¡etky vybrané" +msgstr "VymazaÅ¥ Horizontálny Návod" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Create Horizontal and Vertical Guides" -msgstr "Popis:" +msgstr "VytvoriÅ¥ Horizontálne a Vertikálne Návody" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Move pivot" -msgstr "VÅ¡etky vybrané" +msgstr "Presunúť pivot" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotate CanvasItem" -msgstr "" +msgstr "OtoÄiÅ¥ CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move anchor" -msgstr "" +msgstr "Presunúť kovadlinu" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Resize CanvasItem" -msgstr "" +msgstr "ZmeniÅ¥ VeľkosÅ¥ CanvasItem-u" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale CanvasItem" -msgstr "" +msgstr "VeľkosÅ¥ CanvasItem-u" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Move CanvasItem" -msgstr "" +msgstr "Presunúť CanvasItem" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" "Children of containers have their anchors and margins values overridden by " "their parent." msgstr "" +"DieÅ¥a kontajnerov majú svoje kovadliny a okraje prepÃsané svojimi rodiÄmi." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Presets for the anchors and margins values of a Control node." -msgstr "" +msgstr "PrenastaviÅ¥ pre kovadliny a okraje hodnoty Control node-u." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" "When active, moving Control nodes changes their anchors instead of their " "margins." msgstr "" +"Pri aktivovanÃ, pohybovanim Control node-ov zmenÃte ich kovadliny namiesto " +"ich okrajov." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Top Left" -msgstr "" +msgstr "Vľavo Hore" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Top Right" -msgstr "" +msgstr "Vpravo Hore" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Bottom Right" -msgstr "" +msgstr "Vpravo Dole" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Bottom Left" -msgstr "" +msgstr "Vľavo Dole" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Left" -msgstr "" +msgstr "Od Stredu Vľavo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Top" -msgstr "" +msgstr "Od Stredu Hore" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Right" -msgstr "" +msgstr "Od Stredu Vpravo" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Bottom" -msgstr "" +msgstr "Od Stredu Dole" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center" -msgstr "" +msgstr "V Strede" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Left Wide" -msgstr "Lineárne" +msgstr "Ľavá Å Ãrka" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Top Wide" -msgstr "" +msgstr "Horná Å Ãrka" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Right Wide" -msgstr "Lineárne" +msgstr "Pravá Å Ãrka" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Bottom Wide" -msgstr "" +msgstr "Dolná Å Ãrka" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "VCenter Wide" -msgstr "" +msgstr "VerStredná Å Ãrka" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "HCenter Wide" -msgstr "" +msgstr "HorStredná Å Ãrka" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Full Rect" -msgstr "" +msgstr "Plný Obdĺžnik" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Keep Ratio" -msgstr "" +msgstr "UdržovaÅ¥ Pomer" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Anchors only" -msgstr "" +msgstr "Iba Kovadliny" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors and Margins" -msgstr "" +msgstr "ZmeniÅ¥ Kovadliny a Okraje" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Change Anchors" -msgstr "" +msgstr "ZmeniÅ¥ Kovadliny" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5290,6 +5281,8 @@ msgid "" "Game Camera Override\n" "Overrides game camera with editor viewport camera." msgstr "" +"PrepÃsanie Hernej Kamery\n" +"PrepÃsaÅ¥ hernú kameru s viewport kamerou editora." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5297,104 +5290,103 @@ msgid "" "Game Camera Override\n" "No game instance running." msgstr "" +"PrepÃsanie Hernej Kamery\n" +"Nieje spustená žiadna herná inÅ¡tancia." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Lock Selected" -msgstr "VÅ¡etky vybrané" +msgstr "Zamknúť OznaÄené" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Unlock Selected" -msgstr "VÅ¡etky vybrané" +msgstr "Odomknúť OznaÄené" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Group Selected" -msgstr "OdstrániÅ¥ výber" +msgstr "PridaÅ¥ OznaÄené do Skupiny" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp -#, fuzzy msgid "Ungroup Selected" -msgstr "OdstrániÅ¥ výber" +msgstr "OdskupiÅ¥ OznaÄené" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Paste Pose" -msgstr "" +msgstr "PrilepiÅ¥ Pózu" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Clear Guides" -msgstr "VÅ¡etky vybrané" +msgstr "ZmazaÅ¥ Návody" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Create Custom Bone(s) from Node(s)" -msgstr "" +msgstr "VytvoriÅ¥ Vlastnú KosÅ¥(i) z Node-u(ou)" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Clear Bones" -msgstr "VÅ¡etky vybrané" +msgstr "ZmazaÅ¥ Kosti" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make IK Chain" -msgstr "" +msgstr "VytvoriÅ¥ IK ReÅ¥az" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear IK Chain" -msgstr "" +msgstr "ZmazaÅ¥ IK ReÅ¥az" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" "Warning: Children of a container get their position and size determined only " "by their parent." msgstr "" +"Upozornenie: DieÅ¥a kontajnera zÃska ich pozÃciu a veľkosÅ¥ iba podľa svojho " +"rodiÄa." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/texture_region_editor_plugin.cpp #: editor/plugins/tile_set_editor_plugin.cpp scene/gui/graph_edit.cpp msgid "Zoom Reset" -msgstr "" +msgstr "ResetovaÅ¥ PriblÞenie" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Select Mode" -msgstr "" +msgstr "VybraÅ¥ Režim" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Drag: Rotate" -msgstr "" +msgstr "PotiahnutÃm: OtáÄenie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+Drag: Move" -msgstr "" +msgstr "Alt+Potiahnutie: Pohyb" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving)." msgstr "" +"StaÄte 'v' pre Zmenu Pivot-a, 'Shift+v' pre hýbanie s Pivot-om (keÄ sa hýbe)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Alt+RMB: Depth list selection" -msgstr "" +msgstr "Alt+RMB: Výber hĺbkového zoznamu" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Move Mode" -msgstr "" +msgstr "Move Mode" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Mode" -msgstr "" +msgstr "RotaÄný Režim" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Mode" -msgstr "" +msgstr "Zmena Veľkosti" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp @@ -5402,187 +5394,186 @@ msgid "" "Show a list of all objects at the position clicked\n" "(same as Alt+RMB in select mode)." msgstr "" +"ZobraziÅ¥ list vÅ¡etkých objektov na kliknutej pozÃcii\n" +"(rovnako ako Alt+RMB v výberovom režime)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Click to change object's rotation pivot." -msgstr "" +msgstr "Kliknite pre zmenu rotaÄného pivota objektu." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Pan Mode" -msgstr "" +msgstr "Pohyb Mód" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Ruler Mode" -msgstr "Režim Interpolácie" +msgstr "PravÃtko" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Toggle smart snapping." -msgstr "" +msgstr "Prepnúť smart prichytenie." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Smart Snap" -msgstr "" +msgstr "PoužiÅ¥ Smart Prichytenie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Toggle grid snapping." -msgstr "" +msgstr "Prepnúť Prichytenie Mriežky." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Grid Snap" -msgstr "" +msgstr "PoužiÅ¥ PrÃchyt Mriežky" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snapping Options" -msgstr "" +msgstr "Možnosti Prichytávania" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Rotation Snap" -msgstr "" +msgstr "PoužiÅ¥ Prichytávanie Rotácie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Scale Snap" -msgstr "" +msgstr "PoužiÅ¥ Prichytávanie Veľkosti" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap Relative" -msgstr "" +msgstr "PrichytiÅ¥ RelatÃvne" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Use Pixel Snap" -msgstr "" +msgstr "PoužiÅ¥ Pixelové Prichytenie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Smart Snapping" -msgstr "" +msgstr "Smart Prichytávanie" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Configure Snap..." -msgstr "" +msgstr "KonfigurovaÅ¥ Prichytávanie..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Parent" -msgstr "" +msgstr "PrichytiÅ¥ na RodiÄa" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Node Anchor" -msgstr "" +msgstr "PrichytiÅ¥ na Kovadlinu Node-u" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Node Sides" -msgstr "" +msgstr "PrichitiÅ¥ na strany Node-u" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Node Center" -msgstr "" +msgstr "PrichytiÅ¥ na Stred Node-u" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Snap to Other Nodes" -msgstr "VložiÅ¥" +msgstr "PrichytiÅ¥ na Ostatné Node-y" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Snap to Guides" -msgstr "" +msgstr "PrichytiÅ¥ na Návody" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Lock the selected object in place (can't be moved)." -msgstr "" +msgstr "Zamknúť oznaÄený objekt na mieste (už sa s nÃm nebude daÅ¥ hýbaÅ¥)." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Unlock the selected object (can be moved)." -msgstr "" +msgstr "Odomknúť oznaÄený objekt (dá sa s nÃm hýbaÅ¥)." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Makes sure the object's children are not selectable." -msgstr "" +msgstr "Uistite sa že sa nedá oznaÄiÅ¥ dieÅ¥a objektu." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "Restores the object's children's ability to be selected." -msgstr "" +msgstr "Aby ste oznaÄili dieÅ¥a objektu tak mu musÃte obnoviÅ¥ schopnosÅ¥." #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Skeleton Options" -msgstr "VÅ¡etky vybrané" +msgstr "Nastavenia Kostry" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Bones" -msgstr "" +msgstr "ZobraziÅ¥ Kosti" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Make Custom Bone(s) from Node(s)" -msgstr "" +msgstr "VytvoriÅ¥ Vlastnú KosÅ¥(i) z Node-u(ou)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Custom Bones" -msgstr "" +msgstr "ZmazaÅ¥ Vlastné Kosti" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp msgid "View" -msgstr "" +msgstr "Zobrazenie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Always Show Grid" -msgstr "" +msgstr "Vždy ZobraziÅ¥ Mriežku" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Helpers" -msgstr "" +msgstr "ZobraziÅ¥ PomocnÃkov" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Rulers" -msgstr "" +msgstr "ZobraziÅ¥ PravÃtka" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Guides" -msgstr "" +msgstr "ZobraziÅ¥ Návody" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Origin" -msgstr "" +msgstr "ZobraziÅ¥ Pôvod" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Viewport" -msgstr "" +msgstr "ZobraziÅ¥ Výrez" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Show Group And Lock Icons" -msgstr "" +msgstr "ZobraziÅ¥ Skupinu a Zamknúť Ikony" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Center Selection" -msgstr "" +msgstr "Výber Stredu" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Frame Selection" -msgstr "" +msgstr "Výber Frame-u" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Preview Canvas Scale" -msgstr "" +msgstr "PredzobraziÅ¥ VeľkosÅ¥ Plátna" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Translation mask for inserting keys." -msgstr "" +msgstr "Prekladová maska na vkladanie kľúÄov." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Rotation mask for inserting keys." -msgstr "" +msgstr "RotaÄná maska na vkladanie kľúÄov." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Scale mask for inserting keys." -msgstr "" +msgstr "Veľkostná maska na vkladanie kľúÄov." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert keys (based on mask)." -msgstr "" +msgstr "Vkladanie kľúÄov (založené na maske)." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -5591,67 +5582,69 @@ msgid "" "Keys are only added to existing tracks, no new tracks will be created.\n" "Keys must be inserted manually for the first time." msgstr "" +"Automaticky vložiÅ¥ kľúÄe keÄ sú objekty preložené, rotované alebo zväÄÅ¡ené " +"(založené na maske).\n" +"KľúÄe sú pridané iba do existujúcich track-ov, nebudú vytvorené žiadne nové " +"tracky.\n" +"Prvý krát musia byÅ¥ kľúÄe vložené manuálne." #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Auto Insert Key" -msgstr "Animácia VložiÅ¥ KľúÄ" +msgstr "Automaticky VložiÅ¥ KľúÄ" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Animation Key and Pose Options" -msgstr "Dĺžka ÄŒasu Animácie (v sekundách)" +msgstr "AnimaÄný KÄ¾ÃºÄ a Možnosti PozÃcie" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Insert Key (Existing Tracks)" -msgstr "" +msgstr "Vložte KÄ¾ÃºÄ (Existujúce Tracky)" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Copy Pose" -msgstr "" +msgstr "KopÃrovaÅ¥ PozÃciu" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Clear Pose" -msgstr "" +msgstr "ZmazaÅ¥ PozÃciu" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Multiply grid step by 2" -msgstr "" +msgstr "ZdvojnásobiÅ¥ krok mriežky dvomi" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Divide grid step by 2" -msgstr "" +msgstr "vydeliÅ¥ krok mriežky dvomi" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Pan View" -msgstr "" +msgstr "Zobrazenie Pan" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Add %s" -msgstr "" +msgstr "PridaÅ¥ %s" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Adding %s..." -msgstr "" +msgstr "Pridávanie %s..." #: editor/plugins/canvas_item_editor_plugin.cpp msgid "Cannot instantiate multiple nodes without root." -msgstr "" +msgstr "Nie je možné vytvoriÅ¥ inÅ¡tanciu viacerých node-ov bez koreňa." #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Create Node" -msgstr "" +msgstr "VytvoriÅ¥ Node" #: editor/plugins/canvas_item_editor_plugin.cpp #: editor/plugins/spatial_editor_plugin.cpp editor/scene_tree_dock.cpp msgid "Error instancing scene from %s" -msgstr "" +msgstr "Chyba pri inÅ¡talácovanà scény z %s" #: editor/plugins/canvas_item_editor_plugin.cpp -#, fuzzy msgid "Change Default Type" -msgstr "ZmeniÅ¥ %s Typ" +msgstr "ZmeniÅ¥ Predvolený Typ" #: editor/plugins/canvas_item_editor_plugin.cpp msgid "" @@ -5660,214 +5653,204 @@ msgid "" msgstr "" #: editor/plugins/collision_polygon_editor_plugin.cpp -#, fuzzy msgid "Create Polygon3D" -msgstr "VytvoriÅ¥ adresár" +msgstr "VytvoriÅ¥ Polygon3D" #: editor/plugins/collision_polygon_editor_plugin.cpp msgid "Edit Poly" -msgstr "" +msgstr "UpraviÅ¥ Poly" #: editor/plugins/collision_polygon_editor_plugin.cpp msgid "Edit Poly (Remove Point)" -msgstr "" +msgstr "UpraviÅ¥ Poly (OdstrániÅ¥ Bod)" #: editor/plugins/collision_shape_2d_editor_plugin.cpp msgid "Set Handle" -msgstr "" +msgstr "NastaviÅ¥ Rukoväť" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Load Emission Mask" -msgstr "" +msgstr "NaÄÃÅ¥ Emisnú Masku" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/cpu_particles_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp -#, fuzzy msgid "Restart" -msgstr "UložiÅ¥ súbor" +msgstr "ReÅ¡tartovaÅ¥" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Clear Emission Mask" -msgstr "" +msgstr "ZmazaÅ¥ Emisnú Masku" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Particles" -msgstr "" +msgstr "Particly" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Generated Point Count:" -msgstr "" +msgstr "Generovaný Bodový PoÄet:" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Emission Mask" -msgstr "" +msgstr "Emisná Maska" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Solid Pixels" -msgstr "" +msgstr "Pevné Pixely" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Border Pixels" -msgstr "" +msgstr "OhraniÄené Pixely" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp -#, fuzzy msgid "Directed Border Pixels" -msgstr "PrieÄinky a Súbory:" +msgstr "Pixely s Priamym OhraniÄenÃm" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Capture from Pixel" -msgstr "" +msgstr "SnÃmanie z Pixelu" #: editor/plugins/cpu_particles_2d_editor_plugin.cpp #: editor/plugins/particles_2d_editor_plugin.cpp msgid "Emission Colors" -msgstr "" +msgstr "Emisné Farby" #: editor/plugins/cpu_particles_editor_plugin.cpp msgid "CPUParticles" -msgstr "" +msgstr "CPUParticly" #: editor/plugins/cpu_particles_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Create Emission Points From Mesh" -msgstr "" +msgstr "VytvoriÅ¥ Emisné Body z Mesh-u" #: editor/plugins/cpu_particles_editor_plugin.cpp #: editor/plugins/particles_editor_plugin.cpp msgid "Create Emission Points From Node" -msgstr "" +msgstr "VytvoriÅ¥ Emisné Body z Node-u" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat 0" -msgstr "" +msgstr "Plochý 0" #: editor/plugins/curve_editor_plugin.cpp msgid "Flat 1" -msgstr "" +msgstr "Plochý 1" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp msgid "Ease In" -msgstr "" +msgstr "ZvyÅ¡ovanie" #: editor/plugins/curve_editor_plugin.cpp editor/property_editor.cpp msgid "Ease Out" -msgstr "" +msgstr "Znižovanie" #: editor/plugins/curve_editor_plugin.cpp msgid "Smoothstep" -msgstr "" +msgstr "Hladkýkrok" #: editor/plugins/curve_editor_plugin.cpp msgid "Modify Curve Point" -msgstr "" +msgstr "ModifikovaÅ¥ Bod Krivky" #: editor/plugins/curve_editor_plugin.cpp msgid "Modify Curve Tangent" -msgstr "" +msgstr "ModifikovaÅ¥ Tangetu Krivky" #: editor/plugins/curve_editor_plugin.cpp msgid "Load Curve Preset" -msgstr "" +msgstr "NaÄÃtaÅ¥ Predvoľbu Krivky" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Add Point" -msgstr "Signály:" +msgstr "PridaÅ¥ Bod" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Remove Point" -msgstr "VÅ¡etky vybrané" +msgstr "VymazaÅ¥ Bod" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Left Linear" -msgstr "Lineárne" +msgstr "Lineárne Vľavo" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Right Linear" -msgstr "Lineárne" +msgstr "Lineárne Vpravo" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Load Preset" -msgstr "NaÄÃtaÅ¥ predvolené" +msgstr "NaÄÃtaÅ¥ Predvoľbu" #: editor/plugins/curve_editor_plugin.cpp -#, fuzzy msgid "Remove Curve Point" -msgstr "VÅ¡etky vybrané" +msgstr "VymazaÅ¥ Bod Krivky" #: editor/plugins/curve_editor_plugin.cpp msgid "Toggle Curve Linear Tangent" -msgstr "" +msgstr "Prepnúť Lineárnu Tangetu Krivky" #: editor/plugins/curve_editor_plugin.cpp msgid "Hold Shift to edit tangents individually" -msgstr "" +msgstr "Podržte Shift aby ste upravili tangetu individuálne" #: editor/plugins/curve_editor_plugin.cpp msgid "Right click to add point" -msgstr "" +msgstr "Pravým kliknutÃm pridáťe Bod" #: editor/plugins/gi_probe_editor_plugin.cpp msgid "Bake GI Probe" -msgstr "" +msgstr "VypiecÅ¥ GI Probe" #: editor/plugins/gradient_editor_plugin.cpp msgid "Gradient Edited" -msgstr "" +msgstr "Prechod je Upravený" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item %d" -msgstr "" +msgstr "Predmet %d" #: editor/plugins/item_list_editor_plugin.cpp msgid "Items" -msgstr "" +msgstr "Predmety" #: editor/plugins/item_list_editor_plugin.cpp msgid "Item List Editor" -msgstr "" +msgstr "List Editor Predmetov" #: editor/plugins/light_occluder_2d_editor_plugin.cpp msgid "Create Occluder Polygon" -msgstr "" +msgstr "VytvoriÅ¥ Occluder Polygon" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Mesh is empty!" -msgstr "" +msgstr "Mesh je prázdny!" #: editor/plugins/mesh_instance_editor_plugin.cpp -#, fuzzy msgid "Couldn't create a Trimesh collision shape." -msgstr "VytvoriÅ¥ adresár" +msgstr "Nepodarilo sa vytvoriÅ¥ Trimesh collision shape." #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Static Trimesh Body" -msgstr "" +msgstr "VytvoriÅ¥ Static Trimesh Telo" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "This doesn't work on scene root!" -msgstr "" +msgstr "Toto nefunguje na koreni scény!" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Create Trimesh Static Shape" -msgstr "" +msgstr "VytvoriÅ¥ Trimesh Static Shape" #: editor/plugins/mesh_instance_editor_plugin.cpp msgid "Can't create a single convex collision shape for the scene root." @@ -6529,11 +6512,11 @@ msgstr "" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Snap" -msgstr "" +msgstr "PrichytiÅ¥" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Enable Snap" -msgstr "" +msgstr "PovoliÅ¥ Prichytávanie" #: editor/plugins/polygon_2d_editor_plugin.cpp msgid "Grid" @@ -7356,7 +7339,7 @@ msgstr "Filter:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Cinematic Preview" -msgstr "" +msgstr "Filmové Predzobrazenie" #: editor/plugins/spatial_editor_plugin.cpp msgid "Not available when using the GLES2 renderer." @@ -7419,11 +7402,11 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" -msgstr "" +msgstr "PrichytiÅ¥ Node-y Na Zem" #: editor/plugins/spatial_editor_plugin.cpp msgid "Couldn't find a solid floor to snap the selection to." -msgstr "" +msgstr "Nepodarilo sa nájsÅ¥ pevnú zem na prichytenie výberu." #: editor/plugins/spatial_editor_plugin.cpp msgid "" @@ -7438,7 +7421,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Use Snap" -msgstr "" +msgstr "PoužiÅ¥ Prichytávanie" #: editor/plugins/spatial_editor_plugin.cpp msgid "Bottom View" @@ -7492,7 +7475,7 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Object to Floor" -msgstr "" +msgstr "PrichytiÅ¥ Objekt na Zem" #: editor/plugins/spatial_editor_plugin.cpp msgid "Transform Dialog..." @@ -7541,19 +7524,19 @@ msgstr "" #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Settings" -msgstr "" +msgstr "Nastavenie Prichytenia" #: editor/plugins/spatial_editor_plugin.cpp msgid "Translate Snap:" -msgstr "" +msgstr "PreložiÅ¥ Preloženie:" #: editor/plugins/spatial_editor_plugin.cpp msgid "Rotate Snap (deg.):" -msgstr "" +msgstr "Prichytenie Rotácie (v stupňoch.):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Scale Snap (%):" -msgstr "" +msgstr "Prichytenie Veľkosti (%):" #: editor/plugins/spatial_editor_plugin.cpp msgid "Viewport Settings" @@ -7610,7 +7593,7 @@ msgstr "VytvoriÅ¥ adresár" #: editor/plugins/sprite_editor_plugin.cpp msgid "Mesh2D Preview" -msgstr "" +msgstr "PredzobraziÅ¥ Mash2D" #: editor/plugins/sprite_editor_plugin.cpp #, fuzzy @@ -7619,7 +7602,7 @@ msgstr "VytvoriÅ¥ adresár" #: editor/plugins/sprite_editor_plugin.cpp msgid "Polygon2D Preview" -msgstr "" +msgstr "PredzobraziÅ¥ Polygon2D" #: editor/plugins/sprite_editor_plugin.cpp #, fuzzy @@ -7627,9 +7610,8 @@ msgid "Create CollisionPolygon2D" msgstr "VytvoriÅ¥ adresár" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "CollisionPolygon2D Preview" -msgstr "VytvoriÅ¥ adresár" +msgstr "PredzobraziÅ¥ CollisionPolygon2D" #: editor/plugins/sprite_editor_plugin.cpp #, fuzzy @@ -7637,9 +7619,8 @@ msgid "Create LightOccluder2D" msgstr "VytvoriÅ¥ adresár" #: editor/plugins/sprite_editor_plugin.cpp -#, fuzzy msgid "LightOccluder2D Preview" -msgstr "VytvoriÅ¥ adresár" +msgstr "PredzobraziÅ¥ LightOccluder2D" #: editor/plugins/sprite_editor_plugin.cpp msgid "Sprite is empty!" @@ -7701,7 +7682,7 @@ msgstr "" #: editor/plugins/sprite_editor_plugin.cpp msgid "Update Preview" -msgstr "" +msgstr "PredzobraziÅ¥ VylepÅ¡enie" #: editor/plugins/sprite_editor_plugin.cpp msgid "Settings:" @@ -7835,7 +7816,7 @@ msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Snap Mode:" -msgstr "" +msgstr "Režim Prichytenia:" #: editor/plugins/texture_region_editor_plugin.cpp #: scene/resources/visual_shader.cpp @@ -7844,11 +7825,11 @@ msgstr "" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Pixel Snap" -msgstr "" +msgstr "Prichytenie Pixelov" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Grid Snap" -msgstr "" +msgstr "Prichytenie Mriežky" #: editor/plugins/texture_region_editor_plugin.cpp msgid "Auto Slice" @@ -8274,6 +8255,7 @@ msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp msgid "Enable snap and show grid (configurable via the Inspector)." msgstr "" +"PovoliÅ¥ prichytávanie a zobraziÅ¥ mriežku (konfigurovatelné cez inÅ¡pektor)." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Display Tile Names (Hold Alt Key)" @@ -8322,11 +8304,12 @@ msgid "Delete selected Rect." msgstr "VÅ¡etky vybrané" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "" "Select current edited sub-tile.\n" "Click on another Tile to edit it." -msgstr "VytvoriÅ¥ adresár" +msgstr "" +"VybraÅ¥ aktuálne upravený pod-nadpis.\n" +"Kliknite na ÄalÅ¡Ã Nadpis aby ste ho upravili." #: editor/plugins/tile_set_editor_plugin.cpp #, fuzzy @@ -8334,13 +8317,16 @@ msgid "Delete polygon." msgstr "VÅ¡etky vybrané" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "" "LMB: Set bit on.\n" "RMB: Set bit off.\n" "Shift+LMB: Set wildcard bit.\n" "Click on another Tile to edit it." -msgstr "VytvoriÅ¥ adresár" +msgstr "" +"LMB: Zapnúť bit.\n" +"RMB: Vypnúť bit.\n" +"Shift+LMB: NastaviÅ¥ wildcard bit.\n" +"Kliknite na ÄalÅ¡Ã Nadpis pre úpravu." #: editor/plugins/tile_set_editor_plugin.cpp msgid "" @@ -8356,11 +8342,12 @@ msgid "" msgstr "" #: editor/plugins/tile_set_editor_plugin.cpp -#, fuzzy msgid "" "Select sub-tile to change its z index.\n" "Click on another Tile to edit it." -msgstr "VytvoriÅ¥ adresár" +msgstr "" +"VybraÅ¥ podnadpis aby ste zmenili jeho index.\n" +"Kliknite na ÄalÅ¡Ã Nadpis na úpravu." #: editor/plugins/tile_set_editor_plugin.cpp msgid "Set Tile Region" @@ -9832,6 +9819,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" @@ -10488,14 +10476,12 @@ msgid "Make node as Root" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes and any children?" -msgstr "VÅ¡etky vybrané" +msgstr "ZmazaÅ¥ %d node-y a nejaké deti?" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes?" -msgstr "VÅ¡etky vybrané" +msgstr "ZmazaÅ¥ %d node-y?" #: editor/scene_tree_dock.cpp msgid "Delete the root node \"%s\"?" @@ -10506,9 +10492,8 @@ msgid "Delete node \"%s\" and its children?" msgstr "" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete node \"%s\"?" -msgstr "VÅ¡etky vybrané" +msgstr "ZmazaÅ¥ node \"%s\"?" #: editor/scene_tree_dock.cpp msgid "Can not perform with the root node." @@ -10711,9 +10696,8 @@ msgid "Button Group" msgstr "TlaÄidlo" #: editor/scene_tree_editor.cpp -#, fuzzy msgid "(Connecting From)" -msgstr "PripojiÅ¥ Signál: " +msgstr "(Pripájanie z)" #: editor/scene_tree_editor.cpp msgid "Node configuration warning:" @@ -10917,9 +10901,8 @@ msgid "Attach Node Script" msgstr "Popis:" #: editor/script_editor_debugger.cpp -#, fuzzy msgid "Remote " -msgstr "VÅ¡etky vybrané" +msgstr "Diaľkový " #: editor/script_editor_debugger.cpp msgid "Bytes:" @@ -11312,7 +11295,7 @@ msgstr "" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Snap View" -msgstr "" +msgstr "PrichytiÅ¥ Zobrazenie" #: modules/gridmap/grid_map_editor_plugin.cpp msgid "Clip Disabled" @@ -12361,13 +12344,12 @@ msgid "" msgstr "" #: scene/3d/collision_shape.cpp -#, fuzzy msgid "" "A shape must be provided for CollisionShape to function. Please create a " "shape resource for it." msgstr "" -"MusÃte nastaviÅ¥ tvar objektu CollisionShape2D aby fungoval. ProsÃm, vytvorte " -"preň tvarový objekt!" +"Aby CollisionShape fungoval musÃte nastaviÅ¥ tvar. ProsÃm, vytvorte preň " +"tvarový objekt." #: scene/3d/collision_shape.cpp msgid "" @@ -12625,9 +12607,8 @@ msgid "Viewport size must be greater than 0 to render anything." msgstr "" #: scene/resources/visual_shader_nodes.cpp -#, fuzzy msgid "Invalid source for preview." -msgstr "Nesprávna veľkosÅ¥ pÃsma." +msgstr "Neplatný zdroj pre predzobrazenie." #: scene/resources/visual_shader_nodes.cpp #, fuzzy diff --git a/editor/translations/sl.po b/editor/translations/sl.po index c40bc3b40f..b095b4d9b7 100644 --- a/editor/translations/sl.po +++ b/editor/translations/sl.po @@ -1172,6 +1172,9 @@ msgstr "Ustanovitelji Projekta" msgid "Lead Developer" msgstr "Vodilni Razvajalec" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Upravljalnik Projekta " @@ -1193,6 +1196,16 @@ msgid "Gold Sponsors" msgstr "Zlati Sponzorji" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Srebrni Donatorji" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronasti Donatorji" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Majhni Sponzorji" @@ -10166,6 +10179,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Upravljalnik Projekta" diff --git a/editor/translations/sq.po b/editor/translations/sq.po index 2df44bdd5b..b4789e5591 100644 --- a/editor/translations/sq.po +++ b/editor/translations/sq.po @@ -1114,6 +1114,9 @@ msgstr "Themeluesit e Projektit" msgid "Lead Developer" msgstr "Krye Zhvilluesi" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Menaxheri Projektit " @@ -1135,6 +1138,16 @@ msgid "Gold Sponsors" msgstr "Sponsorat Flori" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Dhuruesit Argjend" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Dhuruesit Bronz" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsorat" @@ -9817,6 +9830,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po index 0bb67647f8..09a0750482 100644 --- a/editor/translations/sr_Cyrl.po +++ b/editor/translations/sr_Cyrl.po @@ -1228,6 +1228,9 @@ msgstr "ОÑнивачи пројекта" msgid "Lead Developer" msgstr "Главни девелопер" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp #, fuzzy msgid "Project Manager " @@ -1250,6 +1253,16 @@ msgid "Gold Sponsors" msgstr "Златни Ñпонзори" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Сребрни донатори" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Бронзани донатори" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Мали Ñпонзори" @@ -10994,6 +11007,7 @@ msgstr "" "пројектима?\n" "Ово може потрајати." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Менаџер пројекта" diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po index 4dece6c33c..14f9fd8d1f 100644 --- a/editor/translations/sr_Latn.po +++ b/editor/translations/sr_Latn.po @@ -1116,6 +1116,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1137,6 +1140,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9617,6 +9628,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/sv.po b/editor/translations/sv.po index d3cda1a61a..562939496f 100644 --- a/editor/translations/sv.po +++ b/editor/translations/sv.po @@ -17,12 +17,13 @@ # Kristoffer Grundström <swedishsailfishosuser@tutanota.com>, 2020. # Jonas Robertsson <jonas.robertsson@posteo.net>, 2020. # André Andersson <andre.eric.andersson@gmail.com>, 2020. +# Andreas Westrell <andreas.westrell@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-15 02:42+0000\n" -"Last-Translator: Jonas Robertsson <jonas.robertsson@posteo.net>\n" +"PO-Revision-Date: 2020-08-18 02:54+0000\n" +"Last-Translator: Andreas Westrell <andreas.westrell@gmail.com>\n" "Language-Team: Swedish <https://hosted.weblate.org/projects/godot-engine/" "godot/sv/>\n" "Language: sv\n" @@ -1129,9 +1130,12 @@ msgstr "Projektgrundare" msgid "Lead Developer" msgstr "Ledande utvecklare" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " -msgstr "Projekthanterare " +msgstr "Projektledare " #: editor/editor_about.cpp msgid "Developers" @@ -1150,6 +1154,16 @@ msgid "Gold Sponsors" msgstr "Guldsponsorer" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Silverdonatorer" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronsdonatorer" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Minisponsorer" @@ -1231,9 +1245,8 @@ msgid "Success!" msgstr "Klart!" #: editor/editor_asset_installer.cpp -#, fuzzy msgid "Package Contents:" -msgstr "InnehÃ¥ll:" +msgstr "Packet InnehÃ¥ll:" #: editor/editor_asset_installer.cpp editor/editor_node.cpp msgid "Install" @@ -1256,9 +1269,8 @@ msgid "Rename Audio Bus" msgstr "Byt namn pÃ¥ Ljud-Buss" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Change Audio Bus Volume" -msgstr "Växla Ljud-Buss Solo" +msgstr "Växla Ljud-Buss Volum" #: editor/editor_audio_buses.cpp msgid "Toggle Audio Bus Solo" @@ -1385,9 +1397,8 @@ msgid "Add Bus" msgstr "Lägg till Buss" #: editor/editor_audio_buses.cpp -#, fuzzy msgid "Add a new Audio Bus to this layout." -msgstr "Spara Ljud-Buss Layout Som..." +msgstr "Lägg till en ny Audio-Buss för detta layout" #: editor/editor_audio_buses.cpp editor/editor_properties.cpp #: editor/plugins/animation_player_editor_plugin.cpp editor/property_editor.cpp @@ -10059,6 +10070,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Projektledare" diff --git a/editor/translations/ta.po b/editor/translations/ta.po index 01cbcc1881..a6df89a718 100644 --- a/editor/translations/ta.po +++ b/editor/translations/ta.po @@ -4,13 +4,14 @@ # This file is distributed under the same license as the Godot source code. # # Senthil Kumar K <logickumar@gmail.com>, 2017. -# +# Survesh VRL <123survesh@gmail.com>, 2020. +# Sridhar <sreeafmarketing@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2018-12-13 14:43+0100\n" -"Last-Translator: Senthil Kumar K <logickumar@gmail.com>\n" +"PO-Revision-Date: 2020-09-01 10:38+0000\n" +"Last-Translator: Sridhar <sreeafmarketing@gmail.com>\n" "Language-Team: Tamil <https://hosted.weblate.org/projects/godot-engine/godot/" "ta/>\n" "Language: ta\n" @@ -18,34 +19,37 @@ 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.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp msgid "Invalid type argument to convert(), use TYPE_* constants." -msgstr "" +msgstr "தவறான வகை வாதம௠மாறà¯à®±à¯(), TYPE_ * மாறிலிகளைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯." #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp msgid "Expected a string of length 1 (a character)." -msgstr "" +msgstr "நீளமà¯à®³à¯à®³ சொல௠(ஒர௠எழà¯à®¤à¯à®¤à¯) எதிரà¯à®ªà®¾à®°à¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯." #: 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" -msgstr "" +msgstr "தவறான உளà¯à®³à¯€à®Ÿà¯% i (அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ) இல௠வெளிபà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®²à¯" #: core/math/expression.cpp +#, fuzzy msgid "self can't be used because instance is null (not passed)" msgstr "" +"சà¯à®¯à®¤à¯à®¤à¯ˆ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯, à®à®©à¯†à®©à®¿à®²à¯ உதாரணமà¯(instance) பூஜà¯à®¯à®®à®¾à®©à®¤à¯ " +"(நிறைவேறà¯à®±à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ)" #: core/math/expression.cpp msgid "Invalid operands to operator %s, %s and %s." -msgstr "" +msgstr "ஆபரேடà¯à®Ÿà®°à¯% s,% s மறà¯à®±à¯à®®à¯% s கà¯à®•à¯ தவறான செயலà¯à®ªà®¾à®Ÿà¯à®•à®³à¯ உளà¯à®³à®¤à¯." #: core/math/expression.cpp msgid "Invalid index of type %s for base type %s" @@ -1108,6 +1112,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1129,6 +1136,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9536,6 +9551,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/te.po b/editor/translations/te.po index 3523306b0d..ce1fc1d478 100644 --- a/editor/translations/te.po +++ b/editor/translations/te.po @@ -1086,6 +1086,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1107,6 +1110,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9468,6 +9479,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/th.po b/editor/translations/th.po index 279f8c08ba..1408e9edb3 100644 --- a/editor/translations/th.po +++ b/editor/translations/th.po @@ -6,12 +6,13 @@ # Poommetee Ketson (Noshyaar) <poommetee@protonmail.com>, 2017-2018. # Thanachart Monpassorn <nunf_2539@hotmail.com>, 2020. # Anonymous <noreply@weblate.org>, 2020. +# Lon3r <mptube.p@gmail.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-05-26 13:41+0000\n" -"Last-Translator: Thanachart Monpassorn <nunf_2539@hotmail.com>\n" +"PO-Revision-Date: 2020-08-28 13:09+0000\n" +"Last-Translator: Lon3r <mptube.p@gmail.com>\n" "Language-Team: Thai <https://hosted.weblate.org/projects/godot-engine/godot/" "th/>\n" "Language: th\n" @@ -19,7 +20,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.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -744,9 +745,8 @@ msgid "Method in target node must be specified." msgstr "ต้à¸à¸‡à¸£à¸°à¸šà¸¸à¹€à¸¡à¸˜à¸à¸”ในโหนดเป้าหมาย" #: editor/connections_dialog.cpp -#, fuzzy msgid "Method name must be a valid identifier." -msgstr "ไม่สามารถใช้ชื่à¸à¸™à¸µà¹‰à¹„ด้:" +msgstr "ไม่สามารถใช้ชื่à¸à¸™à¸µà¹‰à¹„ด้." #: editor/connections_dialog.cpp msgid "" @@ -1101,6 +1101,9 @@ msgstr "ผู้ริเริ่มโครงà¸à¸²à¸£" msgid "Lead Developer" msgstr "ผู้พัฒนาหลัà¸" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "ผู้จัดà¸à¸²à¸£à¹‚ครงà¸à¸²à¸£ " @@ -1122,6 +1125,16 @@ msgid "Gold Sponsors" msgstr "ผู้สนับสนุนระดับทà¸à¸‡" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "ผู้บริจาคระดับเงิน" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "ผู้บริจาคระดับทà¸à¸‡à¹à¸”ง" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "ผู้สนับสนุน" @@ -1438,7 +1451,7 @@ msgstr "จัดลำดับà¸à¸à¹‚ต้โหลด" #: editor/editor_autoload_settings.cpp msgid "Can't add autoload:" -msgstr "" +msgstr "เพิ่มà¸à¸à¹‚ต้โหลดไม่ได้:" #: editor/editor_autoload_settings.cpp msgid "Add AutoLoad" @@ -1607,7 +1620,7 @@ msgstr "โหมดเคลื่à¸à¸™à¸¢à¹‰à¸²à¸¢" #: editor/editor_feature_profile.cpp #, fuzzy msgid "FileSystem and Import Docks" -msgstr "ระบบไฟล์" +msgstr "ระบบไฟล์ à¹à¸¥à¸° นำเข้า" #: editor/editor_feature_profile.cpp msgid "Erase profile '%s'? (no undo)" @@ -2051,7 +2064,7 @@ msgstr "à¸à¸³à¸«à¸™à¸”" #: editor/editor_inspector.cpp msgid "Set Multiple:" -msgstr "" +msgstr "à¸à¸³à¸«à¸™à¸” หลายà¸à¸¢à¹ˆà¸²à¸‡:" #: editor/editor_log.cpp msgid "Output:" @@ -2103,19 +2116,21 @@ msgstr "โหนด" #: editor/editor_network_profiler.cpp msgid "Incoming RPC" -msgstr "" +msgstr "RPC à¸à¸³à¸¥à¸±à¸‡à¸¡à¸²" #: editor/editor_network_profiler.cpp msgid "Incoming RSET" -msgstr "" +msgstr "RSET à¸à¸³à¸¥à¸±à¸‡à¸¡à¸²" #: editor/editor_network_profiler.cpp +#, fuzzy msgid "Outgoing RPC" -msgstr "" +msgstr "RPC à¸à¸³à¸¥à¸±à¸‡à¸à¸à¸" #: editor/editor_network_profiler.cpp +#, fuzzy msgid "Outgoing RSET" -msgstr "" +msgstr "RSET à¸à¸³à¸¥à¸±à¸‡à¸à¸à¸" #: editor/editor_node.cpp editor/project_manager.cpp msgid "New Window" @@ -9845,6 +9860,7 @@ msgstr "" "ทำà¸à¸²à¸£à¸ªà¹à¸à¸™à¸«à¸²à¹‚ปรเจà¸à¸•à¹Œ ในโฟลเดà¸à¸£à¹Œ %s หรืà¸à¹„ม่?\n" "à¸à¸²à¸ˆà¸ˆà¸°à¹ƒà¸Šà¹‰à¹€à¸§à¸¥à¸²à¸ªà¸±à¸à¸„รู่" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "ตัวจัดà¸à¸²à¸£à¹‚ปรเจà¸à¸•à¹Œ" diff --git a/editor/translations/tr.po b/editor/translations/tr.po index edc01421d2..1ac1204e09 100644 --- a/editor/translations/tr.po +++ b/editor/translations/tr.po @@ -50,12 +50,13 @@ # Vedat Günel <gunel15@itu.edu.tr>, 2020. # Ahmet Elgün <ahmetelgn@gmail.com>, 2020. # Efruz Yıldırır <efruzyildirir@gmail.com>, 2020. +# Hazar <duurkak@yandex.com>, 2020. msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-06 04:41+0000\n" -"Last-Translator: Efruz Yıldırır <efruzyildirir@gmail.com>\n" +"PO-Revision-Date: 2020-08-20 15:20+0000\n" +"Last-Translator: Hazar <duurkak@yandex.com>\n" "Language-Team: Turkish <https://hosted.weblate.org/projects/godot-engine/" "godot/tr/>\n" "Language: tr\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.2-dev\n" +"X-Generator: Weblate 4.2.1-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1160,6 +1161,9 @@ msgstr "Projenin Kurucuları" msgid "Lead Developer" msgstr "BaÅŸ GeliÅŸtirici" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Proje Yöneticisi " @@ -1181,6 +1185,16 @@ msgid "Gold Sponsors" msgstr "Altın Sponsorlar" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "Gümüş Bağışçılar" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "Bronz Bağışçılar" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Mini Sponsorlar" @@ -7431,6 +7445,11 @@ msgid "" "Closed eye: Gizmo is hidden.\n" "Half-open eye: Gizmo is also visible through opaque surfaces (\"x-ray\")." msgstr "" +"Görünürlük ifadelerini deÄŸiÅŸtirmek için tıklayın.\n" +"\n" +"Açık göz: Gizmo görünür.\n" +"Kapalı göz: Gizmo görünmez.\n" +"Yarı-açık göz: Gizmo aynı zamanda saydam yüzeylerden görünür (\"x-ray\")." #: editor/plugins/spatial_editor_plugin.cpp msgid "Snap Nodes To Floor" @@ -9893,6 +9912,7 @@ msgstr "" "misiniz?\n" "Bu biraz zaman alabilir." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Proje Yöneticisi" @@ -10516,9 +10536,8 @@ msgid "Instance Child Scene" msgstr "Çocuk Sahnesini Örnekle" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach Script" -msgstr "Betik Ä°liÅŸtir" +msgstr "BetiÄŸi Ayır" #: editor/scene_tree_dock.cpp msgid "This operation can't be done on the tree root." @@ -10555,7 +10574,6 @@ msgid "Make node as Root" msgstr "Düğümü Kök düğüm yap" #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Delete %d nodes and any children?" msgstr "\"%s\" düğümü ve alt düğümleri silinsin mi?" @@ -10693,6 +10711,8 @@ msgid "" "This is probably because this editor was built with all language modules " "disabled." msgstr "" +"Bir yazı eklenemiyor: kayıtlı dil yok.\n" +"Bu muhtemelen editor tüm dil modülleri kapalıyken kurulduÄŸu için oldu." #: editor/scene_tree_dock.cpp msgid "Add Child Node" @@ -10743,14 +10763,12 @@ msgstr "" "alınmış bir sahne oluÅŸturur." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Attach a new or existing script to the selected node." -msgstr "Seçili düğüm için yeni veya mevcut bir betik iliÅŸtir." +msgstr "Seçili düğüme yeni veya mevcut bir betik iliÅŸtir." #: editor/scene_tree_dock.cpp -#, fuzzy msgid "Detach the script from the selected node." -msgstr "Seçilen düğüm için betik temizle." +msgstr "Seçilen düğümden betiÄŸi ayır." #: editor/scene_tree_dock.cpp msgid "Remote" diff --git a/editor/translations/uk.po b/editor/translations/uk.po index f7386bf72d..672785a2aa 100644 --- a/editor/translations/uk.po +++ b/editor/translations/uk.po @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: Ukrainian (Godot Engine)\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-08-04 06:43+0000\n" +"PO-Revision-Date: 2020-09-05 09:37+0000\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <https://hosted.weblate.org/projects/godot-engine/" "godot/uk/>\n" @@ -29,7 +29,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1136,6 +1136,9 @@ msgstr "ЗаÑновники проєкту" msgid "Lead Developer" msgstr "Ведучий розробник" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Керівник проектів " @@ -1157,6 +1160,14 @@ msgid "Gold Sponsors" msgstr "Золоті ÑпонÑори" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "Срібні донори" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "Бронзові донори" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Міні-ÑпонÑори" @@ -9902,6 +9913,7 @@ msgstr "" "Ви Ñправді хочете виконати пошук у %s теках наÑвних проєктів Godot?\n" "Пошук може бути доволі тривалим." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Керівник проекту" diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po index 4f4dccd8bb..89208b4070 100644 --- a/editor/translations/ur_PK.po +++ b/editor/translations/ur_PK.po @@ -1104,6 +1104,9 @@ msgstr "" msgid "Lead Developer" msgstr "" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "" @@ -1125,6 +1128,14 @@ msgid "Gold Sponsors" msgstr "" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "" @@ -9703,6 +9714,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/vi.po b/editor/translations/vi.po index bd52b850e4..579b8550ee 100644 --- a/editor/translations/vi.po +++ b/editor/translations/vi.po @@ -1128,6 +1128,9 @@ msgstr "Các đồng sáng láºp dá»± án" msgid "Lead Developer" msgstr "Phát triển chÃnh" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "Quản là Dá»± án " @@ -1149,6 +1152,16 @@ msgid "Gold Sponsors" msgstr "Nhà tà i trợ Và ng" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "NgÆ°á»i ủng há»™ Bạc" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "NgÆ°á»i ủng há»™ Äồng" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "Nhà tà i trợ Nhá»" @@ -9883,6 +9896,7 @@ msgstr "" "Bạn có chắc chắn quét các thÆ° mục %s để tìm các dá»± án Godot có sẵn?\n" "Äiá»u nà y sẽ mất chút thá»i gian." +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "Trình quản lý Dá»± án" diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po index f35da2476c..fede4b0528 100644 --- a/editor/translations/zh_CN.po +++ b/editor/translations/zh_CN.po @@ -70,12 +70,13 @@ # Silence Tai <silence.m@hotmail.com>, 2020. # MintSoda <lionlxh@qq.com>, 2020. # Gardner Belgrade <hapenia@sina.com>, 2020. +# godhidden <z2zz2zz@yahoo.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-08-11 14:04+0000\n" -"Last-Translator: Gardner Belgrade <hapenia@sina.com>\n" +"PO-Revision-Date: 2020-09-05 09:37+0000\n" +"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n" "Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/" "godot-engine/godot/zh_Hans/>\n" "Language: zh_CN\n" @@ -83,7 +84,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1168,6 +1169,9 @@ msgstr "项目创始人" msgid "Lead Developer" msgstr "主è¦å¼€å‘者" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "项目管ç†å‘˜ " @@ -1189,6 +1193,14 @@ msgid "Gold Sponsors" msgstr "黄金赞助" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "白银赞助" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "é’铜赞助" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "è¿·ä½ èµžåŠ©" @@ -7014,7 +7026,7 @@ msgstr "转到行..." #: editor/plugins/script_text_editor.cpp #: modules/visual_script/visual_script_editor.cpp msgid "Toggle Breakpoint" -msgstr "设置æ–点" +msgstr "切æ¢æ–点" #: editor/plugins/script_text_editor.cpp msgid "Remove All Breakpoints" @@ -7402,7 +7414,7 @@ msgstr "æ’入动画帧" #: editor/plugins/spatial_editor_plugin.cpp msgid "Focus Origin" -msgstr "显示原点" +msgstr "èšç„¦åŽŸç‚¹" #: editor/plugins/spatial_editor_plugin.cpp msgid "Focus Selection" @@ -9402,7 +9414,7 @@ msgstr "包文件" #: editor/project_export.cpp msgid "Features" -msgstr "功能" +msgstr "特性" #: editor/project_export.cpp msgid "Custom (comma-separated):" @@ -9748,6 +9760,7 @@ msgstr "" "您确定è¦æ‰«æ%s文件夹ä¸çš„现有Godot项目å—? \n" "è¿™å¯èƒ½éœ€è¦ä¸€æ®µæ—¶é—´ã€‚" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "项目管ç†å™¨" diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po index d4e1bf62dd..7c7571fff0 100644 --- a/editor/translations/zh_HK.po +++ b/editor/translations/zh_HK.po @@ -1158,6 +1158,9 @@ msgstr "專案開è’人" msgid "Lead Developer" msgstr "主è¦é–‹ç™¼è€…" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "é–‹å•Ÿ Project Manager " @@ -1179,6 +1182,16 @@ msgid "Gold Sponsors" msgstr "黃金級贊助人" #: editor/editor_about.cpp +#, fuzzy +msgid "Silver Sponsors" +msgstr "白銀級æ款人" + +#: editor/editor_about.cpp +#, fuzzy +msgid "Bronze Sponsors" +msgstr "é’銅級æ款人" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "è¿·ä½ è´ŠåŠ©äºº" @@ -10130,6 +10143,7 @@ msgid "" "This could take a while." msgstr "" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "" diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po index 51efdfd2b8..9063126888 100644 --- a/editor/translations/zh_TW.po +++ b/editor/translations/zh_TW.po @@ -29,8 +29,8 @@ msgid "" msgstr "" "Project-Id-Version: Godot Engine editor\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-07-31 03:47+0000\n" -"Last-Translator: MintSoda <lionlxh@qq.com>\n" +"PO-Revision-Date: 2020-09-08 11: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" "Language: zh_TW\n" @@ -38,7 +38,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.2-dev\n" +"X-Generator: Weblate 4.3-dev\n" #: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp #: modules/visual_script/visual_script_builtin_funcs.cpp @@ -1124,6 +1124,9 @@ msgstr "專案創始人" msgid "Lead Developer" msgstr "主è¦é–‹ç™¼è€…" +#. TRANSLATORS: This refers to a job title. +#. The trailing space is used to distinguish with the project list application, +#. you do not have to keep it in your translation. #: editor/editor_about.cpp msgid "Project Manager " msgstr "專案管ç†å“¡ " @@ -1145,6 +1148,14 @@ msgid "Gold Sponsors" msgstr "黃金贊助" #: editor/editor_about.cpp +msgid "Silver Sponsors" +msgstr "白銀贊助" + +#: editor/editor_about.cpp +msgid "Bronze Sponsors" +msgstr "é’銅贊助" + +#: editor/editor_about.cpp msgid "Mini Sponsors" msgstr "è¿·ä½ è´ŠåŠ©" @@ -9710,6 +9721,7 @@ msgstr "" "確定è¦æŽƒæ %s ä¸çš„ Godot 專案嗎?\n" "這å¯èƒ½éœ€è¦ä¸€æ®µæ™‚間。" +#. TRANSLATORS: This refers to the application where users manage their Godot projects. #: editor/project_manager.cpp msgid "Project Manager" msgstr "專案管ç†å“¡" diff --git a/glsl_builders.py b/glsl_builders.py index af9afcae70..29971fd4e7 100644 --- a/glsl_builders.py +++ b/glsl_builders.py @@ -96,8 +96,6 @@ def build_rd_header(filename): out_file = filename + ".gen.h" fd = open(out_file, "w") - enum_constants = [] - fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") out_file_base = out_file @@ -165,7 +163,6 @@ class RAWHeaderStruct: def include_file_in_raw_header(filename, header_data, depth): fs = open(filename, "r") line = fs.readline() - text = "" while line: @@ -192,8 +189,6 @@ def build_raw_header(filename): out_file = filename + ".gen.h" fd = open(out_file, "w") - enum_constants = [] - fd.write("/* WARNING, THIS FILE WAS GENERATED, DO NOT EDIT */\n") out_file_base = out_file.replace(".glsl.gen.h", "_shader_glsl") @@ -211,11 +206,6 @@ def build_raw_header(filename): fd.close() -def build_rd_headers(target, source, env): - for x in source: - build_rd_header(str(x)) - - def build_raw_headers(target, source, env): for x in source: build_raw_header(str(x)) diff --git a/main/main.cpp b/main/main.cpp index cb67d26043..ced8d7227a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2292,6 +2292,13 @@ bool Main::start() { } if (project_manager || editor) { + if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CONSOLE_WINDOW)) { + // Hide console window if requested (Windows-only). + bool hide_console = EditorSettings::get_singleton()->get_setting( + "interface/editor/hide_console_window"); + DisplayServer::get_singleton()->console_set_visible(!hide_console); + } + // Load SSL Certificates from Editor Settings (or builtin) Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting( "network/ssl/editor_ssl_certificates") diff --git a/main/main_builders.py b/main/main_builders.py index 2ea774e3b4..aa91201c3e 100644 --- a/main/main_builders.py +++ b/main/main_builders.py @@ -4,7 +4,6 @@ All such functions are invoked in a subprocess on Windows to prevent build flaki """ from platform_methods import subprocess_main -from collections import OrderedDict def make_splash(target, source, env): diff --git a/main/splash_editor.png b/main/splash_editor.png Binary files differindex 29931a71db..855646b346 100644 --- a/main/splash_editor.png +++ b/main/splash_editor.png diff --git a/methods.py b/methods.py index bcb6d13e1f..8f14de6dac 100644 --- a/methods.py +++ b/methods.py @@ -536,6 +536,7 @@ def generate_vs_project(env, num_jobs): '(if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64"))', 'set "tools=yes"', '(if "$(Configuration)"=="release" (set "tools=no"))', + 'set "custom_modules=%s"' % env["custom_modules"], 'call "' + batch_file + '" !plat!', ] @@ -555,15 +556,15 @@ def generate_vs_project(env, num_jobs): # last double quote off, confusing MSBuild env["MSVSBUILDCOM"] = build_commandline( "scons --directory=\"$(ProjectDir.TrimEnd('\\'))\" platform=windows progress=no target=$(Configuration)" - " tools=!tools! -j" + str(num_jobs) + " tools=!tools! custom_modules=!custom_modules! -j" + str(num_jobs) ) env["MSVSREBUILDCOM"] = build_commandline( "scons --directory=\"$(ProjectDir.TrimEnd('\\'))\" platform=windows progress=no target=$(Configuration)" - " tools=!tools! vsproj=yes -j" + str(num_jobs) + " tools=!tools! custom_modules=!custom_modules! vsproj=yes -j" + str(num_jobs) ) env["MSVSCLEANCOM"] = build_commandline( "scons --directory=\"$(ProjectDir.TrimEnd('\\'))\" --clean platform=windows progress=no" - " target=$(Configuration) tools=!tools! -j" + str(num_jobs) + " target=$(Configuration) tools=!tools! custom_modules=!custom_modules! -j" + str(num_jobs) ) # This version information (Win32, x64, Debug, Release, Release_Debug seems to be diff --git a/misc/dist/html/fixed-size.html b/misc/dist/html/fixed-size.html index a5633115d5..85064b34fd 100644 --- a/misc/dist/html/fixed-size.html +++ b/misc/dist/html/fixed-size.html @@ -236,7 +236,6 @@ $GODOT_HEAD_INCLUDE const DEBUG_ENABLED = $GODOT_DEBUG_ENABLED; const INDETERMINATE_STATUS_STEP_MS = 100; - var container = document.getElementById('container'); var canvas = document.getElementById('canvas'); var statusProgress = document.getElementById('status-progress'); var statusProgressInner = document.getElementById('status-progress-inner'); diff --git a/misc/dist/html/full-size.html b/misc/dist/html/full-size.html index 435013cb5e..be25ce4839 100644 --- a/misc/dist/html/full-size.html +++ b/misc/dist/html/full-size.html @@ -201,7 +201,7 @@ $GODOT_HEAD_INCLUDE throw new Error('Invalid status mode'); } statusMode = mode; - } + }; function animateStatusIndeterminate(ms) { diff --git a/modules/arkit/register_types.h b/modules/arkit/register_types.h index 5c697baf68..f8939a1e3f 100644 --- a/modules/arkit/register_types.h +++ b/modules/arkit/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef ARKIT_REGISTER_TYPES_H +#define ARKIT_REGISTER_TYPES_H + void register_arkit_types(); void unregister_arkit_types(); + +#endif // ARKIT_REGISTER_TYPES_H diff --git a/modules/basis_universal/texture_basisu.h b/modules/basis_universal/texture_basisu.h index 8de151ede0..20ecf15a59 100644 --- a/modules/basis_universal/texture_basisu.h +++ b/modules/basis_universal/texture_basisu.h @@ -28,6 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef BASIS_UNIVERSAL_TEXTURE_BASISU_H +#define BASIS_UNIVERSAL_TEXTURE_BASISU_H + #include "scene/resources/texture.h" #ifdef TOOLS_ENABLED @@ -75,3 +78,5 @@ public: }; #endif + +#endif // BASIS_UNIVERSAL_TEXTURE_BASISU_H diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 32c3240a35..f517eecf64 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -849,8 +849,8 @@ void RigidBodyBullet::on_enter_area(AreaBullet *p_area) { } else { if (areasWhereIam[i]->get_spOv_priority() > p_area->get_spOv_priority()) { // The position was found, just shift all elements - for (int j = i; j < areaWhereIamCount; ++j) { - areasWhereIam[j + 1] = areasWhereIam[j]; + for (int j = areaWhereIamCount; j > i; j--) { + areasWhereIam[j] = areasWhereIam[j - 1]; } areasWhereIam[i] = p_area; break; diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 274493ed17..74d6e073b3 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -308,7 +308,7 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { } btCollisionShape *CapsuleShapeBullet::internal_create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge) { - return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1] + p_extra_edge)); + return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_extra_edge, height * p_implicit_scale[1])); } /* Cylinder */ diff --git a/modules/camera/register_types.h b/modules/camera/register_types.h index f2753cb6d7..e34f84bf2c 100644 --- a/modules/camera/register_types.h +++ b/modules/camera/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef CAMERA_REGISTER_TYPES_H +#define CAMERA_REGISTER_TYPES_H + void register_camera_types(); void unregister_camera_types(); + +#endif // CAMERA_REGISTER_TYPES_H diff --git a/modules/cvtt/register_types.h b/modules/cvtt/register_types.h index 8472980c6a..36b5e332d6 100644 --- a/modules/cvtt/register_types.h +++ b/modules/cvtt/register_types.h @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef TOOLS_ENABLED - #ifndef CVTT_REGISTER_TYPES_H #define CVTT_REGISTER_TYPES_H +#ifdef TOOLS_ENABLED + void register_cvtt_types(); void unregister_cvtt_types(); -#endif // CVTT_REGISTER_TYPES_H - #endif // TOOLS_ENABLED + +#endif // CVTT_REGISTER_TYPES_H diff --git a/modules/denoise/register_types.h b/modules/denoise/register_types.h index 2ffc36ee2c..f0f1f44bfe 100644 --- a/modules/denoise/register_types.h +++ b/modules/denoise/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef DENOISE_REGISTER_TYPES_H +#define DENOISE_REGISTER_TYPES_H + void register_denoise_types(); void unregister_denoise_types(); + +#endif // DENOISE_REGISTER_TYPES_H diff --git a/modules/denoise/resource_to_cpp.py b/modules/denoise/resource_to_cpp.py index 4c0b67f701..6c83277355 100644 --- a/modules/denoise/resource_to_cpp.py +++ b/modules/denoise/resource_to_cpp.py @@ -17,8 +17,6 @@ ## ======================================================================== ## import os -import sys -import argparse from array import array # Generates a C++ file from the specified binary resource file diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 26c40b625c..1fa19f4ff5 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -40,9 +40,10 @@ extern "C" { #endif +static_assert(sizeof(godot_char16_string) == sizeof(Char16String), "Char16String size mismatch"); static_assert(sizeof(godot_char_string) == sizeof(CharString), "CharString size mismatch"); static_assert(sizeof(godot_string) == sizeof(String), "String size mismatch"); -static_assert(sizeof(godot_char_type) == sizeof(CharType), "CharType size mismatch"); +static_assert(sizeof(godot_char_type) == sizeof(char32_t), "char32_t size mismatch"); godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs) { const CharString *cs = (const CharString *)p_cs; @@ -62,6 +63,24 @@ void GDAPI godot_char_string_destroy(godot_char_string *p_cs) { cs->~CharString(); } +godot_int GDAPI godot_char16_string_length(const godot_char16_string *p_cs) { + const Char16String *cs = (const Char16String *)p_cs; + + return cs->length(); +} + +const char16_t GDAPI *godot_char16_string_get_data(const godot_char16_string *p_cs) { + const Char16String *cs = (const Char16String *)p_cs; + + return cs->get_data(); +} + +void GDAPI godot_char16_string_destroy(godot_char16_string *p_cs) { + Char16String *cs = (Char16String *)p_cs; + + cs->~Char16String(); +} + void GDAPI godot_string_new(godot_string *r_dest) { String *dest = (String *)r_dest; memnew_placement(dest, String); @@ -70,27 +89,97 @@ void GDAPI godot_string_new(godot_string *r_dest) { void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src) { String *dest = (String *)r_dest; const String *src = (const String *)p_src; - memnew_placement(dest, String(*src)); + memnew_placement(dest, String); + *dest = String(*src); +} + +void GDAPI godot_string_new_with_latin1_chars(godot_string *r_dest, const char *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String(p_contents); +} + +void GDAPI godot_string_new_with_utf8_chars(godot_string *r_dest, const char *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf8(p_contents); +} + +void GDAPI godot_string_new_with_utf16_chars(godot_string *r_dest, const char16_t *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf16(p_contents); +} + +void GDAPI godot_string_new_with_utf32_chars(godot_string *r_dest, const char32_t *p_contents) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents); +} + +void GDAPI godot_string_new_with_wide_chars(godot_string *r_dest, const wchar_t *p_contents) { + String *dest = (String *)r_dest; + if (sizeof(wchar_t) == 2) { + // wchar_t is 16 bit, parse. + memnew_placement(dest, String); + dest->parse_utf16((const char16_t *)p_contents); + } else { + // wchar_t is 32 bit, copy. + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents); + } +} + +void GDAPI godot_string_new_with_latin1_chars_and_len(godot_string *r_dest, const char *p_contents, const int p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String(p_contents, p_size); +} + +void GDAPI godot_string_new_with_utf8_chars_and_len(godot_string *r_dest, const char *p_contents, const int p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf8(p_contents, p_size); +} + +void GDAPI godot_string_new_with_utf16_chars_and_len(godot_string *r_dest, const char16_t *p_contents, const int p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + dest->parse_utf16(p_contents, p_size); +} + +void GDAPI godot_string_new_with_utf32_chars_and_len(godot_string *r_dest, const char32_t *p_contents, const int p_size) { + String *dest = (String *)r_dest; + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents, p_size); } -void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size) { +void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const wchar_t *p_contents, const int p_size) { String *dest = (String *)r_dest; - memnew_placement(dest, String(p_contents, p_size)); + if (sizeof(wchar_t) == 2) { + // wchar_t is 16 bit, parse. + memnew_placement(dest, String); + dest->parse_utf16((const char16_t *)p_contents, p_size); + } else { + // wchar_t is 32 bit, copy. + memnew_placement(dest, String); + *dest = String((const char32_t *)p_contents, p_size); + } } -const wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx) { +const godot_char_type GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx) { String *self = (String *)p_self; return &(self->operator[](p_idx)); } -wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx) { +godot_char_type GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx) { const String *self = (const String *)p_self; return self->operator[](p_idx); } -const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self) { +const godot_char_type GDAPI *godot_string_get_data(const godot_string *p_self) { const String *self = (const String *)p_self; - return self->c_str(); + return self->get_data(); } godot_bool GDAPI godot_string_operator_equal(const godot_string *p_self, const godot_string *p_b) { @@ -162,22 +251,14 @@ godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self, return self->begins_with(p_char_array); } -godot_array GDAPI godot_string_bigrams(const godot_string *p_self) { +godot_packed_string_array GDAPI godot_string_bigrams(const godot_string *p_self) { const String *self = (const String *)p_self; - Vector<String> return_value = self->bigrams(); - - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - - return result; + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->bigrams())); + return ret; }; -godot_string GDAPI godot_string_chr(wchar_t p_character) { +godot_string GDAPI godot_string_chr(godot_char_type p_character) { godot_string result; memnew_placement(&result, String(String::chr(p_character))); @@ -191,88 +272,73 @@ godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_ return self->ends_with(*string); } -godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to) { +godot_bool GDAPI godot_string_ends_with_char_array(const godot_string *p_self, const char *p_char_array) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + + return self->ends_with(p_char_array); +} + +godot_int GDAPI godot_string_count(const godot_string *p_self, const godot_string *p_what, godot_int p_from, godot_int p_to) { + const String *self = (const String *)p_self; + const String *what = (const String *)p_what; return self->count(*what, p_from, p_to); } -godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to) { +godot_int GDAPI godot_string_countn(const godot_string *p_self, const godot_string *p_what, godot_int p_from, godot_int p_to) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->countn(*what, p_from, p_to); } -godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what) { +godot_int GDAPI godot_string_find(const godot_string *p_self, const godot_string *p_what) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->find(*what); } -godot_int GDAPI godot_string_find_from(const godot_string *p_self, godot_string p_what, godot_int p_from) { +godot_int GDAPI godot_string_find_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->find(*what, p_from); } -godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_array *p_keys) { +godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_packed_string_array *p_keys) { const String *self = (const String *)p_self; - - Vector<String> keys; - Array *keys_proxy = (Array *)p_keys; - keys.resize(keys_proxy->size()); - for (int i = 0; i < keys_proxy->size(); i++) { - keys.write[i] = (*keys_proxy)[i]; - } - - return self->findmk(keys); + const Vector<String> *keys = (const Vector<String> *)p_keys; + return self->findmk(*keys); } -godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot_array *p_keys, godot_int p_from) { +godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot_packed_string_array *p_keys, godot_int p_from) { const String *self = (const String *)p_self; - - Vector<String> keys; - Array *keys_proxy = (Array *)p_keys; - keys.resize(keys_proxy->size()); - for (int i = 0; i < keys_proxy->size(); i++) { - keys.write[i] = (*keys_proxy)[i]; - } - - return self->findmk(keys, p_from); + const Vector<String> *keys = (const Vector<String> *)p_keys; + return self->findmk(*keys, p_from); } -godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key) { +godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_packed_string_array *p_keys, godot_int p_from, godot_int *r_key) { const String *self = (const String *)p_self; - - Vector<String> keys; - Array *keys_proxy = (Array *)p_keys; - keys.resize(keys_proxy->size()); - for (int i = 0; i < keys_proxy->size(); i++) { - keys.write[i] = (*keys_proxy)[i]; - } - + const Vector<String> *keys = (const Vector<String> *)p_keys; int key; - int ret = self->findmk(keys, p_from, &key); + int ret = self->findmk(*keys, p_from, &key); if (r_key) { *r_key = key; } return ret; } -godot_int GDAPI godot_string_findn(const godot_string *p_self, godot_string p_what) { +godot_int GDAPI godot_string_findn(const godot_string *p_self, const godot_string *p_what) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->findn(*what); } -godot_int GDAPI godot_string_findn_from(const godot_string *p_self, godot_string p_what, godot_int p_from) { +godot_int GDAPI godot_string_findn_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->findn(*what, p_from); } @@ -303,21 +369,9 @@ godot_string GDAPI godot_string_hex_encode_buffer(const uint8_t *p_buffer, godot return result; } -godot_int GDAPI godot_string_hex_to_int(const godot_string *p_self) { - const String *self = (const String *)p_self; - - return self->hex_to_int(); -} - -godot_int GDAPI godot_string_hex_to_int_without_prefix(const godot_string *p_self) { - const String *self = (const String *)p_self; - - return self->hex_to_int(true); -} - -godot_string GDAPI godot_string_insert(const godot_string *p_self, godot_int p_at_pos, godot_string p_string) { +godot_string GDAPI godot_string_insert(const godot_string *p_self, godot_int p_at_pos, const godot_string *p_string) { const String *self = (const String *)p_self; - String *content = (String *)&p_string; + const String *content = (const String *)p_string; godot_string result; memnew_placement(&result, String(self->insert(p_at_pos, *content))); @@ -440,58 +494,58 @@ godot_string GDAPI godot_string_pad_zeros(const godot_string *p_self, godot_int return result; } -godot_string GDAPI godot_string_replace(const godot_string *p_self, godot_string p_key, godot_string p_with) { +godot_string GDAPI godot_string_replace(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with) { const String *self = (const String *)p_self; - String *key = (String *)&p_key; - String *with = (String *)&p_with; + const String *key = (const String *)p_key; + const String *with = (const String *)p_with; godot_string result; memnew_placement(&result, String(self->replace(*key, *with))); return result; } -godot_string GDAPI godot_string_replacen(const godot_string *p_self, godot_string p_key, godot_string p_with) { +godot_string GDAPI godot_string_replacen(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with) { const String *self = (const String *)p_self; - String *key = (String *)&p_key; - String *with = (String *)&p_with; + const String *key = (const String *)p_key; + const String *with = (const String *)p_with; godot_string result; memnew_placement(&result, String(self->replacen(*key, *with))); return result; } -godot_int GDAPI godot_string_rfind(const godot_string *p_self, godot_string p_what) { +godot_int GDAPI godot_string_rfind(const godot_string *p_self, const godot_string *p_what) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->rfind(*what); } -godot_int GDAPI godot_string_rfindn(const godot_string *p_self, godot_string p_what) { +godot_int GDAPI godot_string_rfindn(const godot_string *p_self, const godot_string *p_what) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->rfindn(*what); } -godot_int GDAPI godot_string_rfind_from(const godot_string *p_self, godot_string p_what, godot_int p_from) { +godot_int GDAPI godot_string_rfind_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->rfind(*what, p_from); } -godot_int GDAPI godot_string_rfindn_from(const godot_string *p_self, godot_string p_what, godot_int p_from) { +godot_int GDAPI godot_string_rfindn_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from) { const String *self = (const String *)p_self; - String *what = (String *)&p_what; + const String *what = (const String *)p_what; return self->rfindn(*what, p_from); } -godot_string GDAPI godot_string_replace_first(const godot_string *p_self, godot_string p_key, godot_string p_with) { +godot_string GDAPI godot_string_replace_first(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with) { const String *self = (const String *)p_self; - String *key = (String *)&p_key; - String *with = (String *)&p_with; + const String *key = (const String *)p_key; + const String *with = (const String *)p_with; godot_string result; memnew_placement(&result, String(self->replace_first(*key, *with))); @@ -541,16 +595,16 @@ godot_string GDAPI godot_string_substr(const godot_string *p_self, godot_int p_f return result; } -double GDAPI godot_string_to_float(const godot_string *p_self) { +godot_int GDAPI godot_string_to_int(const godot_string *p_self) { const String *self = (const String *)p_self; - return self->to_float(); + return self->to_int(); } -godot_int GDAPI godot_string_to_int(const godot_string *p_self) { +double GDAPI godot_string_to_float(const godot_string *p_self) { const String *self = (const String *)p_self; - return self->to_int(); + return self->to_float(); } godot_string GDAPI godot_string_capitalize(const godot_string *p_self) { @@ -581,11 +635,15 @@ double GDAPI godot_string_char_to_float(const char *p_what) { return String::to_float(p_what); } +double GDAPI godot_string_wchar_to_float(const wchar_t *p_str, const wchar_t **r_end) { + return String::to_float(p_str, r_end); +} + godot_int GDAPI godot_string_char_to_int(const char *p_what) { return String::to_int(p_what); } -int64_t GDAPI godot_string_wchar_to_int(const wchar_t *p_str) { +godot_int GDAPI godot_string_wchar_to_int(const wchar_t *p_str) { return String::to_int(p_str); } @@ -593,42 +651,32 @@ godot_int GDAPI godot_string_char_to_int_with_len(const char *p_what, godot_int return String::to_int(p_what, p_len); } -int64_t GDAPI godot_string_char_to_int64_with_len(const wchar_t *p_str, int p_len) { +godot_int GDAPI godot_string_wchar_to_int_with_len(const wchar_t *p_str, int p_len) { return String::to_int(p_str, p_len); } -int64_t GDAPI godot_string_hex_to_int64(const godot_string *p_self) { +godot_int GDAPI godot_string_hex_to_int(const godot_string *p_self) { const String *self = (const String *)p_self; return self->hex_to_int(false); } -int64_t GDAPI godot_string_hex_to_int64_with_prefix(const godot_string *p_self) { +godot_int GDAPI godot_string_hex_to_int_with_prefix(const godot_string *p_self) { const String *self = (const String *)p_self; return self->hex_to_int(); } -int64_t GDAPI godot_string_to_int64(const godot_string *p_self) { +godot_string GDAPI godot_string_get_slice(const godot_string *p_self, const godot_string *p_splitter, godot_int p_slice) { const String *self = (const String *)p_self; - - return self->to_int(); -} - -double GDAPI godot_string_unicode_char_to_float(const wchar_t *p_str, const wchar_t **r_end) { - return String::to_float(p_str, r_end); -} - -godot_string GDAPI godot_string_get_slice(const godot_string *p_self, godot_string p_splitter, godot_int p_slice) { - const String *self = (const String *)p_self; - String *splitter = (String *)&p_splitter; + const String *splitter = (const String *)p_splitter; godot_string result; memnew_placement(&result, String(self->get_slice(*splitter, p_slice))); return result; } -godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p_splitter, godot_int p_slice) { +godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, godot_char_type p_splitter, godot_int p_slice) { const String *self = (const String *)p_self; godot_string result; memnew_placement(&result, String(self->get_slicec(p_splitter, p_slice))); @@ -636,221 +684,149 @@ godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p return result; } -godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter) { +godot_packed_string_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; const String *splitter = (const String *)p_splitter; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<String> return_value = self->split(*splitter, false); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - - return result; + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->split(*splitter, false))); + return ret; } -godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter) { +godot_packed_string_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; const String *splitter = (const String *)p_splitter; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<String> return_value = self->split(*splitter); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->split(*splitter, true))); + return ret; +} - return result; +godot_packed_string_array GDAPI godot_string_split_with_maxsplit(const godot_string *p_self, const godot_string *p_splitter, const godot_bool p_allow_empty, const godot_int p_maxsplit) { + const String *self = (const String *)p_self; + const String *splitter = (const String *)p_splitter; + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->split(*splitter, p_allow_empty, p_maxsplit))); + return ret; } -godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter) { +godot_packed_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; const String *splitter = (const String *)p_splitter; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<float> return_value = self->split_floats(*splitter, false); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - return result; + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->rsplit(*splitter, false))); + return ret; } -godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_self, const godot_string *p_splitter) { +godot_packed_string_array GDAPI godot_string_rsplit_allow_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; const String *splitter = (const String *)p_splitter; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<float> return_value = self->split_floats(*splitter); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - return result; + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->rsplit(*splitter, true))); + return ret; } -godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_array *p_splitters) { +godot_packed_string_array GDAPI godot_string_rsplit_with_maxsplit(const godot_string *p_self, const godot_string *p_splitter, const godot_bool p_allow_empty, const godot_int p_maxsplit) { const String *self = (const String *)p_self; + const String *splitter = (const String *)p_splitter; - Vector<String> splitters; - Array *splitter_proxy = (Array *)p_splitters; - splitters.resize(splitter_proxy->size()); - for (int i = 0; i < splitter_proxy->size(); i++) { - splitters.write[i] = (*splitter_proxy)[i]; - } - - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<float> return_value = self->split_floats_mk(splitters, false); + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->rsplit(*splitter, p_allow_empty, p_maxsplit))); + return ret; +} - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } +godot_packed_float32_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter) { + const String *self = (const String *)p_self; + const String *splitter = (const String *)p_splitter; - return result; + godot_packed_float32_array ret; + memnew_placement(&ret, Vector<float>(self->split_floats(*splitter, false))); + return ret; } -godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters) { +godot_packed_float32_array GDAPI godot_string_split_floats_allow_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; + const String *splitter = (const String *)p_splitter; - Vector<String> splitters; - Array *splitter_proxy = (Array *)p_splitters; - splitters.resize(splitter_proxy->size()); - for (int i = 0; i < splitter_proxy->size(); i++) { - splitters.write[i] = (*splitter_proxy)[i]; - } - - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<float> return_value = self->split_floats_mk(splitters); + godot_packed_float32_array ret; + memnew_placement(&ret, Vector<float>(self->split_floats(*splitter, true))); + return ret; +} - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } +godot_packed_float32_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_packed_string_array *p_splitters) { + const String *self = (const String *)p_self; + const Vector<String> *splitters = (const Vector<String> *)p_splitters; - return result; + godot_packed_float32_array ret; + memnew_placement(&ret, Vector<float>(self->split_floats_mk(*splitters, false))); + return ret; } -godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter) { +godot_packed_float32_array GDAPI godot_string_split_floats_mk_allow_empty(const godot_string *p_self, const godot_packed_string_array *p_splitters) { const String *self = (const String *)p_self; - const String *splitter = (const String *)p_splitter; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<int> return_value = self->split_ints(*splitter, false); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } + const Vector<String> *splitters = (const Vector<String> *)p_splitters; - return result; + godot_packed_float32_array ret; + memnew_placement(&ret, Vector<float>(self->split_floats_mk(*splitters, true))); + return ret; } -godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_self, const godot_string *p_splitter) { +godot_packed_int32_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; const String *splitter = (const String *)p_splitter; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<int> return_value = self->split_ints(*splitter); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - return result; + godot_packed_int32_array ret; + memnew_placement(&ret, Vector<int>(self->split_ints(*splitter, false))); + return ret; } -godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_array *p_splitters) { +godot_packed_int32_array GDAPI godot_string_split_ints_allow_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; + const String *splitter = (const String *)p_splitter; - Vector<String> splitters; - Array *splitter_proxy = (Array *)p_splitters; - splitters.resize(splitter_proxy->size()); - for (int i = 0; i < splitter_proxy->size(); i++) { - splitters.write[i] = (*splitter_proxy)[i]; - } - - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<int> return_value = self->split_ints_mk(splitters, false); - - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - - return result; + godot_packed_int32_array ret; + memnew_placement(&ret, Vector<int>(self->split_ints(*splitter, true))); + return ret; } -godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters) { +godot_packed_int32_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_packed_string_array *p_splitters) { const String *self = (const String *)p_self; + const Vector<String> *splitters = (const Vector<String> *)p_splitters; - Vector<String> splitters; - Array *splitter_proxy = (Array *)p_splitters; - splitters.resize(splitter_proxy->size()); - for (int i = 0; i < splitter_proxy->size(); i++) { - splitters.write[i] = (*splitter_proxy)[i]; - } - - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<int> return_value = self->split_ints_mk(splitters); + godot_packed_int32_array ret; + memnew_placement(&ret, Vector<int>(self->split_ints_mk(*splitters, false))); + return ret; +} - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } +godot_packed_int32_array GDAPI godot_string_split_ints_mk_allow_empty(const godot_string *p_self, const godot_packed_string_array *p_splitters) { + const String *self = (const String *)p_self; + const Vector<String> *splitters = (const Vector<String> *)p_splitters; - return result; + godot_packed_int32_array ret; + memnew_placement(&ret, Vector<int>(self->split_ints_mk(*splitters, true))); + return ret; } -godot_array GDAPI godot_string_split_spaces(const godot_string *p_self) { +godot_packed_string_array GDAPI godot_string_split_spaces(const godot_string *p_self) { const String *self = (const String *)p_self; - godot_array result; - memnew_placement(&result, Array); - Array *proxy = (Array *)&result; - Vector<String> return_value = self->split_spaces(); - proxy->resize(return_value.size()); - for (int i = 0; i < return_value.size(); i++) { - (*proxy)[i] = return_value[i]; - } - - return result; + godot_packed_string_array ret; + memnew_placement(&ret, Vector<String>(self->split_spaces())); + return ret; } -godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, godot_string p_splitter) { +godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; - String *splitter = (String *)&p_splitter; + const String *splitter = (const String *)p_splitter; return self->get_slice_count(*splitter); } -wchar_t GDAPI godot_string_char_lowercase(wchar_t p_char) { +godot_char_type GDAPI godot_string_char_lowercase(godot_char_type p_char) { return String::char_lowercase(p_char); } -wchar_t GDAPI godot_string_char_uppercase(wchar_t p_char) { +godot_char_type GDAPI godot_string_char_uppercase(godot_char_type p_char) { return String::char_uppercase(p_char); } @@ -894,7 +870,7 @@ godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos return result; } -wchar_t GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx) { +godot_char_type GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx) { const String *self = (const String *)p_self; return self->ord_at(p_idx); @@ -917,6 +893,14 @@ godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_po return result; } +godot_string GDAPI godot_string_repeat(const godot_string *p_self, godot_int p_count) { + const String *self = (const String *)p_self; + godot_string result; + memnew_placement(&result, String(self->repeat(p_count))); + + return result; +} + godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bool p_left, godot_bool p_right) { const String *self = (const String *)p_self; godot_string result; @@ -948,7 +932,7 @@ godot_char_string GDAPI godot_string_ascii(const godot_string *p_self) { return result; } -godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self) { +godot_char_string GDAPI godot_string_latin1(const godot_string *p_self) { const String *self = (const String *)p_self; godot_char_string result; @@ -994,6 +978,42 @@ godot_string GDAPI godot_string_chars_to_utf8_with_len(const char *p_utf8, godot return result; } +godot_char16_string GDAPI godot_string_utf16(const godot_string *p_self) { + const String *self = (const String *)p_self; + + godot_char16_string result; + + memnew_placement(&result, Char16String(self->utf16())); + + return result; +} + +godot_bool GDAPI godot_string_parse_utf16(godot_string *p_self, const char16_t *p_utf16) { + String *self = (String *)p_self; + + return self->parse_utf16(p_utf16); +} + +godot_bool GDAPI godot_string_parse_utf16_with_len(godot_string *p_self, const char16_t *p_utf16, godot_int p_len) { + String *self = (String *)p_self; + + return self->parse_utf16(p_utf16, p_len); +} + +godot_string GDAPI godot_string_chars_to_utf16(const char16_t *p_utf16) { + godot_string result; + memnew_placement(&result, String(String::utf16(p_utf16))); + + return result; +} + +godot_string GDAPI godot_string_chars_to_utf16_with_len(const char16_t *p_utf16, godot_int p_len) { + godot_string result; + memnew_placement(&result, String(String::utf16(p_utf16, p_len))); + + return result; +} + uint32_t GDAPI godot_string_hash(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1014,28 +1034,18 @@ uint32_t GDAPI godot_string_hash_chars_with_len(const char *p_cstr, godot_int p_ return String::hash(p_cstr, p_len); } -uint32_t GDAPI godot_string_hash_utf8_chars(const wchar_t *p_str) { +uint32_t GDAPI godot_string_hash_wide_chars(const wchar_t *p_str) { return String::hash(p_str); } -uint32_t GDAPI godot_string_hash_utf8_chars_with_len(const wchar_t *p_str, godot_int p_len) { +uint32_t GDAPI godot_string_hash_wide_chars_with_len(const wchar_t *p_str, godot_int p_len) { return String::hash(p_str, p_len); } godot_packed_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self) { const String *self = (const String *)p_self; - Vector<uint8_t> tmp_result = self->md5_buffer(); - godot_packed_byte_array result; - memnew_placement(&result, PackedByteArray); - PackedByteArray *proxy = (PackedByteArray *)&result; - uint8_t *proxy_writer = proxy->ptrw(); - proxy->resize(tmp_result.size()); - - for (int i = 0; i < tmp_result.size(); i++) { - proxy_writer[i] = tmp_result[i]; - } - + memnew_placement(&result, PackedByteArray(self->md5_buffer())); return result; } @@ -1047,23 +1057,28 @@ godot_string GDAPI godot_string_md5_text(const godot_string *p_self) { return result; } -godot_packed_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_self) { +godot_packed_byte_array GDAPI godot_string_sha1_buffer(const godot_string *p_self) { const String *self = (const String *)p_self; - Vector<uint8_t> tmp_result = self->sha256_buffer(); - godot_packed_byte_array result; - memnew_placement(&result, PackedByteArray); - PackedByteArray *proxy = (PackedByteArray *)&result; - uint8_t *proxy_writer = proxy->ptrw(); - proxy->resize(tmp_result.size()); + memnew_placement(&result, PackedByteArray(self->sha1_buffer())); + return result; +} - for (int i = 0; i < tmp_result.size(); i++) { - proxy_writer[i] = tmp_result[i]; - } +godot_string GDAPI godot_string_sha1_text(const godot_string *p_self) { + const String *self = (const String *)p_self; + godot_string result; + memnew_placement(&result, String(self->sha1_text())); return result; } +godot_packed_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_self) { + const String *self = (const String *)p_self; + godot_packed_byte_array result; + memnew_placement(&result, PackedByteArray(self->sha256_buffer())); + return result; +} + godot_string GDAPI godot_string_sha256_text(const godot_string *p_self) { const String *self = (const String *)p_self; godot_string result; @@ -1206,15 +1221,6 @@ godot_string GDAPI godot_string_json_escape(const godot_string *p_self) { return result; } -godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line) { - const String *self = (const String *)p_self; - godot_string result; - String return_value = self->word_wrap(p_chars_per_line); - memnew_placement(&result, String(return_value)); - - return result; -} - godot_string GDAPI godot_string_xml_escape(const godot_string *p_self) { const String *self = (const String *)p_self; godot_string result; @@ -1260,6 +1266,22 @@ godot_string GDAPI godot_string_percent_encode(const godot_string *p_self) { return result; } +godot_string GDAPI godot_string_join(const godot_string *p_self, const godot_packed_string_array *p_parts) { + const String *self = (const String *)p_self; + const Vector<String> *parts = (const Vector<String> *)p_parts; + godot_string result; + String return_value = self->join(*parts); + memnew_placement(&result, String(return_value)); + + return result; +} + +godot_bool GDAPI godot_string_is_valid_filename(const godot_string *p_self) { + const String *self = (const String *)p_self; + + return self->is_valid_filename(); +} + godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1325,31 +1347,22 @@ godot_string GDAPI godot_string_trim_suffix(const godot_string *p_self, const go return result; } -godot_string GDAPI godot_string_rstrip(const godot_string *p_self, const godot_string *p_chars) { +godot_string GDAPI godot_string_lstrip(const godot_string *p_self, const godot_string *p_chars) { const String *self = (const String *)p_self; String *chars = (String *)p_chars; godot_string result; - String return_value = self->rstrip(*chars); + String return_value = self->lstrip(*chars); memnew_placement(&result, String(return_value)); return result; } -godot_packed_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_divisor, - const godot_bool p_allow_empty, const godot_int p_maxsplit) { +godot_string GDAPI godot_string_rstrip(const godot_string *p_self, const godot_string *p_chars) { const String *self = (const String *)p_self; - String *divisor = (String *)p_divisor; - - godot_packed_string_array result; - memnew_placement(&result, PackedStringArray); - PackedStringArray *proxy = (PackedStringArray *)&result; - String *proxy_writer = proxy->ptrw(); - Vector<String> tmp_result = self->rsplit(*divisor, p_allow_empty, p_maxsplit); - proxy->resize(tmp_result.size()); - - for (int i = 0; i < tmp_result.size(); i++) { - proxy_writer[i] = tmp_result[i]; - } + String *chars = (String *)p_chars; + godot_string result; + String return_value = self->rstrip(*chars); + memnew_placement(&result, String(return_value)); return result; } diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 8ccf44ff1a..82bfbd23de 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -3732,6 +3732,27 @@ ] }, { + "name": "godot_char16_string_length", + "return_type": "godot_int", + "arguments": [ + ["const godot_char16_string *", "p_cs"] + ] + }, + { + "name": "godot_char16_string_get_data", + "return_type": "const char16_t *", + "arguments": [ + ["const godot_char16_string *", "p_cs"] + ] + }, + { + "name": "godot_char16_string_destroy", + "return_type": "void", + "arguments": [ + ["godot_char16_string *", "p_cs"] + ] + }, + { "name": "godot_string_new", "return_type": "void", "arguments": [ @@ -3747,7 +3768,83 @@ ] }, { - "name": "godot_string_new_with_wide_string", + "name": "godot_string_new_with_latin1_chars", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char *", "p_contents"] + ] + }, + { + "name": "godot_string_new_with_utf8_chars", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char *", "p_contents"] + ] + }, + { + "name": "godot_string_new_with_utf16_chars", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char16_t *", "p_contents"] + ] + }, + { + "name": "godot_string_new_with_utf32_chars", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char32_t *", "p_contents"] + ] + }, + { + "name": "godot_string_new_with_wide_chars", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const wchar_t *", "p_contents"] + ] + }, + { + "name": "godot_string_new_with_latin1_chars_and_len", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char *", "p_contents"], + ["const int", "p_size"] + ] + }, + { + "name": "godot_string_new_with_utf8_chars_and_len", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char *", "p_contents"], + ["const int", "p_size"] + ] + }, + { + "name": "godot_string_new_with_utf16_chars_and_len", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char16_t *", "p_contents"], + ["const int", "p_size"] + ] + }, + { + "name": "godot_string_new_with_utf32_chars_and_len", + "return_type": "void", + "arguments": [ + ["godot_string *", "r_dest"], + ["const char32_t *", "p_contents"], + ["const int", "p_size"] + ] + }, + { + "name": "godot_string_new_with_wide_chars_and_len", "return_type": "void", "arguments": [ ["godot_string *", "r_dest"], @@ -3757,7 +3854,7 @@ }, { "name": "godot_string_operator_index", - "return_type": "const wchar_t *", + "return_type": "const godot_char_type *", "arguments": [ ["godot_string *", "p_self"], ["const godot_int", "p_idx"] @@ -3765,15 +3862,15 @@ }, { "name": "godot_string_operator_index_const", - "return_type": "wchar_t", + "return_type": "godot_char_type", "arguments": [ ["const godot_string *", "p_self"], ["const godot_int", "p_idx"] ] }, { - "name": "godot_string_wide_str", - "return_type": "const wchar_t *", + "name": "godot_string_get_data", + "return_type": "const godot_char_type *", "arguments": [ ["const godot_string *", "p_self"] ] @@ -3807,7 +3904,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"], + ["const godot_string *", "p_what"], ["godot_int", "p_from"], ["godot_int", "p_to"] ] @@ -3817,7 +3914,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"], + ["const godot_string *", "p_what"], ["godot_int", "p_from"], ["godot_int", "p_to"] ] @@ -3878,7 +3975,7 @@ }, { "name": "godot_string_bigrams", - "return_type": "godot_array", + "return_type": "godot_packed_string_array", "arguments": [ ["const godot_string *", "p_self"] ] @@ -3887,7 +3984,7 @@ "name": "godot_string_chr", "return_type": "godot_string", "arguments": [ - ["wchar_t", "p_character"] + ["godot_char_type", "p_character"] ] }, { @@ -3899,11 +3996,19 @@ ] }, { + "name": "godot_string_ends_with_char_array", + "return_type": "godot_bool", + "arguments": [ + ["const godot_string *", "p_self"], + ["const char *", "p_char_array"] + ] + }, + { "name": "godot_string_find", "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"] + ["const godot_string *", "p_what"] ] }, { @@ -3911,7 +4016,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"], + ["const godot_string *", "p_what"], ["godot_int", "p_from"] ] }, @@ -3920,7 +4025,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_keys"] + ["const godot_packed_string_array *", "p_keys"] ] }, { @@ -3928,7 +4033,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_keys"], + ["const godot_packed_string_array *", "p_keys"], ["godot_int", "p_from"] ] }, @@ -3937,7 +4042,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_keys"], + ["const godot_packed_string_array *", "p_keys"], ["godot_int", "p_from"], ["godot_int *", "r_key"] ] @@ -3947,7 +4052,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"] + ["const godot_string *", "p_what"] ] }, { @@ -3955,7 +4060,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"], + ["const godot_string *", "p_what"], ["godot_int", "p_from"] ] }, @@ -3985,26 +4090,12 @@ ] }, { - "name": "godot_string_hex_to_int", - "return_type": "godot_int", - "arguments": [ - ["const godot_string *", "p_self"] - ] - }, - { - "name": "godot_string_hex_to_int_without_prefix", - "return_type": "godot_int", - "arguments": [ - ["const godot_string *", "p_self"] - ] - }, - { "name": "godot_string_insert", "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], ["godot_int", "p_at_pos"], - ["godot_string", "p_string"] + ["const godot_string *", "p_string"] ] }, { @@ -4137,8 +4228,8 @@ "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_key"], - ["godot_string", "p_with"] + ["const godot_string *", "p_key"], + ["const godot_string *", "p_with"] ] }, { @@ -4146,8 +4237,8 @@ "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_key"], - ["godot_string", "p_with"] + ["const godot_string *", "p_key"], + ["const godot_string *", "p_with"] ] }, { @@ -4155,8 +4246,8 @@ "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_key"], - ["godot_string", "p_with"] + ["const godot_string *", "p_key"], + ["const godot_string *", "p_with"] ] }, { @@ -4164,7 +4255,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"] + ["const godot_string *", "p_what"] ] }, { @@ -4172,7 +4263,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"] + ["const godot_string *", "p_what"] ] }, { @@ -4180,7 +4271,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"], + ["const godot_string *", "p_what"], ["godot_int", "p_from"] ] }, @@ -4189,7 +4280,7 @@ "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_what"], + ["const godot_string *", "p_what"], ["godot_int", "p_from"] ] }, @@ -4237,15 +4328,15 @@ ] }, { - "name": "godot_string_to_float", - "return_type": "double", + "name": "godot_string_to_int", + "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"] ] }, { - "name": "godot_string_to_int", - "return_type": "godot_int", + "name": "godot_string_to_float", + "return_type": "double", "arguments": [ ["const godot_string *", "p_self"] ] @@ -4279,6 +4370,14 @@ ] }, { + "name": "godot_string_wchar_to_float", + "return_type": "double", + "arguments": [ + ["const wchar_t *", "p_str"], + ["const wchar_t **", "r_end"] + ] + }, + { "name": "godot_string_char_to_int", "return_type": "godot_int", "arguments": [ @@ -4287,7 +4386,7 @@ }, { "name": "godot_string_wchar_to_int", - "return_type": "int64_t", + "return_type": "godot_int", "arguments": [ ["const wchar_t *", "p_str"] ] @@ -4301,48 +4400,33 @@ ] }, { - "name": "godot_string_char_to_int64_with_len", - "return_type": "int64_t", + "name": "godot_string_wchar_to_int_with_len", + "return_type": "godot_int", "arguments": [ ["const wchar_t *", "p_str"], ["int", "p_len"] ] }, { - "name": "godot_string_hex_to_int64", - "return_type": "int64_t", - "arguments": [ - ["const godot_string *", "p_self"] - ] - }, - { - "name": "godot_string_hex_to_int64_with_prefix", - "return_type": "int64_t", + "name": "godot_string_hex_to_int", + "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"] ] }, { - "name": "godot_string_to_int64", - "return_type": "int64_t", + "name": "godot_string_hex_to_int_with_prefix", + "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"] ] }, { - "name": "godot_string_unicode_char_to_float", - "return_type": "double", - "arguments": [ - ["const wchar_t *", "p_str"], - ["const wchar_t **", "r_end"] - ] - }, - { "name": "godot_string_get_slice_count", "return_type": "godot_int", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_splitter"] + ["const godot_string *", "p_splitter"] ] }, { @@ -4350,7 +4434,7 @@ "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], - ["godot_string", "p_splitter"], + ["const godot_string *", "p_splitter"], ["godot_int", "p_slice"] ] }, @@ -4359,13 +4443,13 @@ "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], - ["wchar_t", "p_splitter"], + ["godot_char_type", "p_splitter"], ["godot_int", "p_slice"] ] }, { "name": "godot_string_split", - "return_type": "godot_array", + "return_type": "godot_packed_string_array", "arguments": [ ["const godot_string *", "p_self"], ["const godot_string *", "p_splitter"] @@ -4373,23 +4457,59 @@ }, { "name": "godot_string_split_allow_empty", - "return_type": "godot_array", + "return_type": "godot_packed_string_array", "arguments": [ ["const godot_string *", "p_self"], ["const godot_string *", "p_splitter"] ] }, { + "name": "godot_string_split_with_maxsplit", + "return_type": "godot_packed_string_array", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_splitter"], + ["const godot_bool", "p_allow_empty"], + ["const godot_int", "p_maxsplit"] + ] + }, + { + "name": "godot_string_rsplit", + "return_type": "godot_packed_string_array", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_splitter"] + ] + }, + { + "name": "godot_string_rsplit_allow_empty", + "return_type": "godot_packed_string_array", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_splitter"] + ] + }, + { + "name": "godot_string_rsplit_with_maxsplit", + "return_type": "godot_packed_string_array", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_splitter"], + ["const godot_bool", "p_allow_empty"], + ["const godot_int", "p_maxsplit"] + ] + }, + { "name": "godot_string_split_floats", - "return_type": "godot_array", + "return_type": "godot_packed_float32_array", "arguments": [ ["const godot_string *", "p_self"], ["const godot_string *", "p_splitter"] ] }, { - "name": "godot_string_split_floats_allows_empty", - "return_type": "godot_array", + "name": "godot_string_split_floats_allow_empty", + "return_type": "godot_packed_float32_array", "arguments": [ ["const godot_string *", "p_self"], ["const godot_string *", "p_splitter"] @@ -4397,31 +4517,31 @@ }, { "name": "godot_string_split_floats_mk", - "return_type": "godot_array", + "return_type": "godot_packed_float32_array", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_splitters"] + ["const godot_packed_string_array *", "p_splitters"] ] }, { - "name": "godot_string_split_floats_mk_allows_empty", - "return_type": "godot_array", + "name": "godot_string_split_floats_mk_allow_empty", + "return_type": "godot_packed_float32_array", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_splitters"] + ["const godot_packed_string_array *", "p_splitters"] ] }, { "name": "godot_string_split_ints", - "return_type": "godot_array", + "return_type": "godot_packed_int32_array", "arguments": [ ["const godot_string *", "p_self"], ["const godot_string *", "p_splitter"] ] }, { - "name": "godot_string_split_ints_allows_empty", - "return_type": "godot_array", + "name": "godot_string_split_ints_allow_empty", + "return_type": "godot_packed_int32_array", "arguments": [ ["const godot_string *", "p_self"], ["const godot_string *", "p_splitter"] @@ -4429,29 +4549,29 @@ }, { "name": "godot_string_split_ints_mk", - "return_type": "godot_array", + "return_type": "godot_packed_int32_array", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_splitters"] + ["const godot_packed_string_array *", "p_splitters"] ] }, { - "name": "godot_string_split_ints_mk_allows_empty", - "return_type": "godot_array", + "name": "godot_string_split_ints_mk_allow_empty", + "return_type": "godot_packed_int32_array", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_array *", "p_splitters"] + ["const godot_packed_string_array *", "p_splitters"] ] }, { "name": "godot_string_split_spaces", - "return_type": "godot_array", + "return_type": "godot_packed_string_array", "arguments": [ ["const godot_string *", "p_self"] ] }, { - "name": "godot_string_rstrip", + "name": "godot_string_lstrip", "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], @@ -4459,13 +4579,11 @@ ] }, { - "name": "godot_string_rsplit", - "return_type": "godot_packed_string_array", + "name": "godot_string_rstrip", + "return_type": "godot_string", "arguments": [ ["const godot_string *", "p_self"], - ["const godot_string *", "p_divisor"], - ["const godot_bool", "p_allow_empty"], - ["const godot_int", "p_maxsplit"] + ["const godot_string *", "p_chars"] ] }, { @@ -4486,16 +4604,16 @@ }, { "name": "godot_string_char_lowercase", - "return_type": "wchar_t", + "return_type": "godot_char_type", "arguments": [ - ["wchar_t", "p_char"] + ["godot_char_type", "p_char"] ] }, { "name": "godot_string_char_uppercase", - "return_type": "wchar_t", + "return_type": "godot_char_type", "arguments": [ - ["wchar_t", "p_char"] + ["godot_char_type", "p_char"] ] }, { @@ -4536,7 +4654,7 @@ }, { "name": "godot_string_ord_at", - "return_type": "wchar_t", + "return_type": "godot_char_type", "arguments": [ ["const godot_string *", "p_self"], ["godot_int", "p_idx"] @@ -4559,6 +4677,14 @@ ] }, { + "name": "godot_string_repeat", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"], + ["godot_int", "p_count"] + ] + }, + { "name": "godot_string_strip_edges", "return_type": "godot_string", "arguments": [ @@ -4591,7 +4717,7 @@ ] }, { - "name": "godot_string_ascii_extended", + "name": "godot_string_latin1", "return_type": "godot_char_string", "arguments": [ ["const godot_string *", "p_self"] @@ -4622,17 +4748,26 @@ ] }, { - "name": "godot_string_chars_to_utf8", - "return_type": "godot_string", + "name": "godot_string_utf16", + "return_type": "godot_char16_string", "arguments": [ - ["const char *", "p_utf8"] + ["const godot_string *", "p_self"] ] }, { - "name": "godot_string_chars_to_utf8_with_len", - "return_type": "godot_string", + "name": "godot_string_parse_utf16", + "return_type": "godot_bool", "arguments": [ - ["const char *", "p_utf8"], + ["godot_string *", "p_self"], + ["const char16_t *", "p_utf16"] + ] + }, + { + "name": "godot_string_parse_utf16_with_len", + "return_type": "godot_bool", + "arguments": [ + ["godot_string *", "p_self"], + ["const char16_t *", "p_utf16"], ["godot_int", "p_len"] ] }, @@ -4666,14 +4801,14 @@ ] }, { - "name": "godot_string_hash_utf8_chars", + "name": "godot_string_hash_wide_chars", "return_type": "uint32_t", "arguments": [ ["const wchar_t *", "p_str"] ] }, { - "name": "godot_string_hash_utf8_chars_with_len", + "name": "godot_string_hash_wide_chars_with_len", "return_type": "uint32_t", "arguments": [ ["const wchar_t *", "p_str"], @@ -4695,6 +4830,20 @@ ] }, { + "name": "godot_string_sha1_buffer", + "return_type": "godot_packed_byte_array", + "arguments": [ + ["const godot_string *", "p_self"] + ] + }, + { + "name": "godot_string_sha1_text", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"] + ] + }, + { "name": "godot_string_sha256_buffer", "return_type": "godot_packed_byte_array", "arguments": [ @@ -4823,14 +4972,6 @@ ] }, { - "name": "godot_string_word_wrap", - "return_type": "godot_string", - "arguments": [ - ["const godot_string *", "p_self"], - ["godot_int", "p_chars_per_line"] - ] - }, - { "name": "godot_string_xml_escape", "return_type": "godot_string", "arguments": [ @@ -4866,6 +5007,21 @@ ] }, { + "name": "godot_string_join", + "return_type": "godot_string", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_packed_string_array *", "p_parts"] + ] + }, + { + "name": "godot_string_is_valid_filename", + "return_type": "godot_bool", + "arguments": [ + ["const godot_string *", "p_self"] + ] + }, + { "name": "godot_string_is_valid_float", "return_type": "godot_bool", "arguments": [ diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index d89383dc1b..0582d95f63 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -38,10 +38,11 @@ extern "C" { #include <stdint.h> #include <wchar.h> -typedef wchar_t godot_char_type; +typedef char32_t godot_char_type; #define GODOT_STRING_SIZE sizeof(void *) #define GODOT_CHAR_STRING_SIZE sizeof(void *) +#define GODOT_CHAR16_STRING_SIZE sizeof(void *) #ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED #define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED @@ -58,6 +59,13 @@ typedef struct { } godot_char_string; #endif +#ifndef GODOT_CORE_API_GODOT_CHAR16_STRING_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_CHAR16_STRING_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_CHAR16_STRING_SIZE]; +} godot_char16_string; +#endif + // reduce extern "C" nesting for VS2013 #ifdef __cplusplus } @@ -75,13 +83,28 @@ godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs); const char GDAPI *godot_char_string_get_data(const godot_char_string *p_cs); void GDAPI godot_char_string_destroy(godot_char_string *p_cs); +godot_int GDAPI godot_char16_string_length(const godot_char16_string *p_cs); +const char16_t GDAPI *godot_char16_string_get_data(const godot_char16_string *p_cs); +void GDAPI godot_char16_string_destroy(godot_char16_string *p_cs); + void GDAPI godot_string_new(godot_string *r_dest); void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src); -void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size); -const wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx); -wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx); -const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self); +void GDAPI godot_string_new_with_latin1_chars(godot_string *r_dest, const char *p_contents); +void GDAPI godot_string_new_with_utf8_chars(godot_string *r_dest, const char *p_contents); +void GDAPI godot_string_new_with_utf16_chars(godot_string *r_dest, const char16_t *p_contents); +void GDAPI godot_string_new_with_utf32_chars(godot_string *r_dest, const char32_t *p_contents); +void GDAPI godot_string_new_with_wide_chars(godot_string *r_dest, const wchar_t *p_contents); + +void GDAPI godot_string_new_with_latin1_chars_and_len(godot_string *r_dest, const char *p_contents, const int p_size); +void GDAPI godot_string_new_with_utf8_chars_and_len(godot_string *r_dest, const char *p_contents, const int p_size); +void GDAPI godot_string_new_with_utf16_chars_and_len(godot_string *r_dest, const char16_t *p_contents, const int p_size); +void GDAPI godot_string_new_with_utf32_chars_and_len(godot_string *r_dest, const char32_t *p_contents, const int p_size); +void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const wchar_t *p_contents, const int p_size); + +const godot_char_type GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx); +godot_char_type GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx); +const godot_char_type GDAPI *godot_string_get_data(const godot_string *p_self); godot_bool GDAPI godot_string_operator_equal(const godot_string *p_self, const godot_string *p_b); godot_bool GDAPI godot_string_operator_less(const godot_string *p_self, const godot_string *p_b); @@ -89,7 +112,7 @@ godot_string GDAPI godot_string_operator_plus(const godot_string *p_self, const /* Standard size stuff */ -godot_int GDAPI godot_string_length(const godot_string *p_self); +/*+++*/ godot_int GDAPI godot_string_length(const godot_string *p_self); /* Helpers */ @@ -99,24 +122,25 @@ signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, c godot_bool GDAPI godot_string_begins_with(const godot_string *p_self, const godot_string *p_string); godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self, const char *p_char_array); -godot_array GDAPI godot_string_bigrams(const godot_string *p_self); -godot_string GDAPI godot_string_chr(wchar_t p_character); +godot_packed_string_array GDAPI godot_string_bigrams(const godot_string *p_self); +godot_string GDAPI godot_string_chr(godot_char_type p_character); godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_string *p_string); -godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to); -godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to); -godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what); -godot_int GDAPI godot_string_find_from(const godot_string *p_self, godot_string p_what, godot_int p_from); -godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_array *p_keys); -godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot_array *p_keys, godot_int p_from); -godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key); -godot_int GDAPI godot_string_findn(const godot_string *p_self, godot_string p_what); -godot_int GDAPI godot_string_findn_from(const godot_string *p_self, godot_string p_what, godot_int p_from); +godot_bool GDAPI godot_string_ends_with_char_array(const godot_string *p_self, const char *p_char_array); +godot_int GDAPI godot_string_count(const godot_string *p_self, const godot_string *p_what, godot_int p_from, godot_int p_to); +godot_int GDAPI godot_string_countn(const godot_string *p_self, const godot_string *p_what, godot_int p_from, godot_int p_to); +godot_int GDAPI godot_string_find(const godot_string *p_self, const godot_string *p_what); +godot_int GDAPI godot_string_find_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from); +godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_packed_string_array *p_keys); +godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot_packed_string_array *p_keys, godot_int p_from); +godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_packed_string_array *p_keys, godot_int p_from, godot_int *r_key); +godot_int GDAPI godot_string_findn(const godot_string *p_self, const godot_string *p_what); +godot_int GDAPI godot_string_findn_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from); godot_string GDAPI godot_string_format(const godot_string *p_self, const godot_variant *p_values); godot_string GDAPI godot_string_format_with_custom_placeholder(const godot_string *p_self, const godot_variant *p_values, const char *p_placeholder); godot_string GDAPI godot_string_hex_encode_buffer(const uint8_t *p_buffer, godot_int p_len); godot_int GDAPI godot_string_hex_to_int(const godot_string *p_self); -godot_int GDAPI godot_string_hex_to_int_without_prefix(const godot_string *p_self); -godot_string GDAPI godot_string_insert(const godot_string *p_self, godot_int p_at_pos, godot_string p_string); +godot_int GDAPI godot_string_hex_to_int_with_prefix(const godot_string *p_self); +godot_string GDAPI godot_string_insert(const godot_string *p_self, godot_int p_at_pos, const godot_string *p_string); godot_bool GDAPI godot_string_is_numeric(const godot_string *p_self); godot_bool GDAPI godot_string_is_subsequence_of(const godot_string *p_self, const godot_string *p_string); godot_bool GDAPI godot_string_is_subsequence_ofi(const godot_string *p_self, const godot_string *p_string); @@ -133,13 +157,13 @@ godot_string GDAPI godot_string_num_scientific(double p_num); godot_string GDAPI godot_string_num_with_decimals(double p_num, godot_int p_decimals); godot_string GDAPI godot_string_pad_decimals(const godot_string *p_self, godot_int p_digits); godot_string GDAPI godot_string_pad_zeros(const godot_string *p_self, godot_int p_digits); -godot_string GDAPI godot_string_replace_first(const godot_string *p_self, godot_string p_key, godot_string p_with); -godot_string GDAPI godot_string_replace(const godot_string *p_self, godot_string p_key, godot_string p_with); -godot_string GDAPI godot_string_replacen(const godot_string *p_self, godot_string p_key, godot_string p_with); -godot_int GDAPI godot_string_rfind(const godot_string *p_self, godot_string p_what); -godot_int GDAPI godot_string_rfindn(const godot_string *p_self, godot_string p_what); -godot_int GDAPI godot_string_rfind_from(const godot_string *p_self, godot_string p_what, godot_int p_from); -godot_int GDAPI godot_string_rfindn_from(const godot_string *p_self, godot_string p_what, godot_int p_from); +godot_string GDAPI godot_string_replace_first(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with); +godot_string GDAPI godot_string_replace(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with); +godot_string GDAPI godot_string_replacen(const godot_string *p_self, const godot_string *p_key, const godot_string *p_with); +godot_int GDAPI godot_string_rfind(const godot_string *p_self, const godot_string *p_what); +godot_int GDAPI godot_string_rfindn(const godot_string *p_self, const godot_string *p_what); +godot_int GDAPI godot_string_rfind_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from); +godot_int GDAPI godot_string_rfindn_from(const godot_string *p_self, const godot_string *p_what, godot_int p_from); godot_string GDAPI godot_string_rpad(const godot_string *p_self, godot_int p_min_length); godot_string GDAPI godot_string_rpad_with_custom_character(const godot_string *p_self, godot_int p_min_length, const godot_string *p_character); godot_real GDAPI godot_string_similarity(const godot_string *p_self, const godot_string *p_string); @@ -151,64 +175,79 @@ godot_int GDAPI godot_string_to_int(const godot_string *p_self); godot_string GDAPI godot_string_camelcase_to_underscore(const godot_string *p_self); godot_string GDAPI godot_string_camelcase_to_underscore_lowercased(const godot_string *p_self); godot_string GDAPI godot_string_capitalize(const godot_string *p_self); + double GDAPI godot_string_char_to_float(const char *p_what); +double GDAPI godot_string_wchar_to_float(const wchar_t *p_str, const wchar_t **r_end); + godot_int GDAPI godot_string_char_to_int(const char *p_what); -int64_t GDAPI godot_string_wchar_to_int(const wchar_t *p_str); +godot_int GDAPI godot_string_wchar_to_int(const wchar_t *p_str); + godot_int GDAPI godot_string_char_to_int_with_len(const char *p_what, godot_int p_len); -int64_t GDAPI godot_string_char_to_int64_with_len(const wchar_t *p_str, int p_len); -int64_t GDAPI godot_string_hex_to_int64(const godot_string *p_self); -int64_t GDAPI godot_string_hex_to_int64_with_prefix(const godot_string *p_self); -int64_t GDAPI godot_string_to_int64(const godot_string *p_self); -double GDAPI godot_string_unicode_char_to_float(const wchar_t *p_str, const wchar_t **r_end); - -godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, godot_string p_splitter); -godot_string GDAPI godot_string_get_slice(const godot_string *p_self, godot_string p_splitter, godot_int p_slice); -godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p_splitter, godot_int p_slice); - -godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter); -godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter); -godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter); -godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_self, const godot_string *p_splitter); -godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_array *p_splitters); -godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters); -godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter); -godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_self, const godot_string *p_splitter); -godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_array *p_splitters); -godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters); -godot_array GDAPI godot_string_split_spaces(const godot_string *p_self); - -wchar_t GDAPI godot_string_char_lowercase(wchar_t p_char); -wchar_t GDAPI godot_string_char_uppercase(wchar_t p_char); +godot_int GDAPI godot_string_wchar_to_int_with_len(const wchar_t *p_str, int p_len); + +godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, const godot_string *p_splitter); +godot_string GDAPI godot_string_get_slice(const godot_string *p_self, const godot_string *p_splitter, godot_int p_slice); +godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, godot_char_type p_splitter, godot_int p_slice); + +godot_packed_string_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_string_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_string_array GDAPI godot_string_split_with_maxsplit(const godot_string *p_self, const godot_string *p_splitter, const godot_bool p_allow_empty, const godot_int p_maxsplit); + +godot_packed_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_string_array GDAPI godot_string_rsplit_allow_empty(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_string_array GDAPI godot_string_rsplit_with_maxsplit(const godot_string *p_self, const godot_string *p_splitter, const godot_bool p_allow_empty, const godot_int p_maxsplit); + +godot_packed_float32_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_float32_array GDAPI godot_string_split_floats_allow_empty(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_float32_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_packed_string_array *p_splitters); +godot_packed_float32_array GDAPI godot_string_split_floats_mk_allow_empty(const godot_string *p_self, const godot_packed_string_array *p_splitters); +godot_packed_int32_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_int32_array GDAPI godot_string_split_ints_allow_empty(const godot_string *p_self, const godot_string *p_splitter); +godot_packed_int32_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_packed_string_array *p_splitters); +godot_packed_int32_array GDAPI godot_string_split_ints_mk_allow_empty(const godot_string *p_self, const godot_packed_string_array *p_splitters); + +godot_packed_string_array GDAPI godot_string_split_spaces(const godot_string *p_self); + +godot_char_type GDAPI godot_string_char_lowercase(godot_char_type p_char); +godot_char_type GDAPI godot_string_char_uppercase(godot_char_type p_char); godot_string GDAPI godot_string_to_lower(const godot_string *p_self); godot_string GDAPI godot_string_to_upper(const godot_string *p_self); godot_string GDAPI godot_string_get_basename(const godot_string *p_self); godot_string GDAPI godot_string_get_extension(const godot_string *p_self); godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos); -wchar_t GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx); +godot_char_type GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx); godot_string GDAPI godot_string_plus_file(const godot_string *p_self, const godot_string *p_file); godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_pos); +godot_string GDAPI godot_string_repeat(const godot_string *p_self, godot_int p_count); godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bool p_left, godot_bool p_right); godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self); void GDAPI godot_string_erase(godot_string *p_self, godot_int p_pos, godot_int p_chars); godot_char_string GDAPI godot_string_ascii(const godot_string *p_self); -godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self); +godot_char_string GDAPI godot_string_latin1(const godot_string *p_self); + godot_char_string GDAPI godot_string_utf8(const godot_string *p_self); godot_bool GDAPI godot_string_parse_utf8(godot_string *p_self, const char *p_utf8); godot_bool GDAPI godot_string_parse_utf8_with_len(godot_string *p_self, const char *p_utf8, godot_int p_len); -godot_string GDAPI godot_string_chars_to_utf8(const char *p_utf8); -godot_string GDAPI godot_string_chars_to_utf8_with_len(const char *p_utf8, godot_int p_len); + +godot_char16_string GDAPI godot_string_utf16(const godot_string *p_self); +godot_bool GDAPI godot_string_parse_utf16(godot_string *p_self, const char16_t *p_utf16); +godot_bool GDAPI godot_string_parse_utf16_with_len(godot_string *p_self, const char16_t *p_utf16, godot_int p_len); uint32_t GDAPI godot_string_hash(const godot_string *p_self); uint64_t GDAPI godot_string_hash64(const godot_string *p_self); + uint32_t GDAPI godot_string_hash_chars(const char *p_cstr); uint32_t GDAPI godot_string_hash_chars_with_len(const char *p_cstr, godot_int p_len); -uint32_t GDAPI godot_string_hash_utf8_chars(const wchar_t *p_str); -uint32_t GDAPI godot_string_hash_utf8_chars_with_len(const wchar_t *p_str, godot_int p_len); +uint32_t GDAPI godot_string_hash_wide_chars(const wchar_t *p_str); +uint32_t GDAPI godot_string_hash_wide_chars_with_len(const wchar_t *p_str, godot_int p_len); + godot_packed_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self); godot_string GDAPI godot_string_md5_text(const godot_string *p_self); +godot_packed_byte_array GDAPI godot_string_sha1_buffer(const godot_string *p_self); +godot_string GDAPI godot_string_sha1_text(const godot_string *p_self); godot_packed_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_self); godot_string GDAPI godot_string_sha256_text(const godot_string *p_self); @@ -231,14 +270,15 @@ godot_string GDAPI godot_string_c_unescape(const godot_string *p_self); godot_string GDAPI godot_string_http_escape(const godot_string *p_self); godot_string GDAPI godot_string_http_unescape(const godot_string *p_self); godot_string GDAPI godot_string_json_escape(const godot_string *p_self); -godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line); godot_string GDAPI godot_string_xml_escape(const godot_string *p_self); godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_self); godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self); godot_string GDAPI godot_string_percent_decode(const godot_string *p_self); godot_string GDAPI godot_string_percent_encode(const godot_string *p_self); +godot_string GDAPI godot_string_join(const godot_string *p_self, const godot_packed_string_array *p_parts); +godot_bool GDAPI godot_string_is_valid_filename(const godot_string *p_self); godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self); godot_bool GDAPI godot_string_is_valid_hex_number(const godot_string *p_self, godot_bool p_with_prefix); godot_bool GDAPI godot_string_is_valid_html_color(const godot_string *p_self); @@ -249,8 +289,8 @@ godot_bool GDAPI godot_string_is_valid_ip_address(const godot_string *p_self); godot_string GDAPI godot_string_dedent(const godot_string *p_self); godot_string GDAPI godot_string_trim_prefix(const godot_string *p_self, const godot_string *p_prefix); godot_string GDAPI godot_string_trim_suffix(const godot_string *p_self, const godot_string *p_suffix); +godot_string GDAPI godot_string_lstrip(const godot_string *p_self, const godot_string *p_chars); godot_string GDAPI godot_string_rstrip(const godot_string *p_self, const godot_string *p_chars); -godot_packed_string_array GDAPI godot_string_rsplit(const godot_string *p_self, const godot_string *p_divisor, const godot_bool p_allow_empty, const godot_int p_maxsplit); void GDAPI godot_string_destroy(godot_string *p_self); diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp index 019fa0d1f8..8dbaec4e75 100644 --- a/modules/gdnative/nativescript/api_generator.cpp +++ b/modules/gdnative/nativescript/api_generator.cpp @@ -176,10 +176,10 @@ List<ClassAPI> generate_c_api_classes() { // Register global constants as a fake GlobalConstants singleton class { ClassAPI global_constants_api; - global_constants_api.class_name = L"GlobalConstants"; + global_constants_api.class_name = "GlobalConstants"; global_constants_api.api_type = ClassDB::API_CORE; global_constants_api.is_singleton = true; - global_constants_api.singleton_name = L"GlobalConstants"; + global_constants_api.singleton_name = "GlobalConstants"; global_constants_api.is_instanciable = false; const int constants_count = GlobalConstants::get_global_constant_count(); for (int i = 0; i < constants_count; ++i) { diff --git a/modules/gdnative/tests/test_string.h b/modules/gdnative/tests/test_string.h new file mode 100644 index 0000000000..aeb855a1c4 --- /dev/null +++ b/modules/gdnative/tests/test_string.h @@ -0,0 +1,1980 @@ +/*************************************************************************/ +/* test_string.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 TEST_GDNATIVE_STRING_H +#define TEST_GDNATIVE_STRING_H + +namespace TestGDNativeString { + +#include "gdnative/string.h" + +#include "tests/test_macros.h" + +int u32scmp(const char32_t *l, const char32_t *r) { + for (; *l == *r && *l && *r; l++, r++) + ; + return *l - *r; +} + +TEST_CASE("[GDNative String] Construct from Latin-1 char string") { + godot_string s; + + godot_string_new_with_latin1_chars(&s, "Hello"); + CHECK(u32scmp(godot_string_get_data(&s), U"Hello") == 0); + godot_string_destroy(&s); + + godot_string_new_with_latin1_chars_and_len(&s, "Hello", 3); + CHECK(u32scmp(godot_string_get_data(&s), U"Hel") == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Construct from wchar_t string") { + godot_string s; + + godot_string_new_with_wide_chars(&s, L"Give me"); + CHECK(u32scmp(godot_string_get_data(&s), U"Give me") == 0); + godot_string_destroy(&s); + + godot_string_new_with_wide_chars_and_len(&s, L"Give me", 3); + CHECK(u32scmp(godot_string_get_data(&s), U"Giv") == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Construct from UTF-8 char string") { + static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x304A, 0 }; + static const uint8_t u8str[] = { 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; + + godot_string s; + + godot_string_new_with_utf8_chars(&s, (const char *)u8str); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf8_chars_and_len(&s, (const char *)u8str, 5); + CHECK(u32scmp(godot_string_get_data(&s), u32str_short) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf32_chars(&s, u32str); + godot_char_string cs = godot_string_utf8(&s); + godot_string_parse_utf8(&s, godot_char_string_get_data(&cs)); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + godot_char_string_destroy(&cs); + + godot_string_new_with_utf32_chars(&s, u32str); + cs = godot_string_utf8(&s); + godot_string_parse_utf8_with_len(&s, godot_char_string_get_data(&cs), godot_char_string_length(&cs)); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + godot_char_string_destroy(&cs); +} + +TEST_CASE("[GDNative String] Construct from UTF-8 string with BOM") { + static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x304A, 0 }; + static const uint8_t u8str[] = { 0xEF, 0xBB, 0xBF, 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; + + godot_string s; + + godot_string_new_with_utf8_chars(&s, (const char *)u8str); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf8_chars_and_len(&s, (const char *)u8str, 8); + CHECK(u32scmp(godot_string_get_data(&s), u32str_short) == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Construct from UTF-16 string") { + static const char32_t u32str[] = { 0x0045, 0x0020, 0x1F3A4, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x1F3A4, 0 }; + static const char16_t u16str[] = { 0x0045, 0x0020, 0xD83C, 0xDFA4, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 }; + + godot_string s; + + godot_string_new_with_utf16_chars(&s, u16str); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf16_chars_and_len(&s, u16str, 4); + CHECK(u32scmp(godot_string_get_data(&s), u32str_short) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf32_chars(&s, u32str); + godot_char16_string cs = godot_string_utf16(&s); + godot_string_parse_utf16(&s, godot_char16_string_get_data(&cs)); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + godot_char16_string_destroy(&cs); + + godot_string_new_with_utf32_chars(&s, u32str); + cs = godot_string_utf16(&s); + godot_string_parse_utf16_with_len(&s, godot_char16_string_get_data(&cs), godot_char16_string_length(&cs)); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + godot_char16_string_destroy(&cs); +} + +TEST_CASE("[GDNative String] Construct from UTF-16 string with BOM ") { + static const char32_t u32str[] = { 0x0045, 0x0020, 0x1F3A4, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const char32_t u32str_short[] = { 0x0045, 0x0020, 0x1F3A4, 0 }; + static const char16_t u16str[] = { 0xFEFF, 0x0045, 0x0020, 0xD83C, 0xDFA4, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 }; + static const char16_t u16str_swap[] = { 0xFFFE, 0x4500, 0x2000, 0x3CD8, 0xA4DF, 0x0F36, 0x8830, 0x4630, 0x3CD8, 0xA4DF, 0 }; + + godot_string s; + + godot_string_new_with_utf16_chars(&s, u16str); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf16_chars(&s, u16str_swap); + CHECK(u32scmp(godot_string_get_data(&s), u32str) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf16_chars_and_len(&s, u16str, 5); + CHECK(u32scmp(godot_string_get_data(&s), u32str_short) == 0); + godot_string_destroy(&s); + + godot_string_new_with_utf16_chars_and_len(&s, u16str_swap, 5); + CHECK(u32scmp(godot_string_get_data(&s), u32str_short) == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Construct string copy") { + godot_string s, t; + + godot_string_new_with_latin1_chars(&s, "Hello"); + godot_string_new_copy(&t, &s); + CHECK(u32scmp(godot_string_get_data(&t), U"Hello") == 0); + godot_string_destroy(&t); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Construct empty string") { + godot_string s; + + godot_string_new(&s); + CHECK(u32scmp(godot_string_get_data(&s), U"") == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] ASCII/Latin-1") { + godot_string s; + godot_string_new_with_utf32_chars(&s, U"Primero Leche"); + + godot_char_string cs = godot_string_ascii(&s); + CHECK(strcmp(godot_char_string_get_data(&cs), "Primero Leche") == 0); + godot_char_string_destroy(&cs); + + cs = godot_string_latin1(&s); + CHECK(strcmp(godot_char_string_get_data(&cs), "Primero Leche") == 0); + godot_char_string_destroy(&cs); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Comparisons (equal)") { + godot_string s, t; + + godot_string_new_with_latin1_chars(&s, "Test Compare"); + godot_string_new_with_latin1_chars(&t, "Test Compare"); + CHECK(godot_string_operator_equal(&s, &t)); + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] Comparisons (operator <)") { + godot_string s, t; + + godot_string_new_with_latin1_chars(&s, "Bees"); + + godot_string_new_with_latin1_chars(&t, "Elephant"); + CHECK(godot_string_operator_less(&s, &t)); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Amber"); + CHECK(!godot_string_operator_less(&s, &t)); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Beatrix"); + CHECK(!godot_string_operator_less(&s, &t)); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Concatenation (operator +)") { + godot_string s, t, x; + + godot_string_new_with_latin1_chars(&s, "Hel"); + godot_string_new_with_latin1_chars(&t, "lo"); + x = godot_string_operator_plus(&s, &t); + CHECK(u32scmp(godot_string_get_data(&x), U"Hello") == 0); + godot_string_destroy(&x); + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] Testing size and length of string") { + godot_string s; + + godot_string_new_with_latin1_chars(&s, "Mellon"); + CHECK(godot_string_length(&s) == 6); + godot_string_destroy(&s); + + godot_string_new_with_latin1_chars(&s, "Mellon1"); + CHECK(godot_string_length(&s) == 7); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Testing for empty string") { + godot_string s; + + godot_string_new_with_latin1_chars(&s, "Mellon"); + CHECK(!godot_string_empty(&s)); + godot_string_destroy(&s); + + godot_string_new_with_latin1_chars(&s, ""); + CHECK(godot_string_empty(&s)); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Test chr") { + godot_string s; + + s = godot_string_chr('H'); + CHECK(u32scmp(godot_string_get_data(&s), U"H") == 0); + godot_string_destroy(&s); + + s = godot_string_chr(0x3012); + CHECK(godot_string_operator_index_const(&s, 0) == 0x3012); + godot_string_destroy(&s); + + ERR_PRINT_OFF + s = godot_string_chr(0xd812); + CHECK(godot_string_operator_index_const(&s, 0) == 0xfffd); // Unpaired UTF-16 surrogate + godot_string_destroy(&s); + + s = godot_string_chr(0x20d812); + CHECK(godot_string_operator_index_const(&s, 0) == 0xfffd); // Outside UTF-32 range + godot_string_destroy(&s); + ERR_PRINT_ON +} + +TEST_CASE("[GDNative String] Operator []") { + godot_string s; + + godot_string_new_with_latin1_chars(&s, "Hello"); + CHECK(*godot_string_operator_index(&s, 1) == 'e'); + CHECK(godot_string_operator_index_const(&s, 0) == 'H'); + CHECK(godot_string_ord_at(&s, 0) == 'H'); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Case function test") { + godot_string s, t; + + godot_string_new_with_latin1_chars(&s, "MoMoNgA"); + + t = godot_string_to_upper(&s); + CHECK(u32scmp(godot_string_get_data(&t), U"MOMONGA") == 0); + godot_string_destroy(&t); + + t = godot_string_to_lower(&s); + CHECK(u32scmp(godot_string_get_data(&t), U"momonga") == 0); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Case compare function test") { + godot_string s, t; + + godot_string_new_with_latin1_chars(&s, "MoMoNgA"); + godot_string_new_with_latin1_chars(&t, "momonga"); + + CHECK(godot_string_casecmp_to(&s, &t) != 0); + CHECK(godot_string_nocasecmp_to(&s, &t) == 0); + + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] Natural compare function test") { + godot_string s, t; + + godot_string_new_with_latin1_chars(&s, "img2.png"); + godot_string_new_with_latin1_chars(&t, "img10.png"); + + CHECK(godot_string_nocasecmp_to(&s, &t) > 0); + CHECK(godot_string_naturalnocasecmp_to(&s, &t) < 0); + + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] hex_encode_buffer") { + static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3 }; + godot_string s = godot_string_hex_encode_buffer(u8str, 6); + CHECK(u32scmp(godot_string_get_data(&s), U"45e3818a8fe3") == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Substr") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "Killer Baby"); + t = godot_string_substr(&s, 3, 4); + CHECK(u32scmp(godot_string_get_data(&t), U"ler ") == 0); + godot_string_destroy(&t); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Find") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "Pretty Woman Woman"); + + godot_string_new_with_latin1_chars(&t, "Revenge of the Monster Truck"); + CHECK(godot_string_find(&s, &t) == -1); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "tty"); + CHECK(godot_string_find(&s, &t) == 3); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Wo"); + CHECK(godot_string_find_from(&s, &t, 9) == 13); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "man"); + CHECK(godot_string_rfind(&s, &t) == 15); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Find no case") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "Pretty Whale Whale"); + + godot_string_new_with_latin1_chars(&t, "WHA"); + CHECK(godot_string_findn(&s, &t) == 7); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "WHA"); + CHECK(godot_string_findn_from(&s, &t, 9) == 13); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "WHA"); + CHECK(godot_string_rfindn(&s, &t) == 13); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Revenge of the Monster SawFish"); + CHECK(godot_string_findn(&s, &t) == -1); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Find MK") { + godot_packed_string_array keys; + godot_packed_string_array_new(&keys); + +#define PUSH_KEY(x) \ + { \ + godot_string t; \ + godot_string_new_with_latin1_chars(&t, x); \ + godot_packed_string_array_push_back(&keys, &t); \ + godot_string_destroy(&t); \ + } + + PUSH_KEY("sty") + PUSH_KEY("tty") + PUSH_KEY("man") + + godot_string s; + godot_string_new_with_latin1_chars(&s, "Pretty Woman"); + godot_int key = 0; + + CHECK(godot_string_findmk(&s, &keys) == 3); + CHECK(godot_string_findmk_from_in_place(&s, &keys, 0, &key) == 3); + CHECK(key == 1); + + CHECK(godot_string_findmk_from(&s, &keys, 5) == 9); + CHECK(godot_string_findmk_from_in_place(&s, &keys, 5, &key) == 9); + CHECK(key == 2); + + godot_string_destroy(&s); + godot_packed_string_array_destroy(&keys); + +#undef PUSH_KEY +} + +TEST_CASE("[GDNative String] Find and replace") { + godot_string s, c, w; + godot_string_new_with_latin1_chars(&s, "Happy Birthday, Anna!"); + godot_string_new_with_latin1_chars(&c, "Birthday"); + godot_string_new_with_latin1_chars(&w, "Halloween"); + godot_string t = godot_string_replace(&s, &c, &w); + CHECK(u32scmp(godot_string_get_data(&t), U"Happy Halloween, Anna!") == 0); + godot_string_destroy(&s); + godot_string_destroy(&c); + godot_string_destroy(&w); + + godot_string_new_with_latin1_chars(&c, "H"); + godot_string_new_with_latin1_chars(&w, "W"); + s = godot_string_replace_first(&t, &c, &w); + godot_string_destroy(&t); + godot_string_destroy(&c); + godot_string_destroy(&w); + + CHECK(u32scmp(godot_string_get_data(&s), U"Wappy Halloween, Anna!") == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Insertion") { + godot_string s, t, r, u; + godot_string_new_with_latin1_chars(&s, "Who is Frederic?"); + godot_string_new_with_latin1_chars(&t, "?"); + godot_string_new_with_latin1_chars(&r, " Chopin"); + + u = godot_string_insert(&s, godot_string_find(&s, &t), &r); + CHECK(u32scmp(godot_string_get_data(&u), U"Who is Frederic Chopin?") == 0); + + godot_string_destroy(&s); + godot_string_destroy(&t); + godot_string_destroy(&r); + godot_string_destroy(&u); +} + +TEST_CASE("[GDNative String] Number to string") { + godot_string s; + s = godot_string_num(3.141593); + CHECK(u32scmp(godot_string_get_data(&s), U"3.141593") == 0); + godot_string_destroy(&s); + + s = godot_string_num_with_decimals(3.141593, 3); + CHECK(u32scmp(godot_string_get_data(&s), U"3.142") == 0); + godot_string_destroy(&s); + + s = godot_string_num_real(3.141593); + CHECK(u32scmp(godot_string_get_data(&s), U"3.141593") == 0); + godot_string_destroy(&s); + + s = godot_string_num_scientific(30000000); + CHECK(u32scmp(godot_string_get_data(&s), U"3e+07") == 0); + godot_string_destroy(&s); + + s = godot_string_num_int64(3141593, 10); + CHECK(u32scmp(godot_string_get_data(&s), U"3141593") == 0); + godot_string_destroy(&s); + + s = godot_string_num_int64(0xA141593, 16); + CHECK(u32scmp(godot_string_get_data(&s), U"a141593") == 0); + godot_string_destroy(&s); + + s = godot_string_num_int64_capitalized(0xA141593, 16, true); + CHECK(u32scmp(godot_string_get_data(&s), U"A141593") == 0); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] String to integer") { + static const wchar_t *wnums[4] = { L"1237461283", L"- 22", L"0", L" - 1123412" }; + static const char *nums[4] = { "1237461283", "- 22", "0", " - 1123412" }; + static const int num[4] = { 1237461283, -22, 0, -1123412 }; + + for (int i = 0; i < 4; i++) { + godot_string s; + godot_string_new_with_latin1_chars(&s, nums[i]); + CHECK(godot_string_to_int(&s) == num[i]); + godot_string_destroy(&s); + + CHECK(godot_string_char_to_int(nums[i]) == num[i]); + CHECK(godot_string_wchar_to_int(wnums[i]) == num[i]); + } +} + +TEST_CASE("[GDNative String] Hex to integer") { + static const char *nums[4] = { "0xFFAE", "22", "0", "AADDAD" }; + static const int64_t num[4] = { 0xFFAE, 0x22, 0, 0xAADDAD }; + static const bool wo_prefix[4] = { false, true, true, true }; + static const bool w_prefix[4] = { true, false, true, false }; + + for (int i = 0; i < 4; i++) { + godot_string s; + godot_string_new_with_latin1_chars(&s, nums[i]); + CHECK((godot_string_hex_to_int_with_prefix(&s) == num[i]) == w_prefix[i]); + CHECK((godot_string_hex_to_int(&s) == num[i]) == wo_prefix[i]); + godot_string_destroy(&s); + } +} + +TEST_CASE("[GDNative String] String to float") { + static const wchar_t *wnums[4] = { L"-12348298412.2", L"0.05", L"2.0002", L" -0.0001" }; + static const char *nums[4] = { "-12348298412.2", "0.05", "2.0002", " -0.0001" }; + static const double num[4] = { -12348298412.2, 0.05, 2.0002, -0.0001 }; + + for (int i = 0; i < 4; i++) { + godot_string s; + godot_string_new_with_latin1_chars(&s, nums[i]); + CHECK(!(ABS(godot_string_to_float(&s) - num[i]) > 0.00001)); + godot_string_destroy(&s); + + CHECK(!(ABS(godot_string_char_to_float(nums[i]) - num[i]) > 0.00001)); + CHECK(!(ABS(godot_string_wchar_to_float(wnums[i], nullptr) - num[i]) > 0.00001)); + } +} + +TEST_CASE("[GDNative String] CamelCase to underscore") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "TestTestStringGD"); + + t = godot_string_camelcase_to_underscore(&s); + CHECK(u32scmp(godot_string_get_data(&t), U"Test_Test_String_GD") == 0); + godot_string_destroy(&t); + + t = godot_string_camelcase_to_underscore_lowercased(&s); + CHECK(u32scmp(godot_string_get_data(&t), U"test_test_string_gd") == 0); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Slicing") { + godot_string s, c; + godot_string_new_with_latin1_chars(&s, "Mars,Jupiter,Saturn,Uranus"); + godot_string_new_with_latin1_chars(&c, ","); + + const char32_t *slices[4] = { U"Mars", U"Jupiter", U"Saturn", U"Uranus" }; + for (int i = 0; i < godot_string_get_slice_count(&s, &c); i++) { + godot_string t; + t = godot_string_get_slice(&s, &c, i); + CHECK(u32scmp(godot_string_get_data(&t), slices[i]) == 0); + godot_string_destroy(&t); + + t = godot_string_get_slicec(&s, U',', i); + CHECK(u32scmp(godot_string_get_data(&t), slices[i]) == 0); + godot_string_destroy(&t); + } + + godot_string_destroy(&c); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Splitting") { + godot_string s, c; + godot_string_new_with_latin1_chars(&s, "Mars,Jupiter,Saturn,Uranus"); + godot_string_new_with_latin1_chars(&c, ","); + + godot_packed_string_array l; + + const char32_t *slices_l[3] = { U"Mars", U"Jupiter", U"Saturn,Uranus" }; + const char32_t *slices_r[3] = { U"Mars,Jupiter", U"Saturn", U"Uranus" }; + + l = godot_string_split_with_maxsplit(&s, &c, true, 2); + CHECK(godot_packed_string_array_size(&l) == 3); + for (int i = 0; i < godot_packed_string_array_size(&l); i++) { + godot_string t = godot_packed_string_array_get(&l, i); + CHECK(u32scmp(godot_string_get_data(&t), slices_l[i]) == 0); + godot_string_destroy(&t); + } + godot_packed_string_array_destroy(&l); + + l = godot_string_rsplit_with_maxsplit(&s, &c, true, 2); + CHECK(godot_packed_string_array_size(&l) == 3); + for (int i = 0; i < godot_packed_string_array_size(&l); i++) { + godot_string t = godot_packed_string_array_get(&l, i); + CHECK(u32scmp(godot_string_get_data(&t), slices_r[i]) == 0); + godot_string_destroy(&t); + } + godot_packed_string_array_destroy(&l); + godot_string_destroy(&s); + + godot_string_new_with_latin1_chars(&s, "Mars Jupiter Saturn Uranus"); + const char32_t *slices_s[4] = { U"Mars", U"Jupiter", U"Saturn", U"Uranus" }; + l = godot_string_split_spaces(&s); + for (int i = 0; i < godot_packed_string_array_size(&l); i++) { + godot_string t = godot_packed_string_array_get(&l, i); + CHECK(u32scmp(godot_string_get_data(&t), slices_s[i]) == 0); + godot_string_destroy(&t); + } + godot_packed_string_array_destroy(&l); + godot_string_destroy(&s); + + godot_string c1, c2; + godot_string_new_with_latin1_chars(&c1, ";"); + godot_string_new_with_latin1_chars(&c2, " "); + + godot_string_new_with_latin1_chars(&s, "1.2;2.3 4.5"); + const double slices_d[3] = { 1.2, 2.3, 4.5 }; + + godot_packed_float32_array lf = godot_string_split_floats_allow_empty(&s, &c1); + CHECK(godot_packed_float32_array_size(&lf) == 2); + for (int i = 0; i < godot_packed_float32_array_size(&lf); i++) { + CHECK(ABS(godot_packed_float32_array_get(&lf, i) - slices_d[i]) <= 0.00001); + } + godot_packed_float32_array_destroy(&lf); + + godot_packed_string_array keys; + godot_packed_string_array_new(&keys); + godot_packed_string_array_push_back(&keys, &c1); + godot_packed_string_array_push_back(&keys, &c2); + + lf = godot_string_split_floats_mk_allow_empty(&s, &keys); + CHECK(godot_packed_float32_array_size(&lf) == 3); + for (int i = 0; i < godot_packed_float32_array_size(&lf); i++) { + CHECK(ABS(godot_packed_float32_array_get(&lf, i) - slices_d[i]) <= 0.00001); + } + godot_packed_float32_array_destroy(&lf); + + godot_string_destroy(&s); + godot_string_new_with_latin1_chars(&s, "1;2 4"); + const int slices_i[3] = { 1, 2, 4 }; + + godot_packed_int32_array li = godot_string_split_ints_allow_empty(&s, &c1); + CHECK(godot_packed_int32_array_size(&li) == 2); + for (int i = 0; i < godot_packed_int32_array_size(&li); i++) { + CHECK(godot_packed_int32_array_get(&li, i) == slices_i[i]); + } + godot_packed_int32_array_destroy(&li); + + li = godot_string_split_ints_mk_allow_empty(&s, &keys); + CHECK(godot_packed_int32_array_size(&li) == 3); + for (int i = 0; i < godot_packed_int32_array_size(&li); i++) { + CHECK(godot_packed_int32_array_get(&li, i) == slices_i[i]); + } + godot_packed_int32_array_destroy(&li); + + godot_string_destroy(&s); + godot_string_destroy(&c); + godot_string_destroy(&c1); + godot_string_destroy(&c2); + godot_packed_string_array_destroy(&keys); +} + +TEST_CASE("[GDNative String] Erasing") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "Josephine is such a cute girl!"); + godot_string_new_with_latin1_chars(&t, "cute "); + + godot_string_erase(&s, godot_string_find(&s, &t), godot_string_length(&t)); + + CHECK(u32scmp(godot_string_get_data(&s), U"Josephine is such a girl!") == 0); + + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +struct test_27_data { + char const *data; + char const *part; + bool expected; +}; + +TEST_CASE("[GDNative String] Begins with") { + test_27_data tc[] = { + { "res://foobar", "res://", true }, + { "res", "res://", false }, + { "abc", "abc", true } + }; + size_t count = sizeof(tc) / sizeof(tc[0]); + bool state = true; + for (size_t i = 0; state && i < count; ++i) { + godot_string s; + godot_string_new_with_latin1_chars(&s, tc[i].data); + + state = godot_string_begins_with_char_array(&s, tc[i].part) == tc[i].expected; + if (state) { + godot_string t; + godot_string_new_with_latin1_chars(&t, tc[i].part); + state = godot_string_begins_with(&s, &t) == tc[i].expected; + godot_string_destroy(&t); + } + godot_string_destroy(&s); + + CHECK(state); + if (!state) { + break; + } + }; + CHECK(state); +} + +TEST_CASE("[GDNative String] Ends with") { + test_27_data tc[] = { + { "res://foobar", "foobar", true }, + { "res", "res://", false }, + { "abc", "abc", true } + }; + size_t count = sizeof(tc) / sizeof(tc[0]); + bool state = true; + for (size_t i = 0; state && i < count; ++i) { + godot_string s; + godot_string_new_with_latin1_chars(&s, tc[i].data); + + state = godot_string_ends_with_char_array(&s, tc[i].part) == tc[i].expected; + if (state) { + godot_string t; + godot_string_new_with_latin1_chars(&t, tc[i].part); + state = godot_string_ends_with(&s, &t) == tc[i].expected; + godot_string_destroy(&t); + } + godot_string_destroy(&s); + + CHECK(state); + if (!state) { + break; + } + }; + CHECK(state); +} + +TEST_CASE("[GDNative String] format") { + godot_string value_format, t; + godot_string_new_with_latin1_chars(&value_format, "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""); + + godot_variant key_v, val_v; + godot_dictionary value_dictionary; + godot_dictionary_new(&value_dictionary); + + godot_string_new_with_latin1_chars(&t, "red"); + godot_variant_new_string(&key_v, &t); + godot_string_destroy(&t); + godot_variant_new_int(&val_v, 10); + godot_dictionary_set(&value_dictionary, &key_v, &val_v); + godot_variant_destroy(&key_v); + godot_variant_destroy(&val_v); + + godot_string_new_with_latin1_chars(&t, "green"); + godot_variant_new_string(&key_v, &t); + godot_string_destroy(&t); + godot_variant_new_int(&val_v, 20); + godot_dictionary_set(&value_dictionary, &key_v, &val_v); + godot_variant_destroy(&key_v); + godot_variant_destroy(&val_v); + + godot_string_new_with_latin1_chars(&t, "blue"); + godot_variant_new_string(&key_v, &t); + godot_string_destroy(&t); + godot_string_new_with_latin1_chars(&t, "bla"); + godot_variant_new_string(&val_v, &t); + godot_string_destroy(&t); + godot_dictionary_set(&value_dictionary, &key_v, &val_v); + godot_variant_destroy(&key_v); + godot_variant_destroy(&val_v); + + godot_string_new_with_latin1_chars(&t, "alpha"); + godot_variant_new_string(&key_v, &t); + godot_string_destroy(&t); + godot_variant_new_real(&val_v, 0.4); + godot_dictionary_set(&value_dictionary, &key_v, &val_v); + godot_variant_destroy(&key_v); + godot_variant_destroy(&val_v); + + godot_variant dict_v; + godot_variant_new_dictionary(&dict_v, &value_dictionary); + godot_string s = godot_string_format_with_custom_placeholder(&value_format, &dict_v, "$_"); + + CHECK(u32scmp(godot_string_get_data(&s), U"red=\"10\" green=\"20\" blue=\"bla\" alpha=\"0.4\"") == 0); + + godot_dictionary_destroy(&value_dictionary); + godot_string_destroy(&s); + godot_variant_destroy(&dict_v); + godot_string_destroy(&value_format); +} + +TEST_CASE("[GDNative String] sprintf") { + //godot_string GDAPI (const godot_string *p_self, const godot_array *p_values, godot_bool *p_error); + godot_string format, output; + godot_array args; + bool error; + +#define ARRAY_PUSH_STRING(x) \ + { \ + godot_variant v; \ + godot_string t; \ + godot_string_new_with_latin1_chars(&t, x); \ + godot_variant_new_string(&v, &t); \ + godot_string_destroy(&t); \ + godot_array_push_back(&args, &v); \ + godot_variant_destroy(&v); \ + } + +#define ARRAY_PUSH_INT(x) \ + { \ + godot_variant v; \ + godot_variant_new_int(&v, x); \ + godot_array_push_back(&args, &v); \ + godot_variant_destroy(&v); \ + } + +#define ARRAY_PUSH_REAL(x) \ + { \ + godot_variant v; \ + godot_variant_new_real(&v, x); \ + godot_array_push_back(&args, &v); \ + godot_variant_destroy(&v); \ + } + + godot_array_new(&args); + + // %% + godot_string_new_with_latin1_chars(&format, "fish %% frog"); + godot_array_clear(&args); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish % frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + //////// INTS + + // Int + godot_string_new_with_latin1_chars(&format, "fish %d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(5); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 5 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Int left padded with zeroes. + godot_string_new_with_latin1_chars(&format, "fish %05d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(5); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 00005 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Int left padded with spaces. + godot_string_new_with_latin1_chars(&format, "fish %5d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(5); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 5 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Int right padded with spaces. + godot_string_new_with_latin1_chars(&format, "fish %-5d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(5); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 5 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Int with sign (positive). + godot_string_new_with_latin1_chars(&format, "fish %+d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(5); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish +5 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Negative int. + godot_string_new_with_latin1_chars(&format, "fish %d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(-5); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish -5 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Hex (lower) + godot_string_new_with_latin1_chars(&format, "fish %x frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(45); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 2d frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Hex (upper) + godot_string_new_with_latin1_chars(&format, "fish %X frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(45); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 2D frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Octal + godot_string_new_with_latin1_chars(&format, "fish %o frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 143 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + ////// REALS + + // Real + godot_string_new_with_latin1_chars(&format, "fish %f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 99.990000 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real left-padded + godot_string_new_with_latin1_chars(&format, "fish %11f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 99.990000 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real right-padded + godot_string_new_with_latin1_chars(&format, "fish %-11f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 99.990000 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real given int. + godot_string_new_with_latin1_chars(&format, "fish %f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 99.000000 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real with sign (positive). + godot_string_new_with_latin1_chars(&format, "fish %+f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish +99.990000 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real with 1 decimals. + godot_string_new_with_latin1_chars(&format, "fish %.1f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 100.0 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real with 12 decimals. + godot_string_new_with_latin1_chars(&format, "fish %.12f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 99.990000000000 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Real with no decimals. + godot_string_new_with_latin1_chars(&format, "fish %.f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 100 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + /////// Strings. + + // String + godot_string_new_with_latin1_chars(&format, "fish %s frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish cheese frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // String left-padded + godot_string_new_with_latin1_chars(&format, "fish %10s frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish cheese frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // String right-padded + godot_string_new_with_latin1_chars(&format, "fish %-10s frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish cheese frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + ///// Characters + + // Character as string. + godot_string_new_with_latin1_chars(&format, "fish %c frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("A"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish A frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Character as int. + godot_string_new_with_latin1_chars(&format, "fish %c frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(65); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish A frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + ///// Dynamic width + + // String dynamic width + godot_string_new_with_latin1_chars(&format, "fish %*s frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(10); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + REQUIRE(u32scmp(godot_string_get_data(&output), U"fish cheese frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Int dynamic width + godot_string_new_with_latin1_chars(&format, "fish %*d frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(10); + ARRAY_PUSH_INT(99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + REQUIRE(u32scmp(godot_string_get_data(&output), U"fish 99 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Float dynamic width + godot_string_new_with_latin1_chars(&format, "fish %*.*f frog"); + godot_array_clear(&args); + ARRAY_PUSH_INT(10); + ARRAY_PUSH_INT(3); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error == false); + CHECK(u32scmp(godot_string_get_data(&output), U"fish 99.990 frog") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + ///// Errors + + // More formats than arguments. + godot_string_new_with_latin1_chars(&format, "fish %s %s frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"not enough arguments for format string") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // More arguments than formats. + godot_string_new_with_latin1_chars(&format, "fish %s frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("hello"); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"not all arguments converted during string formatting") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Incomplete format. + godot_string_new_with_latin1_chars(&format, "fish %10"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"incomplete format") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Bad character in format string + godot_string_new_with_latin1_chars(&format, "fish %&f frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"unsupported format character") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Too many decimals. + godot_string_new_with_latin1_chars(&format, "fish %2.2.2f frog"); + godot_array_clear(&args); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"too many decimal points in format") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // * not a number + godot_string_new_with_latin1_chars(&format, "fish %*f frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("cheese"); + ARRAY_PUSH_REAL(99.99); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"* wants number") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Character too long. + godot_string_new_with_latin1_chars(&format, "fish %c frog"); + godot_array_clear(&args); + ARRAY_PUSH_STRING("sc"); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"%c requires number or single-character string") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + // Character bad type. + godot_string_new_with_latin1_chars(&format, "fish %c frog"); + godot_array_clear(&args); + godot_array t; + godot_array_new(&t); + godot_variant v; + godot_variant_new_array(&v, &t); + godot_array_destroy(&t); + godot_array_push_back(&args, &v); + godot_variant_destroy(&v); + output = godot_string_sprintf(&format, &args, &error); + REQUIRE(error); + CHECK(u32scmp(godot_string_get_data(&output), U"%c requires number or single-character string") == 0); + godot_string_destroy(&format); + godot_string_destroy(&output); + + godot_array_destroy(&args); +#undef ARRAY_PUSH_INT +#undef ARRAY_PUSH_REAL +#undef ARRAY_PUSH_STRING +} + +TEST_CASE("[GDNative String] is_numeric") { +#define IS_NUM_TEST(x, r) \ + { \ + godot_string t; \ + godot_string_new_with_latin1_chars(&t, x); \ + CHECK(godot_string_is_numeric(&t) == r); \ + godot_string_destroy(&t); \ + } + + IS_NUM_TEST("12", true); + IS_NUM_TEST("1.2", true); + IS_NUM_TEST("AF", false); + IS_NUM_TEST("-12", true); + IS_NUM_TEST("-1.2", true); + +#undef IS_NUM_TEST +} + +TEST_CASE("[GDNative String] pad") { + godot_string s, c; + godot_string_new_with_latin1_chars(&s, "test"); + godot_string_new_with_latin1_chars(&c, "x"); + + godot_string l = godot_string_lpad_with_custom_character(&s, 10, &c); + CHECK(u32scmp(godot_string_get_data(&l), U"xxxxxxtest") == 0); + godot_string_destroy(&l); + + godot_string r = godot_string_rpad_with_custom_character(&s, 10, &c); + CHECK(u32scmp(godot_string_get_data(&r), U"testxxxxxx") == 0); + godot_string_destroy(&r); + + godot_string_destroy(&s); + godot_string_destroy(&c); + + godot_string_new_with_latin1_chars(&s, "10.10"); + c = godot_string_pad_decimals(&s, 4); + CHECK(u32scmp(godot_string_get_data(&c), U"10.1000") == 0); + godot_string_destroy(&c); + c = godot_string_pad_zeros(&s, 4); + CHECK(u32scmp(godot_string_get_data(&c), U"0010.10") == 0); + godot_string_destroy(&c); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] is_subsequence_of") { + godot_string a, t; + godot_string_new_with_latin1_chars(&a, "is subsequence of"); + + godot_string_new_with_latin1_chars(&t, "sub"); + CHECK(godot_string_is_subsequence_of(&t, &a)); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Sub"); + CHECK(!godot_string_is_subsequence_of(&t, &a)); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Sub"); + CHECK(godot_string_is_subsequence_ofi(&t, &a)); + godot_string_destroy(&t); + + godot_string_destroy(&a); +} + +TEST_CASE("[GDNative String] match") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "*.png"); + + godot_string_new_with_latin1_chars(&t, "img1.png"); + CHECK(godot_string_match(&t, &s)); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "img1.jpeg"); + CHECK(!godot_string_match(&t, &s)); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "img1.Png"); + CHECK(!godot_string_match(&t, &s)); + CHECK(godot_string_matchn(&t, &s)); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] IPVX address to string") { + godot_string ip; + + godot_string_new_with_latin1_chars(&ip, "192.168.0.1"); + CHECK(godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); + + godot_string_new_with_latin1_chars(&ip, "192.368.0.1"); + CHECK(!godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); + + godot_string_new_with_latin1_chars(&ip, "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + CHECK(godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); + + godot_string_new_with_latin1_chars(&ip, "2001:0db8:85j3:0000:0000:8a2e:0370:7334"); + CHECK(!godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); + + godot_string_new_with_latin1_chars(&ip, "2001:0db8:85f345:0000:0000:8a2e:0370:7334"); + CHECK(!godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); + + godot_string_new_with_latin1_chars(&ip, "2001:0db8::0:8a2e:370:7334"); + CHECK(godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); + + godot_string_new_with_latin1_chars(&ip, "::ffff:192.168.0.1"); + CHECK(godot_string_is_valid_ip_address(&ip)); + godot_string_destroy(&ip); +} + +TEST_CASE("[GDNative String] Capitalize against many strings") { +#define CAP_TEST(i, o) \ + godot_string_new_with_latin1_chars(&input, i); \ + godot_string_new_with_latin1_chars(&output, o); \ + test = godot_string_capitalize(&input); \ + CHECK(u32scmp(godot_string_get_data(&output), godot_string_get_data(&test)) == 0); \ + godot_string_destroy(&input); \ + godot_string_destroy(&output); \ + godot_string_destroy(&test); + + godot_string input, output, test; + + CAP_TEST("bytes2var", "Bytes 2 Var"); + CAP_TEST("linear2db", "Linear 2 Db"); + CAP_TEST("vector3", "Vector 3"); + CAP_TEST("sha256", "Sha 256"); + CAP_TEST("2db", "2 Db"); + CAP_TEST("PascalCase", "Pascal Case"); + CAP_TEST("PascalPascalCase", "Pascal Pascal Case"); + CAP_TEST("snake_case", "Snake Case"); + CAP_TEST("snake_snake_case", "Snake Snake Case"); + CAP_TEST("sha256sum", "Sha 256 Sum"); + CAP_TEST("cat2dog", "Cat 2 Dog"); + CAP_TEST("function(name)", "Function(name)"); + CAP_TEST("snake_case_function(snake_case_arg)", "Snake Case Function(snake Case Arg)"); + CAP_TEST("snake_case_function( snake_case_arg )", "Snake Case Function( Snake Case Arg )"); + +#undef CAP_TEST +} + +TEST_CASE("[GDNative String] lstrip and rstrip") { +#define LSTRIP_TEST(x, y, z) \ + { \ + godot_string xx, yy, zz, rr; \ + godot_string_new_with_latin1_chars(&xx, x); \ + godot_string_new_with_latin1_chars(&yy, y); \ + godot_string_new_with_latin1_chars(&zz, z); \ + rr = godot_string_lstrip(&xx, &yy); \ + state = state && (u32scmp(godot_string_get_data(&rr), godot_string_get_data(&zz)) == 0); \ + godot_string_destroy(&xx); \ + godot_string_destroy(&yy); \ + godot_string_destroy(&zz); \ + godot_string_destroy(&rr); \ + } + +#define RSTRIP_TEST(x, y, z) \ + { \ + godot_string xx, yy, zz, rr; \ + godot_string_new_with_latin1_chars(&xx, x); \ + godot_string_new_with_latin1_chars(&yy, y); \ + godot_string_new_with_latin1_chars(&zz, z); \ + rr = godot_string_rstrip(&xx, &yy); \ + state = state && (u32scmp(godot_string_get_data(&rr), godot_string_get_data(&zz)) == 0); \ + godot_string_destroy(&xx); \ + godot_string_destroy(&yy); \ + godot_string_destroy(&zz); \ + godot_string_destroy(&rr); \ + } + +#define LSTRIP_UTF8_TEST(x, y, z) \ + { \ + godot_string xx, yy, zz, rr; \ + godot_string_new_with_utf8_chars(&xx, x); \ + godot_string_new_with_utf8_chars(&yy, y); \ + godot_string_new_with_utf8_chars(&zz, z); \ + rr = godot_string_lstrip(&xx, &yy); \ + state = state && (u32scmp(godot_string_get_data(&rr), godot_string_get_data(&zz)) == 0); \ + godot_string_destroy(&xx); \ + godot_string_destroy(&yy); \ + godot_string_destroy(&zz); \ + godot_string_destroy(&rr); \ + } + +#define RSTRIP_UTF8_TEST(x, y, z) \ + { \ + godot_string xx, yy, zz, rr; \ + godot_string_new_with_utf8_chars(&xx, x); \ + godot_string_new_with_utf8_chars(&yy, y); \ + godot_string_new_with_utf8_chars(&zz, z); \ + rr = godot_string_rstrip(&xx, &yy); \ + state = state && (u32scmp(godot_string_get_data(&rr), godot_string_get_data(&zz)) == 0); \ + godot_string_destroy(&xx); \ + godot_string_destroy(&yy); \ + godot_string_destroy(&zz); \ + godot_string_destroy(&rr); \ + } + + bool state = true; + + // strip none + LSTRIP_TEST("abc", "", "abc"); + RSTRIP_TEST("abc", "", "abc"); + // strip one + LSTRIP_TEST("abc", "a", "bc"); + RSTRIP_TEST("abc", "c", "ab"); + // strip lots + LSTRIP_TEST("bababbababccc", "ab", "ccc"); + RSTRIP_TEST("aaabcbcbcbbcbbc", "cb", "aaa"); + // strip empty string + LSTRIP_TEST("", "", ""); + RSTRIP_TEST("", "", ""); + // strip to empty string + LSTRIP_TEST("abcabcabc", "bca", ""); + RSTRIP_TEST("abcabcabc", "bca", ""); + // don't strip wrong end + LSTRIP_TEST("abc", "c", "abc"); + LSTRIP_TEST("abca", "a", "bca"); + RSTRIP_TEST("abc", "a", "abc"); + RSTRIP_TEST("abca", "a", "abc"); + // in utf-8 "¿" (\u00bf) has the same first byte as "µ" (\u00b5) + // and the same second as "ÿ" (\u00ff) + LSTRIP_UTF8_TEST("¿", "µÿ", "¿"); + RSTRIP_UTF8_TEST("¿", "µÿ", "¿"); + LSTRIP_UTF8_TEST("樘", "µÿ", "¿ÿ"); + RSTRIP_UTF8_TEST("樘", "µÿ", "µ¿"); + + // the above tests repeated with additional superfluous strip chars + + // strip none + LSTRIP_TEST("abc", "qwjkl", "abc"); + RSTRIP_TEST("abc", "qwjkl", "abc"); + // strip one + LSTRIP_TEST("abc", "qwajkl", "bc"); + RSTRIP_TEST("abc", "qwcjkl", "ab"); + // strip lots + LSTRIP_TEST("bababbababccc", "qwabjkl", "ccc"); + RSTRIP_TEST("aaabcbcbcbbcbbc", "qwcbjkl", "aaa"); + // strip empty string + LSTRIP_TEST("", "qwjkl", ""); + RSTRIP_TEST("", "qwjkl", ""); + // strip to empty string + LSTRIP_TEST("abcabcabc", "qwbcajkl", ""); + RSTRIP_TEST("abcabcabc", "qwbcajkl", ""); + // don't strip wrong end + LSTRIP_TEST("abc", "qwcjkl", "abc"); + LSTRIP_TEST("abca", "qwajkl", "bca"); + RSTRIP_TEST("abc", "qwajkl", "abc"); + RSTRIP_TEST("abca", "qwajkl", "abc"); + // in utf-8 "¿" (\u00bf) has the same first byte as "µ" (\u00b5) + // and the same second as "ÿ" (\u00ff) + LSTRIP_UTF8_TEST("¿", "qwaµÿjkl", "¿"); + RSTRIP_UTF8_TEST("¿", "qwaµÿjkl", "¿"); + LSTRIP_UTF8_TEST("樘", "qwaµÿjkl", "¿ÿ"); + RSTRIP_UTF8_TEST("樘", "qwaµÿjkl", "µ¿"); + + CHECK(state); + +#undef LSTRIP_TEST +#undef RSTRIP_TEST +#undef LSTRIP_UTF8_TEST +#undef RSTRIP_UTF8_TEST +} + +TEST_CASE("[GDNative String] Cyrillic to_lower()") { + godot_string upper, lower, test; + godot_string_new_with_utf8_chars(&upper, "ÐБВГДЕÐЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬÐЮЯ"); + godot_string_new_with_utf8_chars(&lower, "абвгдеёжзийклмнопрÑтуфхцчшщъыьÑÑŽÑ"); + + test = godot_string_to_lower(&upper); + + CHECK((u32scmp(godot_string_get_data(&test), godot_string_get_data(&lower)) == 0)); + + godot_string_destroy(&upper); + godot_string_destroy(&lower); + godot_string_destroy(&test); +} + +TEST_CASE("[GDNative String] Count and countn functionality") { +#define COUNT_TEST(x, y, r) \ + { \ + godot_string s, t; \ + godot_string_new_with_latin1_chars(&s, x); \ + godot_string_new_with_latin1_chars(&t, y); \ + state = state && (godot_string_count(&s, &t, 0, 0) == r); \ + godot_string_destroy(&s); \ + godot_string_destroy(&t); \ + } + +#define COUNTR_TEST(x, y, a, b, r) \ + { \ + godot_string s, t; \ + godot_string_new_with_latin1_chars(&s, x); \ + godot_string_new_with_latin1_chars(&t, y); \ + state = state && (godot_string_count(&s, &t, a, b) == r); \ + godot_string_destroy(&s); \ + godot_string_destroy(&t); \ + } + +#define COUNTN_TEST(x, y, r) \ + { \ + godot_string s, t; \ + godot_string_new_with_latin1_chars(&s, x); \ + godot_string_new_with_latin1_chars(&t, y); \ + state = state && (godot_string_countn(&s, &t, 0, 0) == r); \ + godot_string_destroy(&s); \ + godot_string_destroy(&t); \ + } + +#define COUNTNR_TEST(x, y, a, b, r) \ + { \ + godot_string s, t; \ + godot_string_new_with_latin1_chars(&s, x); \ + godot_string_new_with_latin1_chars(&t, y); \ + state = state && (godot_string_countn(&s, &t, a, b) == r); \ + godot_string_destroy(&s); \ + godot_string_destroy(&t); \ + } + bool state = true; + + COUNT_TEST("", "Test", 0); + COUNT_TEST("Test", "", 0); + COUNT_TEST("Test", "test", 0); + COUNT_TEST("Test", "TEST", 0); + COUNT_TEST("TEST", "TEST", 1); + COUNT_TEST("Test", "Test", 1); + COUNT_TEST("aTest", "Test", 1); + COUNT_TEST("Testa", "Test", 1); + COUNT_TEST("TestTestTest", "Test", 3); + COUNT_TEST("TestTestTest", "TestTest", 1); + COUNT_TEST("TestGodotTestGodotTestGodot", "Test", 3); + + COUNTR_TEST("TestTestTestTest", "Test", 4, 8, 1); + COUNTR_TEST("TestTestTestTest", "Test", 4, 12, 2); + COUNTR_TEST("TestTestTestTest", "Test", 4, 16, 3); + COUNTR_TEST("TestTestTestTest", "Test", 4, 0, 3); + + COUNTN_TEST("Test", "test", 1); + COUNTN_TEST("Test", "TEST", 1); + COUNTN_TEST("testTest-Testatest", "tEst", 4); + COUNTNR_TEST("testTest-TeStatest", "tEsT", 4, 16, 2); + + CHECK(state); + +#undef COUNT_TEST +#undef COUNTR_TEST +#undef COUNTN_TEST +#undef COUNTNR_TEST +} + +TEST_CASE("[GDNative String] Bigrams") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, "abcd"); + godot_packed_string_array bigr = godot_string_bigrams(&s); + godot_string_destroy(&s); + + CHECK(godot_packed_string_array_size(&bigr) == 3); + + t = godot_packed_string_array_get(&bigr, 0); + CHECK(u32scmp(godot_string_get_data(&t), U"ab") == 0); + godot_string_destroy(&t); + + t = godot_packed_string_array_get(&bigr, 1); + CHECK(u32scmp(godot_string_get_data(&t), U"bc") == 0); + godot_string_destroy(&t); + + t = godot_packed_string_array_get(&bigr, 2); + CHECK(u32scmp(godot_string_get_data(&t), U"cd") == 0); + godot_string_destroy(&t); + + godot_packed_string_array_destroy(&bigr); +} + +TEST_CASE("[GDNative String] c-escape/unescape") { + godot_string s; + godot_string_new_with_latin1_chars(&s, "\\1\a2\b\f3\n45\r6\t7\v8\'9\?0\""); + godot_string t = godot_string_c_escape(&s); + godot_string u = godot_string_c_unescape(&t); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&s)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] dedent") { + godot_string s, t; + godot_string_new_with_latin1_chars(&s, " aaa\n bbb"); + godot_string_new_with_latin1_chars(&t, "aaa\nbbb"); + godot_string u = godot_string_dedent(&s); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Path functions") { + static const char *path[4] = { "C:\\Godot\\project\\test.tscn", "/Godot/project/test.xscn", "../Godot/project/test.scn", "Godot\\test.doc" }; + static const char *base_dir[4] = { "C:\\Godot\\project", "/Godot/project", "../Godot/project", "Godot" }; + static const char *base_name[4] = { "C:\\Godot\\project\\test", "/Godot/project/test", "../Godot/project/test", "Godot\\test" }; + static const char *ext[4] = { "tscn", "xscn", "scn", "doc" }; + static const char *file[4] = { "test.tscn", "test.xscn", "test.scn", "test.doc" }; + static const bool abs[4] = { true, true, false, false }; + + for (int i = 0; i < 4; i++) { + godot_string s, t, u, f; + godot_string_new_with_latin1_chars(&s, path[i]); + + t = godot_string_get_base_dir(&s); + godot_string_new_with_latin1_chars(&u, base_dir[i]); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + t = godot_string_get_basename(&s); + godot_string_new_with_latin1_chars(&u, base_name[i]); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + t = godot_string_get_extension(&s); + godot_string_new_with_latin1_chars(&u, ext[i]); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + t = godot_string_get_file(&s); + godot_string_new_with_latin1_chars(&u, file[i]); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string s_simp; + s_simp = godot_string_simplify_path(&s); + t = godot_string_get_base_dir(&s_simp); + godot_string_new_with_latin1_chars(&u, file[i]); + f = godot_string_plus_file(&t, &u); + CHECK(u32scmp(godot_string_get_data(&f), godot_string_get_data(&s_simp)) == 0); + godot_string_destroy(&f); + godot_string_destroy(&u); + godot_string_destroy(&t); + godot_string_destroy(&s_simp); + + CHECK(godot_string_is_abs_path(&s) == abs[i]); + CHECK(godot_string_is_rel_path(&s) != abs[i]); + + godot_string_destroy(&s); + } + + static const char *file_name[3] = { "test.tscn", "test://.xscn", "?tes*t.scn" }; + static const bool valid[3] = { true, false, false }; + for (int i = 0; i < 3; i++) { + godot_string s; + godot_string_new_with_latin1_chars(&s, file_name[i]); + CHECK(godot_string_is_valid_filename(&s) == valid[i]); + godot_string_destroy(&s); + } +} + +TEST_CASE("[GDNative String] hash") { + godot_string a, b, c; + godot_string_new_with_latin1_chars(&a, "Test"); + godot_string_new_with_latin1_chars(&b, "Test"); + godot_string_new_with_latin1_chars(&c, "West"); + CHECK(godot_string_hash(&a) == godot_string_hash(&b)); + CHECK(godot_string_hash(&a) != godot_string_hash(&c)); + + CHECK(godot_string_hash64(&a) == godot_string_hash64(&b)); + CHECK(godot_string_hash64(&a) != godot_string_hash64(&c)); + + godot_string_destroy(&a); + godot_string_destroy(&b); + godot_string_destroy(&c); +} + +TEST_CASE("[GDNative String] http_escape/unescape") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, "Godot Engine:'docs'"); + godot_string_new_with_latin1_chars(&t, "Godot%20Engine%3A%27docs%27"); + + u = godot_string_http_escape(&s); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + + u = godot_string_http_unescape(&t); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&s)) == 0); + godot_string_destroy(&u); + + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] percent_encode/decode") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, "Godot Engine:'docs'"); + godot_string_new_with_latin1_chars(&t, "Godot%20Engine%3a%27docs%27"); + + u = godot_string_percent_encode(&s); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + + u = godot_string_percent_decode(&t); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&s)) == 0); + godot_string_destroy(&u); + + godot_string_destroy(&s); + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] xml_escape/unescape") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, "\"Test\" <test@test&'test'>"); + + t = godot_string_xml_escape_with_quotes(&s); + u = godot_string_xml_unescape(&t); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&s)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + t = godot_string_xml_escape(&s); + u = godot_string_xml_unescape(&t); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&s)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Strip escapes") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, "\t\tTest Test\r\n Test"); + godot_string_new_with_latin1_chars(&t, "Test Test Test"); + + u = godot_string_strip_escapes(&s); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + + godot_string_destroy(&t); + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Strip edges") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, "\t Test Test "); + + godot_string_new_with_latin1_chars(&t, "Test Test "); + u = godot_string_strip_edges(&s, true, false); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "\t Test Test"); + u = godot_string_strip_edges(&s, false, true); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "Test Test"); + u = godot_string_strip_edges(&s, true, true); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Similarity") { + godot_string a, b, c; + godot_string_new_with_latin1_chars(&a, "Test"); + godot_string_new_with_latin1_chars(&b, "West"); + godot_string_new_with_latin1_chars(&c, "Toad"); + + CHECK(godot_string_similarity(&a, &b) > godot_string_similarity(&a, &c)); + + godot_string_destroy(&a); + godot_string_destroy(&b); + godot_string_destroy(&c); +} + +TEST_CASE("[GDNative String] Trim") { + godot_string s, t, u, p; + godot_string_new_with_latin1_chars(&s, "aaaTestbbb"); + + godot_string_new_with_latin1_chars(&p, "aaa"); + godot_string_new_with_latin1_chars(&t, "Testbbb"); + u = godot_string_trim_prefix(&s, &p); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + godot_string_destroy(&p); + + godot_string_new_with_latin1_chars(&p, "bbb"); + godot_string_new_with_latin1_chars(&t, "aaaTest"); + u = godot_string_trim_suffix(&s, &p); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + godot_string_destroy(&p); + + godot_string_new_with_latin1_chars(&p, "Test"); + u = godot_string_trim_suffix(&s, &p); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&s)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&p); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Right/Left") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, "aaaTestbbb"); + // ^ + + godot_string_new_with_latin1_chars(&t, "tbbb"); + u = godot_string_right(&s, 6); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&t, "aaaTes"); + u = godot_string_left(&s, 6); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_destroy(&s); +} + +TEST_CASE("[GDNative String] Repeat") { + godot_string t, u; + godot_string_new_with_latin1_chars(&t, "ab"); + + u = godot_string_repeat(&t, 4); + CHECK(u32scmp(godot_string_get_data(&u), U"abababab") == 0); + godot_string_destroy(&u); + + godot_string_destroy(&t); +} + +TEST_CASE("[GDNative String] SHA1/SHA256/MD5") { + godot_string s, t, sha1, sha256, md5; + godot_string_new_with_latin1_chars(&s, "Godot"); + godot_string_new_with_latin1_chars(&sha1, "a1e91f39b9fce6a9998b14bdbe2aa2b39dc2d201"); + static uint8_t sha1_buf[20] = { + 0xA1, 0xE9, 0x1F, 0x39, 0xB9, 0xFC, 0xE6, 0xA9, 0x99, 0x8B, 0x14, 0xBD, 0xBE, 0x2A, 0xA2, 0xB3, + 0x9D, 0xC2, 0xD2, 0x01 + }; + godot_string_new_with_latin1_chars(&sha256, "2a02b2443f7985d89d09001086ae3dcfa6eb0f55c6ef170715d42328e16e6cb8"); + static uint8_t sha256_buf[32] = { + 0x2A, 0x02, 0xB2, 0x44, 0x3F, 0x79, 0x85, 0xD8, 0x9D, 0x09, 0x00, 0x10, 0x86, 0xAE, 0x3D, 0xCF, + 0xA6, 0xEB, 0x0F, 0x55, 0xC6, 0xEF, 0x17, 0x07, 0x15, 0xD4, 0x23, 0x28, 0xE1, 0x6E, 0x6C, 0xB8 + }; + godot_string_new_with_latin1_chars(&md5, "4a336d087aeb0390da10ee2ea7cb87f8"); + static uint8_t md5_buf[16] = { + 0x4A, 0x33, 0x6D, 0x08, 0x7A, 0xEB, 0x03, 0x90, 0xDA, 0x10, 0xEE, 0x2E, 0xA7, 0xCB, 0x87, 0xF8 + }; + + godot_packed_byte_array buf = godot_string_sha1_buffer(&s); + CHECK(memcmp(sha1_buf, godot_packed_byte_array_ptr(&buf), 20) == 0); + godot_packed_byte_array_destroy(&buf); + + t = godot_string_sha1_text(&s); + CHECK(u32scmp(godot_string_get_data(&t), godot_string_get_data(&sha1)) == 0); + godot_string_destroy(&t); + + buf = godot_string_sha256_buffer(&s); + CHECK(memcmp(sha256_buf, godot_packed_byte_array_ptr(&buf), 32) == 0); + godot_packed_byte_array_destroy(&buf); + + t = godot_string_sha256_text(&s); + CHECK(u32scmp(godot_string_get_data(&t), godot_string_get_data(&sha256)) == 0); + godot_string_destroy(&t); + + buf = godot_string_md5_buffer(&s); + CHECK(memcmp(md5_buf, godot_packed_byte_array_ptr(&buf), 16) == 0); + godot_packed_byte_array_destroy(&buf); + + t = godot_string_md5_text(&s); + CHECK(u32scmp(godot_string_get_data(&t), godot_string_get_data(&md5)) == 0); + godot_string_destroy(&t); + + godot_string_destroy(&s); + godot_string_destroy(&sha1); + godot_string_destroy(&sha256); + godot_string_destroy(&md5); +} + +TEST_CASE("[GDNative String] Join") { + godot_string s, t, u; + godot_string_new_with_latin1_chars(&s, ", "); + + godot_packed_string_array parts; + godot_packed_string_array_new(&parts); + godot_string_new_with_latin1_chars(&t, "One"); + godot_packed_string_array_push_back(&parts, &t); + godot_string_destroy(&t); + godot_string_new_with_latin1_chars(&t, "B"); + godot_packed_string_array_push_back(&parts, &t); + godot_string_destroy(&t); + godot_string_new_with_latin1_chars(&t, "C"); + godot_packed_string_array_push_back(&parts, &t); + godot_string_destroy(&t); + + godot_string_new_with_latin1_chars(&u, "One, B, C"); + t = godot_string_join(&s, &parts); + CHECK(u32scmp(godot_string_get_data(&u), godot_string_get_data(&t)) == 0); + godot_string_destroy(&u); + godot_string_destroy(&t); + + godot_string_destroy(&s); + godot_packed_string_array_destroy(&parts); +} + +TEST_CASE("[GDNative String] Is_*") { + static const char *data[12] = { "-30", "100", "10.1", "10,1", "1e2", "1e-2", "1e2e3", "0xAB", "AB", "Test1", "1Test", "Test*1" }; + static bool isnum[12] = { true, true, true, false, false, false, false, false, false, false, false, false }; + static bool isint[12] = { true, true, false, false, false, false, false, false, false, false, false, false }; + static bool ishex[12] = { true, true, false, false, true, false, true, false, true, false, false, false }; + static bool ishex_p[12] = { false, false, false, false, false, false, false, true, false, false, false, false }; + static bool isflt[12] = { true, true, true, false, true, true, false, false, false, false, false, false }; + static bool isid[12] = { false, false, false, false, false, false, false, false, true, true, false, false }; + + for (int i = 0; i < 12; i++) { + godot_string s; + godot_string_new_with_latin1_chars(&s, data[i]); + CHECK(godot_string_is_numeric(&s) == isnum[i]); + CHECK(godot_string_is_valid_integer(&s) == isint[i]); + CHECK(godot_string_is_valid_hex_number(&s, false) == ishex[i]); + CHECK(godot_string_is_valid_hex_number(&s, true) == ishex_p[i]); + CHECK(godot_string_is_valid_float(&s) == isflt[i]); + CHECK(godot_string_is_valid_identifier(&s) == isid[i]); + godot_string_destroy(&s); + } +} + +TEST_CASE("[GDNative String] humanize_size") { + godot_string s; + + s = godot_string_humanize_size(1000); + CHECK(u32scmp(godot_string_get_data(&s), U"1000 B") == 0); + godot_string_destroy(&s); + + s = godot_string_humanize_size(1025); + CHECK(u32scmp(godot_string_get_data(&s), U"1.00 KiB") == 0); + godot_string_destroy(&s); + + s = godot_string_humanize_size(1025300); + CHECK(u32scmp(godot_string_get_data(&s), U"1001.2 KiB") == 0); + godot_string_destroy(&s); + + s = godot_string_humanize_size(100523550); + CHECK(u32scmp(godot_string_get_data(&s), U"95.86 MiB") == 0); + godot_string_destroy(&s); + + s = godot_string_humanize_size(5345555000); + CHECK(u32scmp(godot_string_get_data(&s), U"4.97 GiB") == 0); + godot_string_destroy(&s); +} + +} // namespace TestGDNativeString + +#endif // TEST_GDNATIVE_STRING_H diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index e528fc6623..918581bc9b 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -369,24 +369,19 @@ <description> Returns the floating-point modulus of [code]a/b[/code] that wraps equally in positive and negative. [codeblock] - var i = -6 - while i < 5: - prints(i, fposmod(i, 3)) - i += 1 + for i in 7: + var x = 0.5 * i - 1.5 + print("%4.1f %4.1f %4.1f" % [x, fmod(x, 1.5), fposmod(x, 1.5)]) [/codeblock] Produces: [codeblock] - -6 0 - -5 1 - -4 2 - -3 0 - -2 1 - -1 2 - 0 0 - 1 1 - 2 2 - 3 0 - 4 1 + -1.5 -0.0 0.0 + -1.0 -1.0 0.5 + -0.5 -0.5 1.0 + 0.0 0.0 0.0 + 0.5 0.5 0.5 + 1.0 1.0 1.0 + 1.5 0.0 0.0 [/codeblock] </description> </method> @@ -771,24 +766,18 @@ <description> Returns the integer modulus of [code]a/b[/code] that wraps equally in positive and negative. [codeblock] - var i = -6 - while i < 5: - prints(i, posmod(i, 3)) - i += 1 + for i in range(-3, 4): + print("%2.0f %2.0f %2.0f" % [i, i % 3, posmod(i, 3)]) [/codeblock] Produces: [codeblock] - -6 0 - -5 1 - -4 2 - -3 0 - -2 1 - -1 2 - 0 0 - 1 1 - 2 2 - 3 0 - 4 1 + -3 0 0 + -2 -2 1 + -1 -1 2 + 0 0 0 + 1 1 1 + 2 2 2 + 3 0 0 [/codeblock] </description> </method> @@ -991,27 +980,15 @@ <description> Returns an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment). [codeblock] - for i in range(4): - print(i) - for i in range(2, 5): - print(i) - for i in range(0, 6, 2): - print(i) + print(range(4)) + print(range(2, 5)) + print(range(0, 6, 2)) [/codeblock] Output: [codeblock] - 0 - 1 - 2 - 3 - - 2 - 3 - 4 - - 0 - 2 - 4 + [0, 1, 2, 3] + [2, 3, 4] + [0, 2, 4] [/codeblock] </description> </method> diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index e2038954e3..9a3273d201 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -33,15 +33,15 @@ #include "../gdscript_tokenizer.h" #include "editor/editor_settings.h" -static bool _is_char(CharType c) { +static bool _is_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } -static bool _is_hex_symbol(CharType c) { +static bool _is_hex_symbol(char32_t c) { return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } -static bool _is_bin_symbol(CharType c) { +static bool _is_bin_symbol(char32_t c) { return (c == '0' || c == '1'); } @@ -119,7 +119,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) /* search the line */ bool match = true; - const CharType *start_key = color_regions[c].start_key.c_str(); + const char32_t *start_key = color_regions[c].start_key.get_data(); for (int k = 0; k < start_key_length; k++) { if (start_key[k] != str[from + k]) { match = false; @@ -156,7 +156,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting(int p_line) /* search the line */ int region_end_index = -1; int end_key_length = color_regions[in_region].end_key.length(); - const CharType *end_key = color_regions[in_region].end_key.c_str(); + const char32_t *end_key = color_regions[in_region].end_key.get_data(); for (; from < line_length; from++) { if (line_length - from < end_key_length) { break; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 788b3c87ab..943a49060f 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -794,7 +794,7 @@ void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) { resolve_match_branch(static_cast<GDScriptParser::MatchBranchNode *>(p_node), nullptr); break; case GDScriptParser::Node::PARAMETER: - resolve_pararameter(static_cast<GDScriptParser::ParameterNode *>(p_node)); + resolve_parameter(static_cast<GDScriptParser::ParameterNode *>(p_node)); break; case GDScriptParser::Node::PATTERN: resolve_match_pattern(static_cast<GDScriptParser::PatternNode *>(p_node), nullptr); @@ -848,7 +848,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * parser->current_function = p_function; for (int i = 0; i < p_function->parameters.size(); i++) { - resolve_pararameter(p_function->parameters[i]); + resolve_parameter(p_function->parameters[i]); #ifdef DEBUG_ENABLED if (p_function->parameters[i]->usages == 0 && !String(p_function->parameters[i]->identifier->name).begins_with("_")) { parser->push_warning(p_function->parameters[i]->identifier, GDScriptWarning::UNUSED_PARAMETER, p_function->identifier->name, p_function->parameters[i]->identifier->name); @@ -1264,14 +1264,18 @@ void GDScriptAnalyzer::resolve_match_pattern(GDScriptParser::PatternNode *p_matc p_match_pattern->set_datatype(result); } -void GDScriptAnalyzer::resolve_pararameter(GDScriptParser::ParameterNode *p_parameter) { +void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parameter) { GDScriptParser::DataType result; result.kind = GDScriptParser::DataType::VARIANT; if (p_parameter->default_value != nullptr) { reduce_expression(p_parameter->default_value); result = p_parameter->default_value->get_datatype(); - result.type_source = GDScriptParser::DataType::INFERRED; + if (p_parameter->infer_datatype) { + result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + } else { + result.type_source = GDScriptParser::DataType::INFERRED; + } result.is_constant = false; } @@ -1282,7 +1286,7 @@ void GDScriptAnalyzer::resolve_pararameter(GDScriptParser::ParameterNode *p_para if (p_parameter->default_value != nullptr) { if (!is_type_compatible(result, p_parameter->default_value->get_datatype())) { - push_error(vformat(R"(Type of default value for parameter "%s" (%s) is not compatible with paremeter type (%s).)", p_parameter->identifier->name, p_parameter->default_value->get_datatype().to_string(), p_parameter->datatype_specifier->get_datatype().to_string()), p_parameter->default_value); + push_error(vformat(R"(Type of default value for parameter "%s" (%s) is not compatible with parameter type (%s).)", p_parameter->identifier->name, p_parameter->default_value->get_datatype().to_string(), p_parameter->datatype_specifier->get_datatype().to_string()), p_parameter->default_value); } else if (p_parameter->default_value->get_datatype().is_variant()) { mark_node_unsafe(p_parameter); } @@ -2073,18 +2077,32 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod push_error(vformat(R"(Cannot find constant "%s" on type "%s".)", name, base.to_string()), p_identifier); } } else { - Callable::CallError temp; - Variant dummy = Variant::construct(base.builtin_type, nullptr, 0, temp); - List<PropertyInfo> properties; - dummy.get_property_list(&properties); - for (const List<PropertyInfo>::Element *E = properties.front(); E != nullptr; E = E->next()) { - const PropertyInfo &prop = E->get(); - if (prop.name == name) { - p_identifier->set_datatype(type_from_property(prop)); + switch (base.builtin_type) { + case Variant::NIL: { + push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier); + return; + } + case Variant::DICTIONARY: { + GDScriptParser::DataType dummy; + dummy.kind = GDScriptParser::DataType::VARIANT; + p_identifier->set_datatype(dummy); return; } + default: { + Callable::CallError temp; + Variant dummy = Variant::construct(base.builtin_type, nullptr, 0, temp); + List<PropertyInfo> properties; + dummy.get_property_list(&properties); + for (const List<PropertyInfo>::Element *E = properties.front(); E != nullptr; E = E->next()) { + const PropertyInfo &prop = E->get(); + if (prop.name == name) { + p_identifier->set_datatype(type_from_property(prop)); + return; + } + } + push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); + } } - push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); } return; } @@ -2969,7 +2987,7 @@ bool GDScriptAnalyzer::validate_call_arg(const List<GDScriptParser::DataType> &p if (arg_type.is_variant()) { // Argument can be anything, so this is unsafe. mark_node_unsafe(p_call->arguments[i]); - } else if (!is_type_compatible(par_type, arg_type, true)) { + } else if (par_type.is_hard_type() && !is_type_compatible(par_type, arg_type, true)) { // Supertypes are acceptable for dynamic compliance, but it's unsafe. mark_node_unsafe(p_call); if (!is_type_compatible(arg_type, par_type)) { diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 4e06e0a530..c3911cce76 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -67,7 +67,7 @@ class GDScriptAnalyzer { void resolve_match(GDScriptParser::MatchNode *p_match); void resolve_match_branch(GDScriptParser::MatchBranchNode *p_match_branch, GDScriptParser::ExpressionNode *p_match_test); void resolve_match_pattern(GDScriptParser::PatternNode *p_match_pattern, GDScriptParser::ExpressionNode *p_match_test); - void resolve_pararameter(GDScriptParser::ParameterNode *p_parameter); + void resolve_parameter(GDScriptParser::ParameterNode *p_parameter); void resolve_return(GDScriptParser::ReturnNode *p_return); // Reduction functions. diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 992f8f4b58..57b95f5b21 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -108,20 +108,20 @@ GDScriptParserRef::~GDScriptParserRef() { if (analyzer != nullptr) { memdelete(analyzer); } - MutexLock(GDScriptCache::singleton->lock); + MutexLock lock(GDScriptCache::singleton->lock); GDScriptCache::singleton->parser_map.erase(path); } GDScriptCache *GDScriptCache::singleton = nullptr; void GDScriptCache::remove_script(const String &p_path) { - MutexLock(singleton->lock); + MutexLock lock(singleton->lock); singleton->shallow_gdscript_cache.erase(p_path); singleton->full_gdscript_cache.erase(p_path); } Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptParserRef::Status p_status, Error &r_error, const String &p_owner) { - MutexLock(singleton->lock); + MutexLock lock(singleton->lock); Ref<GDScriptParserRef> ref; if (p_owner != String()) { singleton->dependencies[p_owner].insert(p_path); @@ -168,7 +168,7 @@ String GDScriptCache::get_source_code(const String &p_path) { } Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const String &p_owner) { - MutexLock(singleton->lock); + MutexLock lock(singleton->lock); if (p_owner != String()) { singleton->dependencies[p_owner].insert(p_path); } @@ -190,7 +190,7 @@ Ref<GDScript> GDScriptCache::get_shallow_script(const String &p_path, const Stri } Ref<GDScript> GDScriptCache::get_full_script(const String &p_path, Error &r_error, const String &p_owner) { - MutexLock(singleton->lock); + MutexLock lock(singleton->lock); if (p_owner != String()) { singleton->dependencies[p_owner].insert(p_path); diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index aa48a7cdb4..e59f99fc56 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1058,7 +1058,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a err_text = "Got a freed object as a result of the call."; OPCODE_BREAK; } - if (obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) { + if (obj && obj->is_class_ptr(GDScriptFunctionState::get_class_ptr_static())) { err_text = R"(Trying to call an async function without "await".)"; OPCODE_BREAK; } diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp index fefbf906f0..31ce63bc6e 100644 --- a/modules/gdscript/gdscript_functions.cpp +++ b/modules/gdscript/gdscript_functions.cpp @@ -635,7 +635,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_ case TEXT_CHAR: { VALIDATE_ARG_COUNT(1); VALIDATE_ARG_NUM(0); - CharType result[2] = { *p_args[0], 0 }; + char32_t result[2] = { *p_args[0], 0 }; r_ret = String(result); } break; case TEXT_ORD: { diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d890103f15..2a69db130b 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -327,7 +327,7 @@ Error GDScriptParser::parse(const String &p_source_code, const String &p_script_ bool found = false; const String &line = lines[i]; for (int j = 0; j < line.size(); j++) { - if (line[j] == CharType(0xFFFF)) { + if (line[j] == char32_t(0xFFFF)) { found = true; break; } else if (line[j] == '\t') { @@ -1042,7 +1042,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { if (check(GDScriptTokenizer::Token::BRACE_CLOSE)) { break; // Allow trailing comma. } - if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifer for enum key.)")) { + if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier for enum key.)")) { EnumNode::Value item; item.identifier = parse_identifier(); item.parent_enum = enum_node; @@ -2516,7 +2516,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p_previous_operand, bool p_can_assign) { if (match(GDScriptTokenizer::Token::LITERAL)) { if (previous.literal.get_type() != Variant::STRING) { - push_error(R"(Expect node path as string or identifer after "$".)"); + push_error(R"(Expect node path as string or identifier after "$".)"); return nullptr; } GetNodeNode *get_node = alloc_node<GetNodeNode>(); @@ -2539,7 +2539,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p } while (match(GDScriptTokenizer::Token::SLASH)); return get_node; } else { - push_error(R"(Expect node path as string or identifer after "$".)"); + push_error(R"(Expect node path as string or identifier after "$".)"); return nullptr; } } diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index f5cf1e29f0..9a40aa50ac 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -222,7 +222,7 @@ String GDScriptTokenizer::get_token_name(Token::Type p_token_type) { void GDScriptTokenizer::set_source_code(const String &p_source_code) { source = p_source_code; if (source.empty()) { - _source = L""; + _source = U""; } else { _source = source.ptr(); } @@ -263,7 +263,7 @@ bool GDScriptTokenizer::is_past_cursor() const { return true; } -CharType GDScriptTokenizer::_advance() { +char32_t GDScriptTokenizer::_advance() { if (unlikely(_is_at_end())) { return '\0'; } @@ -282,15 +282,15 @@ CharType GDScriptTokenizer::_advance() { return _peek(-1); } -void GDScriptTokenizer::push_paren(CharType p_char) { +void GDScriptTokenizer::push_paren(char32_t p_char) { paren_stack.push_back(p_char); } -bool GDScriptTokenizer::pop_paren(CharType p_expected) { +bool GDScriptTokenizer::pop_paren(char32_t p_expected) { if (paren_stack.empty()) { return false; } - CharType actual = paren_stack.back()->get(); + char32_t actual = paren_stack.back()->get(); paren_stack.pop_back(); return actual == p_expected; @@ -302,19 +302,19 @@ GDScriptTokenizer::Token GDScriptTokenizer::pop_error() { return error; } -static bool _is_alphanumeric(CharType c) { +static bool _is_alphanumeric(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } -static bool _is_digit(CharType c) { +static bool _is_digit(char32_t c) { return (c >= '0' && c <= '9'); } -static bool _is_hex_digit(CharType c) { +static bool _is_hex_digit(char32_t c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } -static bool _is_binary_digit(CharType c) { +static bool _is_binary_digit(char32_t c) { return (c == '0' || c == '1'); } @@ -404,7 +404,7 @@ void GDScriptTokenizer::push_error(const Token &p_error) { error_stack.push_back(p_error); } -GDScriptTokenizer::Token GDScriptTokenizer::make_paren_error(CharType p_paren) { +GDScriptTokenizer::Token GDScriptTokenizer::make_paren_error(char32_t p_paren) { if (paren_stack.empty()) { return make_error(vformat("Closing \"%c\" doesn't have an opening counterpart.", p_paren)); } @@ -413,8 +413,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::make_paren_error(CharType p_paren) { return error; } -GDScriptTokenizer::Token GDScriptTokenizer::check_vcs_marker(CharType p_test, Token::Type p_double_type) { - const CharType *next = _current + 1; +GDScriptTokenizer::Token GDScriptTokenizer::check_vcs_marker(char32_t p_test, Token::Type p_double_type) { + const char32_t *next = _current + 1; int chars = 2; // Two already matched. // Test before consuming characters, since we don't want to consume more than needed. @@ -578,7 +578,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::potential_identifier() { } void GDScriptTokenizer::newline(bool p_make_token) { - // Don't overwrite previous newline, nor create if we want a line contination. + // Don't overwrite previous newline, nor create if we want a line continuation. if (p_make_token && !pending_newline && !line_continuation) { Token newline(Token::NEWLINE); newline.start_line = line; @@ -602,7 +602,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::number() { bool has_decimal = false; bool has_exponent = false; bool has_error = false; - bool (*digit_check_func)(CharType) = _is_digit; + bool (*digit_check_func)(char32_t) = _is_digit; if (_peek(-1) == '.') { has_decimal = true; @@ -762,7 +762,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() { _advance(); } - CharType quote_char = _peek(-1); + char32_t quote_char = _peek(-1); if (_peek() == quote_char && _peek(1) == quote_char) { is_multiline = true; @@ -779,7 +779,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() { return make_error("Unterminated string."); } - CharType ch = _peek(); + char32_t ch = _peek(); if (ch == '\\') { // Escape pattern. @@ -789,13 +789,13 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() { } // Grab escape character. - CharType code = _peek(); + char32_t code = _peek(); _advance(); if (_is_at_end()) { return make_error("Unterminated string."); } - CharType escaped = 0; + char32_t escaped = 0; bool valid_escape = true; switch (code) { @@ -836,8 +836,8 @@ GDScriptTokenizer::Token GDScriptTokenizer::string() { return make_error("Unterminated string."); } - CharType digit = _peek(); - CharType value = 0; + char32_t digit = _peek(); + char32_t value = 0; if (digit >= '0' && digit <= '9') { value = digit - '0'; } else if (digit >= 'a' && digit <= 'f') { @@ -940,7 +940,7 @@ void GDScriptTokenizer::check_indent() { } for (;;) { - CharType current_indent_char = _peek(); + char32_t current_indent_char = _peek(); int indent_count = 0; if (current_indent_char != ' ' && current_indent_char != '\t' && current_indent_char != '\r' && current_indent_char != '\n' && current_indent_char != '#') { @@ -970,7 +970,7 @@ void GDScriptTokenizer::check_indent() { // Check indent level. bool mixed = false; while (!_is_at_end()) { - CharType space = _peek(); + char32_t space = _peek(); if (space == '\t') { // Consider individual tab columns. column += tab_size - 1; @@ -1103,7 +1103,7 @@ void GDScriptTokenizer::_skip_whitespace() { } for (;;) { - CharType c = _peek(); + char32_t c = _peek(); switch (c) { case ' ': _advance(); @@ -1192,7 +1192,7 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() { return make_token(Token::TK_EOF); } - const CharType c = _advance(); + const char32_t c = _advance(); if (c == '\\') { // Line continuation with backslash. diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 100ed3f132..4453982d08 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -183,14 +183,14 @@ public: private: String source; - const CharType *_source = nullptr; - const CharType *_current = nullptr; + const char32_t *_source = nullptr; + const char32_t *_current = nullptr; int line = -1, column = -1; int cursor_line = -1, cursor_column = -1; int tab_size = 4; // Keep track of multichar tokens. - const CharType *_start = nullptr; + const char32_t *_start = nullptr; int start_line = 0, start_column = 0; int leftmost_column = 0, rightmost_column = 0; @@ -202,30 +202,30 @@ private: Token last_newline; int pending_indents = 0; List<int> indent_stack; - List<CharType> paren_stack; - CharType indent_char = '\0'; + List<char32_t> paren_stack; + char32_t indent_char = '\0'; int position = 0; int length = 0; _FORCE_INLINE_ bool _is_at_end() { return position >= length; } - _FORCE_INLINE_ CharType _peek(int p_offset = 0) { return position + p_offset >= 0 && position + p_offset < length ? _current[p_offset] : '\0'; } + _FORCE_INLINE_ char32_t _peek(int p_offset = 0) { return position + p_offset >= 0 && position + p_offset < length ? _current[p_offset] : '\0'; } int indent_level() const { return indent_stack.size(); } bool has_error() const { return !error_stack.empty(); } Token pop_error(); - CharType _advance(); + char32_t _advance(); void _skip_whitespace(); void check_indent(); Token make_error(const String &p_message); void push_error(const String &p_message); void push_error(const Token &p_error); - Token make_paren_error(CharType p_paren); + Token make_paren_error(char32_t p_paren); Token make_token(Token::Type p_type); Token make_literal(const Variant &p_literal); Token make_identifier(const StringName &p_identifier); - Token check_vcs_marker(CharType p_test, Token::Type p_double_type); - void push_paren(CharType p_char); - bool pop_paren(CharType p_expected); + Token check_vcs_marker(char32_t p_test, Token::Type p_double_type); + void push_paren(char32_t p_char); + bool pop_paren(char32_t p_expected); void newline(bool p_make_token); Token number(); diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 4d79d9d395..668dfd4835 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -491,7 +491,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position & int start_pos = p_position.character; for (int c = p_position.character; c >= 0; c--) { start_pos = c; - CharType ch = line[c]; + char32_t ch = line[c]; bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; if (!valid_char) { break; @@ -500,7 +500,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position & int end_pos = p_position.character; for (int c = p_position.character; c < line.length(); c++) { - CharType ch = line[c]; + char32_t ch = line[c]; bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; if (!valid_char) { break; @@ -552,7 +552,7 @@ Error ExtendGDScriptParser::get_left_function_call(const lsp::Position &p_positi } while (c >= 0) { - const CharType &character = line[c]; + const char32_t &character = line[c]; if (character == ')') { ++bracket_stack; } else if (character == '(') { diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 7dad878eb1..da4cbe34c7 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -84,7 +84,7 @@ public: return; } - // TODO: Readd compiled/encrypted GDScript on export. + // TODO: Readd compiled GDScript on export. return; } }; diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp index 501bfff075..12a982df6e 100644 --- a/modules/mbedtls/crypto_mbedtls.cpp +++ b/modules/mbedtls/crypto_mbedtls.cpp @@ -43,8 +43,8 @@ #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" #define PEM_END_CRT "-----END CERTIFICATE-----\n" -#include "mbedtls/pem.h" #include <mbedtls/debug.h> +#include <mbedtls/pem.h> CryptoKey *CryptoKeyMbedTLS::create() { return memnew(CryptoKeyMbedTLS); @@ -294,20 +294,15 @@ Ref<X509Certificate> CryptoMbedTLS::generate_self_signed_certificate(Ref<CryptoK unsigned char buf[4096]; memset(buf, 0, 4096); - Ref<X509CertificateMbedTLS> out; - out.instance(); - mbedtls_x509write_crt_pem(&crt, buf, 4096, mbedtls_ctr_drbg_random, &ctr_drbg); - - int err = mbedtls_x509_crt_parse(&(out->cert), buf, 4096); - if (err != 0) { - mbedtls_mpi_free(&serial); - mbedtls_x509write_crt_free(&crt); - ERR_PRINT("Generated invalid certificate: " + itos(err)); - return nullptr; - } - + int ret = mbedtls_x509write_crt_pem(&crt, buf, 4096, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_mpi_free(&serial); mbedtls_x509write_crt_free(&crt); + ERR_FAIL_COND_V_MSG(ret != 0, nullptr, "Failed to generate certificate: " + itos(ret)); + buf[4095] = '\0'; // Make sure strlen can't fail. + + Ref<X509CertificateMbedTLS> out; + out.instance(); + out->load_from_memory(buf, strlen((char *)buf) + 1); // Use strlen to find correct output size. return out; } diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 3e771e06f0..e959312393 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -1,6 +1,5 @@ import os import os.path -import sys import subprocess from SCons.Script import Dir, Environment diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py index 03f4e57f02..6a621c3c8b 100644 --- a/modules/mono/build_scripts/solution_builder.py +++ b/modules/mono/build_scripts/solution_builder.py @@ -8,9 +8,6 @@ def find_dotnet_cli(): import os.path if os.name == "nt": - windows_exts = os.environ["PATHEXT"] - windows_exts = windows_exts.split(os.pathsep) if windows_exts else [] - for hint_dir in os.environ["PATH"].split(os.pathsep): hint_dir = hint_dir.strip('"') hint_path = os.path.join(hint_dir, "dotnet") diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index dfc59e6ccb..4f8faffde2 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -88,7 +88,7 @@ <PropertyGroup> <!-- ExportDebug also defines DEBUG like Debug does. --> <DefineConstants Condition=" '$(Configuration)' == 'ExportDebug' ">$(DefineConstants);DEBUG</DefineConstants> - <!-- Debug defines TOOLS to differenciate between Debug and ExportDebug configurations. --> + <!-- Debug defines TOOLS to differentiate between Debug and ExportDebug configurations. --> <DefineConstants Condition=" '$(Configuration)' == 'Debug' ">$(DefineConstants);TOOLS</DefineConstants> <DefineConstants>$(GodotDefineConstants);$(DefineConstants)</DefineConstants> diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs index e6b0e8f1df..b217ae4bf7 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; namespace GodotTools.Core { @@ -14,14 +15,18 @@ namespace GodotTools.Core if (Path.DirectorySeparatorChar == '\\') dir = dir.Replace("/", "\\") + "\\"; - Uri fullPath = new Uri(Path.GetFullPath(path), UriKind.Absolute); - Uri relRoot = new Uri(Path.GetFullPath(dir), UriKind.Absolute); + var fullPath = new Uri(Path.GetFullPath(path), UriKind.Absolute); + var relRoot = new Uri(Path.GetFullPath(dir), UriKind.Absolute); - return relRoot.MakeRelativeUri(fullPath).ToString(); + // MakeRelativeUri converts spaces to %20, hence why we need UnescapeDataString + return Uri.UnescapeDataString(relRoot.MakeRelativeUri(fullPath).ToString()); } public static string NormalizePath(this string path) { + if (string.IsNullOrEmpty(path)) + return path; + bool rooted = path.IsAbsolutePath(); path = path.Replace('\\', '/'); @@ -31,7 +36,17 @@ namespace GodotTools.Core path = string.Join(Path.DirectorySeparatorChar.ToString(), parts).Trim(); - return rooted ? Path.DirectorySeparatorChar + path : path; + if (!rooted) + return path; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + string maybeDrive = parts[0]; + if (maybeDrive.Length == 2 && maybeDrive[1] == ':') + return path; // Already has drive letter + } + + return Path.DirectorySeparatorChar + path; } private static readonly string DriveRoot = Path.GetPathRoot(Environment.CurrentDirectory); @@ -45,7 +60,7 @@ namespace GodotTools.Core public static string ToSafeDirName(this string dirName, bool allowDirSeparator = false) { - var invalidChars = new List<string> { ":", "*", "?", "\"", "<", ">", "|" }; + var invalidChars = new List<string> {":", "*", "?", "\"", "<", ">", "|"}; if (allowDirSeparator) { diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs index 6f318aab4a..cc0da44a13 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs @@ -2,6 +2,7 @@ using GodotTools.Core; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; namespace GodotTools.ProjectEditor @@ -88,7 +89,7 @@ namespace GodotTools.ProjectEditor string solutionPath = Path.Combine(DirectoryPath, Name + ".sln"); string content = string.Format(SolutionTemplate, projectsDecl, slnPlatformsCfg, projPlatformsCfg); - File.WriteAllText(solutionPath, content); + File.WriteAllText(solutionPath, content, Encoding.UTF8); // UTF-8 with BOM } public DotNetSolution(string name) diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs index 4041c56597..4e2c0f17cc 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs @@ -61,10 +61,9 @@ namespace GodotTools.ProjectEditor if (item.ItemType != itemType) continue; - string normalizedExclude = item.Exclude.NormalizePath(); - - var glob = MSBuildGlob.Parse(normalizedExclude); + string normalizedRemove = item.Remove.NormalizePath(); + var glob = MSBuildGlob.Parse(normalizedRemove); excluded.AddRange(includedFiles.Where(includedFile => glob.IsMatch(includedFile))); } diff --git a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs index a8afb38728..1d800b8151 100644 --- a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs +++ b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs @@ -48,7 +48,7 @@ namespace GodotTools var firstMatch = classes.FirstOrDefault(classDecl => classDecl.BaseCount != 0 && // If it doesn't inherit anything, it can't be a Godot.Object. - classDecl.SearchName != searchName // Filter by the name we're looking for + classDecl.SearchName == searchName // Filter by the name we're looking for ); if (firstMatch == null) diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index f60e469503..42ede3f3f3 100755 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -328,7 +328,7 @@ MONO_AOT_MODE_LAST = 1000, if (lipoExitCode != 0) throw new Exception($"Command 'lipo' exited with code: {lipoExitCode}"); - // TODO: Add the AOT lib and interpreter libs as device only to supress warnings when targeting the simulator + // TODO: Add the AOT lib and interpreter libs as device only to suppress warnings when targeting the simulator // Add the fat AOT static library to the Xcode project exporter.AddIosProjectStaticLib(fatOutputFilePath); diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 3148458d7e..2a450c5b87 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -31,6 +31,7 @@ namespace GodotTools private CheckBox aboutDialogCheckBox; private Button bottomPanelBtn; + private Button toolBarBuildButton; public GodotIdeManager GodotIdeManager { get; private set; } @@ -127,6 +128,7 @@ namespace GodotTools { menuPopup.RemoveItem(menuPopup.GetItemIndex((int)MenuOptions.CreateSln)); bottomPanelBtn.Show(); + toolBarBuildButton.Show(); } private void _ShowAboutDialog() @@ -468,6 +470,15 @@ namespace GodotTools aboutVBox.AddChild(aboutDialogCheckBox); } + toolBarBuildButton = new Button + { + Text = "Build", + HintTooltip = "Build solution", + FocusMode = Control.FocusModeEnum.None + }; + toolBarBuildButton.PressedSignal += _BuildSolutionPressed; + AddControlToContainer(CustomControlContainer.Toolbar, toolBarBuildButton); + if (File.Exists(GodotSharpDirs.ProjectSlnPath) && File.Exists(GodotSharpDirs.ProjectCsProjPath)) { ApplyNecessaryChangesToSolution(); @@ -475,20 +486,12 @@ namespace GodotTools else { bottomPanelBtn.Hide(); + toolBarBuildButton.Hide(); menuPopup.AddItem("Create C# solution".TTR(), (int)MenuOptions.CreateSln); } menuPopup.IdPressed += _MenuOptionPressed; - var buildButton = new Button - { - Text = "Build", - HintTooltip = "Build solution", - FocusMode = Control.FocusModeEnum.None - }; - buildButton.PressedSignal += _BuildSolutionPressed; - AddControlToContainer(CustomControlContainer.Toolbar, buildButton); - // External editor settings EditorDef("mono/editor/external_editor", ExternalEditorId.None); diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp index 430c82953e..f7d6e7e302 100644 --- a/modules/mono/editor/script_class_parser.cpp +++ b/modules/mono/editor/script_class_parser.cpp @@ -151,7 +151,7 @@ ScriptClassParser::Token ScriptClassParser::get_token() { case '"': { bool verbatim = idx != 0 && code[idx - 1] == '@'; - CharType begin_str = code[idx]; + char32_t begin_str = code[idx]; idx++; String tk_string = String(); while (true) { @@ -170,13 +170,13 @@ ScriptClassParser::Token ScriptClassParser::get_token() { } else if (code[idx] == '\\' && !verbatim) { //escaped characters... idx++; - CharType next = code[idx]; + char32_t next = code[idx]; if (next == 0) { error_str = "Unterminated String"; error = true; return TK_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -234,7 +234,7 @@ ScriptClassParser::Token ScriptClassParser::get_token() { if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) { //a number - const CharType *rptr; + const char32_t *rptr; double number = String::to_float(&code[idx], &rptr); idx += (rptr - &code[idx]); value = number; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index a963810d63..f77d3052f4 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -44,6 +44,15 @@ namespace Godot.Collections Add(element); } + public Array(params object[] array) : this() + { + if (array == null) + { + throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'"); + } + safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array)); + } + internal Array(ArraySafeHandle handle) { safeHandle = handle; @@ -72,6 +81,11 @@ namespace Godot.Collections return godot_icall_Array_Resize(GetPtr(), newSize); } + public static Array operator +(Array left, Array right) + { + return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr())); + } + // IDisposable public void Dispose() @@ -155,6 +169,9 @@ namespace Godot.Collections internal extern static IntPtr godot_icall_Array_Ctor(); [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array); + + [MethodImpl(MethodImplOptions.InternalCall)] internal extern static void godot_icall_Array_Dtor(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] @@ -176,6 +193,9 @@ namespace Godot.Collections internal extern static void godot_icall_Array_Clear(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] + internal extern static IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right); + + [MethodImpl(MethodImplOptions.InternalCall)] internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item); [MethodImpl(MethodImplOptions.InternalCall)] @@ -231,6 +251,15 @@ namespace Godot.Collections objectArray = new Array(collection); } + public Array(params T[] array) : this() + { + if (array == null) + { + throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'"); + } + objectArray = new Array(array); + } + public Array(Array array) { objectArray = array; @@ -266,6 +295,11 @@ namespace Godot.Collections return objectArray.Resize(newSize); } + public static Array<T> operator +(Array<T> left, Array<T> right) + { + return new Array<T>(left.objectArray + right.objectArray); + } + // IList<T> public T this[int index] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index 41b4e9367f..9421a24b34 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -624,41 +624,46 @@ namespace Godot return instance.Length; } - // <summary> - // Do a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'. - // </summary> - public static bool ExprMatch(this string instance, string expr, bool caseSensitive) + /// <summary> + /// Do a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'. + /// </summary> + private static bool ExprMatch(this string instance, string expr, bool caseSensitive) { - if (expr.Length == 0 || instance.Length == 0) - return false; + // case '\0': + if (expr.Length == 0) + return instance.Length == 0; switch (expr[0]) { - case '\0': - return instance[0] == 0; case '*': - return ExprMatch(expr + 1, instance, caseSensitive) || instance[0] != 0 && ExprMatch(expr, instance + 1, caseSensitive); + return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && ExprMatch(instance.Substring(1), expr, caseSensitive)); case '?': - return instance[0] != 0 && instance[0] != '.' && ExprMatch(expr + 1, instance + 1, caseSensitive); + return instance.Length > 0 && instance[0] != '.' && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); default: - return (caseSensitive ? instance[0] == expr[0] : char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && - ExprMatch(expr + 1, instance + 1, caseSensitive); + if (instance.Length == 0) return false; + return (caseSensitive ? instance[0] == expr[0] : char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); } } - // <summary> - // Do a simple case sensitive expression match, using ? and * wildcards (see [method expr_match]). - // </summary> + /// <summary> + /// Do a simple case sensitive expression match, using ? and * wildcards (see [method expr_match]). + /// </summary> public static bool Match(this string instance, string expr, bool caseSensitive = true) { + if (instance.Length == 0 || expr.Length == 0) + return false; + return instance.ExprMatch(expr, caseSensitive); } - // <summary> - // Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]). - // </summary> + /// <summary> + /// Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]). + /// </summary> public static bool MatchN(this string instance, string expr) { + if (instance.Length == 0 || expr.Length == 0) + return false; + return instance.ExprMatch(expr, caseSensitive: false); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 26bd828a5b..3dff37279b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -670,41 +670,37 @@ namespace Godot public static bool operator <(Vector2 left, Vector2 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { return left.y < right.y; } - return left.x < right.x; } public static bool operator >(Vector2 left, Vector2 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { return left.y > right.y; } - return left.x > right.x; } public static bool operator <=(Vector2 left, Vector2 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { return left.y <= right.y; } - return left.x <= right.x; } public static bool operator >=(Vector2 left, Vector2 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { return left.y >= right.y; } - return left.x >= right.x; } @@ -714,7 +710,6 @@ namespace Godot { return Equals((Vector2)obj); } - return false; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index d9b16a6afd..4a4a2a43cd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -713,49 +713,53 @@ namespace Godot public static bool operator <(Vector3 left, Vector3 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { - if (Mathf.IsEqualApprox(left.y, right.y)) + if (left.y == right.y) + { return left.z < right.z; + } return left.y < right.y; } - return left.x < right.x; } public static bool operator >(Vector3 left, Vector3 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { - if (Mathf.IsEqualApprox(left.y, right.y)) + if (left.y == right.y) + { return left.z > right.z; + } return left.y > right.y; } - return left.x > right.x; } public static bool operator <=(Vector3 left, Vector3 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { - if (Mathf.IsEqualApprox(left.y, right.y)) + if (left.y == right.y) + { return left.z <= right.z; + } return left.y < right.y; } - return left.x < right.x; } public static bool operator >=(Vector3 left, Vector3 right) { - if (Mathf.IsEqualApprox(left.x, right.x)) + if (left.x == right.x) { - if (Mathf.IsEqualApprox(left.y, right.y)) + if (left.y == right.y) + { return left.z >= right.z; + } return left.y > right.y; } - return left.x > right.x; } diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp index 766b00d612..3313e8cb77 100644 --- a/modules/mono/glue/collections_glue.cpp +++ b/modules/mono/glue/collections_glue.cpp @@ -104,10 +104,31 @@ void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index) { } } +Array *godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array) { + Array *godot_array = memnew(Array); + unsigned int count = mono_array_length(mono_array); + godot_array->resize(count); + for (unsigned int i = 0; i < count; i++) { + MonoObject *item = mono_array_get(mono_array, MonoObject *, i); + godot_icall_Array_SetAt(godot_array, i, item); + } + return godot_array; +} + Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) { return memnew(Array(ptr->duplicate(deep))); } +Array *godot_icall_Array_Concatenate(Array *left, Array *right) { + int count = left->size() + right->size(); + Array *new_array = memnew(Array(left->duplicate(false))); + new_array->resize(count); + for (unsigned int i = 0; i < (unsigned int)right->size(); i++) { + new_array->operator[](i + left->size()) = right->operator[](i); + } + return new_array; +} + int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) { return ptr->find(GDMonoMarshal::mono_object_to_variant(item)); } @@ -284,6 +305,7 @@ MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) { void godot_register_collections_icalls() { mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor_MonoArray", (void *)godot_icall_Array_Ctor_MonoArray); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At", (void *)godot_icall_Array_At); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At_Generic", (void *)godot_icall_Array_At_Generic); @@ -291,6 +313,7 @@ void godot_register_collections_icalls() { mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear); + mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Concatenate", (void *)godot_icall_Array_Concatenate); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo); mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Duplicate", (void *)godot_icall_Array_Duplicate); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 9dbeee57ce..6e351001d4 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -107,7 +107,7 @@ void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, [[maybe_unused]] GDMonoAssembly *gdassembly = memnew(GDMonoAssembly(name, image, assembly)); #ifdef GD_MONO_HOT_RELOAD - const char *path = mono_image_get_filename(image); + String path = String::utf8(mono_image_get_filename(image)); if (FileAccess::exists(path)) { gdassembly->modified_time = FileAccess::get_modified_time(path); } @@ -464,7 +464,9 @@ GDMonoAssembly *GDMonoAssembly::load(const String &p_name, MonoAssemblyName *p_a if (!assembly) { assembly = _load_assembly_search(p_name, p_aname, p_refonly, p_search_dirs); - ERR_FAIL_NULL_V(assembly, nullptr); + if (!assembly) { + return nullptr; + } } GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); @@ -487,7 +489,9 @@ GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_ if (!assembly) { assembly = _real_load_assembly_from(p_path, p_refonly); - ERR_FAIL_NULL_V(assembly, nullptr); + if (!assembly) { + return nullptr; + } } GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index c5a988b8c3..b8ee0204c4 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -64,25 +64,32 @@ static int get_log_level_id(const char *p_log_level) { return -1; } +static String make_text(const char *log_domain, const char *log_level, const char *message) { + String text(message); + text += " (in domain "; + text += log_domain; + if (log_level) { + text += ", "; + text += log_level; + } + text += ")"; + return text; +} + void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) { FileAccess *f = GDMonoLog::get_singleton()->log_file; if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) { - String text(message); - text += " (in domain "; - text += log_domain; - if (log_level) { - text += ", "; - text += log_level; - } - text += ")\n"; + String text = make_text(log_domain, log_level, message); + text += "\n"; f->seek_end(); f->store_string(text); } if (fatal) { - ERR_PRINT("Mono: FATAL ERROR, ABORTING! Logfile: '" + GDMonoLog::get_singleton()->log_file_path + "'."); + String text = make_text(log_domain, log_level, message); + ERR_PRINT("Mono: FATAL ERROR '" + text + "', ABORTING! Logfile: '" + GDMonoLog::get_singleton()->log_file_path + "'."); // Make sure to flush before aborting f->flush(); f->close(); diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 6d7d5f76cd..c460e283ea 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -311,44 +311,6 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_ return false; } -String mono_to_utf8_string(MonoString *p_mono_string) { - MonoError error; - char *utf8 = mono_string_to_utf8_checked(p_mono_string, &error); - - if (!mono_error_ok(&error)) { - ERR_PRINT(String() + "Failed to convert MonoString* to UTF-8: '" + mono_error_get_message(&error) + "'."); - mono_error_cleanup(&error); - return String(); - } - - String ret = String::utf8(utf8); - - mono_free(utf8); - - return ret; -} - -String mono_to_utf16_string(MonoString *p_mono_string) { - int len = mono_string_length(p_mono_string); - String ret; - - if (len == 0) { - return ret; - } - - ret.resize(len + 1); - ret.set(len, 0); - - CharType *src = (CharType *)mono_string_chars(p_mono_string); - CharType *dst = ret.ptrw(); - - for (int i = 0; i < len; i++) { - dst[i] = src[i]; - } - - return ret; -} - MonoObject *variant_to_mono_object(const Variant *p_var) { ManagedType type; diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 4ff330fd43..a1fd975916 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -69,15 +69,11 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_ // String -String mono_to_utf8_string(MonoString *p_mono_string); -String mono_to_utf16_string(MonoString *p_mono_string); - _FORCE_INLINE_ String mono_string_to_godot_not_null(MonoString *p_mono_string) { - if constexpr (sizeof(CharType) == 2) { - return mono_to_utf16_string(p_mono_string); - } - - return mono_to_utf8_string(p_mono_string); + char32_t *utf32 = (char32_t *)mono_string_to_utf32(p_mono_string); + String ret = String(utf32); + mono_free(utf32); + return ret; } _FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { @@ -88,20 +84,8 @@ _FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) { return mono_string_to_godot_not_null(p_mono_string); } -_FORCE_INLINE_ MonoString *mono_from_utf8_string(const String &p_string) { - return mono_string_new(mono_domain_get(), p_string.utf8().get_data()); -} - -_FORCE_INLINE_ MonoString *mono_from_utf16_string(const String &p_string) { - return mono_string_from_utf16((mono_unichar2 *)p_string.c_str()); -} - _FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) { - if constexpr (sizeof(CharType) == 2) { - return mono_from_utf16_string(p_string); - } - - return mono_from_utf8_string(p_string); + return mono_string_from_utf32((mono_unichar4 *)(p_string.get_data())); } // Variant diff --git a/modules/mono/register_types.h b/modules/mono/register_types.h index 7fd0d24eb0..e30d9a8abd 100644 --- a/modules/mono/register_types.h +++ b/modules/mono/register_types.h @@ -28,5 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef MONO_REGISTER_TYPES_H +#define MONO_REGISTER_TYPES_H + void register_mono_types(); void unregister_mono_types(); + +#endif // MONO_REGISTER_TYPES_H diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp index e0cf916a01..a619f0b975 100644 --- a/modules/mono/utils/mono_reg_utils.cpp +++ b/modules/mono/utils/mono_reg_utils.cpp @@ -71,12 +71,12 @@ LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value) buffer.resize(512); DWORD dwBufferSize = buffer.size(); - LONG res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); + LONG res = RegQueryValueExW(hKey, (LPCWSTR)(p_value_name.utf16().get_data()), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); if (res == ERROR_MORE_DATA) { // dwBufferSize now contains the actual size buffer.resize(dwBufferSize); - res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); + res = RegQueryValueExW(hKey, (LPCWSTR)(p_value_name.utf16().get_data()), 0, nullptr, (LPBYTE)buffer.ptr(), &dwBufferSize); } if (res == ERROR_SUCCESS) { @@ -90,7 +90,7 @@ LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value) LONG _find_mono_in_reg(const String &p_subkey, MonoRegInfo &r_info, bool p_old_reg = false) { HKEY hKey; - LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey); + LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, (LPCWSTR)(p_subkey.utf16().get_data()), &hKey); if (res != ERROR_SUCCESS) goto cleanup; @@ -127,7 +127,7 @@ LONG _find_mono_in_reg_old(const String &p_subkey, MonoRegInfo &r_info) { String default_clr; HKEY hKey; - LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey); + LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, (LPCWSTR)(p_subkey.utf16().get_data()), &hKey); if (res != ERROR_SUCCESS) goto cleanup; diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index ccfaf5aba7..5d1abd0c09 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -54,12 +54,16 @@ String cwd() { #ifdef WINDOWS_ENABLED const DWORD expected_size = ::GetCurrentDirectoryW(0, nullptr); - String buffer; + Char16String buffer; buffer.resize((int)expected_size); - if (::GetCurrentDirectoryW(expected_size, buffer.ptrw()) == 0) + if (::GetCurrentDirectoryW(expected_size, (wchar_t *)buffer.ptrw()) == 0) return "."; - return buffer.simplify_path(); + String result; + if (result.parse_utf16(buffer.ptr())) { + return "."; + } + return result.simplify_path(); #else char buffer[PATH_MAX]; if (::getcwd(buffer, sizeof(buffer)) == nullptr) { @@ -86,7 +90,7 @@ String abspath(const String &p_path) { String realpath(const String &p_path) { #ifdef WINDOWS_ENABLED // Open file without read/write access - HANDLE hFile = ::CreateFileW(p_path.c_str(), 0, + HANDLE hFile = ::CreateFileW((LPCWSTR)(p_path.utf16().get_data()), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); @@ -100,12 +104,18 @@ String realpath(const String &p_path) { return p_path; } - String buffer; + Char16String buffer; buffer.resize((int)expected_size); - ::GetFinalPathNameByHandleW(hFile, buffer.ptrw(), expected_size, FILE_NAME_NORMALIZED); + ::GetFinalPathNameByHandleW(hFile, (wchar_t *)buffer.ptrw(), expected_size, FILE_NAME_NORMALIZED); ::CloseHandle(hFile); - return buffer.simplify_path(); + + String result; + if (result.parse_utf16(buffer.ptr())) { + return p_path; + } + + return result.simplify_path(); #elif UNIX_ENABLED char *resolved_path = ::realpath(p_path.utf8().get_data(), nullptr); @@ -130,7 +140,7 @@ String join(const String &p_a, const String &p_b) { return p_b; } - const CharType a_last = p_a[p_a.length() - 1]; + const char32_t a_last = p_a[p_a.length() - 1]; if ((a_last == '/' || a_last == '\\') || (p_b.size() > 0 && (p_b[0] == '/' || p_b[0] == '\\'))) { return p_a + p_b; diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index f8d9804de4..65da4328f6 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -49,7 +49,7 @@ int sfind(const String &p_text, int p_from) { return -1; } - const CharType *src = p_text.c_str(); + const char32_t *src = p_text.get_data(); for (int i = p_from; i <= (len - src_len); i++) { bool found = true; @@ -64,7 +64,7 @@ int sfind(const String &p_text, int p_from) { found = src[read_pos] == '%'; break; case 1: { - CharType c = src[read_pos]; + char32_t c = src[read_pos]; found = src[read_pos] == 's' || (c >= '0' && c <= '4'); break; } @@ -121,7 +121,7 @@ String sformat(const String &p_text, const Variant &p1, const Variant &p2, const int result = 0; while ((result = sfind(p_text, search_from)) >= 0) { - CharType c = p_text[result + 1]; + char32_t c = p_text[result + 1]; int req_index = (c == 's' ? findex++ : c - '0'); diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp index 50ca01067b..c10a276eae 100644 --- a/modules/regex/regex.cpp +++ b/modules/regex/regex.cpp @@ -156,26 +156,13 @@ void RegExMatch::_bind_methods() { } void RegEx::_pattern_info(uint32_t what, void *where) const { - if (sizeof(CharType) == 2) { - pcre2_pattern_info_16((pcre2_code_16 *)code, what, where); - - } else { - pcre2_pattern_info_32((pcre2_code_32 *)code, what, where); - } + pcre2_pattern_info_32((pcre2_code_32 *)code, what, where); } void RegEx::clear() { - if (sizeof(CharType) == 2) { - if (code) { - pcre2_code_free_16((pcre2_code_16 *)code); - code = nullptr; - } - - } else { - if (code) { - pcre2_code_free_32((pcre2_code_32 *)code); - code = nullptr; - } + if (code) { + pcre2_code_free_32((pcre2_code_32 *)code); + code = nullptr; } } @@ -187,39 +174,20 @@ Error RegEx::compile(const String &p_pattern) { PCRE2_SIZE offset; uint32_t flags = PCRE2_DUPNAMES; - if (sizeof(CharType) == 2) { - pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx; - pcre2_compile_context_16 *cctx = pcre2_compile_context_create_16(gctx); - PCRE2_SPTR16 p = (PCRE2_SPTR16)pattern.c_str(); - - code = pcre2_compile_16(p, pattern.length(), flags, &err, &offset, cctx); + pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; + pcre2_compile_context_32 *cctx = pcre2_compile_context_create_32(gctx); + PCRE2_SPTR32 p = (PCRE2_SPTR32)pattern.get_data(); - pcre2_compile_context_free_16(cctx); + code = pcre2_compile_32(p, pattern.length(), flags, &err, &offset, cctx); - if (!code) { - PCRE2_UCHAR16 buf[256]; - pcre2_get_error_message_16(err, buf, 256); - String message = String::num(offset) + ": " + String((const CharType *)buf); - ERR_PRINT(message.utf8()); - return FAILED; - } + pcre2_compile_context_free_32(cctx); - } else { - pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; - pcre2_compile_context_32 *cctx = pcre2_compile_context_create_32(gctx); - PCRE2_SPTR32 p = (PCRE2_SPTR32)pattern.c_str(); - - code = pcre2_compile_32(p, pattern.length(), flags, &err, &offset, cctx); - - pcre2_compile_context_free_32(cctx); - - if (!code) { - PCRE2_UCHAR32 buf[256]; - pcre2_get_error_message_32(err, buf, 256); - String message = String::num(offset) + ": " + String((const CharType *)buf); - ERR_PRINT(message.utf8()); - return FAILED; - } + if (!code) { + PCRE2_UCHAR32 buf[256]; + pcre2_get_error_message_32(err, buf, 256); + String message = String::num(offset) + ": " + String((const char32_t *)buf); + ERR_PRINT(message.utf8()); + return FAILED; } return OK; } @@ -234,69 +202,39 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) length = p_end; } - if (sizeof(CharType) == 2) { - pcre2_code_16 *c = (pcre2_code_16 *)code; - pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx; - pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx); - PCRE2_SPTR16 s = (PCRE2_SPTR16)p_subject.c_str(); - - pcre2_match_data_16 *match = pcre2_match_data_create_from_pattern_16(c, gctx); - - int res = pcre2_match_16(c, s, length, p_offset, 0, match, mctx); + pcre2_code_32 *c = (pcre2_code_32 *)code; + pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; + pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx); + PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.get_data(); - if (res < 0) { - pcre2_match_data_free_16(match); - return nullptr; - } - - uint32_t size = pcre2_get_ovector_count_16(match); - PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_16(match); - - result->data.resize(size); - - for (uint32_t i = 0; i < size; i++) { - result->data.write[i].start = ovector[i * 2]; - result->data.write[i].end = ovector[i * 2 + 1]; - } - - pcre2_match_data_free_16(match); - pcre2_match_context_free_16(mctx); - - } else { - pcre2_code_32 *c = (pcre2_code_32 *)code; - pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; - pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx); - PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.c_str(); + pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx); - pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx); + int res = pcre2_match_32(c, s, length, p_offset, 0, match, mctx); - int res = pcre2_match_32(c, s, length, p_offset, 0, match, mctx); - - if (res < 0) { - pcre2_match_data_free_32(match); - pcre2_match_context_free_32(mctx); + if (res < 0) { + pcre2_match_data_free_32(match); + pcre2_match_context_free_32(mctx); - return nullptr; - } + return nullptr; + } - uint32_t size = pcre2_get_ovector_count_32(match); - PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_32(match); + uint32_t size = pcre2_get_ovector_count_32(match); + PCRE2_SIZE *ovector = pcre2_get_ovector_pointer_32(match); - result->data.resize(size); + result->data.resize(size); - for (uint32_t i = 0; i < size; i++) { - result->data.write[i].start = ovector[i * 2]; - result->data.write[i].end = ovector[i * 2 + 1]; - } - - pcre2_match_data_free_32(match); - pcre2_match_context_free_32(mctx); + for (uint32_t i = 0; i < size; i++) { + result->data.write[i].start = ovector[i * 2]; + result->data.write[i].end = ovector[i * 2 + 1]; } + pcre2_match_data_free_32(match); + pcre2_match_context_free_32(mctx); + result->subject = p_subject; uint32_t count; - const CharType *table; + const char32_t *table; uint32_t entry_size; _pattern_info(PCRE2_INFO_NAMECOUNT, &count); @@ -304,7 +242,7 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end) _pattern_info(PCRE2_INFO_NAMEENTRYSIZE, &entry_size); for (uint32_t i = 0; i < count; i++) { - CharType id = table[i * entry_size]; + char32_t id = table[i * entry_size]; if (result->data[id].start == -1) { continue; } @@ -344,7 +282,7 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a const int safety_zone = 1; PCRE2_SIZE olength = p_subject.length() + 1; // space for output string and one terminating \0 character - Vector<CharType> output; + Vector<char32_t> output; output.resize(olength + safety_zone); uint32_t flags = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH; @@ -357,55 +295,28 @@ String RegEx::sub(const String &p_subject, const String &p_replacement, bool p_a length = p_end; } - if (sizeof(CharType) == 2) { - pcre2_code_16 *c = (pcre2_code_16 *)code; - pcre2_general_context_16 *gctx = (pcre2_general_context_16 *)general_ctx; - pcre2_match_context_16 *mctx = pcre2_match_context_create_16(gctx); - PCRE2_SPTR16 s = (PCRE2_SPTR16)p_subject.c_str(); - PCRE2_SPTR16 r = (PCRE2_SPTR16)p_replacement.c_str(); - PCRE2_UCHAR16 *o = (PCRE2_UCHAR16 *)output.ptrw(); + pcre2_code_32 *c = (pcre2_code_32 *)code; + pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; + pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx); + PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.get_data(); + PCRE2_SPTR32 r = (PCRE2_SPTR32)p_replacement.get_data(); + PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.ptrw(); - pcre2_match_data_16 *match = pcre2_match_data_create_from_pattern_16(c, gctx); - - int res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength); - - if (res == PCRE2_ERROR_NOMEMORY) { - output.resize(olength + safety_zone); - o = (PCRE2_UCHAR16 *)output.ptrw(); - res = pcre2_substitute_16(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength); - } + pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx); - pcre2_match_data_free_16(match); - pcre2_match_context_free_16(mctx); + int res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength); - if (res < 0) { - return String(); - } - - } else { - pcre2_code_32 *c = (pcre2_code_32 *)code; - pcre2_general_context_32 *gctx = (pcre2_general_context_32 *)general_ctx; - pcre2_match_context_32 *mctx = pcre2_match_context_create_32(gctx); - PCRE2_SPTR32 s = (PCRE2_SPTR32)p_subject.c_str(); - PCRE2_SPTR32 r = (PCRE2_SPTR32)p_replacement.c_str(); - PCRE2_UCHAR32 *o = (PCRE2_UCHAR32 *)output.ptrw(); - - pcre2_match_data_32 *match = pcre2_match_data_create_from_pattern_32(c, gctx); - - int res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength); - - if (res == PCRE2_ERROR_NOMEMORY) { - output.resize(olength + safety_zone); - o = (PCRE2_UCHAR32 *)output.ptrw(); - res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength); - } + if (res == PCRE2_ERROR_NOMEMORY) { + output.resize(olength + safety_zone); + o = (PCRE2_UCHAR32 *)output.ptrw(); + res = pcre2_substitute_32(c, s, length, p_offset, flags, match, mctx, r, p_replacement.length(), o, &olength); + } - pcre2_match_data_free_32(match); - pcre2_match_context_free_32(mctx); + pcre2_match_data_free_32(match); + pcre2_match_context_free_32(mctx); - if (res < 0) { - return String(); - } + if (res < 0) { + return String(); } return String(output.ptr(), olength); @@ -435,7 +346,7 @@ Array RegEx::get_names() const { ERR_FAIL_COND_V(!is_valid(), result); uint32_t count; - const CharType *table; + const char32_t *table; uint32_t entry_size; _pattern_info(PCRE2_INFO_NAMECOUNT, &count); @@ -453,39 +364,21 @@ Array RegEx::get_names() const { } RegEx::RegEx() { - if (sizeof(CharType) == 2) { - general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, nullptr); - - } else { - general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr); - } + general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr); code = nullptr; } RegEx::RegEx(const String &p_pattern) { - if (sizeof(CharType) == 2) { - general_ctx = pcre2_general_context_create_16(&_regex_malloc, &_regex_free, nullptr); - - } else { - general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr); - } + general_ctx = pcre2_general_context_create_32(&_regex_malloc, &_regex_free, nullptr); code = nullptr; compile(p_pattern); } RegEx::~RegEx() { - if (sizeof(CharType) == 2) { - if (code) { - pcre2_code_free_16((pcre2_code_16 *)code); - } - pcre2_general_context_free_16((pcre2_general_context_16 *)general_ctx); - - } else { - if (code) { - pcre2_code_free_32((pcre2_code_32 *)code); - } - pcre2_general_context_free_32((pcre2_general_context_32 *)general_ctx); + if (code) { + pcre2_code_free_32((pcre2_code_32 *)code); } + pcre2_general_context_free_32((pcre2_general_context_32 *)general_ctx); } void RegEx::_bind_methods() { diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 3aceaf11c5..346833ab9c 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -158,14 +158,16 @@ void AudioStreamOGGVorbis::clear_data() { void AudioStreamOGGVorbis::set_data(const Vector<uint8_t> &p_data) { int src_data_len = p_data.size(); -#define MAX_TEST_MEM (1 << 20) - uint32_t alloc_try = 1024; Vector<char> alloc_mem; char *w; stb_vorbis *ogg_stream = nullptr; stb_vorbis_alloc ogg_alloc; + // Vorbis comments may be up to UINT32_MAX, but that's arguably pretty rare. + // Let's go with 2^30 so we don't risk going out of bounds. + const uint32_t MAX_TEST_MEM = 1 << 30; + while (alloc_try < MAX_TEST_MEM) { alloc_mem.resize(alloc_try); w = alloc_mem.ptrw(); @@ -205,6 +207,8 @@ void AudioStreamOGGVorbis::set_data(const Vector<uint8_t> &p_data) { break; } } + + ERR_FAIL_COND_MSG(alloc_try == MAX_TEST_MEM, vformat("Couldn't set vorbis data even with an alloc buffer of %d bytes, report bug.", MAX_TEST_MEM)); } Vector<uint8_t> AudioStreamOGGVorbis::get_data() const { diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp index 9e7266b95a..5bdcb84244 100644 --- a/modules/tinyexr/image_loader_tinyexr.cpp +++ b/modules/tinyexr/image_loader_tinyexr.cpp @@ -73,8 +73,10 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f } // Read HALF channel as FLOAT. (GH-13490) + bool use_float16 = false; for (int i = 0; i < exr_header.num_channels; i++) { if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) { + use_float16 = true; exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; } } @@ -102,33 +104,10 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f idxB = c; } else if (strcmp(exr_header.channels[c].name, "A") == 0) { idxA = c; - } - } - - if (exr_header.num_channels == 1) { - // Grayscale channel only. - idxR = 0; - idxG = 0; - idxB = 0; - idxA = 0; - } else { - // Assume RGB(A) - if (idxR == -1) { - ERR_PRINT("TinyEXR: R channel not found."); - // @todo { free exr_image } - return ERR_FILE_CORRUPT; - } - - if (idxG == -1) { - ERR_PRINT("TinyEXR: G channel not found."); - // @todo { free exr_image } - return ERR_FILE_CORRUPT; - } - - if (idxB == -1) { - ERR_PRINT("TinyEXR: B channel not found."); - // @todo { free exr_image } - return ERR_FILE_CORRUPT; + } else if (strcmp(exr_header.channels[c].name, "Y") == 0) { + idxR = c; + idxG = c; + idxB = c; } } @@ -138,14 +117,27 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f Image::Format format; int output_channels = 0; + int channel_size = use_float16 ? 2 : 4; if (idxA != -1) { - imgdata.resize(exr_image.width * exr_image.height * 8); //RGBA16 - format = Image::FORMAT_RGBAH; + imgdata.resize(exr_image.width * exr_image.height * 4 * channel_size); //RGBA + format = use_float16 ? Image::FORMAT_RGBAH : Image::FORMAT_RGBAF; output_channels = 4; - } else { - imgdata.resize(exr_image.width * exr_image.height * 6); //RGB16 - format = Image::FORMAT_RGBH; + } else if (idxB != -1) { + ERR_FAIL_COND_V(idxG == -1, ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(idxR == -1, ERR_FILE_CORRUPT); + imgdata.resize(exr_image.width * exr_image.height * 3 * channel_size); //RGB + format = use_float16 ? Image::FORMAT_RGBH : Image::FORMAT_RGBF; output_channels = 3; + } else if (idxG != -1) { + ERR_FAIL_COND_V(idxR == -1, ERR_FILE_CORRUPT); + imgdata.resize(exr_image.width * exr_image.height * 2 * channel_size); //RG + format = use_float16 ? Image::FORMAT_RGH : Image::FORMAT_RGF; + output_channels = 2; + } else { + ERR_FAIL_COND_V(idxR == -1, ERR_FILE_CORRUPT); + imgdata.resize(exr_image.width * exr_image.height * 1 * channel_size); //R + format = use_float16 ? Image::FORMAT_RH : Image::FORMAT_RF; + output_channels = 1; } EXRTile single_image_tile; @@ -175,9 +167,11 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f exr_tiles = exr_image.tiles; } + //print_line("reading format: " + Image::get_format_name(format)); { uint8_t *wd = imgdata.ptrw(); - uint16_t *iw = (uint16_t *)wd; + uint16_t *iw16 = (uint16_t *)wd; + float *iw32 = (float *)wd; // Assume `out_rgba` have enough memory allocated. for (int tile_index = 0; tile_index < num_tiles; tile_index++) { @@ -187,41 +181,99 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f int th = tile.height; const float *r_channel_start = reinterpret_cast<const float *>(tile.images[idxR]); - const float *g_channel_start = reinterpret_cast<const float *>(tile.images[idxG]); - const float *b_channel_start = reinterpret_cast<const float *>(tile.images[idxB]); + const float *g_channel_start = nullptr; + const float *b_channel_start = nullptr; const float *a_channel_start = nullptr; + if (idxG != -1) { + g_channel_start = reinterpret_cast<const float *>(tile.images[idxG]); + } + if (idxB != -1) { + b_channel_start = reinterpret_cast<const float *>(tile.images[idxB]); + } if (idxA != -1) { a_channel_start = reinterpret_cast<const float *>(tile.images[idxA]); } - uint16_t *first_row_w = iw + (tile.offset_y * tile_height * exr_image.width + tile.offset_x * tile_width) * output_channels; + uint16_t *first_row_w16 = iw16 + (tile.offset_y * tile_height * exr_image.width + tile.offset_x * tile_width) * output_channels; + float *first_row_w32 = iw32 + (tile.offset_y * tile_height * exr_image.width + tile.offset_x * tile_width) * output_channels; for (int y = 0; y < th; y++) { const float *r_channel = r_channel_start + y * tile_width; - const float *g_channel = g_channel_start + y * tile_width; - const float *b_channel = b_channel_start + y * tile_width; + const float *g_channel = nullptr; + const float *b_channel = nullptr; const float *a_channel = nullptr; - + if (g_channel_start) { + g_channel = g_channel_start + y * tile_width; + } + if (b_channel_start) { + b_channel = b_channel_start + y * tile_width; + } if (a_channel_start) { a_channel = a_channel_start + y * tile_width; } - uint16_t *row_w = first_row_w + (y * exr_image.width * output_channels); - - for (int x = 0; x < tw; x++) { - Color color(*r_channel++, *g_channel++, *b_channel++); - - if (p_force_linear) { - color = color.to_linear(); + if (use_float16) { + uint16_t *row_w = first_row_w16 + (y * exr_image.width * output_channels); + + for (int x = 0; x < tw; x++) { + Color color; + color.r = *r_channel++; + if (g_channel) { + color.g = *g_channel++; + } + if (b_channel) { + color.b = *b_channel++; + } + if (a_channel) { + color.a = *a_channel++; + } + + if (p_force_linear) { + color = color.to_linear(); + } + + *row_w++ = Math::make_half_float(color.r); + if (g_channel) { + *row_w++ = Math::make_half_float(color.g); + } + if (b_channel) { + *row_w++ = Math::make_half_float(color.b); + } + if (a_channel) { + *row_w++ = Math::make_half_float(color.a); + } } - - *row_w++ = Math::make_half_float(color.r); - *row_w++ = Math::make_half_float(color.g); - *row_w++ = Math::make_half_float(color.b); - - if (idxA != -1) { - *row_w++ = Math::make_half_float(*a_channel++); + } else { + float *row_w = first_row_w32 + (y * exr_image.width * output_channels); + + for (int x = 0; x < tw; x++) { + Color color; + color.r = *r_channel++; + if (g_channel) { + color.g = *g_channel++; + } + if (b_channel) { + color.b = *b_channel++; + } + if (a_channel) { + color.a = *a_channel++; + } + + if (p_force_linear) { + color = color.to_linear(); + } + + *row_w++ = color.r; + if (g_channel) { + *row_w++ = color.g; + } + if (b_channel) { + *row_w++ = color.b; + } + if (a_channel) { + *row_w++ = color.a; + } } } } diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index a0dcd76d10..177f9192b8 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -1060,7 +1060,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in } break; case VisualScriptBuiltinFunc::TEXT_CHAR: { - CharType result[2] = { *p_inputs[0], 0 }; + char32_t result[2] = { *p_inputs[0], 0 }; *r_return = String(result); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 5581ea9318..7c3af016b9 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -2682,7 +2682,8 @@ void VisualScriptEditor::reload(bool p_soft) { _update_graph(); } -void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { +Array VisualScriptEditor::get_breakpoints() { + Array breakpoints; List<StringName> functions; script->get_function_list(&functions); for (List<StringName>::Element *E = functions.front(); E; E = E->next()) { @@ -2691,10 +2692,11 @@ void VisualScriptEditor::get_breakpoints(List<int> *p_breakpoints) { for (List<int>::Element *F = nodes.front(); F; F = F->next()) { Ref<VisualScriptNode> vsn = script->get_node(E->get(), F->get()); if (vsn->is_breakpoint()) { - p_breakpoints->push_back(F->get() - 1); //subtract 1 because breakpoints in text start from zero + breakpoints.push_back(F->get() - 1); //subtract 1 because breakpoints in text start from zero } } } + return breakpoints; } void VisualScriptEditor::add_callback(const String &p_function, PackedStringArray p_args) { diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index 0c5665cee8..b5d5589250 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -312,7 +312,7 @@ public: virtual void ensure_focus() override; virtual void tag_saved_version() override; virtual void reload(bool p_soft) override; - virtual void get_breakpoints(List<int> *p_breakpoints) override; + virtual Array get_breakpoints() override; virtual void add_callback(const String &p_function, PackedStringArray p_args) override; virtual void update_settings() override; virtual bool show_members_overview() override; diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp index 2ac7793b8c..60a439b291 100644 --- a/modules/visual_script/visual_script_expression.cpp +++ b/modules/visual_script/visual_script_expression.cpp @@ -187,7 +187,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { while (true) { #define GET_CHAR() (str_ofs >= expression.length() ? 0 : expression[str_ofs++]) - CharType cchar = GET_CHAR(); + char32_t cchar = GET_CHAR(); if (cchar == 0) { r_token.type = TK_EOF; return OK; @@ -329,7 +329,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { case '"': { String str; while (true) { - CharType ch = GET_CHAR(); + char32_t ch = GET_CHAR(); if (ch == 0) { _set_error("Unterminated String"); @@ -340,13 +340,13 @@ Error VisualScriptExpression::_get_token(Token &r_token) { } else if (ch == '\\') { //escaped characters... - CharType next = GET_CHAR(); + char32_t next = GET_CHAR(); if (next == 0) { _set_error("Unterminated String"); r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -367,7 +367,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { case 'u': { // hex number for (int j = 0; j < 4; j++) { - CharType c = GET_CHAR(); + char32_t c = GET_CHAR(); if (c == 0) { _set_error("Unterminated String"); @@ -379,7 +379,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { r_token.type = TK_ERROR; return ERR_PARSE_ERROR; } - CharType v; + char32_t v; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'f') { @@ -431,7 +431,7 @@ Error VisualScriptExpression::_get_token(Token &r_token) { #define READING_DONE 4 int reading = READING_INT; - CharType c = cchar; + char32_t c = cchar; bool exp_sign = false; bool exp_beg = false; bool is_float = false; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 87aa64211e..1b77ed3168 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -933,36 +933,36 @@ static const char *op_names[] = { }; String VisualScriptOperator::get_caption() const { - static const wchar_t *op_names[] = { + static const char32_t *op_names[] = { //comparison - L"A = B", //OP_EQUAL, - L"A \u2260 B", //OP_NOT_EQUAL, - L"A < B", //OP_LESS, - L"A \u2264 B", //OP_LESS_EQUAL, - L"A > B", //OP_GREATER, - L"A \u2265 B", //OP_GREATER_EQUAL, + U"A = B", //OP_EQUAL, + U"A \u2260 B", //OP_NOT_EQUAL, + U"A < B", //OP_LESS, + U"A \u2264 B", //OP_LESS_EQUAL, + U"A > B", //OP_GREATER, + U"A \u2265 B", //OP_GREATER_EQUAL, //mathematic - L"A + B", //OP_ADD, - L"A - B", //OP_SUBTRACT, - L"A \u00D7 B", //OP_MULTIPLY, - L"A \u00F7 B", //OP_DIVIDE, - L"\u00AC A", //OP_NEGATE, - L"+ A", //OP_POSITIVE, - L"A mod B", //OP_MODULE, - L"A .. B", //OP_STRING_CONCAT, + U"A + B", //OP_ADD, + U"A - B", //OP_SUBTRACT, + U"A \u00D7 B", //OP_MULTIPLY, + U"A \u00F7 B", //OP_DIVIDE, + U"\u00AC A", //OP_NEGATE, + U"+ A", //OP_POSITIVE, + U"A mod B", //OP_MODULE, + U"A .. B", //OP_STRING_CONCAT, //bitwise - L"A << B", //OP_SHIFT_LEFT, - L"A >> B", //OP_SHIFT_RIGHT, - L"A & B", //OP_BIT_AND, - L"A | B", //OP_BIT_OR, - L"A ^ B", //OP_BIT_XOR, - L"~A", //OP_BIT_NEGATE, + U"A << B", //OP_SHIFT_LEFT, + U"A >> B", //OP_SHIFT_RIGHT, + U"A & B", //OP_BIT_AND, + U"A | B", //OP_BIT_OR, + U"A ^ B", //OP_BIT_XOR, + U"~A", //OP_BIT_NEGATE, //logic - L"A and B", //OP_AND, - L"A or B", //OP_OR, - L"A xor B", //OP_XOR, - L"not A", //OP_NOT, - L"A in B", //OP_IN, + U"A and B", //OP_AND, + U"A or B", //OP_OR, + U"A xor B", //OP_XOR, + U"not A", //OP_NOT, + U"A in B", //OP_IN, }; return op_names[op]; diff --git a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml index 2054276655..c80b903e39 100644 --- a/modules/webrtc/doc_classes/WebRTCPeerConnection.xml +++ b/modules/webrtc/doc_classes/WebRTCPeerConnection.xml @@ -97,7 +97,7 @@ { "urls": [ "turn:turn.example.com:3478" ], # One or more TURN servers. "username": "a_username", # Optional username for the TURN server. - "credentials": "a_password", # Optional password for the TURN server. + "credential": "a_password", # Optional password for the TURN server. } ] } diff --git a/modules/webrtc/webrtc_data_channel_gdnative.h b/modules/webrtc/webrtc_data_channel_gdnative.h index b578802250..03396d207d 100644 --- a/modules/webrtc/webrtc_data_channel_gdnative.h +++ b/modules/webrtc/webrtc_data_channel_gdnative.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef WEBRTC_GDNATIVE_ENABLED - #ifndef WEBRTC_DATA_CHANNEL_GDNATIVE_H #define WEBRTC_DATA_CHANNEL_GDNATIVE_H +#ifdef WEBRTC_GDNATIVE_ENABLED + #include "modules/gdnative/include/net/godot_net.h" #include "webrtc_data_channel.h" @@ -75,6 +75,6 @@ public: ~WebRTCDataChannelGDNative(); }; -#endif // WEBRTC_DATA_CHANNEL_GDNATIVE_H - #endif // WEBRTC_GDNATIVE_ENABLED + +#endif // WEBRTC_DATA_CHANNEL_GDNATIVE_H diff --git a/modules/webrtc/webrtc_data_channel_js.h b/modules/webrtc/webrtc_data_channel_js.h index 455866cbf1..7545910e66 100644 --- a/modules/webrtc/webrtc_data_channel_js.h +++ b/modules/webrtc/webrtc_data_channel_js.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef JAVASCRIPT_ENABLED - #ifndef WEBRTC_DATA_CHANNEL_JS_H #define WEBRTC_DATA_CHANNEL_JS_H +#ifdef JAVASCRIPT_ENABLED + #include "webrtc_data_channel.h" class WebRTCDataChannelJS : public WebRTCDataChannel { @@ -88,6 +88,6 @@ public: ~WebRTCDataChannelJS(); }; -#endif // WEBRTC_DATA_CHANNEL_JS_H - #endif // JAVASCRIPT_ENABLED + +#endif // WEBRTC_DATA_CHANNEL_JS_H diff --git a/modules/webrtc/webrtc_multiplayer.h b/modules/webrtc/webrtc_multiplayer.h index bfdcf6daa1..fb37bd7722 100644 --- a/modules/webrtc/webrtc_multiplayer.h +++ b/modules/webrtc/webrtc_multiplayer.h @@ -112,4 +112,4 @@ public: ConnectionStatus get_connection_status() const override; }; -#endif +#endif // WEBRTC_MULTIPLAYER_H diff --git a/modules/webrtc/webrtc_peer_connection_gdnative.h b/modules/webrtc/webrtc_peer_connection_gdnative.h index 74b7db1307..846b65c466 100644 --- a/modules/webrtc/webrtc_peer_connection_gdnative.h +++ b/modules/webrtc/webrtc_peer_connection_gdnative.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifdef WEBRTC_GDNATIVE_ENABLED - #ifndef WEBRTC_PEER_CONNECTION_GDNATIVE_H #define WEBRTC_PEER_CONNECTION_GDNATIVE_H +#ifdef WEBRTC_GDNATIVE_ENABLED + #include "modules/gdnative/include/net/godot_net.h" #include "webrtc_peer_connection.h" @@ -68,6 +68,6 @@ public: ~WebRTCPeerConnectionGDNative(); }; -#endif // WEBRTC_PEER_CONNECTION_GDNATIVE_H - #endif // WEBRTC_GDNATIVE_ENABLED + +#endif // WEBRTC_PEER_CONNECTION_GDNATIVE_H diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 95b778caf6..9a144c0a78 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -453,7 +453,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String name; bool first = true; for (int i = 0; i < basename.length(); i++) { - CharType c = basename[i]; + char32_t c = basename[i]; if (c >= '0' && c <= '9' && first) { continue; } @@ -484,7 +484,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { int segments = 0; bool first = true; for (int i = 0; i < pname.length(); i++) { - CharType c = pname[i]; + char32_t c = pname[i]; if (first && c == '.') { if (r_error) { *r_error = TTR("Package segments must be of non-zero length."); @@ -723,7 +723,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { return OK; } - static Error save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { + static Error save_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { APKExportData *ed = (APKExportData *)p_userdata; String dst_path = p_path.replace_first("res://", "assets/"); @@ -731,7 +731,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { return OK; } - static Error ignore_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { + static Error ignore_apk_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { return OK; } @@ -873,7 +873,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { if (string_flags & UTF8_FLAG) { } else { uint32_t len = decode_uint16(&p_manifest[string_at]); - Vector<CharType> ucstring; + Vector<char32_t> ucstring; ucstring.resize(len + 1); for (uint32_t j = 0; j < len; j++) { uint16_t c = decode_uint16(&p_manifest[string_at + 2 + 2 * j]); @@ -1334,7 +1334,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } else { String str; for (uint32_t i = 0; i < len; i++) { - CharType c = decode_uint16(&p_bytes[offset + i * 2]); + char32_t c = decode_uint16(&p_bytes[offset + i * 2]); if (c == 0) { break; } @@ -1525,7 +1525,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } public: - typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total); + typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key); public: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override { diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h index 209a664f8f..95f870bc35 100644 --- a/platform/android/export/gradle_export_util.h +++ b/platform/android/export/gradle_export_util.h @@ -99,7 +99,7 @@ Error store_string_at_path(const String &p_path, const String &p_data) { // It is used by the export_project_files method to save all the asset files into the gradle project. // It's functionality mirrors that of the method save_apk_file. // This method will be called ONLY when custom build is enabled. -Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { +Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { String dst_path = p_path.replace_first("res://", "res://android/build/assets/"); Error err = store_file_at_path(dst_path, p_data); return err; diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm index 1721da3db6..eea87cecc9 100644 --- a/platform/iphone/display_server_iphone.mm +++ b/platform/iphone/display_server_iphone.mm @@ -701,7 +701,7 @@ Error DisplayServerIPhone::native_video_play(String p_path, float p_volume, Stri if (p_path.begins_with("res://")) { if (PackedData::get_singleton()->has_path(p_path)) { - printf("Unable to play %S using the native player as it resides in a .pck file\n", p_path.c_str()); + printf("Unable to play %s using the native player as it resides in a .pck file\n", p_path.utf8().get_data()); return ERR_INVALID_PARAMETER; } else { p_path = p_path.replace("res:/", ProjectSettings::get_singleton()->get_resource_path()); @@ -712,7 +712,7 @@ Error DisplayServerIPhone::native_video_play(String p_path, float p_volume, Stri memdelete(f); - printf("Playing video: %S\n", p_path.c_str()); + printf("Playing video: %s\n", p_path.utf8().get_data()); String file_path = ProjectSettings::get_singleton()->globalize_path(p_path); diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index a889717f20..97f954ebb2 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -115,7 +115,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { } for (int i = 0; i < pname.length(); i++) { - CharType c = pname[i]; + char32_t c = pname[i]; if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.')) { if (r_error) { *r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c)); diff --git a/platform/iphone/godot_view_gesture_recognizer.h b/platform/iphone/godot_view_gesture_recognizer.h index ca3bd808d1..8d84914712 100644 --- a/platform/iphone/godot_view_gesture_recognizer.h +++ b/platform/iphone/godot_view_gesture_recognizer.h @@ -32,7 +32,7 @@ // emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer. // It catches all gestures incoming to UIView and delays them for 150ms // (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer) -// If touch cancelation or end message is fired it fires delayed +// If touch cancellation or end message is fired it fires delayed // begin touch immediately as well as last touch signal #import <UIKit/UIKit.h> diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm index dfec5d7634..1477f92200 100644 --- a/platform/iphone/in_app_store.mm +++ b/platform/iphone/in_app_store.mm @@ -138,7 +138,7 @@ Error InAppStore::request_product_info(Dictionary p_params) { NSMutableArray *array = [[[NSMutableArray alloc] initWithCapacity:pids.size()] autorelease]; for (int i = 0; i < pids.size(); i++) { - printf("******** adding %ls to product list\n", pids[i].c_str()); + printf("******** adding %s to product list\n", pids[i].utf8().get_data()); NSString *pid = [[[NSString alloc] initWithUTF8String:pids[i].utf8().get_data()] autorelease]; [array addObject:pid]; }; diff --git a/platform/iphone/ios.mm b/platform/iphone/ios.mm index ad26d0ada3..6d7699c0c9 100644 --- a/platform/iphone/ios.mm +++ b/platform/iphone/ios.mm @@ -86,7 +86,7 @@ String iOS::get_rate_url(int p_app_id) const { // ios7 for everything? ret = templ_iOS7.replace("APP_ID", String::num(p_app_id)); - printf("returning rate url %ls\n", ret.c_str()); + printf("returning rate url %s\n", ret.utf8().get_data()); return ret; }; diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm index d1a69642b1..946fd51923 100644 --- a/platform/iphone/os_iphone.mm +++ b/platform/iphone/os_iphone.mm @@ -278,7 +278,7 @@ Error OSIPhone::shell_open(String p_uri) { return ERR_CANT_OPEN; } - printf("opening url %ls\n", p_uri.c_str()); + printf("opening url %s\n", p_uri.utf8().get_data()); // if (@available(iOS 10, *)) { [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; @@ -293,7 +293,7 @@ void OSIPhone::set_user_data_dir(String p_dir) { DirAccess *da = DirAccess::open(p_dir); user_data_dir = da->get_current_dir(); - printf("setting data dir to %ls from %ls\n", user_data_dir.c_str(), p_dir.c_str()); + printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data()); memdelete(da); } diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub index dcf9a46bf9..21456efde5 100644 --- a/platform/javascript/SCsub +++ b/platform/javascript/SCsub @@ -66,5 +66,5 @@ env.Zip( zip_files, ZIPROOT=zip_dir, ZIPSUFFIX="${PROGSUFFIX}${ZIPSUFFIX}", - ZIPCOMSTR="Archving $SOURCES as $TARGET", + ZIPCOMSTR="Archiving $SOURCES as $TARGET", ) diff --git a/platform/javascript/engine/engine.js b/platform/javascript/engine/engine.js index d709422abb..2630812814 100644 --- a/platform/javascript/engine/engine.js +++ b/platform/javascript/engine/engine.js @@ -121,7 +121,7 @@ Function('return this')()['Engine'] = (function() { if (me.onExit) me.onExit(code); me.rtenv = null; - } + }; return new Promise(function(resolve, reject) { preloader.preloadedFiles.forEach(function(file) { me.rtenv['copyToFS'](file.path, file.buffer); @@ -207,18 +207,18 @@ Function('return this')()['Engine'] = (function() { if (this.rtenv) this.rtenv.onExecute = onExecute; this.onExecute = onExecute; - } + }; Engine.prototype.setOnExit = function(onExit) { this.onExit = onExit; - } + }; Engine.prototype.copyToFS = function(path, buffer) { if (this.rtenv == null) { throw new Error("Engine must be inited before copying files"); } this.rtenv['copyToFS'](path, buffer); - } + }; // Closure compiler exported engine methods. /** @export */ diff --git a/platform/linuxbsd/crash_handler_linuxbsd.cpp b/platform/linuxbsd/crash_handler_linuxbsd.cpp index b3553e961a..e2b88b7704 100644 --- a/platform/linuxbsd/crash_handler_linuxbsd.cpp +++ b/platform/linuxbsd/crash_handler_linuxbsd.cpp @@ -67,7 +67,7 @@ static void handle_crash(int sig) { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH); } - fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str()); + fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data()); char **strings = backtrace_symbols(bt_buffer, size); if (strings) { for (size_t i = 1; i < size; i++) { @@ -109,7 +109,7 @@ static void handle_crash(int sig) { output.erase(output.length() - 1, 1); } - fprintf(stderr, "[%ld] %s (%ls)\n", (long int)i, fname, output.c_str()); + fprintf(stderr, "[%ld] %s (%s)\n", (long int)i, fname, output.utf8().get_data()); } free(strings); diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 3eb4c44bc1..f5e2c72bbc 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -35,6 +35,11 @@ def can_build(): print("xinerama not found.. x11 disabled.") return False + x11_error = os.system("pkg-config xext --modversion > /dev/null ") + if x11_error: + print("xext not found.. x11 disabled.") + return False + x11_error = os.system("pkg-config xrandr --modversion > /dev/null ") if x11_error: print("xrandr not found.. x11 disabled.") @@ -194,6 +199,7 @@ def configure(env): env.ParseConfig("pkg-config x11 --cflags --libs") env.ParseConfig("pkg-config xcursor --cflags --libs") env.ParseConfig("pkg-config xinerama --cflags --libs") + env.ParseConfig("pkg-config xext --cflags --libs") env.ParseConfig("pkg-config xrandr --cflags --libs") env.ParseConfig("pkg-config xrender --cflags --libs") env.ParseConfig("pkg-config xi --cflags --libs") diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index fe9e253cc9..e3cf992302 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -50,6 +50,7 @@ #include <X11/Xatom.h> #include <X11/Xutil.h> #include <X11/extensions/Xinerama.h> +#include <X11/extensions/shape.h> // ICCCM #define WM_NormalState 1L // window normal state @@ -782,6 +783,38 @@ void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window XChangeProperty(x11_display, wd.x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length()); } +void DisplayServerX11::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + const WindowData &wd = windows[p_window]; + + int event_base, error_base; + const Bool ext_okay = XShapeQueryExtension(x11_display, &event_base, &error_base); + if (ext_okay) { + Region region; + if (p_region.size() == 0) { + region = XCreateRegion(); + XRectangle rect; + rect.x = 0; + rect.y = 0; + rect.width = window_get_real_size(p_window).x; + rect.height = window_get_real_size(p_window).y; + XUnionRectWithRegion(&rect, region, region); + } else { + XPoint *points = (XPoint *)memalloc(sizeof(XPoint) * p_region.size()); + for (int i = 0; i < p_region.size(); i++) { + points[i].x = p_region[i].x; + points[i].y = p_region[i].y; + } + region = XPolygonRegion(points, p_region.size(), EvenOddRule); + memfree(points); + } + XShapeCombineRegion(x11_display, wd.x11_window, ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion(region); + } +} + void DisplayServerX11::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -3542,7 +3575,12 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode xrandr_handle = dlopen("libXrandr.so.2", RTLD_LAZY); if (!xrandr_handle) { err = dlerror(); - fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err); + // For some arcane reason, NetBSD now ships libXrandr.so.3 while the rest of the world has libXrandr.so.2... + // In case this happens for other X11 platforms in the future, let's give it a try too before failing. + xrandr_handle = dlopen("libXrandr.so.3", RTLD_LAZY); + if (!xrandr_handle) { + fprintf(stderr, "could not load libXrandr.so.2, Error: %s\n", err); + } } else { XRRQueryVersion(x11_display, &xrandr_major, &xrandr_minor); if (((xrandr_major << 8) | xrandr_minor) >= 0x0105) { diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 57cee910a0..e894cf515c 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -291,6 +291,8 @@ public: virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const; virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); diff --git a/platform/linuxbsd/platform_config.h b/platform/linuxbsd/platform_config.h index 764666681f..571ad03db0 100644 --- a/platform/linuxbsd/platform_config.h +++ b/platform/linuxbsd/platform_config.h @@ -31,7 +31,15 @@ #ifdef __linux__ #include <alloca.h> #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) -#include <stdlib.h> + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#include <stdlib.h> // alloca +// FreeBSD and OpenBSD use pthread_set_name_np, while other platforms, +// include NetBSD, use pthread_setname_np. NetBSD's version however requires +// a different format, we handle this directly in thread_posix. +#ifdef __NetBSD__ +#define PTHREAD_NETBSD_SET_NAME +#else #define PTHREAD_BSD_SET_NAME #endif +#endif diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm index 5da0118686..9fb2f63935 100644 --- a/platform/osx/crash_handler_osx.mm +++ b/platform/osx/crash_handler_osx.mm @@ -90,7 +90,7 @@ static void handle_crash(int sig) { if (OS::get_singleton()->get_main_loop()) OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_CRASH); - fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str()); + fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data()); char **strings = backtrace_symbols(bt_buffer, size); if (strings) { void *load_addr = (void *)load_address(); @@ -142,7 +142,7 @@ static void handle_crash(int sig) { } } - fprintf(stderr, "[%zu] %ls\n", i, output.c_str()); + fprintf(stderr, "[%zu] %s\n", i, output.utf8().get_data()); } free(strings); diff --git a/platform/osx/detect.py b/platform/osx/detect.py index a4a382f3a9..6fc1dc65af 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -1,6 +1,5 @@ import os import sys -import subprocess from methods import detect_darwin_sdk_path diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index d8f3f81ff6..073d35008b 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -102,6 +102,8 @@ public: id window_object; id window_view; + Vector<Vector2> mpath; + #if defined(OPENGL_ENABLED) ContextGL_OSX *context_gles2 = nullptr; #endif @@ -240,6 +242,7 @@ public: virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override; virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override; + virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID) override; virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override; virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index adfb47324e..e33af520c9 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -33,6 +33,7 @@ #include "os_osx.h" #include "core/io/marshalls.h" +#include "core/math/geometry_2d.h" #include "core/os/keyboard.h" #include "main/main.h" #include "scene/resources/texture.h" @@ -2404,6 +2405,15 @@ void DisplayServerOSX::window_set_title(const String &p_title, WindowID p_window [wd.window_object setTitle:[NSString stringWithUTF8String:p_title.utf8().get_data()]]; } +void DisplayServerOSX::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + + wd.mpath = p_region; +} + void DisplayServerOSX::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -3356,6 +3366,26 @@ void DisplayServerOSX::process_events() { Input::get_singleton()->flush_accumulated_events(); } + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + WindowData &wd = E->get(); + if (wd.mpath.size() > 0) { + const Vector2 mpos = _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]); + if (Geometry2D::is_point_in_polygon(mpos, wd.mpath)) { + if ([wd.window_object ignoresMouseEvents]) { + [wd.window_object setIgnoresMouseEvents:NO]; + } + } else { + if (![wd.window_object ignoresMouseEvents]) { + [wd.window_object setIgnoresMouseEvents:YES]; + } + } + } else { + if ([wd.window_object ignoresMouseEvents]) { + [wd.window_object setIgnoresMouseEvents:NO]; + } + } + } + [autoreleasePool drain]; autoreleasePool = [[NSAutoreleasePool alloc] init]; } diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 0cf02ef69b..9f2160dd9e 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -78,7 +78,7 @@ class EditorExportPlatformOSX : public EditorExportPlatform { } for (int i = 0; i < pname.length(); i++) { - CharType c = pname[i]; + char32_t c = pname[i]; if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.')) { if (r_error) { *r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c)); diff --git a/platform/server/platform_config.h b/platform/server/platform_config.h index bdff93f02b..73136ec81b 100644 --- a/platform/server/platform_config.h +++ b/platform/server/platform_config.h @@ -31,10 +31,19 @@ #if defined(__linux__) || defined(__APPLE__) #include <alloca.h> #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) -#include <stdlib.h> + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#include <stdlib.h> // alloca +// FreeBSD and OpenBSD use pthread_set_name_np, while other platforms, +// include NetBSD, use pthread_setname_np. NetBSD's version however requires +// a different format, we handle this directly in thread_posix. +#ifdef __NetBSD__ +#define PTHREAD_NETBSD_SET_NAME +#else #define PTHREAD_BSD_SET_NAME #endif +#endif + #ifdef __APPLE__ #define PTHREAD_RENAME_SELF #endif diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py index 04b743f2c8..a7ca26c16c 100644 --- a/platform/uwp/detect.py +++ b/platform/uwp/detect.py @@ -65,12 +65,14 @@ def configure(env): env.Append(CCFLAGS=["/MD"]) env.Append(CPPDEFINES=["DEBUG_ENABLED"]) env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"]) + env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"]) elif env["target"] == "debug": env.Append(CCFLAGS=["/Zi"]) env.Append(CCFLAGS=["/MDd"]) env.Append(CPPDEFINES=["DEBUG_ENABLED"]) env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"]) + env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"]) env.Append(LINKFLAGS=["/DEBUG"]) ## Compiler configuration diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index ede0d7c76b..5679ec3eac 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -961,7 +961,7 @@ class EditorExportPlatformUWP : public EditorExportPlatform { return true; } - static Error save_appx_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) { + static Error save_appx_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) { AppxPackager *packager = (AppxPackager *)p_userdata; String dst_path = p_path.replace_first("res://", "game/"); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 401ba6c35d..44ab075816 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -296,7 +296,7 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a void OS_UWP::set_clipboard(const String &p_text) { DataPackage ^ clip = ref new DataPackage(); clip->RequestedOperation = DataPackageOperation::Copy; - clip->SetText(ref new Platform::String((const wchar_t *)p_text.c_str())); + clip->SetText(ref new Platform::String((LPCWSTR)(p_text.utf16().get_data()))); Clipboard::SetContent(clip); }; @@ -346,8 +346,8 @@ void OS_UWP::finalize_core() { } void OS_UWP::alert(const String &p_alert, const String &p_title) { - Platform::String ^ alert = ref new Platform::String(p_alert.c_str()); - Platform::String ^ title = ref new Platform::String(p_title.c_str()); + Platform::String ^ alert = ref new Platform::String((LPCWSTR)(p_alert.utf16().get_data())); + Platform::String ^ title = ref new Platform::String((LPCWSTR)(p_title.utf16().get_data())); MessageDialog ^ msg = ref new MessageDialog(alert, title); @@ -738,7 +738,7 @@ static String format_error_message(DWORD id) { Error OS_UWP::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { String full_path = "game/" + p_path; - p_library_handle = (void *)LoadPackagedLibrary(full_path.c_str(), 0); + p_library_handle = (void *)LoadPackagedLibrary((LPCWSTR)(full_path.utf16().get_data()), 0); ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + full_path + ", error: " + format_error_message(GetLastError()) + "."); return OK; } diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp index 996d9722f5..02031ef6bb 100644 --- a/platform/windows/crash_handler_windows.cpp +++ b/platform/windows/crash_handler_windows.cpp @@ -175,7 +175,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) { msg = proj_settings->get("debug/settings/crash_handler/message"); } - fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str()); + fprintf(stderr, "Dumping the backtrace. %s\n", msg.utf8().get_data()); int n = 0; do { diff --git a/platform/windows/detect.py b/platform/windows/detect.py index a9f25fa078..6b503c1561 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -65,6 +65,7 @@ def get_opts(): # Vista support dropped after EOL due to GH-10243 ("target_win_version", "Targeted Windows version, >= 0x0601 (Windows 7)", "0x0601"), EnumVariable("debug_symbols", "Add debugging symbols to release builds", "yes", ("yes", "no", "full")), + EnumVariable("windows_subsystem", "Windows subsystem", "gui", ("console", "gui")), BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False), ("msvc_version", "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", None), BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed. Only used on Windows.", False), @@ -177,6 +178,8 @@ def configure_msvc(env, manual_msvc_config): """Configure env to work with MSVC""" # Build type + if env["tests"]: + env["windows_subsystem"] = "console" if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) @@ -199,12 +202,16 @@ def configure_msvc(env, manual_msvc_config): env.AppendUnique(CPPDEFINES=["DEBUG_ENABLED"]) env.Append(LINKFLAGS=["/DEBUG"]) - env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"]) - if env["debug_symbols"] == "full" or env["debug_symbols"] == "yes": env.AppendUnique(CCFLAGS=["/Z7"]) env.AppendUnique(LINKFLAGS=["/DEBUG"]) + if env["windows_subsystem"] == "gui": + env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"]) + else: + env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"]) + env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"]) + ## Compile/link flags env.AppendUnique(CCFLAGS=["/MT", "/Gd", "/GR", "/nologo"]) @@ -302,6 +309,9 @@ def configure_mingw(env): ## Build type + if env["tests"]: + env["windows_subsystem"] = "console" + if env["target"] == "release": env.Append(CCFLAGS=["-msse2"]) @@ -334,7 +344,11 @@ def configure_mingw(env): env.Append(CCFLAGS=["-g3"]) env.Append(CPPDEFINES=["DEBUG_ENABLED"]) - env.Append(LINKFLAGS=["-Wl,--subsystem,windows"]) + if env["windows_subsystem"] == "gui": + env.Append(LINKFLAGS=["-Wl,--subsystem,windows"]) + else: + env.Append(LINKFLAGS=["-Wl,--subsystem,console"]) + env.AppendUnique(CPPDEFINES=["WINDOWS_SUBSYSTEM_CONSOLE"]) ## Compiler configuration @@ -425,7 +439,7 @@ def configure_mingw(env): else: env.Append(LIBS=["cfgmgr32"]) - ## TODO !!! Reenable when OpenGLES Rendering Device is implemented !!! + ## TODO !!! Re-enable when OpenGLES Rendering Device is implemented !!! # env.Append(CPPDEFINES=['OPENGL_ENABLED']) env.Append(LIBS=["opengl32"]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index cd7f28833b..dfbb734ee4 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "display_server_windows.h" + #include "core/io/marshalls.h" +#include "core/math/geometry_2d.h" #include "main/main.h" #include "os_windows.h" #include "scene/resources/texture.h" @@ -42,7 +44,7 @@ static String format_error_message(DWORD id) { size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr); - String msg = "Error " + itos(id) + ": " + String(messageBuffer, size); + String msg = "Error " + itos(id) + ": " + String::utf16((const char16_t *)messageBuffer, size); LocalFree(messageBuffer); @@ -78,7 +80,7 @@ String DisplayServerWindows::get_name() const { } void DisplayServerWindows::alert(const String &p_alert, const String &p_title) { - MessageBoxW(nullptr, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); + MessageBoxW(nullptr, (LPCWSTR)(p_alert.utf16().get_data()), (LPCWSTR)(p_title.utf16().get_data()), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL); } void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { @@ -177,11 +179,12 @@ void DisplayServerWindows::clipboard_set(const String &p_text) { } EmptyClipboard(); - HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(CharType)); + Char16String utf16 = text.utf16(); + HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (utf16.length() + 1) * sizeof(WCHAR)); ERR_FAIL_COND_MSG(mem == nullptr, "Unable to allocate memory for clipboard contents."); LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem); - memcpy(lptstrCopy, text.c_str(), (text.length() + 1) * sizeof(CharType)); + memcpy(lptstrCopy, utf16.get_data(), (utf16.length() + 1) * sizeof(WCHAR)); GlobalUnlock(mem); SetClipboardData(CF_UNICODETEXT, mem); @@ -218,7 +221,7 @@ String DisplayServerWindows::clipboard_get() const { if (mem != nullptr) { LPWSTR ptr = (LPWSTR)GlobalLock(mem); if (ptr != nullptr) { - ret = String((CharType *)ptr); + ret = String::utf16((const char16_t *)ptr); GlobalUnlock(mem); }; }; @@ -593,7 +596,37 @@ void DisplayServerWindows::window_set_title(const String &p_title, WindowID p_wi _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - SetWindowTextW(windows[p_window].hWnd, p_title.c_str()); + SetWindowTextW(windows[p_window].hWnd, (LPCWSTR)(p_title.utf16().get_data())); +} + +void DisplayServerWindows::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + windows[p_window].mpath = p_region; + _update_window_mouse_passthrough(p_window); +} + +void DisplayServerWindows::_update_window_mouse_passthrough(WindowID p_window) { + if (windows[p_window].mpath.size() == 0) { + SetWindowRgn(windows[p_window].hWnd, nullptr, TRUE); + } else { + POINT *points = (POINT *)memalloc(sizeof(POINT) * windows[p_window].mpath.size()); + for (int i = 0; i < windows[p_window].mpath.size(); i++) { + if (windows[p_window].borderless) { + points[i].x = windows[p_window].mpath[i].x; + points[i].y = windows[p_window].mpath[i].y; + } else { + points[i].x = windows[p_window].mpath[i].x + GetSystemMetrics(SM_CXSIZEFRAME); + points[i].y = windows[p_window].mpath[i].y + GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION); + } + } + + HRGN region = CreatePolygonRgn(points, windows[p_window].mpath.size(), ALTERNATE); + SetWindowRgn(windows[p_window].hWnd, region, TRUE); + DeleteObject(region); + memfree(points); + } } int DisplayServerWindows::window_get_current_screen(WindowID p_window) const { @@ -1009,6 +1042,7 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W case WINDOW_FLAG_BORDERLESS: { wd.borderless = p_enabled; _update_window_style(p_window); + _update_window_mouse_passthrough(p_window); } break; case WINDOW_FLAG_ALWAYS_ON_TOP: { ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID && p_enabled, "Transient windows can't become on top"); @@ -1137,17 +1171,10 @@ void DisplayServerWindows::window_set_ime_position(const Point2i &p_pos, WindowI void DisplayServerWindows::console_set_visible(bool p_enabled) { _THREAD_SAFE_METHOD_ - if (console_visible == p_enabled) { + if (console_visible == p_enabled) return; - } - if (p_enabled && GetConsoleWindow() == nullptr) { // Open new console if not attached. - own_console = true; - AllocConsole(); - } - if (own_console) { // Note: Do not hide parent console. - ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); - console_visible = p_enabled; - } + ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); + console_visible = p_enabled; } bool DisplayServerWindows::is_console_visible() const { @@ -1430,13 +1457,13 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const { HKL *layouts = (HKL *)memalloc(layout_count * sizeof(HKL)); GetKeyboardLayoutList(layout_count, layouts); - wchar_t buf[LOCALE_NAME_MAX_LENGTH]; - memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t)); + WCHAR buf[LOCALE_NAME_MAX_LENGTH]; + memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(WCHAR)); LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0); memfree(layouts); - return String(buf).substr(0, 2); + return String::utf16((const char16_t *)buf).substr(0, 2); } String _get_full_layout_name_from_registry(HKL p_layout) { @@ -1444,17 +1471,17 @@ String _get_full_layout_name_from_registry(HKL p_layout) { String ret; HKEY hkey; - wchar_t layout_text[1024]; - memset(layout_text, 0, 1024 * sizeof(wchar_t)); + WCHAR layout_text[1024]; + memset(layout_text, 0, 1024 * sizeof(WCHAR)); - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)id.c_str(), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) { + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)(id.utf16().get_data()), 0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS) { return ret; } DWORD buffer = 1024; DWORD vtype = REG_SZ; if (RegQueryValueExW(hkey, L"Layout Text", NULL, &vtype, (LPBYTE)layout_text, &buffer) == ERROR_SUCCESS) { - ret = String(layout_text); + ret = String::utf16((const char16_t *)layout_text); } RegCloseKey(hkey); return ret; @@ -1470,15 +1497,15 @@ String DisplayServerWindows::keyboard_get_layout_name(int p_index) const { String ret = _get_full_layout_name_from_registry(layouts[p_index]); // Try reading full name from Windows registry, fallback to locale name if failed (e.g. on Wine). if (ret == String()) { - wchar_t buf[LOCALE_NAME_MAX_LENGTH]; - memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t)); + WCHAR buf[LOCALE_NAME_MAX_LENGTH]; + memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(WCHAR)); LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0); - wchar_t name[1024]; - memset(name, 0, 1024 * sizeof(wchar_t)); + WCHAR name[1024]; + memset(name, 0, 1024 * sizeof(WCHAR)); GetLocaleInfoEx(buf, LOCALE_SLOCALIZEDDISPLAYNAME, (LPWSTR)&name, 1024); - ret = String(name); + ret = String::utf16((const char16_t *)name); } memfree(layouts); @@ -2718,7 +2745,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA case WM_DROPFILES: { HDROP hDropInfo = (HDROP)wParam; const int buffsize = 4096; - wchar_t buf[buffsize]; + WCHAR buf[buffsize]; int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, nullptr, 0); @@ -2726,7 +2753,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA for (int i = 0; i < fcount; i++) { DragQueryFileW(hDropInfo, i, buf, buffsize); - String file = buf; + String file = String::utf16((const char16_t *)buf); files.push_back(file); } @@ -3028,18 +3055,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win shift_mem = false; control_mem = false; meta_mem = false; - - if (AttachConsole(ATTACH_PARENT_PROCESS)) { - FILE *_file = nullptr; - freopen_s(&_file, "CONOUT$", "w", stdout); - freopen_s(&_file, "CONOUT$", "w", stderr); - freopen_s(&_file, "CONIN$", "r", stdin); - - printf("\n"); - console_visible = true; - } else { - console_visible = false; - } + console_visible = IsWindowVisible(GetConsoleWindow()); hInstance = ((OS_Windows *)OS::get_singleton())->get_hinstance(); pressrc = 0; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 52f5b0f4a9..0fca2589ae 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -323,6 +323,8 @@ private: HWND hWnd; //layered window + Vector<Vector2> mpath; + bool preserve_window_size = false; bool pre_fs_valid = false; RECT pre_fs_rect; @@ -405,7 +407,6 @@ private: bool drop_events = false; bool in_dispatch_input_event = false; bool console_visible = false; - bool own_console = false; WNDCLASSEXW wc; @@ -417,6 +418,7 @@ private: void _touch_event(WindowID p_window, bool p_pressed, float p_x, float p_y, int idx); void _update_window_style(WindowID p_window, bool p_repaint = true, bool p_maximized = false); + void _update_window_mouse_passthrough(WindowID p_window); void _update_real_mouse_position(WindowID p_window); @@ -478,6 +480,7 @@ public: virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID); + virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID); virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const; virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 5b15896b0c..f73516b370 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -84,7 +84,7 @@ static String format_error_message(DWORD id) { size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr); - String msg = "Error " + itos(id) + ": " + String(messageBuffer, size); + String msg = "Error " + itos(id) + ": " + String::utf16((const char16_t *)messageBuffer, size); LocalFree(messageBuffer); @@ -107,15 +107,11 @@ void RedirectIOToConsole() { // set the screen buffer to be big enough to let us scroll text - GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), - - &coninfo); + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); coninfo.dwSize.Y = MAX_CONSOLE_LINES; - SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), - - coninfo.dwSize); + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); // redirect unbuffered STDOUT to the console @@ -265,10 +261,10 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han DLL_DIRECTORY_COOKIE cookie = nullptr; if (p_also_set_library_path && has_dll_directory_api) { - cookie = add_dll_directory(path.get_base_dir().c_str()); + cookie = add_dll_directory((LPCWSTR)(path.get_base_dir().utf16().get_data())); } - p_library_handle = (void *)LoadLibraryExW(path.c_str(), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); + p_library_handle = (void *)LoadLibraryExW((LPCWSTR)(path.utf16().get_data()), nullptr, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ", error: " + format_error_message(GetLastError()) + "."); if (cookie) { @@ -407,7 +403,7 @@ uint64_t OS_Windows::get_ticks_usec() const { String OS_Windows::_quote_command_line_argument(const String &p_text) const { for (int i = 0; i < p_text.size(); i++) { - CharType c = p_text[i]; + char32_t c = p_text[i]; if (c == ' ' || c == '&' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '=' || c == ';' || c == '!' || c == '\'' || c == '+' || c == ',' || c == '`' || c == '~') { return "\"" + p_text + "\""; } @@ -428,7 +424,7 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, // Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command. argss = _quote_command_line_argument(argss); - FILE *f = _wpopen(argss.c_str(), L"r"); + FILE *f = _wpopen((LPCWSTR)(argss.utf16().get_data()), L"r"); ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); char buf[65535]; @@ -463,13 +459,8 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, ZeroMemory(&pi.pi, sizeof(pi.pi)); LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; - Vector<CharType> modstr; // Windows wants to change this no idea why. - modstr.resize(cmdline.size()); - for (int i = 0; i < cmdline.size(); i++) { - modstr.write[i] = cmdline[i]; - } - - int ret = CreateProcessW(nullptr, modstr.ptrw(), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); + Char16String modstr = cmdline.utf16(); // Windows wants to change this no idea why. + int ret = CreateProcessW(nullptr, (LPWSTR)(modstr.ptrw()), nullptr, nullptr, 0, NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK); if (p_blocking) { @@ -509,26 +500,26 @@ int OS_Windows::get_process_id() const { } Error OS_Windows::set_cwd(const String &p_cwd) { - if (_wchdir(p_cwd.c_str()) != 0) + if (_wchdir((LPCWSTR)(p_cwd.utf16().get_data())) != 0) return ERR_CANT_OPEN; return OK; } String OS_Windows::get_executable_path() const { - wchar_t bufname[4096]; + WCHAR bufname[4096]; GetModuleFileNameW(nullptr, bufname, 4096); - String s = bufname; + String s = String::utf16((const char16_t *)bufname); return s; } bool OS_Windows::has_environment(const String &p_var) const { #ifdef MINGW_ENABLED - return _wgetenv(p_var.c_str()) != nullptr; + return _wgetenv((LPCWSTR)(p_var.utf16().get_data())) != nullptr; #else - wchar_t *env; + WCHAR *env; size_t len; - _wdupenv_s(&env, &len, p_var.c_str()); + _wdupenv_s(&env, &len, (LPCWSTR)(p_var.utf16().get_data())); const bool has_env = env != nullptr; free(env); return has_env; @@ -536,16 +527,16 @@ bool OS_Windows::has_environment(const String &p_var) const { }; String OS_Windows::get_environment(const String &p_var) const { - wchar_t wval[0x7Fff]; // MSDN says 32767 char is the maximum - int wlen = GetEnvironmentVariableW(p_var.c_str(), wval, 0x7Fff); + WCHAR wval[0x7fff]; // MSDN says 32767 char is the maximum + int wlen = GetEnvironmentVariableW((LPCWSTR)(p_var.utf16().get_data()), wval, 0x7fff); if (wlen > 0) { - return wval; + return String::utf16((const char16_t *)wval); } return ""; } bool OS_Windows::set_environment(const String &p_var, const String &p_value) const { - return (bool)SetEnvironmentVariableW(p_var.c_str(), p_value.c_str()); + return (bool)SetEnvironmentVariableW((LPCWSTR)(p_var.utf16().get_data()), (LPCWSTR)(p_value.utf16().get_data())); } String OS_Windows::get_stdin_string(bool p_block) { @@ -558,7 +549,7 @@ String OS_Windows::get_stdin_string(bool p_block) { } Error OS_Windows::shell_open(String p_uri) { - ShellExecuteW(nullptr, nullptr, p_uri.c_str(), nullptr, nullptr, SW_SHOWNORMAL); + ShellExecuteW(nullptr, nullptr, (LPCWSTR)(p_uri.utf16().get_data()), nullptr, nullptr, SW_SHOWNORMAL); return OK; } @@ -701,7 +692,7 @@ String OS_Windows::get_system_dir(SystemDir p_dir) const { PWSTR szPath; HRESULT res = SHGetKnownFolderPath(id, 0, nullptr, &szPath); ERR_FAIL_COND_V(res != S_OK, String()); - String path = String(szPath); + String path = String::utf16((const char16_t *)szPath); CoTaskMemFree(szPath); return path; } @@ -727,7 +718,7 @@ String OS_Windows::get_user_data_dir() const { String OS_Windows::get_unique_id() const { HW_PROFILE_INFO HwProfInfo; ERR_FAIL_COND_V(!GetCurrentHwProfile(&HwProfInfo), ""); - return String(HwProfInfo.szHwProfileGuid); + return String::utf16((const char16_t *)(HwProfInfo.szHwProfileGuid), HW_PROFILE_GUIDLEN); } bool OS_Windows::_check_internal_feature_support(const String &p_feature) { @@ -744,9 +735,11 @@ bool OS_Windows::is_disable_crash_handler() const { Error OS_Windows::move_to_trash(const String &p_path) { SHFILEOPSTRUCTW sf; - WCHAR *from = new WCHAR[p_path.length() + 2]; - wcscpy_s(from, p_path.length() + 1, p_path.c_str()); - from[p_path.length() + 1] = 0; + + Char16String utf16 = p_path.utf16(); + WCHAR *from = new WCHAR[utf16.length() + 2]; + wcscpy_s(from, utf16.length() + 1, (LPCWSTR)(utf16.get_data())); + from[utf16.length() + 1] = 0; sf.hwnd = main_window; sf.wFunc = FO_DELETE; diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 9fd24b5294..a00db36077 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -35,15 +35,15 @@ #include "physics_body_2d.h" #include "servers/physics_server_2d.h" -void RayCast2D::set_cast_to(const Vector2 &p_point) { - cast_to = p_point; +void RayCast2D::set_target_position(const Vector2 &p_point) { + target_position = p_point; if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) { update(); } } -Vector2 RayCast2D::get_cast_to() const { - return cast_to; +Vector2 RayCast2D::get_target_position() const { + return target_position; } void RayCast2D::set_collision_mask(uint32_t p_mask) { @@ -160,8 +160,8 @@ void RayCast2D::_notification(int p_what) { break; } Transform2D xf; - xf.rotate(cast_to.angle()); - xf.translate(Vector2(cast_to.length(), 0)); + xf.rotate(target_position.angle()); + xf.translate(Vector2(target_position.length(), 0)); // Draw an arrow indicating where the RayCast is pointing to Color draw_col = get_tree()->get_debug_collisions_color(); @@ -171,7 +171,7 @@ void RayCast2D::_notification(int p_what) { draw_col.g = g; draw_col.b = g; } - draw_line(Vector2(), cast_to, draw_col, 2); + draw_line(Vector2(), target_position, draw_col, 2); Vector<Vector2> pts; float tsize = 8; pts.push_back(xf.xform(Vector2(tsize, 0))); @@ -206,7 +206,7 @@ void RayCast2D::_update_raycast_state() { Transform2D gt = get_global_transform(); - Vector2 to = cast_to; + Vector2 to = target_position; if (to == Vector2()) { to = Vector2(0, 0.01); } @@ -280,8 +280,8 @@ void RayCast2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast2D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast2D::is_enabled); - ClassDB::bind_method(D_METHOD("set_cast_to", "local_point"), &RayCast2D::set_cast_to); - ClassDB::bind_method(D_METHOD("get_cast_to"), &RayCast2D::get_cast_to); + ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &RayCast2D::set_target_position); + ClassDB::bind_method(D_METHOD("get_target_position"), &RayCast2D::get_target_position); ClassDB::bind_method(D_METHOD("is_colliding"), &RayCast2D::is_colliding); ClassDB::bind_method(D_METHOD("force_raycast_update"), &RayCast2D::force_raycast_update); @@ -316,7 +316,7 @@ void RayCast2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "cast_to"), "set_cast_to", "get_cast_to"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Collide With", "collide_with"); @@ -329,7 +329,7 @@ RayCast2D::RayCast2D() { collided = false; against_shape = 0; collision_mask = 1; - cast_to = Vector2(0, 50); + target_position = Vector2(0, 50); exclude_parent_body = true; collide_with_bodies = true; collide_with_areas = false; diff --git a/scene/2d/ray_cast_2d.h b/scene/2d/ray_cast_2d.h index 6accc264a0..14932f782b 100644 --- a/scene/2d/ray_cast_2d.h +++ b/scene/2d/ray_cast_2d.h @@ -46,7 +46,7 @@ class RayCast2D : public Node2D { uint32_t collision_mask; bool exclude_parent_body; - Vector2 cast_to; + Vector2 target_position; bool collide_with_areas; bool collide_with_bodies; @@ -66,8 +66,8 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; - void set_cast_to(const Vector2 &p_point); - Vector2 get_cast_to() const; + void set_target_position(const Vector2 &p_point); + Vector2 get_target_position() const; void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c7a809f6d8..c2951559a4 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -412,6 +412,9 @@ void TileMap::update_dirty_quadrants() { vs->canvas_item_set_light_mask(canvas_item, get_light_mask()); vs->canvas_item_set_z_index(canvas_item, z_index); + vs->canvas_item_set_default_texture_filter(canvas_item, RS::CanvasItemTextureFilter(CanvasItem::get_texture_filter())); + vs->canvas_item_set_default_texture_repeat(canvas_item, RS::CanvasItemTextureRepeat(CanvasItem::get_texture_repeat())); + q.canvas_items.push_back(canvas_item); if (debug_shapes) { @@ -1687,6 +1690,28 @@ bool TileMap::get_clip_uv() const { return clip_uv; } +void TileMap::set_texture_filter(TextureFilter p_texture_filter) { + CanvasItem::set_texture_filter(p_texture_filter); + for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) { + Quadrant &q = F->get(); + for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) { + RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(E->get(), RS::CanvasItemTextureFilter(p_texture_filter)); + _make_quadrant_dirty(F); + } + } +} + +void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) { + CanvasItem::set_texture_repeat(p_texture_repeat); + for (Map<PosKey, Quadrant>::Element *F = quadrant_map.front(); F; F = F->next()) { + Quadrant &q = F->get(); + for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) { + RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(E->get(), RS::CanvasItemTextureRepeat(p_texture_repeat)); + _make_quadrant_dirty(F); + } + } +} + String TileMap::get_configuration_warning() const { String warning = Node2D::get_configuration_warning(); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index 7a2a3e412c..b9dd8f5405 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -342,6 +342,10 @@ public: String get_configuration_warning() const override; + virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override; + + virtual void set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) override; + void fix_invalid_tiles(); void clear(); diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 56367e9bdd..e7f3f53ca9 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -44,23 +44,36 @@ //TODO: Implement CylinderShape and HeightMapShape? -void CollisionShape3D::make_convex_from_brothers() { +void CollisionShape3D::make_convex_from_siblings() { Node *p = get_parent(); if (!p) { return; } + Vector<Vector3> vertices; + for (int i = 0; i < p->get_child_count(); i++) { Node *n = p->get_child(i); MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(n); if (mi) { Ref<Mesh> m = mi->get_mesh(); if (m.is_valid()) { - Ref<Shape3D> s = m->create_convex_shape(); - set_shape(s); + for (int j = 0; j < m->get_surface_count(); j++) { + Array a = m->surface_get_arrays(j); + if (!a.empty()) { + Vector<Vector3> v = a[RenderingServer::ARRAY_VERTEX]; + for (int k = 0; k < v.size(); k++) { + vertices.append(mi->get_transform().xform(v[k])); + } + } + } } } } + + Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); + shape->set_points(vertices); + set_shape(shape); } void CollisionShape3D::_update_in_shape_owner(bool p_xform_only) { @@ -137,8 +150,8 @@ void CollisionShape3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_shape"), &CollisionShape3D::get_shape); ClassDB::bind_method(D_METHOD("set_disabled", "enable"), &CollisionShape3D::set_disabled); ClassDB::bind_method(D_METHOD("is_disabled"), &CollisionShape3D::is_disabled); - ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape3D::make_convex_from_brothers); - ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ClassDB::bind_method(D_METHOD("make_convex_from_siblings"), &CollisionShape3D::make_convex_from_siblings); + ClassDB::set_method_flags("CollisionShape3D", "make_convex_from_siblings", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape3D::_update_debug_shape); diff --git a/scene/3d/collision_shape_3d.h b/scene/3d/collision_shape_3d.h index a32a3efeb6..35f40d27b1 100644 --- a/scene/3d/collision_shape_3d.h +++ b/scene/3d/collision_shape_3d.h @@ -60,7 +60,7 @@ protected: static void _bind_methods(); public: - void make_convex_from_brothers(); + void make_convex_from_siblings(); void set_shape(const Ref<Shape3D> &p_shape); Ref<Shape3D> get_shape() const; diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index c4480e3ed2..6fa0fc6ecb 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -301,6 +301,36 @@ void GPUParticles3D::_validate_property(PropertyInfo &property) const { } } +void GPUParticles3D::emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { + RS::get_singleton()->particles_emit(particles, p_transform, p_velocity, p_color, p_custom, p_emit_flags); +} + +void GPUParticles3D::_attach_sub_emitter() { + Node *n = get_node_or_null(sub_emitter); + if (n) { + GPUParticles3D *sen = Object::cast_to<GPUParticles3D>(n); + if (sen && sen != this) { + RS::get_singleton()->particles_set_subemitter(particles, sen->particles); + } + } +} + +void GPUParticles3D::set_sub_emitter(const NodePath &p_path) { + if (is_inside_tree()) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + + sub_emitter = p_path; + + if (is_inside_tree() && sub_emitter != NodePath()) { + _attach_sub_emitter(); + } +} + +NodePath GPUParticles3D::get_sub_emitter() const { + return sub_emitter; +} + void GPUParticles3D::_notification(int p_what) { if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { @@ -319,6 +349,16 @@ void GPUParticles3D::_notification(int p_what) { } } + if (p_what == NOTIFICATION_ENTER_TREE) { + if (sub_emitter != NodePath()) { + _attach_sub_emitter(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { // make sure particles are updated before rendering occurs if they were active before if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) { @@ -369,8 +409,14 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &GPUParticles3D::restart); ClassDB::bind_method(D_METHOD("capture_aabb"), &GPUParticles3D::capture_aabb); + ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles3D::set_sub_emitter); + ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles3D::get_sub_emitter); + + ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles3D::emit_particle); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_EXP_RANGE, "1,1000000,1"), "set_amount", "get_amount"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_EXP_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); @@ -396,6 +442,12 @@ void GPUParticles3D::_bind_methods() { BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); BIND_ENUM_CONSTANT(DRAW_ORDER_VIEW_DEPTH); + BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION); + BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE); + BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY); + BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR); + BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM); + BIND_CONSTANT(MAX_DRAW_PASSES); } diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h index e04473727d..0d8dadd31d 100644 --- a/scene/3d/gpu_particles_3d.h +++ b/scene/3d/gpu_particles_3d.h @@ -64,6 +64,7 @@ private: bool local_coords; int fixed_fps; bool fractional_delta; + NodePath sub_emitter; Ref<Material> process_material; @@ -71,6 +72,8 @@ private: Vector<Ref<Mesh>> draw_passes; + void _attach_sub_emitter(); + protected: static void _bind_methods(); void _notification(int p_what); @@ -121,13 +124,27 @@ public: virtual String get_configuration_warning() const override; + void set_sub_emitter(const NodePath &p_path); + NodePath get_sub_emitter() const; + void restart(); + enum EmitFlags { + EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION, + EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE, + EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY, + EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR, + EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM + }; + + void emit_particle(const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); + AABB capture_aabb() const; GPUParticles3D(); ~GPUParticles3D(); }; VARIANT_ENUM_CAST(GPUParticles3D::DrawOrder) +VARIANT_ENUM_CAST(GPUParticles3D::EmitFlags) #endif // PARTICLES_H diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 2a922e3cda..69f09ef569 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -35,8 +35,8 @@ #include "mesh_instance_3d.h" #include "servers/physics_server_3d.h" -void RayCast3D::set_cast_to(const Vector3 &p_point) { - cast_to = p_point; +void RayCast3D::set_target_position(const Vector3 &p_point) { + target_position = p_point; if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) { update_gizmo(); } @@ -45,8 +45,8 @@ void RayCast3D::set_cast_to(const Vector3 &p_point) { } } -Vector3 RayCast3D::get_cast_to() const { - return cast_to; +Vector3 RayCast3D::get_target_position() const { + return target_position; } void RayCast3D::set_collision_mask(uint32_t p_mask) { @@ -202,7 +202,7 @@ void RayCast3D::_update_raycast_state() { Transform gt = get_global_transform(); - Vector3 to = cast_to; + Vector3 to = target_position; if (to == Vector3()) { to = Vector3(0, 0.01, 0); } @@ -276,8 +276,8 @@ void RayCast3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &RayCast3D::set_enabled); ClassDB::bind_method(D_METHOD("is_enabled"), &RayCast3D::is_enabled); - ClassDB::bind_method(D_METHOD("set_cast_to", "local_point"), &RayCast3D::set_cast_to); - ClassDB::bind_method(D_METHOD("get_cast_to"), &RayCast3D::get_cast_to); + ClassDB::bind_method(D_METHOD("set_target_position", "local_point"), &RayCast3D::set_target_position); + ClassDB::bind_method(D_METHOD("get_target_position"), &RayCast3D::get_target_position); ClassDB::bind_method(D_METHOD("is_colliding"), &RayCast3D::is_colliding); ClassDB::bind_method(D_METHOD("force_raycast_update"), &RayCast3D::force_raycast_update); @@ -312,7 +312,7 @@ void RayCast3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclude_parent"), "set_exclude_parent_body", "get_exclude_parent_body"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "cast_to"), "set_cast_to", "get_cast_to"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_GROUP("Collide With", "collide_with"); @@ -360,7 +360,7 @@ void RayCast3D::_update_debug_shape() { Vector<Vector3> verts; verts.push_back(Vector3()); - verts.push_back(cast_to); + verts.push_back(target_position); a[Mesh::ARRAY_VERTEX] = verts; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, a); @@ -387,7 +387,7 @@ RayCast3D::RayCast3D() { collided = false; against_shape = 0; collision_mask = 1; - cast_to = Vector3(0, -1, 0); + target_position = Vector3(0, -1, 0); debug_shape = nullptr; exclude_parent_body = true; collide_with_areas = false; diff --git a/scene/3d/ray_cast_3d.h b/scene/3d/ray_cast_3d.h index 8f617e5491..f4fe7ba621 100644 --- a/scene/3d/ray_cast_3d.h +++ b/scene/3d/ray_cast_3d.h @@ -43,7 +43,7 @@ class RayCast3D : public Node3D { Vector3 collision_point; Vector3 collision_normal; - Vector3 cast_to; + Vector3 target_position; Set<RID> exclude; uint32_t collision_mask; @@ -74,8 +74,8 @@ public: void set_enabled(bool p_enabled); bool is_enabled() const; - void set_cast_to(const Vector3 &p_point); - Vector3 get_cast_to() const; + void set_target_position(const Vector3 &p_point); + Vector3 get_target_position() const; void set_collision_mask(uint32_t p_mask); uint32_t get_collision_mask() const; diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index a267c57f5e..d3d7cdc1ce 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -106,7 +106,7 @@ SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { offset = obj_tocopy.offset; } -SoftBody3D::PinnedPoint SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { +SoftBody3D::PinnedPoint &SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { point_index = obj.point_index; spatial_attachment_path = obj.spatial_attachment_path; spatial_attachment = obj.spatial_attachment; diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index 85cfb81637..c59a0b3aa3 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -74,7 +74,7 @@ public: PinnedPoint(); PinnedPoint(const PinnedPoint &obj_tocopy); - PinnedPoint operator=(const PinnedPoint &obj); + PinnedPoint &operator=(const PinnedPoint &obj); }; private: diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 6fef44481a..2e77d20d4e 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -60,7 +60,7 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventMouseButton> mouse_button = p_event; bool ui_accept = p_event->is_action("ui_accept") && !p_event->is_echo(); - bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) > 0; + bool button_masked = mouse_button.is_valid() && ((1 << (mouse_button->get_button_index() - 1)) & button_mask) != 0; if (button_masked || ui_accept) { on_action_event(p_event); return; @@ -326,12 +326,12 @@ bool BaseButton::is_keep_pressed_outside() const { return keep_pressed_outside; } -void BaseButton::set_shortcut(const Ref<ShortCut> &p_shortcut) { +void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) { shortcut = p_shortcut; set_process_unhandled_input(shortcut.is_valid()); } -Ref<ShortCut> BaseButton::get_shortcut() const { +Ref<Shortcut> BaseButton::get_shortcut() const { return shortcut; } @@ -345,7 +345,7 @@ String BaseButton::get_tooltip(const Point2 &p_pos) const { String tooltip = Control::get_tooltip(p_pos); if (shortcut_in_tooltip && shortcut.is_valid() && shortcut->is_valid()) { String text = shortcut->get_name() + " (" + shortcut->get_as_text() + ")"; - if (shortcut->get_name().nocasecmp_to(tooltip) != 0) { + if (tooltip != String() && shortcut->get_name().nocasecmp_to(tooltip) != 0) { text += "\n" + tooltip; } tooltip = text; @@ -414,7 +414,7 @@ void BaseButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "enabled_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_enabled_focus_mode", "get_enabled_focus_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_shortcut", "get_shortcut"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "Shortcut"), "set_shortcut", "get_shortcut"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "group", PROPERTY_HINT_RESOURCE_TYPE, "ButtonGroup"), "set_button_group", "get_button_group"); BIND_ENUM_CONSTANT(DRAW_NORMAL); diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 12272446d5..8e71931f8b 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -50,7 +50,7 @@ private: bool shortcut_in_tooltip; bool keep_pressed_outside; FocusMode enabled_focus_mode; - Ref<ShortCut> shortcut; + Ref<Shortcut> shortcut; ActionMode action_mode; struct Status { @@ -118,8 +118,8 @@ public: void set_enabled_focus_mode(FocusMode p_mode); FocusMode get_enabled_focus_mode() const; - void set_shortcut(const Ref<ShortCut> &p_shortcut); - Ref<ShortCut> get_shortcut() const; + void set_shortcut(const Ref<Shortcut> &p_shortcut); + Ref<Shortcut> get_shortcut() const; virtual String get_tooltip(const Point2 &p_pos) const override; diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp new file mode 100644 index 0000000000..56cf432b38 --- /dev/null +++ b/scene/gui/code_edit.cpp @@ -0,0 +1,444 @@ +/*************************************************************************/ +/* code_edit.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 "code_edit.h" + +void CodeEdit::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_THEME_CHANGED: + case NOTIFICATION_ENTER_TREE: { + set_gutter_width(main_gutter, cache.row_height); + set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0').width); + set_gutter_width(fold_gutter, cache.row_height / 1.2); + + breakpoint_color = get_theme_color("breakpoint_color"); + breakpoint_icon = get_theme_icon("breakpoint"); + + bookmark_color = get_theme_color("bookmark_color"); + bookmark_icon = get_theme_icon("bookmark"); + + executing_line_color = get_theme_color("executing_line_color"); + executing_line_icon = get_theme_icon("executing_line"); + + line_number_color = get_theme_color("line_number_color"); + + folding_color = get_theme_color("code_folding_color"); + can_fold_icon = get_theme_icon("can_fold"); + folded_icon = get_theme_icon("folded"); + } break; + case NOTIFICATION_DRAW: { + } break; + } +} + +/* Main Gutter */ +void CodeEdit::_update_draw_main_gutter() { + set_gutter_draw(main_gutter, draw_breakpoints || draw_bookmarks || draw_executing_lines); +} + +void CodeEdit::set_draw_breakpoints_gutter(bool p_draw) { + draw_breakpoints = p_draw; + set_gutter_clickable(main_gutter, p_draw); + _update_draw_main_gutter(); +} + +bool CodeEdit::is_drawing_breakpoints_gutter() const { + return draw_breakpoints; +} + +void CodeEdit::set_draw_bookmarks_gutter(bool p_draw) { + draw_bookmarks = p_draw; + _update_draw_main_gutter(); +} + +bool CodeEdit::is_drawing_bookmarks_gutter() const { + return draw_bookmarks; +} + +void CodeEdit::set_draw_executing_lines_gutter(bool p_draw) { + draw_executing_lines = p_draw; + _update_draw_main_gutter(); +} + +bool CodeEdit::is_drawing_executing_lines_gutter() const { + return draw_executing_lines; +} + +void CodeEdit::_main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) { + if (draw_breakpoints && is_line_breakpointed(p_line)) { + int padding = p_region.size.x / 6; + + Rect2 breakpoint_region = p_region; + breakpoint_region.position += Point2(padding, padding); + breakpoint_region.size -= Point2(padding, padding) * 2; + breakpoint_icon->draw_rect(get_canvas_item(), breakpoint_region, false, breakpoint_color); + } + + if (draw_bookmarks && is_line_bookmarked(p_line)) { + int horizontal_padding = p_region.size.x / 2; + int vertical_padding = p_region.size.y / 4; + + Rect2 bookmark_region = p_region; + bookmark_region.position += Point2(horizontal_padding, 0); + bookmark_region.size -= Point2(horizontal_padding * 1.1, vertical_padding); + bookmark_icon->draw_rect(get_canvas_item(), bookmark_region, false, bookmark_color); + } + + if (draw_executing_lines && is_line_executing(p_line)) { + int horizontal_padding = p_region.size.x / 10; + int vertical_padding = p_region.size.y / 4; + + Rect2 executing_line_region = p_region; + executing_line_region.position += Point2(horizontal_padding, vertical_padding); + executing_line_region.size -= Point2(horizontal_padding, vertical_padding) * 2; + executing_line_icon->draw_rect(get_canvas_item(), executing_line_region, false, executing_line_color); + } +} + +// Breakpoints +void CodeEdit::set_line_as_breakpoint(int p_line, bool p_breakpointed) { + int mask = get_line_gutter_metadata(p_line, main_gutter); + set_line_gutter_metadata(p_line, main_gutter, p_breakpointed ? mask | MAIN_GUTTER_BREAKPOINT : mask & ~MAIN_GUTTER_BREAKPOINT); + if (p_breakpointed) { + breakpointed_lines[p_line] = true; + } else if (breakpointed_lines.has(p_line)) { + breakpointed_lines.erase(p_line); + } + emit_signal("breakpoint_toggled", p_line); +} + +bool CodeEdit::is_line_breakpointed(int p_line) const { + return (int)get_line_gutter_metadata(p_line, main_gutter) & MAIN_GUTTER_BREAKPOINT; +} + +void CodeEdit::clear_breakpointed_lines() { + for (int i = 0; i < get_line_count(); i++) { + if (is_line_breakpointed(i)) { + set_line_as_breakpoint(i, false); + } + } +} + +Array CodeEdit::get_breakpointed_lines() const { + Array ret; + for (int i = 0; i < get_line_count(); i++) { + if (is_line_breakpointed(i)) { + ret.append(i); + } + } + return ret; +} + +// Bookmarks +void CodeEdit::set_line_as_bookmarked(int p_line, bool p_bookmarked) { + int mask = get_line_gutter_metadata(p_line, main_gutter); + set_line_gutter_metadata(p_line, main_gutter, p_bookmarked ? mask | MAIN_GUTTER_BOOKMARK : mask & ~MAIN_GUTTER_BOOKMARK); +} + +bool CodeEdit::is_line_bookmarked(int p_line) const { + return (int)get_line_gutter_metadata(p_line, main_gutter) & MAIN_GUTTER_BOOKMARK; +} + +void CodeEdit::clear_bookmarked_lines() { + for (int i = 0; i < get_line_count(); i++) { + if (is_line_bookmarked(i)) { + set_line_as_bookmarked(i, false); + } + } +} + +Array CodeEdit::get_bookmarked_lines() const { + Array ret; + for (int i = 0; i < get_line_count(); i++) { + if (is_line_bookmarked(i)) { + ret.append(i); + } + } + return ret; +} + +// executing lines +void CodeEdit::set_line_as_executing(int p_line, bool p_executing) { + int mask = get_line_gutter_metadata(p_line, main_gutter); + set_line_gutter_metadata(p_line, main_gutter, p_executing ? mask | MAIN_GUTTER_EXECUTING : mask & ~MAIN_GUTTER_EXECUTING); +} + +bool CodeEdit::is_line_executing(int p_line) const { + return (int)get_line_gutter_metadata(p_line, main_gutter) & MAIN_GUTTER_EXECUTING; +} + +void CodeEdit::clear_executing_lines() { + for (int i = 0; i < get_line_count(); i++) { + if (is_line_executing(i)) { + set_line_as_executing(i, false); + } + } +} + +Array CodeEdit::get_executing_lines() const { + Array ret; + for (int i = 0; i < get_line_count(); i++) { + if (is_line_executing(i)) { + ret.append(i); + } + } + return ret; +} + +/* Line numbers */ +void CodeEdit::set_draw_line_numbers(bool p_draw) { + set_gutter_draw(line_number_gutter, p_draw); +} + +bool CodeEdit::is_draw_line_numbers_enabled() const { + return is_gutter_drawn(line_number_gutter); +} + +void CodeEdit::set_line_numbers_zero_padded(bool p_zero_padded) { + p_zero_padded ? line_number_padding = "0" : line_number_padding = " "; + update(); +} + +bool CodeEdit::is_line_numbers_zero_padded() const { + return line_number_padding == "0"; +} + +void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region) { + String fc = String::num(p_line + 1).lpad(line_number_digits, line_number_padding); + + int yofs = p_region.position.y + (cache.row_height - cache.font->get_height()) / 2; + Color number_color = get_line_gutter_item_color(p_line, line_number_gutter); + if (number_color == Color(1, 1, 1)) { + number_color = line_number_color; + } + cache.font->draw(get_canvas_item(), Point2(p_region.position.x, yofs + cache.font->get_ascent()), fc, number_color); +} + +/* Fold Gutter */ +void CodeEdit::set_draw_fold_gutter(bool p_draw) { + set_gutter_draw(fold_gutter, p_draw); +} + +bool CodeEdit::is_drawing_fold_gutter() const { + return is_gutter_drawn(fold_gutter); +} + +void CodeEdit::_fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region) { + if (!can_fold(p_line) && !is_folded(p_line)) { + set_line_gutter_clickable(p_line, fold_gutter, false); + return; + } + set_line_gutter_clickable(p_line, fold_gutter, true); + + int horizontal_padding = p_region.size.x / 10; + int vertical_padding = p_region.size.y / 6; + + p_region.position += Point2(horizontal_padding, vertical_padding); + p_region.size -= Point2(horizontal_padding, vertical_padding) * 2; + + if (can_fold(p_line)) { + can_fold_icon->draw_rect(get_canvas_item(), p_region, false, folding_color); + return; + } + folded_icon->draw_rect(get_canvas_item(), p_region, false, folding_color); +} + +void CodeEdit::_bind_methods() { + /* Main Gutter */ + ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback); + + ClassDB::bind_method(D_METHOD("set_draw_breakpoints_gutter", "enable"), &CodeEdit::set_draw_breakpoints_gutter); + ClassDB::bind_method(D_METHOD("is_drawing_breakpoints_gutter"), &CodeEdit::is_drawing_breakpoints_gutter); + + ClassDB::bind_method(D_METHOD("set_draw_bookmarks_gutter", "enable"), &CodeEdit::set_draw_bookmarks_gutter); + ClassDB::bind_method(D_METHOD("is_drawing_bookmarks_gutter"), &CodeEdit::is_drawing_bookmarks_gutter); + + ClassDB::bind_method(D_METHOD("set_draw_executing_lines_gutter", "enable"), &CodeEdit::set_draw_executing_lines_gutter); + ClassDB::bind_method(D_METHOD("is_drawing_executing_lines_gutter"), &CodeEdit::is_drawing_executing_lines_gutter); + + // Breakpoints + ClassDB::bind_method(D_METHOD("set_line_as_breakpoint", "line", "breakpointed"), &CodeEdit::set_line_as_breakpoint); + ClassDB::bind_method(D_METHOD("is_line_breakpointed", "line"), &CodeEdit::is_line_breakpointed); + ClassDB::bind_method(D_METHOD("clear_breakpointed_lines"), &CodeEdit::clear_breakpointed_lines); + ClassDB::bind_method(D_METHOD("get_breakpointed_lines"), &CodeEdit::get_breakpointed_lines); + + // Bookmarks + ClassDB::bind_method(D_METHOD("set_line_as_bookmarked", "line", "bookmarked"), &CodeEdit::set_line_as_bookmarked); + ClassDB::bind_method(D_METHOD("is_line_bookmarked", "line"), &CodeEdit::is_line_bookmarked); + ClassDB::bind_method(D_METHOD("clear_bookmarked_lines"), &CodeEdit::clear_bookmarked_lines); + ClassDB::bind_method(D_METHOD("get_bookmarked_lines"), &CodeEdit::get_bookmarked_lines); + + // executing lines + ClassDB::bind_method(D_METHOD("set_line_as_executing", "line", "executing"), &CodeEdit::set_line_as_executing); + ClassDB::bind_method(D_METHOD("is_line_executing", "line"), &CodeEdit::is_line_executing); + ClassDB::bind_method(D_METHOD("clear_executing_lines"), &CodeEdit::clear_executing_lines); + ClassDB::bind_method(D_METHOD("get_executing_lines"), &CodeEdit::get_executing_lines); + + /* Line numbers */ + ClassDB::bind_method(D_METHOD("_line_number_draw_callback"), &CodeEdit::_line_number_draw_callback); + + ClassDB::bind_method(D_METHOD("set_draw_line_numbers", "enable"), &CodeEdit::set_draw_line_numbers); + ClassDB::bind_method(D_METHOD("is_draw_line_numbers_enabled"), &CodeEdit::is_draw_line_numbers_enabled); + ClassDB::bind_method(D_METHOD("set_line_numbers_zero_padded", "enable"), &CodeEdit::set_line_numbers_zero_padded); + ClassDB::bind_method(D_METHOD("is_line_numbers_zero_padded"), &CodeEdit::is_line_numbers_zero_padded); + + /* Fold Gutter */ + ClassDB::bind_method(D_METHOD("_fold_gutter_draw_callback"), &CodeEdit::_fold_gutter_draw_callback); + + ClassDB::bind_method(D_METHOD("set_draw_fold_gutter", "enable"), &CodeEdit::set_draw_fold_gutter); + ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &CodeEdit::is_drawing_fold_gutter); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_executing_lines"), "set_draw_executing_lines_gutter", "is_drawing_executing_lines_gutter"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_line_numbers"), "set_draw_line_numbers", "is_draw_line_numbers_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_pad_line_numbers"), "set_line_numbers_zero_padded", "is_line_numbers_zero_padded"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter"); + + ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line"))); +} + +void CodeEdit::_gutter_clicked(int p_line, int p_gutter) { + if (p_gutter == main_gutter) { + if (draw_breakpoints) { + set_line_as_breakpoint(p_line, !is_line_breakpointed(p_line)); + } + return; + } + + if (p_gutter == line_number_gutter) { + cursor_set_line(p_line); + return; + } + + if (p_gutter == fold_gutter) { + if (is_folded(p_line)) { + unfold_line(p_line); + } else if (can_fold(p_line)) { + fold_line(p_line); + } + return; + } +} + +void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) { + if (p_from_line == p_to_line) { + return; + } + + int lc = get_line_count(); + line_number_digits = 1; + while (lc /= 10) { + line_number_digits++; + } + set_gutter_width(line_number_gutter, (line_number_digits + 1) * cache.font->get_char_size('0').width); + + int from_line = MIN(p_from_line, p_to_line); + int line_count = (p_to_line - p_from_line); + List<int> breakpoints; + breakpointed_lines.get_key_list(&breakpoints); + for (const List<int>::Element *E = breakpoints.front(); E; E = E->next()) { + int line = E->get(); + if (line <= from_line) { + continue; + } + breakpointed_lines.erase(line); + + emit_signal("breakpoint_toggled", line); + if (line_count > 0 || line >= p_from_line) { + emit_signal("breakpoint_toggled", line + line_count); + breakpointed_lines[line + line_count] = true; + continue; + } + } +} + +void CodeEdit::_update_gutter_indexes() { + for (int i = 0; i < get_gutter_count(); i++) { + if (get_gutter_name(i) == "main_gutter") { + main_gutter = i; + continue; + } + + if (get_gutter_name(i) == "line_numbers") { + line_number_gutter = i; + continue; + } + + if (get_gutter_name(i) == "fold_gutter") { + fold_gutter = i; + continue; + } + } +} + +CodeEdit::CodeEdit() { + /* Gutters */ + int gutter_idx = 0; + + /* Main Gutter */ + add_gutter(); + set_gutter_name(gutter_idx, "main_gutter"); + set_gutter_draw(gutter_idx, false); + set_gutter_overwritable(gutter_idx, true); + set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM); + set_gutter_custom_draw(gutter_idx, this, "_main_gutter_draw_callback"); + gutter_idx++; + + /* Line numbers */ + add_gutter(); + set_gutter_name(gutter_idx, "line_numbers"); + set_gutter_draw(gutter_idx, false); + set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM); + set_gutter_custom_draw(gutter_idx, this, "_line_number_draw_callback"); + gutter_idx++; + + /* Fold Gutter */ + add_gutter(); + set_gutter_name(gutter_idx, "fold_gutter"); + set_gutter_draw(gutter_idx, false); + set_gutter_type(gutter_idx, GUTTER_TPYE_CUSTOM); + set_gutter_custom_draw(gutter_idx, this, "_fold_gutter_draw_callback"); + gutter_idx++; + + connect("lines_edited_from", callable_mp(this, &CodeEdit::_lines_edited_from)); + connect("gutter_clicked", callable_mp(this, &CodeEdit::_gutter_clicked)); + + connect("gutter_added", callable_mp(this, &CodeEdit::_update_gutter_indexes)); + connect("gutter_removed", callable_mp(this, &CodeEdit::_update_gutter_indexes)); + _update_gutter_indexes(); +} + +CodeEdit::~CodeEdit() { +} diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h new file mode 100644 index 0000000000..c989e5ed79 --- /dev/null +++ b/scene/gui/code_edit.h @@ -0,0 +1,135 @@ +/*************************************************************************/ +/* code_edit.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 CODEEDIT_H +#define CODEEDIT_H + +#include "scene/gui/text_edit.h" + +class CodeEdit : public TextEdit { + GDCLASS(CodeEdit, TextEdit) + +private: + /* Main Gutter */ + enum MainGutterType { + MAIN_GUTTER_BREAKPOINT = 0x01, + MAIN_GUTTER_BOOKMARK = 0x02, + MAIN_GUTTER_EXECUTING = 0x04 + }; + + int main_gutter = -1; + void _update_draw_main_gutter(); + void _main_gutter_draw_callback(int p_line, int p_gutter, const Rect2 &p_region); + + // breakpoints + HashMap<int, bool> breakpointed_lines; + bool draw_breakpoints = false; + Color breakpoint_color = Color(1, 1, 1); + Ref<Texture2D> breakpoint_icon = Ref<Texture2D>(); + + // bookmarks + bool draw_bookmarks = false; + Color bookmark_color = Color(1, 1, 1); + Ref<Texture2D> bookmark_icon = Ref<Texture2D>(); + + // executing lines + bool draw_executing_lines = false; + Color executing_line_color = Color(1, 1, 1); + Ref<Texture2D> executing_line_icon = Ref<Texture2D>(); + + /* Line numbers */ + int line_number_gutter = -1; + int line_number_digits = 0; + String line_number_padding = " "; + Color line_number_color = Color(1, 1, 1); + void _line_number_draw_callback(int p_line, int p_gutter, const Rect2 &p_region); + + /* Fold Gutter */ + int fold_gutter = -1; + bool draw_fold_gutter = false; + Color folding_color = Color(1, 1, 1); + Ref<Texture2D> can_fold_icon = Ref<Texture2D>(); + Ref<Texture2D> folded_icon = Ref<Texture2D>(); + void _fold_gutter_draw_callback(int p_line, int p_gutter, Rect2 p_region); + + void _gutter_clicked(int p_line, int p_gutter); + void _lines_edited_from(int p_from_line, int p_to_line); + + void _update_gutter_indexes(); + +protected: + void _notification(int p_what); + + static void _bind_methods(); + +public: + /* Main Gutter */ + void set_draw_breakpoints_gutter(bool p_draw); + bool is_drawing_breakpoints_gutter() const; + + void set_draw_bookmarks_gutter(bool p_draw); + bool is_drawing_bookmarks_gutter() const; + + void set_draw_executing_lines_gutter(bool p_draw); + bool is_drawing_executing_lines_gutter() const; + + // breakpoints + void set_line_as_breakpoint(int p_line, bool p_breakpointed); + bool is_line_breakpointed(int p_line) const; + void clear_breakpointed_lines(); + Array get_breakpointed_lines() const; + + // bookmarks + void set_line_as_bookmarked(int p_line, bool p_bookmarked); + bool is_line_bookmarked(int p_line) const; + void clear_bookmarked_lines(); + Array get_bookmarked_lines() const; + + // executing lines + void set_line_as_executing(int p_line, bool p_executing); + bool is_line_executing(int p_line) const; + void clear_executing_lines(); + Array get_executing_lines() const; + + /* Line numbers */ + void set_draw_line_numbers(bool p_draw); + bool is_draw_line_numbers_enabled() const; + void set_line_numbers_zero_padded(bool p_zero_padded); + bool is_line_numbers_zero_padded() const; + + /* Fold gutter */ + void set_draw_fold_gutter(bool p_draw); + bool is_drawing_fold_gutter() const; + + CodeEdit(); + ~CodeEdit(); +}; + +#endif // CODEEDIT_H diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index fafbb298b7..cbe0367c7b 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -873,6 +873,7 @@ void ColorPickerButton::_color_changed(const Color &p_color) { void ColorPickerButton::_modal_closed() { emit_signal("popup_closed"); + set_pressed(false); } void ColorPickerButton::pressed() { @@ -976,9 +977,8 @@ void ColorPickerButton::_update_picker() { popup->add_child(picker); add_child(popup); picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed)); - popup->connect("modal_closed", callable_mp(this, &ColorPickerButton::_modal_closed)); popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); - popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false)); + popup->connect("popup_hide", callable_mp(this, &ColorPickerButton::_modal_closed)); picker->set_pick_color(color); picker->set_edit_alpha(edit_alpha); emit_signal("picker_created"); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 11b4c9e857..467d252c81 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -262,6 +262,7 @@ void GraphEdit::remove_child_notify(Node *p_child) { if (gn) { gn->disconnect("offset_changed", callable_mp(this, &GraphEdit::_graph_node_moved)); gn->disconnect("raise_request", callable_mp(this, &GraphEdit::_graph_node_raised)); + gn->disconnect("item_rect_changed", callable_mp((CanvasItem *)connections_layer, &CanvasItem::update)); } } diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index f49acc1b96..9e3418a5c9 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -188,7 +188,7 @@ void Label::_notification(int p_what) { int spaces = 0; while (to && to->char_pos >= 0) { taken += to->pixel_width; - if (to != from && to->space_count) { + if (to->space_count) { spaces += to->space_count; } to = to->next; @@ -235,8 +235,8 @@ void Label::_notification(int p_what) { float x_ofs_shadow = x_ofs; for (int i = 0; i < from->word_len; i++) { if (visible_chars < 0 || chars_total_shadow < visible_chars) { - CharType c = xl_text[i + pos]; - CharType n = xl_text[i + pos + 1]; + char32_t c = xl_text[i + pos]; + char32_t n = xl_text[i + pos + 1]; if (uppercase) { c = String::char_uppercase(c); n = String::char_uppercase(n); @@ -255,8 +255,8 @@ void Label::_notification(int p_what) { } for (int i = 0; i < from->word_len; i++) { if (visible_chars < 0 || chars_total < visible_chars) { - CharType c = xl_text[i + pos]; - CharType n = xl_text[i + pos + 1]; + char32_t c = xl_text[i + pos]; + char32_t n = xl_text[i + pos + 1]; if (uppercase) { c = String::char_uppercase(c); n = String::char_uppercase(n); @@ -308,7 +308,7 @@ int Label::get_longest_line_width() const { real_t line_width = 0; for (int i = 0; i < xl_text.size(); i++) { - CharType current = xl_text[i]; + char32_t current = xl_text[i]; if (uppercase) { current = String::char_uppercase(current); } @@ -390,7 +390,7 @@ void Label::regenerate_word_cache() { WordCache *last = nullptr; for (int i = 0; i <= xl_text.length(); i++) { - CharType current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works + char32_t current = i < xl_text.length() ? xl_text[i] : L' '; //always a space at the end, so the algo works if (uppercase) { current = String::char_uppercase(current); @@ -420,6 +420,22 @@ void Label::regenerate_word_cache() { wc->space_count = space_count; current_word_size = 0; space_count = 0; + } else if ((i == xl_text.length() || current == '\n') && last != nullptr && space_count != 0) { + //in case there are trailing white spaces we add a placeholder word cache with just the spaces + WordCache *wc = memnew(WordCache); + if (word_cache) { + last->next = wc; + } else { + word_cache = wc; + } + last = wc; + + wc->pixel_width = 0; + wc->char_pos = 0; + wc->word_len = 0; + wc->space_count = space_count; + current_word_size = 0; + space_count = 0; } if (current == '\n') { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 14167531a5..1b8f04297d 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -42,7 +42,7 @@ #include "editor/editor_settings.h" #endif #include "scene/main/window.h" -static bool _is_text_char(CharType c) { +static bool _is_text_char(char32_t c) { return !is_symbol(c); } @@ -313,7 +313,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { DisplayServer::get_singleton()->virtual_keyboard_hide(); } - return; } break; case KEY_BACKSPACE: { @@ -582,7 +581,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (k->get_unicode() >= 32 && k->get_keycode() != KEY_DELETE) { if (editable) { selection_delete(); - CharType ucodestr[2] = { (CharType)k->get_unicode(), 0 }; + char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 }; int prev_len = text.length(); append_at_cursor(ucodestr); if (text.length() != prev_len) { @@ -807,8 +806,8 @@ void LineEdit::_notification(int p_what) { break; } - CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; - CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; + char32_t cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; + char32_t next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; int im_char_width = font->get_char_size(cchar, next).width; if ((x_ofs + im_char_width) > ofs_max) { @@ -830,8 +829,8 @@ void LineEdit::_notification(int p_what) { } } - CharType cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs]; - CharType next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1]; + char32_t cchar = (pass && !text.empty()) ? secret_character[0] : t[char_ofs]; + char32_t next = (pass && !text.empty()) ? secret_character[0] : t[char_ofs + 1]; int char_width = font->get_char_size(cchar, next).width; // End of widget, break. @@ -870,8 +869,8 @@ void LineEdit::_notification(int p_what) { break; } - CharType cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; - CharType next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; + char32_t cchar = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs]; + char32_t next = (pass && !text.empty()) ? secret_character[0] : ime_text[ofs + 1]; int im_char_width = font->get_char_size(cchar, next).width; if ((x_ofs + im_char_width) > ofs_max) { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 40bcc243d1..bc70809ad5 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -101,9 +101,11 @@ Size2 PopupMenu::_get_contents_minimum_size() const { minsize.width += check_w; } - int height_limit = get_usable_parent_rect().size.height; - if (minsize.height > height_limit) { - minsize.height = height_limit; + if (is_inside_tree()) { + int height_limit = get_usable_parent_rect().size.height; + if (minsize.height > height_limit) { + minsize.height = height_limit; + } } return minsize; @@ -282,14 +284,15 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { } // Make an area which does not include v scrollbar, so that items are not activated when dragging scrollbar. - Rect2 item_clickable_area = control->get_global_rect(); - float scroll_width = scroll_container->get_v_scrollbar()->is_visible_in_tree() ? scroll_container->get_v_scrollbar()->get_size().width : 0; - item_clickable_area.set_size(Size2(item_clickable_area.size.width - scroll_width, item_clickable_area.size.height)); + Rect2 item_clickable_area = scroll_container->get_rect(); + if (scroll_container->get_v_scrollbar()->is_visible_in_tree()) { + item_clickable_area.size.width -= scroll_container->get_v_scrollbar()->get_size().width; + } Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { - if (!item_clickable_area.has_point(b->get_global_position())) { + if (!item_clickable_area.has_point(b->get_position())) { return; } @@ -331,7 +334,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseMotion> m = p_event; if (m.is_valid()) { - if (!item_clickable_area.has_point(m->get_global_position())) { + if (!item_clickable_area.has_point(m->get_position())) { return; } @@ -714,7 +717,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int } #define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \ - ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid ShortCut."); \ + ERR_FAIL_COND_MSG(p_shortcut.is_null(), "Cannot add item with invalid Shortcut."); \ _ref_shortcut(p_shortcut); \ item.text = p_shortcut->get_name(); \ item.xl_text = tr(item.text); \ @@ -722,7 +725,7 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int item.shortcut = p_shortcut; \ item.shortcut_is_global = p_global; -void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); items.push_back(item); @@ -730,7 +733,7 @@ void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_g child_controls_changed(); } -void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.icon = p_icon; @@ -739,7 +742,7 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortC child_controls_changed(); } -void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX; @@ -748,7 +751,7 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bo child_controls_changed(); } -void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.icon = p_icon; @@ -758,7 +761,7 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref< child_controls_changed(); } -void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON; @@ -767,7 +770,7 @@ void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ child_controls_changed(); } -void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) { +void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { Item item; ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global); item.icon = p_icon; @@ -928,8 +931,8 @@ String PopupMenu::get_item_tooltip(int p_idx) const { return items[p_idx].tooltip; } -Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const { - ERR_FAIL_INDEX_V(p_idx, items.size(), Ref<ShortCut>()); +Ref<Shortcut> PopupMenu::get_item_shortcut(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, items.size(), Ref<Shortcut>()); return items[p_idx].shortcut; } @@ -967,7 +970,7 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) { control->update(); } -void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global) { +void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global) { ERR_FAIL_INDEX(p_idx, items.size()); if (items[p_idx].shortcut.is_valid()) { _unref_shortcut(items[p_idx].shortcut); @@ -1206,7 +1209,7 @@ Array PopupMenu::_get_items() const { return items; } -void PopupMenu::_ref_shortcut(Ref<ShortCut> p_sc) { +void PopupMenu::_ref_shortcut(Ref<Shortcut> p_sc) { if (!shortcut_refcount.has(p_sc)) { shortcut_refcount[p_sc] = 1; p_sc->connect("changed", callable_mp((CanvasItem *)this, &CanvasItem::update)); @@ -1215,7 +1218,7 @@ void PopupMenu::_ref_shortcut(Ref<ShortCut> p_sc) { } } -void PopupMenu::_unref_shortcut(Ref<ShortCut> p_sc) { +void PopupMenu::_unref_shortcut(Ref<Shortcut> p_sc) { ERR_FAIL_COND(!shortcut_refcount.has(p_sc)); shortcut_refcount[p_sc]--; if (shortcut_refcount[p_sc] == 0) { diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 45a3336747..9535fd07d7 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -61,7 +61,7 @@ class PopupMenu : public Popup { int _ofs_cache; int _height_cache; int h_ofs; - Ref<ShortCut> shortcut; + Ref<Shortcut> shortcut; bool shortcut_is_global; bool shortcut_is_disabled; @@ -114,10 +114,10 @@ class PopupMenu : public Popup { Array _get_items() const; void _set_items(const Array &p_items); - Map<Ref<ShortCut>, int> shortcut_refcount; + Map<Ref<Shortcut>, int> shortcut_refcount; - void _ref_shortcut(Ref<ShortCut> p_sc); - void _unref_shortcut(Ref<ShortCut> p_sc); + void _ref_shortcut(Ref<Shortcut> p_sc); + void _unref_shortcut(Ref<Shortcut> p_sc); bool allow_search; uint64_t search_time_msec; @@ -145,12 +145,12 @@ public: void add_multistate_item(const String &p_label, int p_max_states, int p_default_state = 0, int p_id = -1, uint32_t p_accel = 0); - void add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false); - void add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false); - void add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false); - void add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false); - void add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false); - void add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id = -1, bool p_global = false); + void add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); + void add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); + void add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); + void add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); + void add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); + void add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); void add_submenu_item(const String &p_label, const String &p_submenu, int p_id = -1); @@ -166,7 +166,7 @@ public: void set_item_as_checkable(int p_idx, bool p_checkable); void set_item_as_radio_checkable(int p_idx, bool p_radio_checkable); void set_item_tooltip(int p_idx, const String &p_tooltip); - void set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global = false); + void set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global = false); void set_item_h_offset(int p_idx, int p_offset); void set_item_multistate(int p_idx, int p_state); void toggle_item_multistate(int p_idx); @@ -189,7 +189,7 @@ public: bool is_item_radio_checkable(int p_idx) const; bool is_item_shortcut_disabled(int p_idx) const; String get_item_tooltip(int p_idx) const; - Ref<ShortCut> get_item_shortcut(int p_idx) const; + Ref<Shortcut> get_item_shortcut(int p_idx) const; int get_item_state(int p_idx) const; int get_current_index() const; diff --git a/scene/gui/rich_text_effect.h b/scene/gui/rich_text_effect.h index 77c82aa780..a5401f7eaa 100644 --- a/scene/gui/rich_text_effect.h +++ b/scene/gui/rich_text_effect.h @@ -59,7 +59,7 @@ public: bool visibility; Point2 offset; Color color; - CharType character; + char32_t character; float elapsed_time; Dictionary environment; @@ -79,7 +79,7 @@ public: Color get_color() { return color; } void set_color(Color p_color) { color = p_color; } int get_character() { return (int)character; } - void set_character(int p_char) { character = (CharType)p_char; } + void set_character(int p_char) { character = (char32_t)p_char; } Dictionary get_environment() { return environment; } void set_environment(Dictionary p_environment) { environment = p_environment; } }; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 29337e20f3..fb4931ea91 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -256,7 +256,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & lh = line < l.height_caches.size() ? l.height_caches[line] : 1; \ line_ascent = line < l.ascent_caches.size() ? l.ascent_caches[line] : 1; \ line_descent = line < l.descent_caches.size() ? l.descent_caches[line] : 1; \ - if ((p_mode == PROCESS_DRAW) && (align != ALIGN_FILL)) { \ + if (align != ALIGN_FILL) { \ if (line < l.offset_caches.size()) { \ wofs = l.offset_caches[line]; \ } \ @@ -354,8 +354,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & font = p_base_font; } - const CharType *c = text->text.c_str(); - const CharType *cf = c; + const char32_t *c = text->text.get_data(); + const char32_t *cf = c; int ascent = font->get_ascent(); int descent = font->get_descent(); @@ -461,7 +461,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & bool selected = false; Color fx_color = Color(color); Point2 fx_offset; - CharType fx_char = c[i]; + char32_t fx_char = c[i]; if (selection.active) { int cofs = (&c[i]) - cf; diff --git a/scene/gui/shortcut.cpp b/scene/gui/shortcut.cpp index 9f5b9c40c2..f8c7bc44a7 100644 --- a/scene/gui/shortcut.cpp +++ b/scene/gui/shortcut.cpp @@ -32,20 +32,20 @@ #include "core/os/keyboard.h" -void ShortCut::set_shortcut(const Ref<InputEvent> &p_shortcut) { +void Shortcut::set_shortcut(const Ref<InputEvent> &p_shortcut) { shortcut = p_shortcut; emit_changed(); } -Ref<InputEvent> ShortCut::get_shortcut() const { +Ref<InputEvent> Shortcut::get_shortcut() const { return shortcut; } -bool ShortCut::is_shortcut(const Ref<InputEvent> &p_event) const { +bool Shortcut::is_shortcut(const Ref<InputEvent> &p_event) const { return shortcut.is_valid() && shortcut->shortcut_match(p_event); } -String ShortCut::get_as_text() const { +String Shortcut::get_as_text() const { if (shortcut.is_valid()) { return shortcut->as_text(); } else { @@ -53,21 +53,21 @@ String ShortCut::get_as_text() const { } } -bool ShortCut::is_valid() const { +bool Shortcut::is_valid() const { return shortcut.is_valid(); } -void ShortCut::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_shortcut", "event"), &ShortCut::set_shortcut); - ClassDB::bind_method(D_METHOD("get_shortcut"), &ShortCut::get_shortcut); +void Shortcut::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_shortcut", "event"), &Shortcut::set_shortcut); + ClassDB::bind_method(D_METHOD("get_shortcut"), &Shortcut::get_shortcut); - ClassDB::bind_method(D_METHOD("is_valid"), &ShortCut::is_valid); + ClassDB::bind_method(D_METHOD("is_valid"), &Shortcut::is_valid); - ClassDB::bind_method(D_METHOD("is_shortcut", "event"), &ShortCut::is_shortcut); - ClassDB::bind_method(D_METHOD("get_as_text"), &ShortCut::get_as_text); + ClassDB::bind_method(D_METHOD("is_shortcut", "event"), &Shortcut::is_shortcut); + ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_shortcut", "get_shortcut"); } -ShortCut::ShortCut() { +Shortcut::Shortcut() { } diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h index 063d4e43dc..0d7809e5cf 100644 --- a/scene/gui/shortcut.h +++ b/scene/gui/shortcut.h @@ -34,8 +34,8 @@ #include "core/input/input_event.h" #include "core/resource.h" -class ShortCut : public Resource { - GDCLASS(ShortCut, Resource); +class Shortcut : public Resource { + GDCLASS(Shortcut, Resource); Ref<InputEvent> shortcut; @@ -50,7 +50,7 @@ public: String get_as_text() const; - ShortCut(); + Shortcut(); }; #endif // SHORTCUT_H diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp index 8f71aa7cab..d47f771d1d 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tabs.cpp @@ -388,6 +388,7 @@ void Tabs::set_current_tab(int p_current) { } ERR_FAIL_INDEX(p_current, get_tab_count()); + previous = current; current = p_current; _change_notify("current_tab"); @@ -401,6 +402,10 @@ int Tabs::get_current_tab() const { return current; } +int Tabs::get_previous_tab() const { + return previous; +} + int Tabs::get_hovered_tab() const { return hover; } @@ -588,6 +593,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) { void Tabs::clear_tabs() { tabs.clear(); current = 0; + previous = 0; call_deferred("_update_hover"); update(); } @@ -605,6 +611,7 @@ void Tabs::remove_tab(int p_idx) { if (current < 0) { current = 0; + previous = 0; } if (current >= tabs.size()) { current = tabs.size() - 1; @@ -917,6 +924,7 @@ void Tabs::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tab_count"), &Tabs::get_tab_count); ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &Tabs::set_current_tab); ClassDB::bind_method(D_METHOD("get_current_tab"), &Tabs::get_current_tab); + ClassDB::bind_method(D_METHOD("get_previous_tab"), &Tabs::get_previous_tab); ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &Tabs::set_tab_title); ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &Tabs::get_tab_title); ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &Tabs::set_tab_icon); @@ -970,6 +978,7 @@ void Tabs::_bind_methods() { Tabs::Tabs() { current = 0; + previous = 0; tab_align = ALIGN_CENTER; rb_hover = -1; rb_pressing = false; diff --git a/scene/gui/tabs.h b/scene/gui/tabs.h index 8d7f1aa37d..b94c4a37a1 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tabs.h @@ -77,6 +77,7 @@ private: bool missing_right; Vector<Tab> tabs; int current; + int previous; int _get_top_margin() const; TabAlign tab_align; int rb_hover; @@ -138,6 +139,7 @@ public: int get_tab_count() const; void set_current_tab(int p_current); int get_current_tab() const; + int get_previous_tab() const; int get_hovered_tab() const; int get_tab_offset() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index d6d8e74748..957e1c11c7 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -44,23 +44,23 @@ #define TAB_PIXELS -inline bool _is_symbol(CharType c) { +inline bool _is_symbol(char32_t c) { return is_symbol(c); } -static bool _is_text_char(CharType c) { +static bool _is_text_char(char32_t c) { return !is_symbol(c); } -static bool _is_whitespace(CharType c) { +static bool _is_whitespace(char32_t c) { return c == '\t' || c == ' '; } -static bool _is_char(CharType c) { +static bool _is_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } -static bool _is_pair_right_symbol(CharType c) { +static bool _is_pair_right_symbol(char32_t c) { return c == '"' || c == '\'' || c == ')' || @@ -68,7 +68,7 @@ static bool _is_pair_right_symbol(CharType c) { c == '}'; } -static bool _is_pair_left_symbol(CharType c) { +static bool _is_pair_left_symbol(char32_t c) { return c == '"' || c == '\'' || c == '(' || @@ -76,11 +76,11 @@ static bool _is_pair_left_symbol(CharType c) { c == '{'; } -static bool _is_pair_symbol(CharType c) { +static bool _is_pair_symbol(char32_t c) { return _is_pair_left_symbol(c) || _is_pair_right_symbol(c); } -static CharType _get_right_pair_symbol(CharType c) { +static char32_t _get_right_pair_symbol(char32_t c) { if (c == '"') { return '"'; } @@ -107,6 +107,8 @@ static int _find_first_non_whitespace_column_of_line(const String &line) { return left; } +/////////////////////////////////////////////////////////////////////////////// + void TextEdit::Text::set_font(const Ref<Font> &p_font) { font = p_font; } @@ -119,7 +121,7 @@ void TextEdit::Text::_update_line_cache(int p_line) const { int w = 0; int len = text[p_line].data.length(); - const CharType *str = text[p_line].data.c_str(); + const char32_t *str = text[p_line].data.get_data(); // Update width. @@ -165,12 +167,6 @@ void TextEdit::Text::clear_wrap_cache() { } } -void TextEdit::Text::clear_info_icons() { - for (int i = 0; i < text.size(); i++) { - text.write[i].has_info = false; - } -} - void TextEdit::Text::clear() { text.clear(); insert(0, ""); @@ -198,12 +194,9 @@ void TextEdit::Text::set(int p_line, const String &p_text) { void TextEdit::Text::insert(int p_at, const String &p_text) { Line line; + line.gutters.resize(gutter_count); line.marked = false; - line.safe = false; - line.breakpoint = false; - line.bookmark = false; line.hidden = false; - line.has_info = false; line.width_cache = -1; line.wrap_amount_cache = -1; line.data = p_text; @@ -214,7 +207,7 @@ void TextEdit::Text::remove(int p_at) { text.remove(p_at); } -int TextEdit::Text::get_char_width(CharType c, CharType next_c, int px) const { +int TextEdit::Text::get_char_width(char32_t c, char32_t next_c, int px) const { int tab_w = font->get_char_size(' ').width * indent_size; int w = 0; @@ -231,6 +224,32 @@ int TextEdit::Text::get_char_width(CharType c, CharType next_c, int px) const { return w; } +void TextEdit::Text::add_gutter(int p_at) { + for (int i = 0; i < text.size(); i++) { + if (p_at < 0 || p_at > gutter_count) { + text.write[i].gutters.push_back(Gutter()); + } else { + text.write[i].gutters.insert(p_at, Gutter()); + } + } + gutter_count++; +} + +void TextEdit::Text::remove_gutter(int p_gutter) { + for (int i = 0; i < text.size(); i++) { + text.write[i].gutters.remove(p_gutter); + } + gutter_count--; +} + +void TextEdit::Text::move_gutters(int p_from_line, int p_to_line) { + text.write[p_to_line].gutters = text[p_from_line].gutters; + text.write[p_from_line].gutters.clear(); + text.write[p_from_line].gutters.resize(gutter_count); +} + +//////////////////////////////////////////////////////////////////////////////// + void TextEdit::_update_scrollbars() { Size2 size = get_size(); Size2 hmin = h_scroll->get_combined_minimum_size(); @@ -249,23 +268,7 @@ void TextEdit::_update_scrollbars() { } int visible_width = size.width - cache.style_normal->get_minimum_size().width; - int total_width = text.get_max_width(true) + vmin.x; - - if (line_numbers) { - total_width += cache.line_number_w; - } - - if (draw_breakpoint_gutter || draw_bookmark_gutter) { - total_width += cache.breakpoint_gutter_width; - } - - if (draw_info_gutter) { - total_width += cache.info_gutter_width; - } - - if (draw_fold_gutter) { - total_width += cache.fold_gutter_width; - } + int total_width = text.get_max_width(true) + vmin.x + gutters_width + gutter_padding; if (draw_minimap) { total_width += cache.minimap_width; @@ -557,54 +560,16 @@ void TextEdit::_notification(int p_what) { draw_caret = false; } - if (draw_breakpoint_gutter || draw_bookmark_gutter) { - breakpoint_gutter_width = (get_row_height() * 55) / 100; - cache.breakpoint_gutter_width = breakpoint_gutter_width; - } else { - cache.breakpoint_gutter_width = 0; - } - - if (draw_info_gutter) { - info_gutter_width = (get_row_height()); - cache.info_gutter_width = info_gutter_width; - } else { - cache.info_gutter_width = 0; - } - - if (draw_fold_gutter) { - fold_gutter_width = (get_row_height() * 55) / 100; - cache.fold_gutter_width = fold_gutter_width; - } else { - cache.fold_gutter_width = 0; - } - cache.minimap_width = 0; if (draw_minimap) { cache.minimap_width = minimap_width; } - int line_number_char_count = 0; - - { - int lc = text.size(); - cache.line_number_w = 0; - while (lc) { - cache.line_number_w += 1; - lc /= 10; - }; - - if (line_numbers) { - line_number_char_count = cache.line_number_w; - cache.line_number_w = (cache.line_number_w + 1) * cache.font->get_char_size('0').width; - } else { - cache.line_number_w = 0; - } - } _update_scrollbars(); RID ci = get_canvas_item(); RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); - int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width; + int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding; int xmargin_end = size.width - cache.style_normal->get_margin(MARGIN_RIGHT) - cache.minimap_width; // Let's do it easy for now. @@ -654,8 +619,8 @@ void TextEdit::_notification(int p_what) { if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) { if (cursor.column < text[cursor.line].length()) { // Check for open. - CharType c = text[cursor.line][cursor.column]; - CharType closec = 0; + char32_t c = text[cursor.line][cursor.column]; + char32_t closec = 0; if (c == '[') { closec = ']'; @@ -671,10 +636,10 @@ void TextEdit::_notification(int p_what) { for (int i = cursor.line; i < text.size(); i++) { int from = i == cursor.line ? cursor.column + 1 : 0; for (int j = from; j < text[i].length(); j++) { - CharType cc = text[i][j]; + char32_t cc = text[i][j]; // Ignore any brackets inside a string. if (cc == '"' || cc == '\'') { - CharType quotation = cc; + char32_t quotation = cc; do { j++; if (!(j < text[i].length())) { @@ -720,8 +685,8 @@ void TextEdit::_notification(int p_what) { } if (cursor.column > 0) { - CharType c = text[cursor.line][cursor.column - 1]; - CharType closec = 0; + char32_t c = text[cursor.line][cursor.column - 1]; + char32_t closec = 0; if (c == ']') { closec = '['; @@ -737,10 +702,10 @@ void TextEdit::_notification(int p_what) { for (int i = cursor.line; i >= 0; i--) { int from = i == cursor.line ? cursor.column - 2 : text[i].length() - 1; for (int j = from; j >= 0; j--) { - CharType cc = text[i][j]; + char32_t cc = text[i][j]; // Ignore any brackets inside a string. if (cc == '"' || cc == '\'') { - CharType quotation = cc; + char32_t quotation = cc; do { j--; if (!(j >= 0)) { @@ -795,8 +760,6 @@ void TextEdit::_notification(int p_what) { // Check if highlighted words contains only whitespaces (tabs or spaces). bool only_whitespaces_highlighted = highlighted_text.strip_edges() == String(); - String line_num_padding = line_numbers_zero_padded ? "0" : " "; - int cursor_wrap_index = get_cursor_wrap_index(); FontDrawer drawer(cache.font, Color(1, 1, 1)); @@ -1053,103 +1016,52 @@ void TextEdit::_notification(int p_what) { if (line_wrap_index == 0) { // Only do these if we are on the first wrapped part of a line. - if (text.is_breakpoint(line) && !draw_breakpoint_gutter) { -#ifdef TOOLS_ENABLED - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); -#else - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); -#endif - } + int gutter_offset = cache.style_normal->get_margin(MARGIN_LEFT); + for (int g = 0; g < gutters.size(); g++) { + const GutterInfo gutter = gutters[g]; - // Draw bookmark marker. - if (text.is_bookmark(line)) { - if (draw_bookmark_gutter) { - int vertical_gap = (get_row_height() * 40) / 100; - int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100; - int marker_radius = get_row_height() - (vertical_gap * 2); - RenderingServer::get_singleton()->canvas_item_add_circle(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2 + marker_radius / 2, ofs_y + vertical_gap + marker_radius / 2), marker_radius, Color(cache.bookmark_color.r, cache.bookmark_color.g, cache.bookmark_color.b)); + if (!gutter.draw || gutter.width <= 0) { + continue; } - } - // Draw breakpoint marker. - if (text.is_breakpoint(line)) { - if (draw_breakpoint_gutter) { - int vertical_gap = (get_row_height() * 40) / 100; - int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100; - int marker_height = get_row_height() - (vertical_gap * 2); - int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2); - // No transparency on marker. - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2, ofs_y + vertical_gap, marker_width, marker_height), Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); - } - } - - // Draw info icons. - if (draw_info_gutter && text.has_info_icon(line)) { - int vertical_gap = (get_row_height() * 40) / 100; - int horizontal_gap = (cache.info_gutter_width * 30) / 100; - int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width; - - Ref<Texture2D> info_icon = text.get_info_icon(line); - // Ensure the icon fits the gutter size. - Size2i icon_size = info_icon->get_size(); - if (icon_size.width > cache.info_gutter_width - horizontal_gap) { - icon_size.width = cache.info_gutter_width - horizontal_gap; - } - if (icon_size.height > get_row_height() - horizontal_gap) { - icon_size.height = get_row_height() - horizontal_gap; - } + switch (gutter.type) { + case GUTTER_TYPE_STRING: { + const String &text = get_line_gutter_text(line, g); + if (text == "") { + break; + } - Size2i icon_pos; - int xofs = horizontal_gap - (info_icon->get_width() / 4); - int yofs = vertical_gap - (info_icon->get_height() / 4); - icon_pos.x = gutter_left + xofs + ofs_x; - icon_pos.y = ofs_y + yofs; + int yofs = ofs_y + (get_row_height() - cache.font->get_height()) / 2; + cache.font->draw(ci, Point2(gutter_offset + ofs_x, yofs + cache.font->get_ascent()), text, get_line_gutter_item_color(line, g)); + } break; + case GUTTER_TPYE_ICON: { + const Ref<Texture2D> icon = get_line_gutter_icon(line, g); + if (icon.is_null()) { + break; + } - draw_texture_rect(info_icon, Rect2(icon_pos, icon_size)); - } + Rect2i gutter_rect = Rect2i(Point2i(gutter_offset, ofs_y), Size2i(gutter.width, get_row_height())); - // Draw execution marker. - if (executing_line == line) { - if (draw_breakpoint_gutter) { - int icon_extra_size = 4; - int vertical_gap = (get_row_height() * 40) / 100; - int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100; - int marker_height = get_row_height() - (vertical_gap * 2) + icon_extra_size; - int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2) + icon_extra_size; - cache.executing_icon->draw_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2 - icon_extra_size / 2, ofs_y + vertical_gap - icon_extra_size / 2, marker_width, marker_height), false, Color(cache.executing_line_color.r, cache.executing_line_color.g, cache.executing_line_color.b)); - } else { -#ifdef TOOLS_ENABLED - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.executing_line_color); -#else - RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.executing_line_color); -#endif - } - } + int horizontal_padding = gutter_rect.size.x / 6; + int vertical_padding = gutter_rect.size.y / 6; - // Draw fold markers. - if (draw_fold_gutter) { - int horizontal_gap = (cache.fold_gutter_width * 30) / 100; - int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.line_number_w + cache.info_gutter_width; - if (is_folded(line)) { - int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2; - int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2; - cache.folded_icon->draw(ci, Point2(gutter_left + xofs + ofs_x, ofs_y + yofs), cache.code_folding_color); - } else if (can_fold(line)) { - int xofs = -cache.can_fold_icon->get_width() / 2 - horizontal_gap + 3; - int yofs = (get_row_height() - cache.can_fold_icon->get_height()) / 2; - cache.can_fold_icon->draw(ci, Point2(gutter_left + xofs + ofs_x, ofs_y + yofs), cache.code_folding_color); - } - } + gutter_rect.position += Point2(horizontal_padding, vertical_padding); + gutter_rect.size -= Point2(horizontal_padding, vertical_padding) * 2; - // Draw line numbers. - if (cache.line_number_w) { - int yofs = ofs_y + (get_row_height() - cache.font->get_height()) / 2; - String fc = String::num(line + 1); - while (fc.length() < line_number_char_count) { - fc = line_num_padding + fc; + icon->draw_rect(ci, gutter_rect, false, get_line_gutter_item_color(line, g)); + } break; + case GUTTER_TPYE_CUSTOM: { + if (gutter.custom_draw_obj.is_valid()) { + Object *cdo = ObjectDB::get_instance(gutter.custom_draw_obj); + if (cdo) { + Rect2i gutter_rect = Rect2i(Point2i(gutter_offset, ofs_y), Size2i(gutter.width, get_row_height())); + cdo->call(gutter.custom_draw_callback, line, g, Rect2(gutter_rect)); + } + } + } break; } - cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.info_gutter_width + ofs_x, yofs + cache.font->get_ascent()), fc, text.is_safe(line) ? cache.safe_line_number_color : cache.line_number_color); + gutter_offset += gutter.width; } } @@ -1303,8 +1215,8 @@ void TextEdit::_notification(int p_what) { break; } - CharType cchar = ime_text[ofs]; - CharType next = ime_text[ofs + 1]; + char32_t cchar = ime_text[ofs]; + char32_t next = ime_text[ofs + 1]; int im_char_width = cache.font->get_char_size(cchar, next).width; if ((char_ofs + char_margin + im_char_width) >= xmargin_end) { @@ -1399,8 +1311,8 @@ void TextEdit::_notification(int p_what) { break; } - CharType cchar = ime_text[ofs]; - CharType next = ime_text[ofs + 1]; + char32_t cchar = ime_text[ofs]; + char32_t next = ime_text[ofs + 1]; int im_char_width = cache.font->get_char_size(cchar, next).width; if ((char_ofs + char_margin + im_char_width) >= xmargin_end) { @@ -1661,12 +1573,12 @@ void TextEdit::_notification(int p_what) { } } -void TextEdit::_consume_pair_symbol(CharType ch) { +void TextEdit::_consume_pair_symbol(char32_t ch) { int cursor_position_to_move = cursor_get_column() + 1; - CharType ch_single[2] = { ch, 0 }; - CharType ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 }; - CharType ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 }; + char32_t ch_single[2] = { ch, 0 }; + char32_t ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 }; + char32_t ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 }; if (is_selection_active()) { int new_column, new_line; @@ -1771,8 +1683,8 @@ void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column bool remove_right_symbol = false; if (cursor.column < text[cursor.line].length() && cursor.column > 0) { - CharType left_char = text[cursor.line][cursor.column - 1]; - CharType right_char = text[cursor.line][cursor.column]; + char32_t left_char = text[cursor.line][cursor.column - 1]; + char32_t right_char = text[cursor.line][cursor.column]; if (right_char == _get_right_pair_symbol(left_char)) { remove_right_symbol = true; @@ -1797,18 +1709,34 @@ void TextEdit::backspace_at_cursor() { int prev_line = cursor.column ? cursor.line : cursor.line - 1; int prev_column = cursor.column ? (cursor.column - 1) : (text[cursor.line - 1].length()); - if (is_line_hidden(cursor.line)) { - set_line_as_hidden(prev_line, true); - } - if (is_line_set_as_breakpoint(cursor.line)) { - if (!text.is_breakpoint(prev_line)) { - emit_signal("breakpoint_toggled", prev_line); + if (cursor.line != prev_line) { + for (int i = 0; i < gutters.size(); i++) { + if (!gutters[i].overwritable) { + continue; + } + + if (text.get_line_gutter_text(cursor.line, i) != "") { + text.set_line_gutter_text(prev_line, i, text.get_line_gutter_text(cursor.line, i)); + text.set_line_gutter_item_color(prev_line, i, text.get_line_gutter_item_color(cursor.line, i)); + } + + if (text.get_line_gutter_icon(cursor.line, i).is_valid()) { + text.set_line_gutter_icon(prev_line, i, text.get_line_gutter_icon(cursor.line, i)); + text.set_line_gutter_item_color(prev_line, i, text.get_line_gutter_item_color(cursor.line, i)); + } + + if (text.get_line_gutter_metadata(cursor.line, i) != "") { + text.set_line_gutter_metadata(prev_line, i, text.get_line_gutter_metadata(cursor.line, i)); + } + + if (text.is_line_gutter_clickable(cursor.line, i)) { + text.set_line_gutter_clickable(prev_line, i, true); + } } - set_line_as_breakpoint(prev_line, true); } - if (text.has_info_icon(cursor.line)) { - set_line_info_icon(prev_line, text.get_info_icon(cursor.line), text.get_info(cursor.line)); + if (is_line_hidden(cursor.line)) { + set_line_as_hidden(prev_line, true); } if (auto_brace_completion_enabled && @@ -1998,7 +1926,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co row = text.size() - 1; col = text[row].size(); } else { - int colx = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width); + int colx = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding); colx += cursor.x_ofs; col = get_char_pos_for_line(colx, row, wrap_index); if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) { @@ -2043,7 +1971,7 @@ Vector2i TextEdit::_get_cursor_pixel_pos() { // Calculate final pixel position int y = (row - get_v_scroll_offset() + 1 /*Bottom of line*/) * get_row_height(); - int x = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs; + int x = cache.style_normal->get_margin(MARGIN_LEFT) + gutters_width + gutter_padding - cursor.x_ofs; int ix = 0; while (ix < rows2[0].size() && ix < cursor.column) { if (cache.font != nullptr) { @@ -2178,45 +2106,24 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { int row, col; _get_mouse_pos(Point2i(mb->get_position().x, mb->get_position().y), row, col); - // Toggle breakpoint on gutter click. - if (draw_breakpoint_gutter) { - int gutter = cache.style_normal->get_margin(MARGIN_LEFT); - if (mb->get_position().x > gutter - 6 && mb->get_position().x <= gutter + cache.breakpoint_gutter_width - 3) { - set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row)); - emit_signal("breakpoint_toggled", row); - return; + int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); + for (int i = 0; i < gutters.size(); i++) { + if (!gutters[i].draw || gutters[i].width <= 0) { + continue; } - } - // Emit info clicked. - if (draw_info_gutter && text.has_info_icon(row)) { - int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); - int gutter_left = left_margin + cache.breakpoint_gutter_width; - if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.info_gutter_width - 3) { - emit_signal("info_clicked", row, text.get_info(row)); + if (mb->get_position().x > left_margin && mb->get_position().x <= (left_margin + gutters[i].width) - 3) { + emit_signal("gutter_clicked", row, i); return; } - } - // Toggle fold on gutter click if can. - if (draw_fold_gutter) { - int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); - int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w + cache.info_gutter_width; - if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.fold_gutter_width - 3) { - if (is_folded(row)) { - unfold_line(row); - } else if (can_fold(row)) { - fold_line(row); - } - return; - } + left_margin += gutters[i].width; } // Unfold on folded icon click. if (is_folded(row)) { - int line_width = text.get_line_width(row); - line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.info_gutter_width + cache.fold_gutter_width - cursor.x_ofs; - if (mb->get_position().x > line_width - 3 && mb->get_position().x <= line_width + cache.folded_eol_icon->get_width() + 3) { + left_margin += gutter_padding + text.get_line_width(row) - cursor.x_ofs; + if (mb->get_position().x > left_margin && mb->get_position().x <= left_margin + cache.folded_eol_icon->get_width() + 3) { unfold_line(row); return; } @@ -2540,7 +2447,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (k->get_unicode() > 32) { _reset_caret_blink_timer(); - const CharType chr[2] = { (CharType)k->get_unicode(), 0 }; + const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 }; if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { _consume_pair_symbol(chr[0]); } else { @@ -2784,7 +2691,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } // No need to move the brace below if we are not taking the text with us. - char closing_char = _get_right_pair_symbol(indent_char); + char32_t closing_char = _get_right_pair_symbol(indent_char); if ((closing_char != 0) && (closing_char == text[cursor.line][cursor.column]) && !k->get_command()) { brace_indent = true; ins += "\n" + ins.substr(1, ins.length() - 2); @@ -3312,7 +3219,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // Compute whitespace symbols seq length. int current_line_whitespace_len = 0; while (current_line_whitespace_len < text[cursor.line].length()) { - CharType c = text[cursor.line][current_line_whitespace_len]; + char32_t c = text[cursor.line][current_line_whitespace_len]; if (c != '\t' && c != ' ') { break; } @@ -3458,7 +3365,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { int current_line_whitespace_len = 0; while (current_line_whitespace_len < text[cursor.line].length()) { - CharType c = text[cursor.line][current_line_whitespace_len]; + char32_t c = text[cursor.line][current_line_whitespace_len]; if (c != '\t' && c != ' ') break; current_line_whitespace_len++; @@ -3624,7 +3531,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { } } - const CharType chr[2] = { (CharType)k->get_unicode(), 0 }; + const char32_t chr[2] = { (char32_t)k->get_unicode(), 0 }; if (completion_hint != "" && k->get_unicode() == ')') { completion_hint = ""; @@ -3775,30 +3682,15 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i Vector<String> substrings = p_text.replace("\r", "").split("\n"); - /* STEP 2: Fire breakpoint_toggled signals. */ - // Is this just a new empty line? bool shift_first_line = p_char == 0 && p_text.replace("\r", "") == "\n"; - int i = p_line + !shift_first_line; - int lines = substrings.size() - 1; - for (; i < text.size(); i++) { - if (text.is_breakpoint(i)) { - if ((i - lines < p_line || !text.is_breakpoint(i - lines)) || (i - lines == p_line && !shift_first_line)) { - emit_signal("breakpoint_toggled", i); - } - if (i + lines >= text.size() || !text.is_breakpoint(i + lines)) { - emit_signal("breakpoint_toggled", i + lines); - } - } - } - - /* STEP 3: Add spaces if the char is greater than the end of the line. */ + /* STEP 2: Add spaces if the char is greater than the end of the line. */ while (p_char > text[p_line].length()) { text.set(p_line, text[p_line] + String::chr(' ')); } - /* STEP 4: Separate dest string in pre and post text. */ + /* STEP 3: Separate dest string in pre and post text. */ String preinsert_text = text[p_line].substr(0, p_char); String postinsert_text = text[p_line].substr(p_char, text[p_line].size()); @@ -3818,15 +3710,10 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i } if (shift_first_line) { - text.set_breakpoint(p_line + 1, text.is_breakpoint(p_line)); + text.move_gutters(p_line, p_line + 1); text.set_hidden(p_line + 1, text.is_hidden(p_line)); - if (text.has_info_icon(p_line)) { - text.set_info_icon(p_line + 1, text.get_info_icon(p_line), text.get_info(p_line)); - } - text.set_breakpoint(p_line, false); text.set_hidden(p_line, false); - text.set_info_icon(p_line, nullptr, ""); } text.set_line_wrap_amount(p_line, -1); @@ -3840,7 +3727,7 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i } text_changed_dirty = true; } - emit_signal("line_edited_from", p_line); + emit_signal("lines_edited_from", p_line, r_end_line); } String TextEdit::_base_get_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column) const { @@ -3877,19 +3764,6 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li String pre_text = text[p_from_line].substr(0, p_from_column); String post_text = text[p_to_line].substr(p_to_column, text[p_to_line].length()); - int lines = p_to_line - p_from_line; - - for (int i = p_from_line + 1; i < text.size(); i++) { - if (text.is_breakpoint(i)) { - if (i + lines >= text.size() || !text.is_breakpoint(i + lines)) { - emit_signal("breakpoint_toggled", i); - } - if (i > p_to_line && (i - lines < 0 || !text.is_breakpoint(i - lines))) { - emit_signal("breakpoint_toggled", i - lines); - } - } - } - for (int i = p_from_line; i < p_to_line; i++) { text.remove(p_from_line + 1); } @@ -3903,7 +3777,7 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li } text_changed_dirty = true; } - emit_signal("line_edited_from", p_from_line); + emit_signal("lines_edited_from", p_to_line, p_from_line); } void TextEdit::_insert_text(int p_line, int p_char, const String &p_text, int *r_end_line, int *r_end_char) { @@ -4097,7 +3971,7 @@ int TextEdit::get_total_visible_rows() const { } void TextEdit::_update_wrap_at() { - wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width - wrap_right_offset; + wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.minimap_width - wrap_right_offset; update_cursor_wrap_offset(); text.clear_wrap_cache(); @@ -4132,7 +4006,7 @@ void TextEdit::adjust_viewport_to_cursor() { set_line_as_last_visible(cur_line, cur_wrap); } - int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width; + int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.minimap_width; if (v_scroll->is_visible_in_tree()) { visible_width -= v_scroll->get_combined_minimum_size().width; } @@ -4167,7 +4041,7 @@ void TextEdit::center_viewport_to_cursor() { } set_line_as_center_visible(cursor.line, get_cursor_wrap_index()); - int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - cache.minimap_width; + int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - gutters_width - gutter_padding - cache.minimap_width; if (v_scroll->is_visible_in_tree()) { visible_width -= v_scroll->get_combined_minimum_size().width; } @@ -4251,7 +4125,7 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const { } while (col < line_text.length()) { - CharType c = line_text[col]; + char32_t c = line_text[col]; int w = text.get_char_width(c, line_text[col + 1], px + word_px); int indent_ofs = (cur_wrap_index != 0 ? tab_offset_px : 0); @@ -4614,54 +4488,41 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { return CURSOR_POINTING_HAND; } - int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width; if ((completion_active && completion_rect.has_point(p_pos))) { return CURSOR_ARROW; } - if (p_pos.x < gutter) { - int row, col; - _get_mouse_pos(p_pos, row, col); - int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); - // Breakpoint icon. - if (draw_breakpoint_gutter && p_pos.x > left_margin - 6 && p_pos.x <= left_margin + cache.breakpoint_gutter_width - 3) { - return CURSOR_POINTING_HAND; - } + int row, col; + _get_mouse_pos(p_pos, row, col); - // Info icons. - int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.info_gutter_width; - if (draw_info_gutter && p_pos.x > left_margin + cache.breakpoint_gutter_width - 6 && p_pos.x <= gutter_left - 3) { - if (text.has_info_icon(row)) { - return CURSOR_POINTING_HAND; + int left_margin = cache.style_normal->get_margin(MARGIN_LEFT); + int gutter = left_margin + gutters_width; + if (p_pos.x < gutter) { + for (int i = 0; i < gutters.size(); i++) { + if (!gutters[i].draw) { + continue; } - return CURSOR_ARROW; - } - // Fold icon. - if (draw_fold_gutter && p_pos.x > gutter_left + cache.line_number_w - 6 && p_pos.x <= gutter_left + cache.line_number_w + cache.fold_gutter_width - 3) { - if (is_folded(row) || can_fold(row)) { - return CURSOR_POINTING_HAND; - } else { - return CURSOR_ARROW; + if (p_pos.x > left_margin && p_pos.x <= (left_margin + gutters[i].width) - 3) { + if (gutters[i].clickable || is_line_gutter_clickable(row, i)) { + return CURSOR_POINTING_HAND; + } } + left_margin += gutters[i].width; } + return CURSOR_ARROW; + } + int xmargin_end = get_size().width - cache.style_normal->get_margin(MARGIN_RIGHT); + if (draw_minimap && p_pos.x > xmargin_end - minimap_width && p_pos.x <= xmargin_end) { return CURSOR_ARROW; - } else { - int xmargin_end = get_size().width - cache.style_normal->get_margin(MARGIN_RIGHT); - if (draw_minimap && p_pos.x > xmargin_end - minimap_width && p_pos.x <= xmargin_end) { - return CURSOR_ARROW; - } - - int row, col; - _get_mouse_pos(p_pos, row, col); - // EOL fold icon. - if (is_folded(row)) { - int line_width = text.get_line_width(row); - line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs; - if (p_pos.x > line_width - 3 && p_pos.x <= line_width + cache.folded_eol_icon->get_width() + 3) { - return CURSOR_POINTING_HAND; - } + } + + // EOL fold icon. + if (is_folded(row)) { + gutter += gutter_padding + text.get_line_width(row) - cursor.x_ofs; + if (p_pos.x > gutter - 3 && p_pos.x <= gutter + cache.folded_eol_icon->get_width() + 3) { + return CURSOR_POINTING_HAND; } } @@ -4861,8 +4722,6 @@ void TextEdit::_update_caches() { cache.font = get_theme_font("font"); cache.caret_color = get_theme_color("caret_color"); cache.caret_background_color = get_theme_color("caret_background_color"); - cache.line_number_color = get_theme_color("line_number_color"); - cache.safe_line_number_color = get_theme_color("safe_line_number_color"); cache.font_color = get_theme_color("font_color"); cache.font_color_selected = get_theme_color("font_color_selected"); cache.font_color_readonly = get_theme_color("font_color_readonly"); @@ -4870,9 +4729,6 @@ void TextEdit::_update_caches() { cache.mark_color = get_theme_color("mark_color"); cache.current_line_color = get_theme_color("current_line_color"); cache.line_length_guideline_color = get_theme_color("line_length_guideline_color"); - cache.bookmark_color = get_theme_color("bookmark_color"); - cache.breakpoint_color = get_theme_color("breakpoint_color"); - cache.executing_line_color = get_theme_color("executing_line_color"); cache.code_folding_color = get_theme_color("code_folding_color"); cache.brace_mismatch_color = get_theme_color("brace_mismatch_color"); cache.word_highlighted_color = get_theme_color("word_highlighted_color"); @@ -4887,10 +4743,7 @@ void TextEdit::_update_caches() { cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon = get_theme_icon("tab"); cache.space_icon = get_theme_icon("space"); - cache.folded_icon = get_theme_icon("folded"); - cache.can_fold_icon = get_theme_icon("fold"); cache.folded_eol_icon = get_theme_icon("GuiEllipsis", "EditorIcons"); - cache.executing_icon = get_theme_icon("MainPlay", "EditorIcons"); text.set_font(cache.font); text.clear_width_cache(); @@ -4899,6 +4752,7 @@ void TextEdit::_update_caches() { } } +/* Syntax Highlighting. */ Ref<SyntaxHighlighter> TextEdit::get_syntax_highlighter() { return syntax_highlighter; } @@ -4911,6 +4765,187 @@ void TextEdit::set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighte update(); } +/* Gutters. */ +void TextEdit::_update_gutter_width() { + gutters_width = 0; + for (int i = 0; i < gutters.size(); i++) { + if (gutters[i].draw) { + gutters_width += gutters[i].width; + } + } + if (gutters_width > 0) { + gutter_padding = 2; + } + update(); +} + +void TextEdit::add_gutter(int p_at) { + if (p_at < 0 || p_at > gutters.size()) { + gutters.push_back(GutterInfo()); + } else { + gutters.insert(p_at, GutterInfo()); + } + + for (int i = 0; i < text.size() + 1; i++) { + text.add_gutter(p_at); + } + emit_signal("gutter_added"); + update(); +} + +void TextEdit::remove_gutter(int p_gutter) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + + gutters.remove(p_gutter); + + for (int i = 0; i < text.size() + 1; i++) { + text.remove_gutter(p_gutter); + } + emit_signal("gutter_removed"); + update(); +} + +int TextEdit::get_gutter_count() const { + return gutters.size(); +} + +void TextEdit::set_gutter_name(int p_gutter, const String &p_name) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + gutters.write[p_gutter].name = p_name; +} + +String TextEdit::get_gutter_name(int p_gutter) const { + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), ""); + return gutters[p_gutter].name; +} + +void TextEdit::set_gutter_type(int p_gutter, GutterType p_type) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + gutters.write[p_gutter].type = p_type; + update(); +} + +TextEdit::GutterType TextEdit::get_gutter_type(int p_gutter) const { + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), GUTTER_TYPE_STRING); + return gutters[p_gutter].type; +} + +void TextEdit::set_gutter_width(int p_gutter, int p_width) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + gutters.write[p_gutter].width = p_width; + _update_gutter_width(); +} + +int TextEdit::get_gutter_width(int p_gutter) const { + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), -1); + return gutters[p_gutter].width; +} + +void TextEdit::set_gutter_draw(int p_gutter, bool p_draw) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + gutters.write[p_gutter].draw = p_draw; + _update_gutter_width(); +} + +bool TextEdit::is_gutter_drawn(int p_gutter) const { + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), false); + return gutters[p_gutter].draw; +} + +void TextEdit::set_gutter_clickable(int p_gutter, bool p_clickable) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + gutters.write[p_gutter].clickable = p_clickable; + update(); +} + +bool TextEdit::is_gutter_clickable(int p_gutter) const { + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), false); + return gutters[p_gutter].clickable; +} + +void TextEdit::set_gutter_overwritable(int p_gutter, bool p_overwritable) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + gutters.write[p_gutter].overwritable = p_overwritable; +} + +bool TextEdit::is_gutter_overwritable(int p_gutter) const { + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), false); + return gutters[p_gutter].overwritable; +} + +void TextEdit::set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback) { + ERR_FAIL_INDEX(p_gutter, gutters.size()); + ERR_FAIL_NULL(p_object); + + gutters.write[p_gutter].custom_draw_obj = p_object->get_instance_id(); + gutters.write[p_gutter].custom_draw_callback = p_callback; + update(); +} + +// Line gutters. +void TextEdit::set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata) { + ERR_FAIL_INDEX(p_line, text.size()); + ERR_FAIL_INDEX(p_gutter, gutters.size()); + text.set_line_gutter_metadata(p_line, p_gutter, p_metadata); +} + +Variant TextEdit::get_line_gutter_metadata(int p_line, int p_gutter) const { + ERR_FAIL_INDEX_V(p_line, text.size(), ""); + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), ""); + return text.get_line_gutter_metadata(p_line, p_gutter); +} + +void TextEdit::set_line_gutter_text(int p_line, int p_gutter, const String &p_text) { + ERR_FAIL_INDEX(p_line, text.size()); + ERR_FAIL_INDEX(p_gutter, gutters.size()); + text.set_line_gutter_text(p_line, p_gutter, p_text); + update(); +} + +String TextEdit::get_line_gutter_text(int p_line, int p_gutter) const { + ERR_FAIL_INDEX_V(p_line, text.size(), ""); + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), ""); + return text.get_line_gutter_text(p_line, p_gutter); +} + +void TextEdit::set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon) { + ERR_FAIL_INDEX(p_line, text.size()); + ERR_FAIL_INDEX(p_gutter, gutters.size()); + text.set_line_gutter_icon(p_line, p_gutter, p_icon); + update(); +} + +Ref<Texture2D> TextEdit::get_line_gutter_icon(int p_line, int p_gutter) const { + ERR_FAIL_INDEX_V(p_line, text.size(), Ref<Texture2D>()); + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), Ref<Texture2D>()); + return text.get_line_gutter_icon(p_line, p_gutter); +} + +void TextEdit::set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color) { + ERR_FAIL_INDEX(p_line, text.size()); + ERR_FAIL_INDEX(p_gutter, gutters.size()); + text.set_line_gutter_item_color(p_line, p_gutter, p_color); + update(); +} + +Color TextEdit::get_line_gutter_item_color(int p_line, int p_gutter) { + ERR_FAIL_INDEX_V(p_line, text.size(), Color()); + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), Color()); + return text.get_line_gutter_item_color(p_line, p_gutter); +} + +void TextEdit::set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable) { + ERR_FAIL_INDEX(p_line, text.size()); + ERR_FAIL_INDEX(p_gutter, gutters.size()); + text.set_line_gutter_clickable(p_line, p_gutter, p_clickable); +} + +bool TextEdit::is_line_gutter_clickable(int p_line, int p_gutter) const { + ERR_FAIL_INDEX_V(p_line, text.size(), false); + ERR_FAIL_INDEX_V(p_gutter, gutters.size(), false); + return text.is_line_gutter_clickable(p_line, p_gutter); +} + void TextEdit::add_keyword(const String &p_keyword) { keywords.insert(p_keyword); } @@ -5341,106 +5376,6 @@ void TextEdit::set_line_as_marked(int p_line, bool p_marked) { update(); } -void TextEdit::set_line_as_safe(int p_line, bool p_safe) { - ERR_FAIL_INDEX(p_line, text.size()); - text.set_safe(p_line, p_safe); - update(); -} - -bool TextEdit::is_line_set_as_safe(int p_line) const { - ERR_FAIL_INDEX_V(p_line, text.size(), false); - return text.is_safe(p_line); -} - -void TextEdit::set_executing_line(int p_line) { - ERR_FAIL_INDEX(p_line, text.size()); - executing_line = p_line; - update(); -} - -void TextEdit::clear_executing_line() { - executing_line = -1; - update(); -} - -bool TextEdit::is_line_set_as_bookmark(int p_line) const { - ERR_FAIL_INDEX_V(p_line, text.size(), false); - return text.is_bookmark(p_line); -} - -void TextEdit::set_line_as_bookmark(int p_line, bool p_bookmark) { - ERR_FAIL_INDEX(p_line, text.size()); - text.set_bookmark(p_line, p_bookmark); - update(); -} - -void TextEdit::get_bookmarks(List<int> *p_bookmarks) const { - for (int i = 0; i < text.size(); i++) { - if (text.is_bookmark(i)) { - p_bookmarks->push_back(i); - } - } -} - -Array TextEdit::get_bookmarks_array() const { - Array arr; - for (int i = 0; i < text.size(); i++) { - if (text.is_bookmark(i)) { - arr.append(i); - } - } - return arr; -} - -bool TextEdit::is_line_set_as_breakpoint(int p_line) const { - ERR_FAIL_INDEX_V(p_line, text.size(), false); - return text.is_breakpoint(p_line); -} - -void TextEdit::set_line_as_breakpoint(int p_line, bool p_breakpoint) { - ERR_FAIL_INDEX(p_line, text.size()); - text.set_breakpoint(p_line, p_breakpoint); - update(); -} - -void TextEdit::get_breakpoints(List<int> *p_breakpoints) const { - for (int i = 0; i < text.size(); i++) { - if (text.is_breakpoint(i)) { - p_breakpoints->push_back(i); - } - } -} - -Array TextEdit::get_breakpoints_array() const { - Array arr; - for (int i = 0; i < text.size(); i++) { - if (text.is_breakpoint(i)) { - arr.append(i); - } - } - return arr; -} - -void TextEdit::remove_breakpoints() { - for (int i = 0; i < text.size(); i++) { - if (text.is_breakpoint(i)) { - /* Should "breakpoint_toggled" be fired when breakpoints are removed this way? */ - text.set_breakpoint(i, false); - } - } -} - -void TextEdit::set_line_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info) { - ERR_FAIL_INDEX(p_line, text.size()); - text.set_info_icon(p_line, p_icon, p_info); - update(); -} - -void TextEdit::clear_info_icons() { - text.clear_info_icons(); - update(); -} - void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) { ERR_FAIL_INDEX(p_line, text.size()); if (is_hiding_enabled() || !p_hidden) { @@ -6115,9 +6050,9 @@ void TextEdit::_confirm_completion() { // When inserted into the middle of an existing string/method, don't add an unnecessary quote/bracket. String line = text[cursor.line]; - CharType next_char = line[cursor.column]; - CharType last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1]; - CharType last_completion_char_display = completion_current.display[completion_current.display.length() - 1]; + char32_t next_char = line[cursor.column]; + char32_t last_completion_char = completion_current.insert_text[completion_current.insert_text.length() - 1]; + char32_t last_completion_char_display = completion_current.display[completion_current.display.length() - 1]; if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) { _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); @@ -6161,7 +6096,7 @@ void TextEdit::_cancel_completion() { update(); } -static bool _is_completable(CharType c) { +static bool _is_completable(char32_t c) { return !_is_symbol(c) || c == '"' || c == '\''; } @@ -6292,14 +6227,14 @@ void TextEdit::_update_completion_candidates() { String display_lower = option.display.to_lower(); - const CharType *ssq = &s[0]; - const CharType *ssq_lower = &s_lower[0]; + const char32_t *ssq = &s[0]; + const char32_t *ssq_lower = &s_lower[0]; - const CharType *tgt = &option.display[0]; - const CharType *tgt_lower = &display_lower[0]; + const char32_t *tgt = &option.display[0]; + const char32_t *tgt_lower = &display_lower[0]; - const CharType *ssq_last_tgt = nullptr; - const CharType *ssq_lower_last_tgt = nullptr; + const char32_t *ssq_last_tgt = nullptr; + const char32_t *ssq_lower_last_tgt = nullptr; for (; *tgt; tgt++, tgt_lower++) { if (*ssq == *tgt) { @@ -6416,7 +6351,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { int beg, end; if (select_word(s, col, beg, end)) { bool inside_quotes = false; - CharType selected_quote = '\0'; + char32_t selected_quote = '\0'; int qbegin = 0, qend = 0; for (int i = 0; i < s.length(); i++) { if (s[i] == '"' || s[i] == '\'') { @@ -6502,20 +6437,6 @@ void TextEdit::insert_at(const String &p_text, int at) { } } -void TextEdit::set_show_line_numbers(bool p_show) { - line_numbers = p_show; - update(); -} - -void TextEdit::set_line_numbers_zero_padded(bool p_zero_padded) { - line_numbers_zero_padded = p_zero_padded; - update(); -} - -bool TextEdit::is_show_line_numbers_enabled() const { - return line_numbers; -} - void TextEdit::set_show_line_length_guidelines(bool p_show) { line_length_guidelines = p_show; update(); @@ -6531,69 +6452,6 @@ void TextEdit::set_line_length_guideline_hard_column(int p_column) { update(); } -void TextEdit::set_bookmark_gutter_enabled(bool p_draw) { - draw_bookmark_gutter = p_draw; - update(); -} - -bool TextEdit::is_bookmark_gutter_enabled() const { - return draw_bookmark_gutter; -} - -void TextEdit::set_breakpoint_gutter_enabled(bool p_draw) { - draw_breakpoint_gutter = p_draw; - update(); -} - -bool TextEdit::is_breakpoint_gutter_enabled() const { - return draw_breakpoint_gutter; -} - -void TextEdit::set_breakpoint_gutter_width(int p_gutter_width) { - breakpoint_gutter_width = p_gutter_width; - update(); -} - -int TextEdit::get_breakpoint_gutter_width() const { - return cache.breakpoint_gutter_width; -} - -void TextEdit::set_draw_fold_gutter(bool p_draw) { - draw_fold_gutter = p_draw; - update(); -} - -bool TextEdit::is_drawing_fold_gutter() const { - return draw_fold_gutter; -} - -void TextEdit::set_fold_gutter_width(int p_gutter_width) { - fold_gutter_width = p_gutter_width; - update(); -} - -int TextEdit::get_fold_gutter_width() const { - return cache.fold_gutter_width; -} - -void TextEdit::set_draw_info_gutter(bool p_draw) { - draw_info_gutter = p_draw; - update(); -} - -bool TextEdit::is_drawing_info_gutter() const { - return draw_info_gutter; -} - -void TextEdit::set_info_gutter_width(int p_gutter_width) { - info_gutter_width = p_gutter_width; - update(); -} - -int TextEdit::get_info_gutter_width() const { - return info_gutter_width; -} - void TextEdit::set_draw_minimap(bool p_draw) { draw_minimap = p_draw; update(); @@ -6800,16 +6658,10 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("redo"), &TextEdit::redo); ClassDB::bind_method(D_METHOD("clear_undo_history"), &TextEdit::clear_undo_history); - ClassDB::bind_method(D_METHOD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers); - ClassDB::bind_method(D_METHOD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled); ClassDB::bind_method(D_METHOD("set_draw_tabs"), &TextEdit::set_draw_tabs); ClassDB::bind_method(D_METHOD("is_drawing_tabs"), &TextEdit::is_drawing_tabs); ClassDB::bind_method(D_METHOD("set_draw_spaces"), &TextEdit::set_draw_spaces); ClassDB::bind_method(D_METHOD("is_drawing_spaces"), &TextEdit::is_drawing_spaces); - ClassDB::bind_method(D_METHOD("set_breakpoint_gutter_enabled", "enable"), &TextEdit::set_breakpoint_gutter_enabled); - ClassDB::bind_method(D_METHOD("is_breakpoint_gutter_enabled"), &TextEdit::is_breakpoint_gutter_enabled); - ClassDB::bind_method(D_METHOD("set_draw_fold_gutter"), &TextEdit::set_draw_fold_gutter); - ClassDB::bind_method(D_METHOD("is_drawing_fold_gutter"), &TextEdit::is_drawing_fold_gutter); ClassDB::bind_method(D_METHOD("set_hiding_enabled", "enable"), &TextEdit::set_hiding_enabled); ClassDB::bind_method(D_METHOD("is_hiding_enabled"), &TextEdit::is_hiding_enabled); @@ -6832,6 +6684,40 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_syntax_highlighter", "syntax_highlighter"), &TextEdit::set_syntax_highlighter); ClassDB::bind_method(D_METHOD("get_syntax_highlighter"), &TextEdit::get_syntax_highlighter); + /* Gutters. */ + BIND_ENUM_CONSTANT(GUTTER_TYPE_STRING); + BIND_ENUM_CONSTANT(GUTTER_TPYE_ICON); + BIND_ENUM_CONSTANT(GUTTER_TPYE_CUSTOM); + + ClassDB::bind_method(D_METHOD("add_gutter", "at"), &TextEdit::add_gutter, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("remove_gutter", "gutter"), &TextEdit::remove_gutter); + ClassDB::bind_method(D_METHOD("get_gutter_count"), &TextEdit::get_gutter_count); + ClassDB::bind_method(D_METHOD("set_gutter_name", "gutter", "name"), &TextEdit::set_gutter_name); + ClassDB::bind_method(D_METHOD("get_gutter_name", "gutter"), &TextEdit::get_gutter_name); + ClassDB::bind_method(D_METHOD("set_gutter_type", "gutter", "type"), &TextEdit::set_gutter_type); + ClassDB::bind_method(D_METHOD("get_gutter_type", "gutter"), &TextEdit::get_gutter_type); + ClassDB::bind_method(D_METHOD("set_gutter_width", "gutter", "width"), &TextEdit::set_gutter_width); + ClassDB::bind_method(D_METHOD("get_gutter_width", "gutter"), &TextEdit::get_gutter_width); + ClassDB::bind_method(D_METHOD("set_gutter_draw", "gutter", "draw"), &TextEdit::set_gutter_draw); + ClassDB::bind_method(D_METHOD("is_gutter_drawn", "gutter"), &TextEdit::is_gutter_drawn); + ClassDB::bind_method(D_METHOD("set_gutter_clickable", "gutter", "clickable"), &TextEdit::set_gutter_clickable); + ClassDB::bind_method(D_METHOD("is_gutter_clickable", "gutter"), &TextEdit::is_gutter_clickable); + ClassDB::bind_method(D_METHOD("set_gutter_overwritable", "gutter", "overwritable"), &TextEdit::set_gutter_overwritable); + ClassDB::bind_method(D_METHOD("is_gutter_overwritable", "gutter"), &TextEdit::is_gutter_overwritable); + ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "object", "callback"), &TextEdit::set_gutter_custom_draw); + + // Line gutters. + ClassDB::bind_method(D_METHOD("set_line_gutter_metadata", "line", "gutter", "metadata"), &TextEdit::set_line_gutter_metadata); + ClassDB::bind_method(D_METHOD("get_line_gutter_metadata", "line", "gutter"), &TextEdit::get_line_gutter_metadata); + ClassDB::bind_method(D_METHOD("set_line_gutter_text", "line", "gutter", "text"), &TextEdit::set_line_gutter_text); + ClassDB::bind_method(D_METHOD("get_line_gutter_text", "line", "gutter"), &TextEdit::get_line_gutter_text); + ClassDB::bind_method(D_METHOD("set_line_gutter_icon", "line", "gutter", "icon"), &TextEdit::set_line_gutter_icon); + ClassDB::bind_method(D_METHOD("get_line_gutter_icon", "line", "gutter"), &TextEdit::get_line_gutter_icon); + ClassDB::bind_method(D_METHOD("set_line_gutter_item_color", "line", "gutter", "color"), &TextEdit::set_line_gutter_item_color); + ClassDB::bind_method(D_METHOD("get_line_gutter_item_color", "line", "gutter"), &TextEdit::get_line_gutter_item_color); + ClassDB::bind_method(D_METHOD("set_line_gutter_clickable", "line", "gutter", "clickable"), &TextEdit::set_line_gutter_clickable); + ClassDB::bind_method(D_METHOD("is_line_gutter_clickable", "line", "gutter"), &TextEdit::is_line_gutter_clickable); + ClassDB::bind_method(D_METHOD("set_highlight_current_line", "enabled"), &TextEdit::set_highlight_current_line); ClassDB::bind_method(D_METHOD("is_highlight_current_line_enabled"), &TextEdit::is_highlight_current_line_enabled); @@ -6847,9 +6733,6 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("menu_option", "option"), &TextEdit::menu_option); ClassDB::bind_method(D_METHOD("get_menu"), &TextEdit::get_menu); - ClassDB::bind_method(D_METHOD("get_breakpoints"), &TextEdit::get_breakpoints_array); - ClassDB::bind_method(D_METHOD("remove_breakpoints"), &TextEdit::remove_breakpoints); - ClassDB::bind_method(D_METHOD("draw_minimap", "draw"), &TextEdit::set_draw_minimap); ClassDB::bind_method(D_METHOD("is_drawing_minimap"), &TextEdit::is_drawing_minimap); ClassDB::bind_method(D_METHOD("set_minimap_width", "width"), &TextEdit::set_minimap_width); @@ -6858,11 +6741,8 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "readonly"), "set_readonly", "is_readonly"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), "set_show_line_numbers", "is_show_line_numbers_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "breakpoint_gutter"), "set_breakpoint_gutter_enabled", "is_breakpoint_gutter_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); @@ -6890,11 +6770,12 @@ void TextEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("cursor_changed")); ADD_SIGNAL(MethodInfo("text_changed")); - ADD_SIGNAL(MethodInfo("line_edited_from", PropertyInfo(Variant::INT, "line"))); + ADD_SIGNAL(MethodInfo("lines_edited_from", PropertyInfo(Variant::INT, "from_line"), PropertyInfo(Variant::INT, "to_line"))); ADD_SIGNAL(MethodInfo("request_completion")); - ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "row"))); + ADD_SIGNAL(MethodInfo("gutter_clicked", PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "gutter"))); + ADD_SIGNAL(MethodInfo("gutter_added")); + ADD_SIGNAL(MethodInfo("gutter_removed")); ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column"))); - ADD_SIGNAL(MethodInfo("info_clicked", PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::STRING, "info"))); ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol"))); BIND_ENUM_CONSTANT(MENU_CUT); @@ -6927,13 +6808,6 @@ TextEdit::TextEdit() { _update_caches(); cache.row_height = 1; cache.line_spacing = 1; - cache.line_number_w = 1; - cache.breakpoint_gutter_width = 0; - breakpoint_gutter_width = 0; - cache.fold_gutter_width = 0; - fold_gutter_width = 0; - info_gutter_width = 0; - cache.info_gutter_width = 0; set_default_cursor_shape(CURSOR_IBEAM); indent_size = 4; @@ -6997,15 +6871,9 @@ TextEdit::TextEdit() { completion_active = false; completion_line_ofs = 0; tooltip_obj = nullptr; - line_numbers = false; - line_numbers_zero_padded = false; line_length_guidelines = false; line_length_guideline_soft_col = 80; line_length_guideline_hard_col = 100; - draw_bookmark_gutter = false; - draw_breakpoint_gutter = false; - draw_fold_gutter = false; - draw_info_gutter = false; hiding_enabled = false; next_operation_is_complex = false; scroll_past_end_of_file_enabled = false; @@ -7043,8 +6911,6 @@ TextEdit::TextEdit() { set_readonly(false); menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option)); first_draw = true; - - executing_line = -1; } TextEdit::~TextEdit() { diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index a6bc9963cc..562f4768ae 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -41,28 +41,53 @@ class TextEdit : public Control { GDCLASS(TextEdit, Control); public: + enum GutterType { + GUTTER_TYPE_STRING, + GUTTER_TPYE_ICON, + GUTTER_TPYE_CUSTOM + }; + +private: + struct GutterInfo { + GutterType type = GutterType::GUTTER_TYPE_STRING; + String name = ""; + int width = 24; + bool draw = true; + bool clickable = false; + bool overwritable = false; + + ObjectID custom_draw_obj = ObjectID(); + StringName custom_draw_callback; + }; + Vector<GutterInfo> gutters; + int gutters_width = 0; + int gutter_padding = 0; + + void _update_gutter_width(); + class Text { public: + struct Gutter { + Variant metadata; + bool clickable = false; + + Ref<Texture2D> icon = Ref<Texture2D>(); + String text = ""; + Color color = Color(1, 1, 1); + }; + struct Line { - int width_cache : 24; - bool marked : 1; - bool breakpoint : 1; - bool bookmark : 1; - bool hidden : 1; - bool safe : 1; - bool has_info : 1; - int wrap_amount_cache : 24; - Ref<Texture2D> info_icon; - String info; + Vector<Gutter> gutters; + + int32_t width_cache; + bool marked; + bool hidden; + int32_t wrap_amount_cache; String data; Line() { width_cache = 0; marked = false; - breakpoint = false; - bookmark = false; hidden = false; - safe = false; - has_info = false; wrap_amount_cache = 0; } }; @@ -70,7 +95,8 @@ public: private: mutable Vector<Line> text; Ref<Font> font; - int indent_size; + int indent_size = 4; + int gutter_count = 0; void _update_line_cache(int p_line) const; @@ -79,44 +105,43 @@ public: void set_font(const Ref<Font> &p_font); int get_line_width(int p_line) const; int get_max_width(bool p_exclude_hidden = false) const; - int get_char_width(CharType c, CharType next_c, int px) const; + int get_char_width(char32_t c, char32_t next_c, int px) const; void set_line_wrap_amount(int p_line, int p_wrap_amount) const; int get_line_wrap_amount(int p_line) const; void set(int p_line, const String &p_text); void set_marked(int p_line, bool p_marked) { text.write[p_line].marked = p_marked; } bool is_marked(int p_line) const { return text[p_line].marked; } - void set_bookmark(int p_line, bool p_bookmark) { text.write[p_line].bookmark = p_bookmark; } - bool is_bookmark(int p_line) const { return text[p_line].bookmark; } - void set_breakpoint(int p_line, bool p_breakpoint) { text.write[p_line].breakpoint = p_breakpoint; } - bool is_breakpoint(int p_line) const { return text[p_line].breakpoint; } void set_hidden(int p_line, bool p_hidden) { text.write[p_line].hidden = p_hidden; } bool is_hidden(int p_line) const { return text[p_line].hidden; } - void set_safe(int p_line, bool p_safe) { text.write[p_line].safe = p_safe; } - bool is_safe(int p_line) const { return text[p_line].safe; } - void set_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info) { - if (p_icon.is_null()) { - text.write[p_line].has_info = false; - return; - } - text.write[p_line].info_icon = p_icon; - text.write[p_line].info = p_info; - text.write[p_line].has_info = true; - } - bool has_info_icon(int p_line) const { return text[p_line].has_info; } - const Ref<Texture2D> &get_info_icon(int p_line) const { return text[p_line].info_icon; } - const String &get_info(int p_line) const { return text[p_line].info; } void insert(int p_at, const String &p_text); void remove(int p_at); int size() const { return text.size(); } void clear(); void clear_width_cache(); void clear_wrap_cache(); - void clear_info_icons(); _FORCE_INLINE_ const String &operator[](int p_line) const { return text[p_line].data; } - Text() { indent_size = 4; } + + /* Gutters. */ + void add_gutter(int p_at); + void remove_gutter(int p_gutter); + void move_gutters(int p_from_line, int p_to_line); + + void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata) { text.write[p_line].gutters.write[p_gutter].metadata = p_metadata; } + const Variant &get_line_gutter_metadata(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].metadata; } + + void set_line_gutter_text(int p_line, int p_gutter, const String &p_text) { text.write[p_line].gutters.write[p_gutter].text = p_text; } + const String &get_line_gutter_text(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].text; } + + void set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon) { text.write[p_line].gutters.write[p_gutter].icon = p_icon; } + const Ref<Texture2D> &get_line_gutter_icon(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].icon; } + + void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color) { text.write[p_line].gutters.write[p_gutter].color = p_color; } + const Color &get_line_gutter_item_color(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].color; } + + void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable) { text.write[p_line].gutters.write[p_gutter].clickable = p_clickable; } + bool is_line_gutter_clickable(int p_line, int p_gutter) const { return text[p_line].gutters[p_gutter].clickable; } }; -private: struct Cursor { int last_fit_x; int line, column; ///< cursor @@ -169,60 +194,6 @@ private: } } selection; - struct Cache { - Ref<Texture2D> tab_icon; - Ref<Texture2D> space_icon; - Ref<Texture2D> can_fold_icon; - Ref<Texture2D> folded_icon; - Ref<Texture2D> folded_eol_icon; - Ref<Texture2D> executing_icon; - Ref<StyleBox> style_normal; - Ref<StyleBox> style_focus; - Ref<StyleBox> style_readonly; - Ref<Font> font; - Color completion_background_color; - Color completion_selected_color; - Color completion_existing_color; - Color completion_font_color; - Color caret_color; - Color caret_background_color; - Color line_number_color; - Color safe_line_number_color; - Color font_color; - Color font_color_selected; - Color font_color_readonly; - Color selection_color; - Color mark_color; - Color bookmark_color; - Color breakpoint_color; - Color executing_line_color; - Color code_folding_color; - Color current_line_color; - Color line_length_guideline_color; - Color brace_mismatch_color; - Color word_highlighted_color; - Color search_result_color; - Color search_result_border_color; - Color background_color; - - int row_height; - int line_spacing; - int line_number_w; - int breakpoint_gutter_width; - int fold_gutter_width; - int info_gutter_width; - int minimap_width; - Cache() { - row_height = 0; - line_spacing = 0; - line_number_w = 0; - breakpoint_gutter_width = 0; - fold_gutter_width = 0; - info_gutter_width = 0; - minimap_width = 0; - } - } cache; - Map<int, Dictionary> syntax_highlighting_cache; struct TextOperation { @@ -318,19 +289,10 @@ private: bool cursor_changed_dirty; bool text_changed_dirty; bool undo_enabled; - bool line_numbers; - bool line_numbers_zero_padded; bool line_length_guidelines; int line_length_guideline_soft_col; int line_length_guideline_hard_col; - bool draw_bookmark_gutter; - bool draw_breakpoint_gutter; - int breakpoint_gutter_width; - bool draw_fold_gutter; - int fold_gutter_width; bool hiding_enabled; - bool draw_info_gutter; - int info_gutter_width; bool draw_minimap; int minimap_width; Point2 minimap_char_size; @@ -385,11 +347,8 @@ private: bool context_menu_enabled; bool shortcut_keys_enabled; - bool virtual_keyboard_enabled = true; - int executing_line; - void _generate_context_menu(); int get_visible_rows() const; @@ -447,8 +406,6 @@ private: Size2 get_minimum_size() const override; int _get_control_height() const; - int get_row_height() const; - void _reset_caret_blink_timer(); void _toggle_draw_caret(); @@ -480,6 +437,44 @@ private: int _calculate_spaces_till_next_right_indent(int column); protected: + struct Cache { + Ref<Texture2D> tab_icon; + Ref<Texture2D> space_icon; + Ref<Texture2D> folded_eol_icon; + Ref<StyleBox> style_normal; + Ref<StyleBox> style_focus; + Ref<StyleBox> style_readonly; + Ref<Font> font; + Color completion_background_color; + Color completion_selected_color; + Color completion_existing_color; + Color completion_font_color; + Color caret_color; + Color caret_background_color; + Color font_color; + Color font_color_selected; + Color font_color_readonly; + Color selection_color; + Color mark_color; + Color code_folding_color; + Color current_line_color; + Color line_length_guideline_color; + Color brace_mismatch_color; + Color word_highlighted_color; + Color search_result_color; + Color search_result_border_color; + Color background_color; + + int row_height; + int line_spacing; + int minimap_width; + Cache() { + row_height = 0; + line_spacing = 0; + minimap_width = 0; + } + } cache; + virtual String get_tooltip(const Point2 &p_pos) const override; void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr); @@ -488,15 +483,57 @@ protected: void _gui_input(const Ref<InputEvent> &p_gui_input); void _notification(int p_what); - void _consume_pair_symbol(CharType ch); + void _consume_pair_symbol(char32_t ch); void _consume_backspace_for_pair_symbol(int prev_line, int prev_column); static void _bind_methods(); public: + /* Syntax Highlighting. */ Ref<SyntaxHighlighter> get_syntax_highlighter(); void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter); + /* Gutters. */ + void add_gutter(int p_at = -1); + void remove_gutter(int p_gutter); + int get_gutter_count() const; + + void set_gutter_name(int p_gutter, const String &p_name); + String get_gutter_name(int p_gutter) const; + + void set_gutter_type(int p_gutter, GutterType p_type); + GutterType get_gutter_type(int p_gutter) const; + + void set_gutter_width(int p_gutter, int p_width); + int get_gutter_width(int p_gutter) const; + + void set_gutter_draw(int p_gutter, bool p_draw); + bool is_gutter_drawn(int p_gutter) const; + + void set_gutter_clickable(int p_gutter, bool p_clickable); + bool is_gutter_clickable(int p_gutter) const; + + void set_gutter_overwritable(int p_gutter, bool p_overwritable); + bool is_gutter_overwritable(int p_gutter) const; + + void set_gutter_custom_draw(int p_gutter, Object *p_object, const StringName &p_callback); + + // Line gutters. + void set_line_gutter_metadata(int p_line, int p_gutter, const Variant &p_metadata); + Variant get_line_gutter_metadata(int p_line, int p_gutter) const; + + void set_line_gutter_text(int p_line, int p_gutter, const String &p_text); + String get_line_gutter_text(int p_line, int p_gutter) const; + + void set_line_gutter_icon(int p_line, int p_gutter, Ref<Texture2D> p_icon); + Ref<Texture2D> get_line_gutter_icon(int p_line, int p_gutter) const; + + void set_line_gutter_item_color(int p_line, int p_gutter, const Color &p_color); + Color get_line_gutter_item_color(int p_line, int p_gutter); + + void set_line_gutter_clickable(int p_line, int p_gutter, bool p_clickable); + bool is_line_gutter_clickable(int p_line, int p_gutter) const; + enum MenuItems { MENU_CUT, MENU_COPY, @@ -534,22 +571,6 @@ public: void insert_at(const String &p_text, int at); int get_line_count() const; void set_line_as_marked(int p_line, bool p_marked); - void set_line_as_bookmark(int p_line, bool p_bookmark); - bool is_line_set_as_bookmark(int p_line) const; - void get_bookmarks(List<int> *p_bookmarks) const; - Array get_bookmarks_array() const; - void set_line_as_breakpoint(int p_line, bool p_breakpoint); - bool is_line_set_as_breakpoint(int p_line) const; - void set_executing_line(int p_line); - void clear_executing_line(); - void set_line_as_safe(int p_line, bool p_safe); - bool is_line_set_as_safe(int p_line) const; - void get_breakpoints(List<int> *p_breakpoints) const; - Array get_breakpoints_array() const; - void remove_breakpoints(); - - void set_line_info_icon(int p_line, Ref<Texture2D> p_icon, String p_info = ""); - void clear_info_icons(); void set_line_as_hidden(int p_line, bool p_hidden); bool is_line_hidden(int p_line) const; @@ -569,6 +590,7 @@ public: String get_text(); String get_line(int line) const; void set_line(int line, String new_text); + int get_row_height() const; void backspace_at_cursor(); void indent_left(); @@ -690,39 +712,13 @@ public: void menu_option(int p_option); - void set_show_line_numbers(bool p_show); - bool is_show_line_numbers_enabled() const; - void set_highlight_current_line(bool p_enabled); bool is_highlight_current_line_enabled() const; - void set_line_numbers_zero_padded(bool p_zero_padded); - void set_show_line_length_guidelines(bool p_show); void set_line_length_guideline_soft_column(int p_column); void set_line_length_guideline_hard_column(int p_column); - void set_bookmark_gutter_enabled(bool p_draw); - bool is_bookmark_gutter_enabled() const; - - void set_breakpoint_gutter_enabled(bool p_draw); - bool is_breakpoint_gutter_enabled() const; - - void set_breakpoint_gutter_width(int p_gutter_width); - int get_breakpoint_gutter_width() const; - - void set_draw_fold_gutter(bool p_draw); - bool is_drawing_fold_gutter() const; - - void set_fold_gutter_width(int p_gutter_width); - int get_fold_gutter_width() const; - - void set_draw_info_gutter(bool p_draw); - bool is_drawing_info_gutter() const; - - void set_info_gutter_width(int p_gutter_width); - int get_info_gutter_width() const; - void set_draw_minimap(bool p_draw); bool is_drawing_minimap() const; @@ -764,6 +760,7 @@ public: ~TextEdit(); }; +VARIANT_ENUM_CAST(TextEdit::GutterType); VARIANT_ENUM_CAST(TextEdit::MenuItems); VARIANT_ENUM_CAST(TextEdit::SearchFlags); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 5057f84192..f6636cf392 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2403,11 +2403,16 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { cache.hover_cell = col; if (it != old_it || col != old_col) { - // Only need to update if mouse enters/exits a button - bool was_over_button = old_it && old_it->cells[old_col].custom_button; - bool is_over_button = it && it->cells[col].custom_button; - if (was_over_button || is_over_button) { + if (old_it && old_col >= old_it->cells.size()) { + // Columns may have changed since last update(). update(); + } else { + // Only need to update if mouse enters/exits a button + bool was_over_button = old_it && old_it->cells[old_col].custom_button; + bool is_over_button = it && it->cells[col].custom_button; + if (was_over_button || is_over_button) { + update(); + } } } } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index d6d1134cc9..796408a38d 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -939,9 +939,9 @@ float CanvasItem::draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const ERR_FAIL_COND_V(p_font.is_null(), 0); if (p_font->has_outline()) { - p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], Color(1, 1, 1), true); + p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], Color(1, 1, 1), true); } - return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.c_str()[0], p_modulate); + return p_font->draw_char(canvas_item, p_pos, p_char[0], p_next.get_data()[0], p_modulate); } void CanvasItem::_notify_transform(CanvasItem *p_node) { @@ -1369,6 +1369,7 @@ void CanvasItem::set_texture_filter(TextureFilter p_texture_filter) { } texture_filter = p_texture_filter; _update_texture_filter_changed(true); + _change_notify(); } CanvasItem::TextureFilter CanvasItem::get_texture_filter() const { @@ -1421,6 +1422,7 @@ void CanvasItem::set_texture_repeat(TextureRepeat p_texture_repeat) { } texture_repeat = p_texture_repeat; _update_texture_repeat_changed(true); + _change_notify(); } CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const { diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index d9ffe770ff..3f32df87a7 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -405,10 +405,10 @@ public: void force_update_transform(); - void set_texture_filter(TextureFilter p_texture_filter); + virtual void set_texture_filter(TextureFilter p_texture_filter); TextureFilter get_texture_filter() const; - void set_texture_repeat(TextureRepeat p_texture_repeat); + virtual void set_texture_repeat(TextureRepeat p_texture_repeat); TextureRepeat get_texture_repeat() const; // Used by control nodes to retrieve the parent's anchorable area diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 82ee4dde50..da0169b60b 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -29,6 +29,8 @@ /*************************************************************************/ #include "http_request.h" +#include "core/io/compression.h" +#include "core/ustring.h" void HTTPRequest::_redirect_request(const String &p_new_url) { } @@ -82,7 +84,51 @@ Error HTTPRequest::_parse_url(const String &p_url) { return OK; } +bool HTTPRequest::has_header(const PackedStringArray &p_headers, const String &p_header_name) { + bool exists = false; + + String lower_case_header_name = p_header_name.to_lower(); + for (int i = 0; i < p_headers.size() && !exists; i++) { + String sanitized = p_headers[i].strip_edges().to_lower(); + if (sanitized.begins_with(lower_case_header_name)) { + exists = true; + } + } + + return exists; +} + +String HTTPRequest::get_header_value(const PackedStringArray &p_headers, const String &p_header_name) { + String value = ""; + + String lowwer_case_header_name = p_header_name.to_lower(); + for (int i = 0; i < p_headers.size(); i++) { + if (p_headers[i].find(":", 0) >= 0) { + Vector<String> parts = p_headers[i].split(":", false, 1); + if (parts[0].strip_edges().to_lower() == lowwer_case_header_name) { + value = parts[1].strip_edges(); + break; + } + } + } + + return value; +} + Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const String &p_request_data) { + // Copy the string into a raw buffer + Vector<uint8_t> raw_data; + + CharString charstr = p_request_data.utf8(); + size_t len = charstr.length(); + raw_data.resize(len); + uint8_t *w = raw_data.ptrw(); + copymem(w, charstr.ptr(), len); + + return request_raw(p_url, p_custom_headers, p_ssl_validate_domain, p_method, raw_data); +} + +Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_custom_headers, bool p_ssl_validate_domain, HTTPClient::Method p_method, const Vector<uint8_t> &p_request_data_raw) { ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED); ERR_FAIL_COND_V_MSG(requesting, ERR_BUSY, "HTTPRequest is processing a request. Wait for completion or cancel it before attempting a new one."); @@ -102,7 +148,14 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &p_custom_h headers = p_custom_headers; - request_data = p_request_data; + if (accept_gzip) { + // If the user has specified a different Accept-Encoding, don't overwrite it + if (!has_header(headers, "Accept-Encoding")) { + headers.push_back("Accept-Encoding: gzip, deflate"); + } + } + + request_data = p_request_data_raw; requesting = true; @@ -288,7 +341,7 @@ bool HTTPRequest::_update_connection() { } else { // Did not request yet, do request - Error err = client->request(method, request_string, headers, request_data); + Error err = client->request_raw(method, request_string, headers, request_data); if (err != OK) { call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; @@ -382,9 +435,47 @@ bool HTTPRequest::_update_connection() { ERR_FAIL_V(false); } -void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data) { +void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data) { cancel_request(); - emit_signal("request_completed", p_status, p_code, headers, p_data); + + // Determine if the request body is compressed + bool is_compressed; + String content_encoding = get_header_value(p_headers, "Content-Encoding").to_lower(); + Compression::Mode mode; + if (content_encoding == "gzip") { + mode = Compression::Mode::MODE_GZIP; + is_compressed = true; + } else if (content_encoding == "deflate") { + mode = Compression::Mode::MODE_DEFLATE; + is_compressed = true; + } else { + is_compressed = false; + } + + const PackedByteArray *data = NULL; + + if (accept_gzip && is_compressed && p_data.size() > 0) { + // Decompress request body + PackedByteArray *decompressed = memnew(PackedByteArray); + int result = Compression::decompress_dynamic(decompressed, body_size_limit, p_data.ptr(), p_data.size(), mode); + if (result == OK) { + data = decompressed; + } else if (result == -5) { + WARN_PRINT("Decompressed size of HTTP response body exceeded body_size_limit"); + p_status = RESULT_BODY_SIZE_LIMIT_EXCEEDED; + // Just return the raw data if we failed to decompress it + data = &p_data; + } else { + WARN_PRINT("Failed to decompress HTTP response body"); + p_status = RESULT_BODY_DECOMPRESS_FAILED; + // Just return the raw data if we failed to decompress it + data = &p_data; + } + } else { + data = &p_data; + } + + emit_signal("request_completed", p_status, p_code, p_headers, *data); } void HTTPRequest::_notification(int p_what) { @@ -415,6 +506,14 @@ bool HTTPRequest::is_using_threads() const { return use_threads; } +void HTTPRequest::set_accept_gzip(bool p_gzip) { + accept_gzip = p_gzip; +} + +bool HTTPRequest::is_accepting_gzip() const { + return accept_gzip; +} + void HTTPRequest::set_body_size_limit(int p_bytes) { ERR_FAIL_COND(get_http_client_status() != HTTPClient::STATUS_DISCONNECTED); @@ -481,6 +580,7 @@ void HTTPRequest::_timeout() { void HTTPRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("request", "url", "custom_headers", "ssl_validate_domain", "method", "request_data"), &HTTPRequest::request, DEFVAL(PackedStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(String())); + ClassDB::bind_method(D_METHOD("request_raw", "url", "custom_headers", "ssl_validate_domain", "method", "request_data_raw"), &HTTPRequest::request_raw, DEFVAL(PackedStringArray()), DEFVAL(true), DEFVAL(HTTPClient::METHOD_GET), DEFVAL(PackedByteArray())); ClassDB::bind_method(D_METHOD("cancel_request"), &HTTPRequest::cancel_request); ClassDB::bind_method(D_METHOD("get_http_client_status"), &HTTPRequest::get_http_client_status); @@ -488,6 +588,9 @@ void HTTPRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_threads", "enable"), &HTTPRequest::set_use_threads); ClassDB::bind_method(D_METHOD("is_using_threads"), &HTTPRequest::is_using_threads); + ClassDB::bind_method(D_METHOD("set_accept_gzip", "enable"), &HTTPRequest::set_accept_gzip); + ClassDB::bind_method(D_METHOD("is_accepting_gzip"), &HTTPRequest::is_accepting_gzip); + ClassDB::bind_method(D_METHOD("set_body_size_limit", "bytes"), &HTTPRequest::set_body_size_limit); ClassDB::bind_method(D_METHOD("get_body_size_limit"), &HTTPRequest::get_body_size_limit); @@ -512,6 +615,7 @@ void HTTPRequest::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "download_file", PROPERTY_HINT_FILE), "set_download_file", "get_download_file"); ADD_PROPERTY(PropertyInfo(Variant::INT, "download_chunk_size", PROPERTY_HINT_RANGE, "256,16777216"), "set_download_chunk_size", "get_download_chunk_size"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "accept_gzip"), "set_accept_gzip", "is_accepting_gzip"); ADD_PROPERTY(PropertyInfo(Variant::INT, "body_size_limit", PROPERTY_HINT_RANGE, "-1,2000000000"), "set_body_size_limit", "get_body_size_limit"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_redirects", PROPERTY_HINT_RANGE, "-1,64"), "set_max_redirects", "get_max_redirects"); ADD_PROPERTY(PropertyInfo(Variant::INT, "timeout", PROPERTY_HINT_RANGE, "0,86400"), "set_timeout", "get_timeout"); @@ -527,6 +631,7 @@ void HTTPRequest::_bind_methods() { BIND_ENUM_CONSTANT(RESULT_SSL_HANDSHAKE_ERROR); BIND_ENUM_CONSTANT(RESULT_NO_RESPONSE); BIND_ENUM_CONSTANT(RESULT_BODY_SIZE_LIMIT_EXCEEDED); + BIND_ENUM_CONSTANT(RESULT_BODY_DECOMPRESS_FAILED); BIND_ENUM_CONSTANT(RESULT_REQUEST_FAILED); BIND_ENUM_CONSTANT(RESULT_DOWNLOAD_FILE_CANT_OPEN); BIND_ENUM_CONSTANT(RESULT_DOWNLOAD_FILE_WRITE_ERROR); @@ -544,6 +649,7 @@ HTTPRequest::HTTPRequest() { got_response = false; validate_ssl = false; use_ssl = false; + accept_gzip = true; response_code = 0; request_sent = false; requesting = false; diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 1409965d45..2e8931120b 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -50,6 +50,7 @@ public: RESULT_SSL_HANDSHAKE_ERROR, RESULT_NO_RESPONSE, RESULT_BODY_SIZE_LIMIT_EXCEEDED, + RESULT_BODY_DECOMPRESS_FAILED, RESULT_REQUEST_FAILED, RESULT_DOWNLOAD_FILE_CANT_OPEN, RESULT_DOWNLOAD_FILE_WRITE_ERROR, @@ -68,12 +69,13 @@ private: bool validate_ssl; bool use_ssl; HTTPClient::Method method; - String request_data; + Vector<uint8_t> request_data; bool request_sent; Ref<HTTPClient> client; PackedByteArray body; volatile bool use_threads; + bool accept_gzip; bool got_response; int response_code; @@ -102,12 +104,15 @@ private: Error _parse_url(const String &p_url); Error _request(); + bool has_header(const PackedStringArray &p_headers, const String &p_header_name); + String get_header_value(const PackedStringArray &p_headers, const String &header_name); + volatile bool thread_done; volatile bool thread_request_quit; Thread *thread; - void _request_done(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data); + void _request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data); static void _thread_func(void *p_userdata); protected: @@ -116,12 +121,16 @@ protected: public: Error request(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), bool p_ssl_validate_domain = true, HTTPClient::Method p_method = HTTPClient::METHOD_GET, const String &p_request_data = ""); //connects to a full url and perform request + Error request_raw(const String &p_url, const Vector<String> &p_custom_headers = Vector<String>(), bool p_ssl_validate_domain = true, HTTPClient::Method p_method = HTTPClient::METHOD_GET, const Vector<uint8_t> &p_request_data_raw = Vector<uint8_t>()); //connects to a full url and perform request void cancel_request(); HTTPClient::Status get_http_client_status() const; void set_use_threads(bool p_use); bool is_using_threads() const; + void set_accept_gzip(bool p_gzip); + bool is_accepting_gzip() const; + void set_download_file(const String &p_file); String get_download_file() const; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 6b304c03d2..e7753089c7 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1094,7 +1094,7 @@ String increase_numeric_string(const String &s) { if (!carry) { break; } - CharType n = s[i]; + char32_t n = s[i]; if (n == '9') { // keep carry as true: 9 + 1 res[i] = '0'; } else { @@ -1155,7 +1155,7 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co String name_string = name; String nums; for (int i = name_string.length() - 1; i >= 0; i--) { - CharType n = name_string[i]; + char32_t n = name_string[i]; if (n >= '0' && n <= '9') { nums = String::chr(name_string[i]) + nums; } else { diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 0f74f2e973..e5ab4f9958 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SCENE_MAIN_LOOP_H -#define SCENE_MAIN_LOOP_H +#ifndef SCENE_TREE_H +#define SCENE_TREE_H #include "core/io/multiplayer_api.h" #include "core/os/main_loop.h" @@ -354,4 +354,4 @@ public: VARIANT_ENUM_CAST(SceneTree::GroupCallFlags); -#endif +#endif // SCENE_TREE_H diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index d962171555..b29b40ea5f 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1509,7 +1509,7 @@ void Viewport::_gui_show_tooltip() { } Control *which = nullptr; - String tooltip = _gui_get_tooltip(gui.tooltip, gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos), &which); + String tooltip = _gui_get_tooltip(gui.tooltip, gui.tooltip->get_global_transform().xform_inv(gui.last_mouse_pos), &which); tooltip = tooltip.strip_edges(); if (tooltip.length() == 0) { return; // bye diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 0f6475cf0d..820513c53d 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -81,6 +81,7 @@ #include "scene/gui/center_container.h" #include "scene/gui/check_box.h" #include "scene/gui/check_button.h" +#include "scene/gui/code_edit.h" #include "scene/gui/color_picker.h" #include "scene/gui/color_rect.h" #include "scene/gui/control.h" @@ -230,6 +231,7 @@ static Ref<ResourceFormatLoaderDynamicFont> resource_loader_dynamic_font; static Ref<ResourceFormatLoaderStreamTexture2D> resource_loader_stream_texture; static Ref<ResourceFormatLoaderStreamTextureLayered> resource_loader_texture_layered; +static Ref<ResourceFormatLoaderStreamTexture3D> resource_loader_texture_3d; static Ref<ResourceFormatLoaderBMFont> resource_loader_bmfont; @@ -252,6 +254,9 @@ void register_scene_types() { resource_loader_texture_layered.instance(); ResourceLoader::add_resource_format_loader(resource_loader_texture_layered); + resource_loader_texture_3d.instance(); + ResourceLoader::add_resource_format_loader(resource_loader_texture_3d); + resource_saver_text.instance(); ResourceSaver::add_resource_format_saver(resource_saver_text, true); @@ -291,7 +296,7 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class<ShortCut>(); + ClassDB::register_class<Shortcut>(); ClassDB::register_class<Control>(); ClassDB::register_class<Button>(); ClassDB::register_class<Label>(); @@ -347,6 +352,7 @@ void register_scene_types() { ClassDB::register_class<Tree>(); ClassDB::register_class<TextEdit>(); + ClassDB::register_class<CodeEdit>(); ClassDB::register_class<SyntaxHighlighter>(); ClassDB::register_class<CodeHighlighter>(); @@ -549,6 +555,7 @@ void register_scene_types() { ClassDB::register_class<VisualShaderNodeTexture>(); ClassDB::register_virtual_class<VisualShaderNodeSample3D>(); ClassDB::register_class<VisualShaderNodeTexture2DArray>(); + ClassDB::register_class<VisualShaderNodeTexture3D>(); ClassDB::register_class<VisualShaderNodeCubemap>(); ClassDB::register_virtual_class<VisualShaderNodeUniform>(); ClassDB::register_class<VisualShaderNodeUniformRef>(); @@ -561,6 +568,7 @@ void register_scene_types() { ClassDB::register_class<VisualShaderNodeTextureUniform>(); ClassDB::register_class<VisualShaderNodeTextureUniformTriplanar>(); ClassDB::register_class<VisualShaderNodeTexture2DArrayUniform>(); + ClassDB::register_class<VisualShaderNodeTexture3DUniform>(); ClassDB::register_class<VisualShaderNodeCubemapUniform>(); ClassDB::register_class<VisualShaderNodeIf>(); ClassDB::register_class<VisualShaderNodeSwitch>(); @@ -701,6 +709,9 @@ void register_scene_types() { ClassDB::register_class<CameraTexture>(); ClassDB::register_virtual_class<TextureLayered>(); ClassDB::register_virtual_class<ImageTextureLayered>(); + ClassDB::register_virtual_class<Texture3D>(); + ClassDB::register_class<ImageTexture3D>(); + ClassDB::register_class<StreamTexture3D>(); ClassDB::register_class<Cubemap>(); ClassDB::register_class<CubemapArray>(); ClassDB::register_class<Texture2DArray>(); @@ -864,6 +875,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D"); ClassDB::add_compatibility_class("RigidBody", "RigidBody3D"); ClassDB::add_compatibility_class("Shape", "Shape3D"); + ClassDB::add_compatibility_class("ShortCut", "Shortcut"); ClassDB::add_compatibility_class("Skeleton", "Skeleton3D"); ClassDB::add_compatibility_class("SkeletonIK", "SkeletonIK3D"); ClassDB::add_compatibility_class("SliderJoint", "SliderJoint3D"); @@ -946,6 +958,9 @@ void unregister_scene_types() { ResourceLoader::remove_resource_format_loader(resource_loader_texture_layered); resource_loader_texture_layered.unref(); + ResourceLoader::remove_resource_format_loader(resource_loader_texture_3d); + resource_loader_texture_3d.unref(); + ResourceLoader::remove_resource_format_loader(resource_loader_stream_texture); resource_loader_stream_texture.unref(); diff --git a/scene/resources/default_theme/bookmark.png b/scene/resources/default_theme/bookmark.png Binary files differnew file mode 100644 index 0000000000..9718cf53b6 --- /dev/null +++ b/scene/resources/default_theme/bookmark.png diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 9008f6d5b9..f65f78b332 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -382,8 +382,6 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_icon("tab", "TextEdit", make_icon(tab_png)); theme->set_icon("space", "TextEdit", make_icon(space_png)); - theme->set_icon("folded", "TextEdit", make_icon(arrow_right_png)); - theme->set_icon("fold", "TextEdit", make_icon(arrow_down_png)); theme->set_font("font", "TextEdit", Ref<Font>()); @@ -398,16 +396,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_color("font_color_readonly", "TextEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); theme->set_color("selection_color", "TextEdit", font_color_selection); theme->set_color("mark_color", "TextEdit", Color(1.0, 0.4, 0.4, 0.4)); - theme->set_color("bookmark_color", "TextEdit", Color(0.08, 0.49, 0.98)); - theme->set_color("breakpoint_color", "TextEdit", Color(0.8, 0.8, 0.4, 0.2)); - theme->set_color("executing_line_color", "TextEdit", Color(0.2, 0.8, 0.2, 0.4)); theme->set_color("code_folding_color", "TextEdit", Color(0.8, 0.8, 0.8, 0.8)); theme->set_color("current_line_color", "TextEdit", Color(0.25, 0.25, 0.26, 0.8)); theme->set_color("caret_color", "TextEdit", control_font_color); theme->set_color("caret_background_color", "TextEdit", Color(0, 0, 0)); theme->set_color("brace_mismatch_color", "TextEdit", Color(1, 0.2, 0.2)); - theme->set_color("line_number_color", "TextEdit", Color(0.67, 0.67, 0.67, 0.4)); - theme->set_color("safe_line_number_color", "TextEdit", Color(0.67, 0.78, 0.67, 0.6)); theme->set_color("word_highlighted_color", "TextEdit", Color(0.8, 0.9, 0.9, 0.15)); theme->set_constant("completion_lines", "TextEdit", 7); @@ -415,6 +408,50 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("completion_scroll_width", "TextEdit", 3); theme->set_constant("line_spacing", "TextEdit", 4 * scale); + // CodeEdit + theme->set_stylebox("normal", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); + theme->set_stylebox("focus", "CodeEdit", focus); + theme->set_stylebox("read_only", "CodeEdit", make_stylebox(tree_bg_disabled_png, 4, 4, 4, 4, 0, 0, 0, 0)); + theme->set_stylebox("completion", "CodeEdit", make_stylebox(tree_bg_png, 3, 3, 3, 3, 0, 0, 0, 0)); + + theme->set_icon("tab", "CodeEdit", make_icon(tab_png)); + theme->set_icon("space", "CodeEdit", make_icon(space_png)); + theme->set_icon("breakpoint", "CodeEdit", make_icon(graph_port_png)); + theme->set_icon("bookmark", "CodeEdit", make_icon(bookmark_png)); + theme->set_icon("executing_line", "CodeEdit", make_icon(arrow_right_png)); + theme->set_icon("can_fold", "CodeEdit", make_icon(arrow_down_png)); + theme->set_icon("folded", "CodeEdit", make_icon(arrow_right_png)); + + theme->set_font("font", "CodeEdit", Ref<Font>()); + + theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); + theme->set_color("completion_background_color", "CodeEdit", Color(0.17, 0.16, 0.2)); + theme->set_color("completion_selected_color", "CodeEdit", Color(0.26, 0.26, 0.27)); + theme->set_color("completion_existing_color", "CodeEdit", Color(0.87, 0.87, 0.87, 0.13)); + theme->set_color("completion_scroll_color", "CodeEdit", control_font_color_pressed); + theme->set_color("completion_font_color", "CodeEdit", Color(0.67, 0.67, 0.67)); + theme->set_color("font_color", "CodeEdit", control_font_color); + theme->set_color("font_color_selected", "CodeEdit", Color(0, 0, 0)); + theme->set_color("font_color_readonly", "CodeEdit", Color(control_font_color.r, control_font_color.g, control_font_color.b, 0.5f)); + theme->set_color("selection_color", "CodeEdit", font_color_selection); + theme->set_color("mark_color", "CodeEdit", Color(1.0, 0.4, 0.4, 0.4)); + theme->set_color("bookmark_color", "CodeEdit", Color(0.5, 0.64, 1, 0.8)); + theme->set_color("breakpoint_color", "CodeEdit", Color(0.9, 0.29, 0.3)); + theme->set_color("executing_line_color", "CodeEdit", Color(0.98, 0.89, 0.27)); + theme->set_color("code_folding_color", "CodeEdit", Color(0.8, 0.8, 0.8, 0.8)); + theme->set_color("current_line_color", "CodeEdit", Color(0.25, 0.25, 0.26, 0.8)); + theme->set_color("caret_color", "CodeEdit", control_font_color); + theme->set_color("caret_background_color", "CodeEdit", Color(0, 0, 0)); + theme->set_color("brace_mismatch_color", "CodeEdit", Color(1, 0.2, 0.2)); + theme->set_color("line_number_color", "CodeEdit", Color(0.67, 0.67, 0.67, 0.4)); + theme->set_color("safe_line_number_color", "CodeEdit", Color(0.67, 0.78, 0.67, 0.6)); + theme->set_color("word_highlighted_color", "CodeEdit", Color(0.8, 0.9, 0.9, 0.15)); + + theme->set_constant("completion_lines", "CodeEdit", 7); + theme->set_constant("completion_max_width", "CodeEdit", 50); + theme->set_constant("completion_scroll_width", "CodeEdit", 3); + theme->set_constant("line_spacing", "CodeEdit", 4 * scale); + Ref<Texture2D> empty_icon = memnew(ImageTexture); // HScrollBar diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index edcdb90db9..a15efb593a 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -10,6 +10,10 @@ static const unsigned char arrow_right_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x4, 0x0, 0x0, 0x0, 0xfc, 0x7c, 0x94, 0x6c, 0x0, 0x0, 0x0, 0x2e, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x63, 0x20, 0x17, 0x3c, 0xf8, 0xf, 0x82, 0xf7, 0x13, 0x70, 0x48, 0x3c, 0xf8, 0xf2, 0x50, 0x1b, 0x43, 0x2, 0xa, 0xaf, 0xbe, 0xe0, 0xc6, 0x2e, 0xf1, 0xff, 0xe1, 0x7c, 0x12, 0x24, 0x10, 0x46, 0x11, 0xb6, 0x1c, 0xe1, 0x5c, 0xa, 0x0, 0x0, 0xe0, 0x14, 0x48, 0xb1, 0x3d, 0x1b, 0x7a, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; +static const unsigned char bookmark_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x57, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xed, 0x93, 0x31, 0xa, 0xc0, 0x30, 0xc, 0x3, 0xa5, 0xd0, 0xff, 0x7f, 0x59, 0x1d, 0x8a, 0x42, 0x8, 0x9, 0x95, 0xc9, 0xd2, 0xa1, 0x9a, 0x8c, 0xf1, 0xdd, 0x62, 0x1b, 0x38, 0xc, 0x87, 0x5a, 0x5, 0xae, 0x79, 0xde, 0x2, 0x1, 0x80, 0x94, 0x39, 0x48, 0x76, 0x49, 0x17, 0xa4, 0xf0, 0x24, 0x61, 0x2b, 0x51, 0x8b, 0xfc, 0x82, 0xcf, 0xb, 0x48, 0x7a, 0xdf, 0x75, 0x81, 0xf, 0xe5, 0x29, 0xf7, 0x92, 0x6b, 0x3, 0x1a, 0x1e, 0xda, 0x7c, 0x3d, 0x77, 0x21, 0x7b, 0xa8, 0x74, 0x2e, 0xcb, 0xd, 0xc8, 0x75, 0x13, 0x28, 0x9, 0xed, 0xc2, 0xc8, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + static const unsigned char button_disabled_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x4, 0x0, 0x0, 0x0, 0xb5, 0xfa, 0x37, 0xea, 0x0, 0x0, 0x0, 0xc7, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x6c, 0xd0, 0x81, 0x66, 0x43, 0x31, 0x14, 0x87, 0xf1, 0xf, 0x5, 0x17, 0xb8, 0x28, 0x2e, 0x8, 0x71, 0xf3, 0x6, 0x19, 0xb6, 0xb9, 0xcb, 0xac, 0x95, 0xa4, 0xb7, 0xad, 0x6a, 0xd5, 0x68, 0x5f, 0xe4, 0x3e, 0x76, 0x1e, 0xe1, 0xbf, 0x21, 0xa6, 0xab, 0xf8, 0x1, 0x7c, 0x9c, 0x73, 0xe, 0xac, 0xe8, 0xe8, 0x19, 0x30, 0x58, 0xc6, 0xca, 0x62, 0x18, 0xe8, 0xe9, 0x58, 0x41, 0xc7, 0x1a, 0x87, 0x27, 0x10, 0x49, 0xe4, 0x5f, 0x89, 0x48, 0xc0, 0xe3, 0x58, 0xd3, 0x41, 0x8f, 0xb, 0xcb, 0xbd, 0x7c, 0xeb, 0xbf, 0x7b, 0x9, 0xb, 0x8e, 0x1e, 0x6, 0xfc, 0xad, 0x64, 0x6d, 0xb5, 0x79, 0xb0, 0x55, 0xd6, 0xad, 0xe0, 0x19, 0xc0, 0x10, 0xae, 0xda, 0x34, 0x5c, 0x45, 0xc0, 0x80, 0x25, 0x5e, 0xf4, 0xd5, 0x70, 0x11, 0x11, 0xb, 0x23, 0xe9, 0xac, 0xcf, 0x86, 0xb3, 0x48, 0x8c, 0x30, 0x92, 0x4f, 0xa, 0xd, 0x27, 0x91, 0x6b, 0x70, 0xd4, 0x47, 0xc3, 0xf1, 0x2f, 0x48, 0x7, 0x4d, 0xd, 0x87, 0x3a, 0xc2, 0x12, 0x67, 0xbd, 0x37, 0xcc, 0x75, 0x49, 0x43, 0xd8, 0xe9, 0xad, 0x61, 0x57, 0xcf, 0x1c, 0xf0, 0xfb, 0x32, 0xe9, 0xf5, 0xc9, 0xa4, 0x7d, 0x7d, 0x54, 0x8f, 0x7b, 0x59, 0xe6, 0x92, 0x14, 0x1f, 0x24, 0xcd, 0x3f, 0x7b, 0x6b, 0xa, 0xe, 0x6a, 0x82, 0x91, 0x45, 0x30, 0xba, 0x1, 0x4a, 0x51, 0xc4, 0x35, 0x1f, 0xe5, 0xa1, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 99f87dd6ed..bc983c1d7e 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -239,7 +239,7 @@ float DynamicFontAtSize::get_underline_thickness() const { return underline_thickness; } -const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { +const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFontAtSize::_find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { const Character *chr = char_map.getptr(p_char); ERR_FAIL_COND_V(!chr, (Pair<const Character *, DynamicFontAtSize *>(nullptr, nullptr))); @@ -271,7 +271,7 @@ const Pair<const DynamicFontAtSize::Character *, DynamicFontAtSize *> DynamicFon return Pair<const Character *, DynamicFontAtSize *>(chr, const_cast<DynamicFontAtSize *>(this)); } -Size2 DynamicFontAtSize::get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { +Size2 DynamicFontAtSize::get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const { if (!valid) { return Size2(1, 1); } @@ -297,7 +297,7 @@ String DynamicFontAtSize::get_available_chars() const { FT_ULong charcode = FT_Get_First_Char(face, &gindex); while (gindex != 0) { if (charcode != 0) { - chars += CharType(charcode); + chars += char32_t(charcode); } charcode = FT_Get_Next_Char(face, charcode, &gindex); } @@ -305,7 +305,7 @@ String DynamicFontAtSize::get_available_chars() const { return chars; } -float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const { +float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const { if (!valid) { return 0; } @@ -560,7 +560,7 @@ DynamicFontAtSize::Character DynamicFontAtSize::_bitmap_to_character(FT_Bitmap b return chr; } -DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(CharType p_char) { +DynamicFontAtSize::Character DynamicFontAtSize::_make_outline_char(char32_t p_char) { Character ret = Character::not_found(); if (FT_Load_Char(face, p_char, FT_LOAD_NO_BITMAP | (font->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)) != 0) { @@ -596,7 +596,7 @@ cleanup_stroker: return ret; } -void DynamicFontAtSize::_update_char(CharType p_char) { +void DynamicFontAtSize::_update_char(char32_t p_char) { if (char_map.has(p_char)) { return; } @@ -849,7 +849,7 @@ float DynamicFont::get_underline_thickness() const { return data_at_size->get_underline_thickness(); } -Size2 DynamicFont::get_char_size(CharType p_char, CharType p_next) const { +Size2 DynamicFont::get_char_size(char32_t p_char, char32_t p_next) const { if (!data_at_size.is_valid()) { return Size2(1, 1); } @@ -891,7 +891,7 @@ bool DynamicFont::has_outline() const { return outline_cache_id.outline_size > 0; } -float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const { +float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const { const Ref<DynamicFontAtSize> &font_at_size = p_outline && outline_cache_id.outline_size > 0 ? outline_data_at_size : data_at_size; if (!font_at_size.is_valid()) { diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h index e8637e7e34..a881e21da8 100644 --- a/scene/resources/dynamic_font.h +++ b/scene/resources/dynamic_font.h @@ -159,17 +159,17 @@ class DynamicFontAtSize : public Reference { int y; }; - const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(CharType p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; - Character _make_outline_char(CharType p_char); + const Pair<const Character *, DynamicFontAtSize *> _find_char_with_font(char32_t p_char, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; + Character _make_outline_char(char32_t p_char); TexturePosition _find_texture_pos_for_glyph(int p_color_size, Image::Format p_image_format, int p_width, int p_height); Character _bitmap_to_character(FT_Bitmap bitmap, int yofs, int xofs, float advance); static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count); static void _ft_stream_close(FT_Stream stream); - HashMap<CharType, Character> char_map; + HashMap<char32_t, Character> char_map; - _FORCE_INLINE_ void _update_char(CharType p_char); + _FORCE_INLINE_ void _update_char(char32_t p_char); friend class DynamicFontData; Ref<DynamicFontData> font; @@ -188,10 +188,10 @@ public: float get_underline_position() const; float get_underline_thickness() const; - Size2 get_char_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; + Size2 get_char_size(char32_t p_char, char32_t p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const; String get_available_chars() const; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const; void set_texture_flags(uint32_t p_flags); void update_oversampling(); @@ -277,14 +277,14 @@ public: virtual float get_underline_position() const override; virtual float get_underline_thickness() const override; - virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const override; + virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override; String get_available_chars() const; virtual bool is_distance_field_hint() const override; virtual bool has_outline() const override; - virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; + virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; SelfList<DynamicFont> font_list; diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index ccab88a153..7cc39f661d 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -125,7 +125,7 @@ void BitmapFont::_set_chars(const Vector<int> &p_chars) { Vector<int> BitmapFont::_get_chars() const { Vector<int> chars; - const CharType *key = nullptr; + const char32_t *key = nullptr; while ((key = char_map.next(key))) { const Character *c = char_map.getptr(*key); @@ -272,7 +272,7 @@ Error BitmapFont::create_from_fnt(const String &p_file) { } } } else if (type == "char") { - CharType idx = 0; + char32_t idx = 0; if (keys.has("id")) { idx = keys["id"].to_int(); } @@ -313,7 +313,7 @@ Error BitmapFont::create_from_fnt(const String &p_file) { add_char(idx, texture, rect, ofs, advance); } else if (type == "kerning") { - CharType first = 0, second = 0; + char32_t first = 0, second = 0; int k = 0; if (keys.has("first")) { @@ -385,10 +385,10 @@ int BitmapFont::get_character_count() const { return char_map.size(); }; -Vector<CharType> BitmapFont::get_char_keys() const { - Vector<CharType> chars; +Vector<char32_t> BitmapFont::get_char_keys() const { + Vector<char32_t> chars; chars.resize(char_map.size()); - const CharType *ct = nullptr; + const char32_t *ct = nullptr; int count = 0; while ((ct = char_map.next(ct))) { chars.write[count++] = *ct; @@ -397,7 +397,7 @@ Vector<CharType> BitmapFont::get_char_keys() const { return chars; }; -BitmapFont::Character BitmapFont::get_character(CharType p_char) const { +BitmapFont::Character BitmapFont::get_character(char32_t p_char) const { if (!char_map.has(p_char)) { ERR_FAIL_V(Character()); }; @@ -405,7 +405,7 @@ BitmapFont::Character BitmapFont::get_character(CharType p_char) const { return char_map[p_char]; }; -void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { +void BitmapFont::add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance) { if (p_advance < 0) { p_advance = p_rect.size.width; } @@ -420,7 +420,7 @@ void BitmapFont::add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rec char_map[p_char] = c; } -void BitmapFont::add_kerning_pair(CharType p_A, CharType p_B, int p_kerning) { +void BitmapFont::add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning) { KerningPairKey kpk; kpk.A = p_A; kpk.B = p_B; @@ -444,7 +444,7 @@ Vector<BitmapFont::KerningPairKey> BitmapFont::get_kerning_pair_keys() const { return ret; } -int BitmapFont::get_kerning_pair(CharType p_A, CharType p_B) const { +int BitmapFont::get_kerning_pair(char32_t p_A, char32_t p_B) const { KerningPairKey kpk; kpk.A = p_A; kpk.B = p_B; @@ -482,7 +482,7 @@ Size2 Font::get_string_size(const String &p_string) const { if (l == 0) { return Size2(0, get_height()); } - const CharType *sptr = &p_string[0]; + const char32_t *sptr = &p_string[0]; for (int i = 0; i < l; i++) { w += get_char_size(sptr[i], sptr[i + 1]).width; @@ -534,7 +534,7 @@ Ref<BitmapFont> BitmapFont::get_fallback() const { return fallback; } -float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const { +float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next, const Color &p_modulate, bool p_outline) const { const Character *c = char_map.getptr(p_char); if (!c) { @@ -556,7 +556,7 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c return get_char_size(p_char, p_next).width; } -Size2 BitmapFont::get_char_size(CharType p_char, CharType p_next) const { +Size2 BitmapFont::get_char_size(char32_t p_char, char32_t p_next) const { const Character *c = char_map.getptr(p_char); if (!c) { diff --git a/scene/resources/font.h b/scene/resources/font.h index e6b296800b..c739520da3 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -49,7 +49,7 @@ public: virtual float get_underline_position() const = 0; virtual float get_underline_thickness() const = 0; - virtual Size2 get_char_size(CharType p_char, CharType p_next = 0) const = 0; + virtual Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const = 0; Size2 get_string_size(const String &p_string) const; Size2 get_wordwrap_string_size(const String &p_string, float p_width) const; @@ -59,7 +59,7 @@ public: void draw_halign(RID p_canvas_item, const Point2 &p_pos, HAlign p_align, float p_width, const String &p_text, const Color &p_modulate = Color(1, 1, 1), const Color &p_outline_modulate = Color(1, 1, 1)) const; virtual bool has_outline() const { return false; } - virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0; + virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0; void update_changes(); Font(); @@ -74,8 +74,8 @@ class FontDrawer { struct PendingDraw { RID canvas_item; Point2 pos; - CharType chr; - CharType next; + char32_t chr; + char32_t next; Color modulate; }; @@ -88,7 +88,7 @@ public: has_outline = p_font->has_outline(); } - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1)) { + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1)) { if (has_outline) { PendingDraw draw = { p_canvas_item, p_pos, p_char, p_next, p_modulate }; pending_draws.push_back(draw); @@ -137,7 +137,7 @@ public: }; private: - HashMap<CharType, Character> char_map; + HashMap<char32_t, Character> char_map; Map<KerningPairKey, int> kerning_map; float height; @@ -169,20 +169,20 @@ public: float get_underline_thickness() const override; void add_texture(const Ref<Texture2D> &p_texture); - void add_char(CharType p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1); + void add_char(char32_t p_char, int p_texture_idx, const Rect2 &p_rect, const Size2 &p_align, float p_advance = -1); int get_character_count() const; - Vector<CharType> get_char_keys() const; - Character get_character(CharType p_char) const; + Vector<char32_t> get_char_keys() const; + Character get_character(char32_t p_char) const; int get_texture_count() const; Ref<Texture2D> get_texture(int p_idx) const; - void add_kerning_pair(CharType p_A, CharType p_B, int p_kerning); - int get_kerning_pair(CharType p_A, CharType p_B) const; + void add_kerning_pair(char32_t p_A, char32_t p_B, int p_kerning); + int get_kerning_pair(char32_t p_A, char32_t p_B) const; Vector<KerningPairKey> get_kerning_pair_keys() const; - Size2 get_char_size(CharType p_char, CharType p_next = 0) const override; + Size2 get_char_size(char32_t p_char, char32_t p_next = 0) const override; void set_fallback(const Ref<BitmapFont> &p_fallback); Ref<BitmapFont> get_fallback() const; @@ -192,7 +192,7 @@ public: void set_distance_field_hint(bool p_distance_field); bool is_distance_field_hint() const override; - float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; + float draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, char32_t p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const override; BitmapFont(); ~BitmapFont(); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index fd1fa1b48f..b0a30a5627 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -209,7 +209,6 @@ public: void surface_update_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data); int get_surface_count() const override; - void surface_remove(int p_idx); void clear_surfaces(); diff --git a/scene/resources/mesh_library.h b/scene/resources/mesh_library.h index 7b78398669..450e2c16e3 100644 --- a/scene/resources/mesh_library.h +++ b/scene/resources/mesh_library.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GRID_THEME_H -#define GRID_THEME_H +#ifndef MESH_LIBRARY_H +#define MESH_LIBRARY_H #include "core/map.h" #include "core/resource.h" @@ -96,4 +96,4 @@ public: ~MeshLibrary(); }; -#endif // CUBE_GRID_THEME_H +#endif // MESH_LIBRARY_H diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index cb201bc539..5e8bfd9387 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -848,7 +848,7 @@ Error SceneState::pack(Node *p_scene) { Map<Node *, int> node_map; Map<Node *, int> nodepath_map; - //if using scene inheritance, pack the scene it inherits from + // If using scene inheritance, pack the scene it inherits from. if (scene->get_scene_inherited_state().is_valid()) { String path = scene->get_scene_inherited_state()->get_path(); Ref<PackedScene> instance = ResourceLoader::load(path); @@ -856,8 +856,8 @@ Error SceneState::pack(Node *p_scene) { base_scene_idx = _vm_get_variant(instance, variant_map); } } - //instanced, only direct sub-scnes are supported of course + // Instanced, only direct sub-scenes are supported of course. Error err = _parse_node(scene, scene, -1, name_map, variant_map, node_map, nodepath_map); if (err) { clear(); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index a0095ed952..4bbfa8965a 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -91,13 +91,13 @@ void ParticlesMaterial::init_shaders() { shader_names->emission_texture_normal = "emission_texture_normal"; shader_names->emission_texture_color = "emission_texture_color"; - shader_names->trail_divisor = "trail_divisor"; - shader_names->trail_size_modifier = "trail_size_modifier"; - shader_names->trail_color_modifier = "trail_color_modifier"; - shader_names->gravity = "gravity"; shader_names->lifetime_randomness = "lifetime_randomness"; + + shader_names->sub_emitter_frequency = "sub_emitter_frequency"; + shader_names->sub_emitter_amount_at_end = "sub_emitter_amount_at_end"; + shader_names->sub_emitter_keep_velocity = "sub_emitter_keep_velocity"; } void ParticlesMaterial::finish_shaders() { @@ -192,9 +192,17 @@ void ParticlesMaterial::_update_shader() { } } - code += "uniform vec4 color_value : hint_color;\n"; + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { + if (sub_emitter_mode == SUB_EMITTER_CONSTANT) { + code += "uniform float sub_emitter_frequency;\n"; + } + if (sub_emitter_mode == SUB_EMITTER_AT_END) { + code += "uniform int sub_emitter_amount_at_end;\n"; + } + code += "uniform bool sub_emitter_keep_velocity;\n"; + } - code += "uniform int trail_divisor;\n"; + code += "uniform vec4 color_value : hint_color;\n"; code += "uniform vec3 gravity;\n"; @@ -239,14 +247,6 @@ void ParticlesMaterial::_update_shader() { code += "uniform sampler2D anim_offset_texture;\n"; } - if (trail_size_modifier.is_valid()) { - code += "uniform sampler2D trail_size_modifier;\n"; - } - - if (trail_color_modifier.is_valid()) { - code += "uniform sampler2D trail_color_modifier;\n"; - } - //need a random function code += "\n\n"; code += "float rand_from_seed(inout uint seed) {\n"; @@ -278,7 +278,7 @@ void ParticlesMaterial::_update_shader() { code += "\n"; code += "void compute() {\n"; - code += " uint base_number = NUMBER / uint(trail_divisor);\n"; + code += " uint base_number = NUMBER;\n"; code += " uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);\n"; code += " float angle_rand = rand_from_seed(alt_seed);\n"; code += " float scale_rand = rand_from_seed(alt_seed);\n"; @@ -293,17 +293,7 @@ void ParticlesMaterial::_update_shader() { code += " ivec2 emission_tex_size = textureSize(emission_texture_points, 0);\n"; code += " ivec2 emission_tex_ofs = ivec2(point % emission_tex_size.x, point / emission_tex_size.x);\n"; } - code += " bool restart = false;\n"; - code += " if (CUSTOM.y > CUSTOM.w) {\n"; - code += " restart = true;\n"; - code += " }\n\n"; - code += " if (RESTART || restart) {\n"; - - if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { - code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; - } else { - code += " float tex_linear_velocity = 0.0;\n"; - } + code += " if (RESTART) {\n"; if (tex_parameters[PARAM_ANGLE].is_valid()) { code += " float tex_angle = textureLod(angle_texture, vec2(0.0, 0.0), 0.0).r;\n"; @@ -319,25 +309,34 @@ void ParticlesMaterial::_update_shader() { code += " float spread_rad = spread * degree_to_rad;\n"; + code += " if (RESTART_VELOCITY) {\n"; + + if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) { + code += " float tex_linear_velocity = textureLod(linear_velocity_texture, vec2(0.0, 0.0), 0.0).r;\n"; + } else { + code += " float tex_linear_velocity = 0.0;\n"; + } + if (flags[FLAG_DISABLE_Z]) { - code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; - code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; - code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; + code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; + code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D - code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; - code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; - code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; - code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; - code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; - code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; - code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; - code += " vec_direction = normalize(vec_direction);\n"; - code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; + code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; + code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; + code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; + code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; + code += " vec3 vec_direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; + code += " vec_direction = normalize(vec_direction);\n"; + code += " VELOCITY = vec_direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } + code += " }\n"; code += " float base_angle = (initial_angle + tex_angle) * mix(1.0, angle_rand, initial_angle_random);\n"; code += " CUSTOM.x = base_angle * degree_to_rad;\n"; // angle @@ -345,35 +344,38 @@ void ParticlesMaterial::_update_shader() { code += " CUSTOM.w = (1.0 - lifetime_randomness * rand_from_seed(alt_seed));\n"; code += " CUSTOM.z = (anim_offset + tex_anim_offset) * mix(1.0, anim_offset_rand, anim_offset_random);\n"; // animation offset (0-1) + code += " if (RESTART_POSITION) {\n"; + switch (emission_shape) { case EMISSION_SHAPE_POINT: { - //do none + //do none, identity (will later be multiplied by emission transform) + code += " TRANSFORM = mat4(vec4(1,0,0,0),vec4(0,1,0,0),vec4(0,0,1,0),vec4(0,0,0,1));\n"; } break; case EMISSION_SHAPE_SPHERE: { - code += " float s = rand_from_seed(alt_seed) * 2.0 - 1.0;\n"; - code += " float t = rand_from_seed(alt_seed) * 2.0 * pi;\n"; - code += " float radius = emission_sphere_radius * sqrt(1.0 - s * s);\n"; - code += " TRANSFORM[3].xyz = vec3(radius * cos(t), radius * sin(t), emission_sphere_radius * s);\n"; + code += " float s = rand_from_seed(alt_seed) * 2.0 - 1.0;\n"; + code += " float t = rand_from_seed(alt_seed) * 2.0 * pi;\n"; + code += " float radius = emission_sphere_radius * sqrt(1.0 - s * s);\n"; + code += " TRANSFORM[3].xyz = vec3(radius * cos(t), radius * sin(t), emission_sphere_radius * s);\n"; } break; case EMISSION_SHAPE_BOX: { - code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; + code += " TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;\n"; } break; case EMISSION_SHAPE_POINTS: case EMISSION_SHAPE_DIRECTED_POINTS: { - code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; + code += " TRANSFORM[3].xyz = texelFetch(emission_texture_points, emission_tex_ofs, 0).xyz;\n"; if (emission_shape == EMISSION_SHAPE_DIRECTED_POINTS) { if (flags[FLAG_DISABLE_Z]) { - code += " mat2 rotm;"; - code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; - code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; - code += " VELOCITY.xy = rotm * VELOCITY.xy;\n"; + code += " mat2 rotm;"; + code += " rotm[0] = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xy;\n"; + code += " rotm[1] = rotm[0].yx * vec2(1.0, -1.0);\n"; + code += " if (RESTART_VELOCITY) VELOCITY.xy = rotm * VELOCITY.xy;\n"; } else { - code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; - code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n"; - code += " vec3 tangent = normalize(cross(v0, normal));\n"; - code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; - code += " VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; + code += " vec3 normal = texelFetch(emission_texture_normal, emission_tex_ofs, 0).xyz;\n"; + code += " vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);\n"; + code += " vec3 tangent = normalize(cross(v0, normal));\n"; + code += " vec3 bitangent = normalize(cross(tangent, normal));\n"; + code += " if (RESTART_VELOCITY) VELOCITY = mat3(tangent, bitangent, normal) * VELOCITY;\n"; } } } break; @@ -381,12 +383,14 @@ void ParticlesMaterial::_update_shader() { break; } } - code += " VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; - code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; + + code += " if (RESTART_VELOCITY) VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;\n"; + code += " TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;\n"; if (flags[FLAG_DISABLE_Z]) { - code += " VELOCITY.z = 0.0;\n"; - code += " TRANSFORM[3].z = 0.0;\n"; + code += " VELOCITY.z = 0.0;\n"; + code += " TRANSFORM[3].z = 0.0;\n"; } + code += " }\n"; code += " } else {\n"; @@ -540,11 +544,6 @@ void ParticlesMaterial::_update_shader() { if (emission_color_texture.is_valid() && (emission_shape == EMISSION_SHAPE_POINTS || emission_shape == EMISSION_SHAPE_DIRECTED_POINTS)) { code += " COLOR *= texelFetch(emission_texture_color, emission_tex_ofs, 0);\n"; } - if (trail_color_modifier.is_valid()) { - code += " if (trail_divisor > 1) {\n"; - code += " COLOR *= textureLod(trail_color_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0);\n"; - code += " }\n"; - } code += "\n"; if (flags[FLAG_DISABLE_Z]) { @@ -592,11 +591,6 @@ void ParticlesMaterial::_update_shader() { code += " if (base_scale < 0.000001) {\n"; code += " base_scale = 0.000001;\n"; code += " }\n"; - if (trail_size_modifier.is_valid()) { - code += " if (trail_divisor > 1) {\n"; - code += " base_scale *= textureLod(trail_size_modifier, vec2(float(int(NUMBER) % trail_divisor) / float(trail_divisor - 1), 0.0), 0.0).r;\n"; - code += " }\n"; - } code += " TRANSFORM[0].xyz *= base_scale;\n"; code += " TRANSFORM[1].xyz *= base_scale;\n"; @@ -605,6 +599,33 @@ void ParticlesMaterial::_update_shader() { code += " VELOCITY.z = 0.0;\n"; code += " TRANSFORM[3].z = 0.0;\n"; } + if (sub_emitter_mode != SUB_EMITTER_DISABLED) { + code += " int emit_count = 0;\n"; + switch (sub_emitter_mode) { + case SUB_EMITTER_CONSTANT: { + code += " float interval_from = CUSTOM.y * LIFETIME - DELTA;\n"; + code += " float interval_rem = sub_emitter_frequency - mod(interval_from,sub_emitter_frequency);\n"; + code += " if (DELTA >= interval_rem) emit_count = 1;\n"; + } break; + case SUB_EMITTER_AT_COLLISION: { + //not implemented yet + } break; + case SUB_EMITTER_AT_END: { + //not implemented yet + code += " float unit_delta = DELTA/LIFETIME;\n"; + code += " float end_time = CUSTOM.w * 0.95;\n"; // if we do at the end we might miss it, as it can just get deactivated by emitter + code += " if (CUSTOM.y < end_time && (CUSTOM.y + unit_delta) >= end_time) emit_count = sub_emitter_amount_at_end;\n"; + } break; + default: { + } + } + code += " for(int i=0;i<emit_count;i++) {\n"; + code += " uint flags = FLAG_EMIT_POSITION|FLAG_EMIT_ROT_SCALE;\n"; + code += " if (sub_emitter_keep_velocity) flags|=FLAG_EMIT_VELOCITY;\n"; + code += " emit_particle(TRANSFORM,VELOCITY,vec4(0.0),vec4(0.0),flags);\n"; + code += " }"; + } + code += " if (CUSTOM.y > CUSTOM.w) {"; code += " ACTIVE = false;\n"; code += " }\n"; @@ -951,41 +972,6 @@ int ParticlesMaterial::get_emission_point_count() const { return emission_point_count; } -void ParticlesMaterial::set_trail_divisor(int p_divisor) { - trail_divisor = p_divisor; - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); -} - -int ParticlesMaterial::get_trail_divisor() const { - return trail_divisor; -} - -void ParticlesMaterial::set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier) { - trail_size_modifier = p_trail_size_modifier; - - Ref<CurveTexture> curve = trail_size_modifier; - if (curve.is_valid()) { - curve->ensure_default_setup(); - } - - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); - _queue_shader_change(); -} - -Ref<CurveTexture> ParticlesMaterial::get_trail_size_modifier() const { - return trail_size_modifier; -} - -void ParticlesMaterial::set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier) { - trail_color_modifier = p_trail_color_modifier; - RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); - _queue_shader_change(); -} - -Ref<GradientTexture> ParticlesMaterial::get_trail_color_modifier() const { - return trail_color_modifier; -} - void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { gravity = p_gravity; Vector3 gset = gravity; @@ -1038,11 +1024,54 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const { property.usage = 0; } + if (property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) { + property.usage = 0; + } + + if (property.name == "sub_emitter_amount_at_end" && sub_emitter_mode != SUB_EMITTER_AT_END) { + property.usage = 0; + } + if (property.name.begins_with("orbit_") && !flags[FLAG_DISABLE_Z]) { property.usage = 0; } } +void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { + sub_emitter_mode = p_sub_emitter_mode; + _queue_shader_change(); + _change_notify(); +} + +ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() const { + return sub_emitter_mode; +} + +void ParticlesMaterial::set_sub_emitter_frequency(float p_frequency) { + sub_emitter_frequency = p_frequency; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pas delta instead of frequency, since its easier to compute +} +float ParticlesMaterial::get_sub_emitter_frequency() const { + return sub_emitter_frequency; +} + +void ParticlesMaterial::set_sub_emitter_amount_at_end(int p_amount) { + sub_emitter_amount_at_end = p_amount; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_end, p_amount); +} + +int ParticlesMaterial::get_sub_emitter_amount_at_end() const { + return sub_emitter_amount_at_end; +} + +void ParticlesMaterial::set_sub_emitter_keep_velocity(bool p_enable) { + sub_emitter_keep_velocity = p_enable; + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable); +} +bool ParticlesMaterial::get_sub_emitter_keep_velocity() const { + return sub_emitter_keep_velocity; +} + Shader::Mode ParticlesMaterial::get_shader_mode() const { return Shader::MODE_PARTICLES; } @@ -1096,27 +1125,27 @@ void ParticlesMaterial::_bind_methods() { ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); - ClassDB::bind_method(D_METHOD("set_trail_divisor", "divisor"), &ParticlesMaterial::set_trail_divisor); - ClassDB::bind_method(D_METHOD("get_trail_divisor"), &ParticlesMaterial::get_trail_divisor); - - ClassDB::bind_method(D_METHOD("set_trail_size_modifier", "texture"), &ParticlesMaterial::set_trail_size_modifier); - ClassDB::bind_method(D_METHOD("get_trail_size_modifier"), &ParticlesMaterial::get_trail_size_modifier); - - ClassDB::bind_method(D_METHOD("set_trail_color_modifier", "texture"), &ParticlesMaterial::set_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_trail_color_modifier"), &ParticlesMaterial::get_trail_color_modifier); - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticlesMaterial::set_lifetime_randomness); ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticlesMaterial::get_lifetime_randomness); + ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticlesMaterial::get_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticlesMaterial::set_sub_emitter_mode); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticlesMaterial::get_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticlesMaterial::set_sub_emitter_frequency); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticlesMaterial::get_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticlesMaterial::set_sub_emitter_amount_at_end); + + ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticlesMaterial::get_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticlesMaterial::set_sub_emitter_keep_velocity); + ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); - ADD_GROUP("Trail", "trail_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_divisor", PROPERTY_HINT_RANGE, "1,1000000,1"), "set_trail_divisor", "get_trail_divisor"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_size_modifier", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_trail_size_modifier", "get_trail_size_modifier"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trail_color_modifier", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_trail_color_modifier", "get_trail_color_modifier"); + ADD_GROUP("Emission Shape", "emission_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius"); @@ -1186,6 +1215,12 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "anim_offset_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_ANIM_OFFSET); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "anim_offset_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_ANIM_OFFSET); + ADD_GROUP("Sub Emitter", "sub_emitter_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_mode", PROPERTY_HINT_ENUM, "Disabled,Constant,AtEnd,AtCollision"), "set_sub_emitter_mode", "get_sub_emitter_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sub_emitter_frequency", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_sub_emitter_frequency", "get_sub_emitter_frequency"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sub_emitter_amount_at_end", PROPERTY_HINT_RANGE, "1,32,1"), "set_sub_emitter_amount_at_end", "get_sub_emitter_amount_at_end"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sub_emitter_keep_velocity"), "set_sub_emitter_keep_velocity", "get_sub_emitter_keep_velocity"); + BIND_ENUM_CONSTANT(PARAM_INITIAL_LINEAR_VELOCITY); BIND_ENUM_CONSTANT(PARAM_ANGULAR_VELOCITY); BIND_ENUM_CONSTANT(PARAM_ORBIT_VELOCITY); @@ -1211,6 +1246,12 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS); BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX); + + BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED); + BIND_ENUM_CONSTANT(SUB_EMITTER_CONSTANT); + BIND_ENUM_CONSTANT(SUB_EMITTER_AT_END); + BIND_ENUM_CONSTANT(SUB_EMITTER_AT_COLLISION); + BIND_ENUM_CONSTANT(SUB_EMITTER_MAX); } ParticlesMaterial::ParticlesMaterial() : @@ -1233,11 +1274,15 @@ ParticlesMaterial::ParticlesMaterial() : set_emission_shape(EMISSION_SHAPE_POINT); set_emission_sphere_radius(1); set_emission_box_extents(Vector3(1, 1, 1)); - set_trail_divisor(1); set_gravity(Vector3(0, -9.8, 0)); set_lifetime_randomness(0); emission_point_count = 1; + set_sub_emitter_mode(SUB_EMITTER_DISABLED); + set_sub_emitter_frequency(4); + set_sub_emitter_amount_at_end(1); + set_sub_emitter_keep_velocity(false); + for (int i = 0; i < PARAM_MAX; i++) { set_param_randomness(Parameter(i), 0); } diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h index 1c1b6c92f9..fa8858f67f 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particles_material.h @@ -34,12 +34,22 @@ #ifndef PARTICLES_MATERIAL_H #define PARTICLES_MATERIAL_H +/* + TODO: +-Path following +*Manual emission +-Sub Emitters +-Attractors +-Emitter positions deformable by bones +-Collision +-Proper trails +*/ + class ParticlesMaterial : public Material { GDCLASS(ParticlesMaterial, Material); public: enum Parameter { - PARAM_INITIAL_LINEAR_VELOCITY, PARAM_ANGULAR_VELOCITY, PARAM_ORBIT_VELOCITY, @@ -71,6 +81,14 @@ public: EMISSION_SHAPE_MAX }; + enum SubEmitterMode { + SUB_EMITTER_DISABLED, + SUB_EMITTER_CONSTANT, + SUB_EMITTER_AT_END, + SUB_EMITTER_AT_COLLISION, + SUB_EMITTER_MAX + }; + private: union MaterialKey { struct { @@ -78,10 +96,9 @@ private: uint32_t texture_color : 1; uint32_t flags : 4; uint32_t emission_shape : 2; - uint32_t trail_size_texture : 1; - uint32_t trail_color_texture : 1; uint32_t invalid_key : 1; uint32_t has_emission_color : 1; + uint32_t sub_emitter : 2; }; uint32_t key; @@ -116,9 +133,8 @@ private: mk.texture_color = color_ramp.is_valid() ? 1 : 0; mk.emission_shape = emission_shape; - mk.trail_color_texture = trail_color_modifier.is_valid() ? 1 : 0; - mk.trail_size_texture = trail_size_modifier.is_valid() ? 1 : 0; mk.has_emission_color = emission_shape >= EMISSION_SHAPE_POINTS && emission_color_texture.is_valid(); + mk.sub_emitter = sub_emitter_mode; return mk; } @@ -178,13 +194,13 @@ private: StringName emission_texture_normal; StringName emission_texture_color; - StringName trail_divisor; - StringName trail_size_modifier; - StringName trail_color_modifier; - StringName gravity; StringName lifetime_randomness; + + StringName sub_emitter_frequency; + StringName sub_emitter_amount_at_end; + StringName sub_emitter_keep_velocity; }; static ShaderNames *shader_names; @@ -218,15 +234,14 @@ private: bool anim_loop; - int trail_divisor; - - Ref<CurveTexture> trail_size_modifier; - Ref<GradientTexture> trail_color_modifier; - Vector3 gravity; float lifetime_randomness; + SubEmitterMode sub_emitter_mode; + float sub_emitter_frequency; + int sub_emitter_amount_at_end; + bool sub_emitter_keep_velocity; //do not save emission points here protected: @@ -277,15 +292,6 @@ public: Ref<Texture2D> get_emission_color_texture() const; int get_emission_point_count() const; - void set_trail_divisor(int p_divisor); - int get_trail_divisor() const; - - void set_trail_size_modifier(const Ref<CurveTexture> &p_trail_size_modifier); - Ref<CurveTexture> get_trail_size_modifier() const; - - void set_trail_color_modifier(const Ref<GradientTexture> &p_trail_color_modifier); - Ref<GradientTexture> get_trail_color_modifier() const; - void set_gravity(const Vector3 &p_gravity); Vector3 get_gravity() const; @@ -296,6 +302,18 @@ public: static void finish_shaders(); static void flush_changes(); + void set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode); + SubEmitterMode get_sub_emitter_mode() const; + + void set_sub_emitter_frequency(float p_frequency); + float get_sub_emitter_frequency() const; + + void set_sub_emitter_amount_at_end(int p_amount); + int get_sub_emitter_amount_at_end() const; + + void set_sub_emitter_keep_velocity(bool p_enable); + bool get_sub_emitter_keep_velocity() const; + RID get_shader_rid() const; virtual Shader::Mode get_shader_mode() const override; @@ -307,5 +325,6 @@ public: VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) VARIANT_ENUM_CAST(ParticlesMaterial::Flags) VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) +VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode) #endif // PARTICLES_MATERIAL_H diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 4249542567..92f0353abf 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -142,8 +142,6 @@ void Shader::_bind_methods() { ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param); - //ClassDB::bind_method(D_METHOD("get_param_list"),&Shader::get_fragment_code); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_code", "get_code"); BIND_ENUM_CONSTANT(MODE_SPATIAL); diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp index 3500f6f01e..5d58e71fc5 100644 --- a/scene/resources/syntax_highlighter.cpp +++ b/scene/resources/syntax_highlighter.cpp @@ -53,13 +53,13 @@ Dictionary SyntaxHighlighter::get_line_syntax_highlighting(int p_line) { return color_map; } -void SyntaxHighlighter::_line_edited_from(int p_line) { +void SyntaxHighlighter::_lines_edited_from(int p_from_line, int p_to_line) { if (highlighting_cache.size() < 1) { return; } int cache_size = highlighting_cache.back()->key(); - for (int i = p_line - 1; i <= cache_size; i++) { + for (int i = MIN(p_from_line, p_to_line) - 1; i <= cache_size; i++) { if (highlighting_cache.has(i)) { highlighting_cache.erase(i); } @@ -93,7 +93,7 @@ void SyntaxHighlighter::update_cache() { void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) { if (text_edit && ObjectDB::get_instance(text_edit_instance_id)) { - text_edit->disconnect("line_edited_from", callable_mp(this, &SyntaxHighlighter::_line_edited_from)); + text_edit->disconnect("lines_edited_from", callable_mp(this, &SyntaxHighlighter::_lines_edited_from)); } text_edit = p_text_edit; @@ -101,7 +101,7 @@ void SyntaxHighlighter::set_text_edit(TextEdit *p_text_edit) { return; } text_edit_instance_id = text_edit->get_instance_id(); - text_edit->connect("line_edited_from", callable_mp(this, &SyntaxHighlighter::_line_edited_from)); + text_edit->connect("lines_edited_from", callable_mp(this, &SyntaxHighlighter::_lines_edited_from)); update_cache(); } @@ -125,11 +125,11 @@ void SyntaxHighlighter::_bind_methods() { //////////////////////////////////////////////////////////////////////////////// -static bool _is_char(CharType c) { +static bool _is_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; } -static bool _is_hex_symbol(CharType c) { +static bool _is_hex_symbol(char32_t c) { return ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); } @@ -195,7 +195,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { /* search the line */ bool match = true; - const CharType *start_key = color_regions[c].start_key.c_str(); + const char32_t *start_key = color_regions[c].start_key.get_data(); for (int k = 0; k < start_key_length; k++) { if (start_key[k] != str[from + k]) { match = false; @@ -232,7 +232,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting(int p_line) { /* search the line */ int region_end_index = -1; int end_key_length = color_regions[in_region].end_key.length(); - const CharType *end_key = color_regions[in_region].end_key.c_str(); + const char32_t *end_key = color_regions[in_region].end_key.get_data(); for (; from < line_length; from++) { if (line_length - from < end_key_length) { break; diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h index 40a8870b45..720227a256 100644 --- a/scene/resources/syntax_highlighter.h +++ b/scene/resources/syntax_highlighter.h @@ -40,7 +40,7 @@ class SyntaxHighlighter : public Resource { private: Map<int, Dictionary> highlighting_cache; - void _line_edited_from(int p_line); + void _lines_edited_from(int p_from_line, int p_to_line); protected: ObjectID text_edit_instance_id; // For validity check diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 5681613c04..39237e1a33 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -791,8 +791,312 @@ String ResourceFormatLoaderStreamTexture2D::get_resource_type(const String &p_pa return ""; } +//////////////////////////////////// + +TypedArray<Image> Texture3D::_get_data() const { + Vector<Ref<Image>> data = get_data(); + + TypedArray<Image> ret; + ret.resize(data.size()); + for (int i = 0; i < data.size(); i++) { + ret[i] = data[i]; + } + return ret; +} + +void Texture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format); + ClassDB::bind_method(D_METHOD("get_width"), &Texture3D::get_width); + ClassDB::bind_method(D_METHOD("get_height"), &Texture3D::get_height); + ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth); + ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture3D::has_mipmaps); + ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_data); +} ////////////////////////////////////////// +Image::Format ImageTexture3D::get_format() const { + return format; +} +int ImageTexture3D::get_width() const { + return width; +} +int ImageTexture3D::get_height() const { + return height; +} +int ImageTexture3D::get_depth() const { + return depth; +} +bool ImageTexture3D::has_mipmaps() const { + return mipmaps; +} + +Error ImageTexture3D::_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data) { + Vector<Ref<Image>> images; + images.resize(p_data.size()); + for (int i = 0; i < images.size(); i++) { + images.write[i] = p_data[i]; + } + return create(p_format, p_width, p_height, p_depth, p_mipmaps, images); +} + +void ImageTexture3D::_update(const TypedArray<Image> &p_data) { + Vector<Ref<Image>> images; + images.resize(p_data.size()); + for (int i = 0; i < images.size(); i++) { + images.write[i] = p_data[i]; + } + return update(images); +} + +Error ImageTexture3D::create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { + RID tex = RenderingServer::get_singleton()->texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); + ERR_FAIL_COND_V(tex.is_null(), ERR_CANT_CREATE); + + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_replace(texture, tex); + } + + return OK; +} + +void ImageTexture3D::update(const Vector<Ref<Image>> &p_data) { + ERR_FAIL_COND(!texture.is_valid()); + RenderingServer::get_singleton()->texture_3d_update(texture, p_data); +} + +Vector<Ref<Image>> ImageTexture3D::get_data() const { + ERR_FAIL_COND_V(!texture.is_valid(), Vector<Ref<Image>>()); + return RS::get_singleton()->texture_3d_get(texture); +} + +RID ImageTexture3D::get_rid() const { + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_3d_placeholder_create(); + } + return texture; +} +void ImageTexture3D::set_path(const String &p_path, bool p_take_over) { + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + Resource::set_path(p_path, p_take_over); +} + +void ImageTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("create", "format", "width", "height", "depth", "use_mipmaps", "data"), &ImageTexture3D::_create); + ClassDB::bind_method(D_METHOD("update", "data"), &ImageTexture3D::_update); +} + +ImageTexture3D::ImageTexture3D() { +} + +ImageTexture3D::~ImageTexture3D() { + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } +} + +//////////////////////////////////////////// + +void StreamTexture3D::set_path(const String &p_path, bool p_take_over) { + if (texture.is_valid()) { + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + Resource::set_path(p_path, p_take_over); +} + +Image::Format StreamTexture3D::get_format() const { + return format; +} + +Error StreamTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) { + FileAccessRef f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(!f, ERR_CANT_OPEN); + + uint8_t header[4]; + f->get_buffer(header, 4); + ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED); + + //stored as stream textures (used for lossless and lossy compression) + uint32_t version = f->get_32(); + + if (version > FORMAT_VERSION) { + ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new."); + } + + r_depth = f->get_32(); //depth + f->get_32(); //ignored (mode) + f->get_32(); // ignored (data format) + + f->get_32(); //ignored + int mipmaps = f->get_32(); + f->get_32(); //ignored + f->get_32(); //ignored + + r_mipmaps = mipmaps != 0; + + r_data.clear(); + + for (int i = 0; i < (r_depth + mipmaps); i++) { + Ref<Image> image = StreamTexture2D::load_image_from_file(f, 0); + ERR_FAIL_COND_V(image.is_null() || image->empty(), ERR_CANT_OPEN); + if (i == 0) { + r_format = image->get_format(); + r_width = image->get_width(); + r_height = image->get_height(); + } + r_data.push_back(image); + } + + return OK; +} + +Error StreamTexture3D::load(const String &p_path) { + Vector<Ref<Image>> data; + + int tw, th, td; + Image::Format tfmt; + bool tmm; + + Error err = _load_data(p_path, data, tfmt, tw, th, td, tmm); + if (err) { + return err; + } + + if (texture.is_valid()) { + RID new_texture = RS::get_singleton()->texture_3d_create(tfmt, tw, th, td, tmm, data); + RS::get_singleton()->texture_replace(texture, new_texture); + } else { + texture = RS::get_singleton()->texture_3d_create(tfmt, tw, th, td, tmm, data); + } + + w = tw; + h = th; + d = td; + mipmaps = tmm; + format = tfmt; + + path_to_file = p_path; + + if (get_path() == String()) { + //temporarily set path if no path set for resource, helps find errors + RenderingServer::get_singleton()->texture_set_path(texture, p_path); + } + + _change_notify(); + emit_changed(); + return OK; +} + +String StreamTexture3D::get_load_path() const { + return path_to_file; +} + +int StreamTexture3D::get_width() const { + return w; +} + +int StreamTexture3D::get_height() const { + return h; +} + +int StreamTexture3D::get_depth() const { + return d; +} + +bool StreamTexture3D::has_mipmaps() const { + return mipmaps; +} + +RID StreamTexture3D::get_rid() const { + if (!texture.is_valid()) { + texture = RS::get_singleton()->texture_3d_placeholder_create(); + } + return texture; +} + +Vector<Ref<Image>> StreamTexture3D::get_data() const { + if (texture.is_valid()) { + return RS::get_singleton()->texture_3d_get(texture); + } else { + return Vector<Ref<Image>>(); + } +} + +void StreamTexture3D::reload_from_file() { + String path = get_path(); + if (!path.is_resource_file()) { + return; + } + + path = ResourceLoader::path_remap(path); //remap for translation + path = ResourceLoader::import_remap(path); //remap for import + if (!path.is_resource_file()) { + return; + } + + load(path); +} + +void StreamTexture3D::_validate_property(PropertyInfo &property) const { +} + +void StreamTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("load", "path"), &StreamTexture3D::load); + ClassDB::bind_method(D_METHOD("get_load_path"), &StreamTexture3D::get_load_path); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "load_path", PROPERTY_HINT_FILE, "*.stex"), "load", "get_load_path"); +} + +StreamTexture3D::StreamTexture3D() { + format = Image::FORMAT_MAX; + w = 0; + h = 0; + d = 0; + mipmaps = false; +} + +StreamTexture3D::~StreamTexture3D() { + if (texture.is_valid()) { + RS::get_singleton()->free(texture); + } +} + +///////////////////////////// + +RES ResourceFormatLoaderStreamTexture3D::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) { + Ref<StreamTexture3D> st; + st.instance(); + Error err = st->load(p_path); + if (r_error) { + *r_error = err; + } + if (err != OK) { + return RES(); + } + + return st; +} + +void ResourceFormatLoaderStreamTexture3D::get_recognized_extensions(List<String> *p_extensions) const { + p_extensions->push_back("stex3d"); +} + +bool ResourceFormatLoaderStreamTexture3D::handles_type(const String &p_type) const { + return p_type == "StreamTexture3D"; +} + +String ResourceFormatLoaderStreamTexture3D::get_resource_type(const String &p_path) const { + if (p_path.get_extension().to_lower() == "stex3d") { + return "StreamTexture3D"; + } + return ""; +} + +//////////////////////////////////////////// + int AtlasTexture::get_width() const { if (region.size.width == 0) { if (atlas.is_valid()) { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index fd213859b7..eebbf4f233 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -515,6 +515,122 @@ public: virtual String get_resource_type(const String &p_path) const; }; +class Texture3D : public Texture { + GDCLASS(Texture3D, Texture); + +protected: + static void _bind_methods(); + + TypedArray<Image> _get_data() const; + +public: + virtual Image::Format get_format() const = 0; + virtual int get_width() const = 0; + virtual int get_height() const = 0; + virtual int get_depth() const = 0; + virtual bool has_mipmaps() const = 0; + virtual Vector<Ref<Image>> get_data() const = 0; +}; + +class ImageTexture3D : public Texture3D { + GDCLASS(ImageTexture3D, Texture3D); + + mutable RID texture; + + Image::Format format = Image::FORMAT_MAX; + int width = 1; + int height = 1; + int depth = 1; + bool mipmaps = false; + +protected: + static void _bind_methods(); + + Error _create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data); + void _update(const TypedArray<Image> &p_data); + +public: + virtual Image::Format get_format() const override; + virtual int get_width() const override; + virtual int get_height() const override; + virtual int get_depth() const override; + virtual bool has_mipmaps() const override; + + Error create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); + void update(const Vector<Ref<Image>> &p_data); + virtual Vector<Ref<Image>> get_data() const override; + + virtual RID get_rid() const override; + virtual void set_path(const String &p_path, bool p_take_over = false) override; + + ImageTexture3D(); + ~ImageTexture3D(); +}; + +class StreamTexture3D : public Texture3D { + GDCLASS(StreamTexture3D, Texture3D); + +public: + enum DataFormat { + DATA_FORMAT_IMAGE, + DATA_FORMAT_LOSSLESS, + DATA_FORMAT_LOSSY, + DATA_FORMAT_BASIS_UNIVERSAL, + }; + + enum { + FORMAT_VERSION = 1 + }; + + enum FormatBits { + FORMAT_MASK_IMAGE_FORMAT = (1 << 20) - 1, + FORMAT_BIT_LOSSLESS = 1 << 20, + FORMAT_BIT_LOSSY = 1 << 21, + FORMAT_BIT_STREAM = 1 << 22, + FORMAT_BIT_HAS_MIPMAPS = 1 << 23, + }; + +private: + Error _load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps); + String path_to_file; + mutable RID texture; + Image::Format format; + int w, h, d; + bool mipmaps; + + virtual void reload_from_file() override; + +protected: + static void _bind_methods(); + void _validate_property(PropertyInfo &property) const override; + +public: + Image::Format get_format() const override; + Error load(const String &p_path); + String get_load_path() const; + + int get_width() const override; + int get_height() const override; + int get_depth() const override; + virtual bool has_mipmaps() const override; + virtual RID get_rid() const override; + + virtual void set_path(const String &p_path, bool p_take_over) override; + + virtual Vector<Ref<Image>> get_data() const override; + + StreamTexture3D(); + ~StreamTexture3D(); +}; + +class ResourceFormatLoaderStreamTexture3D : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + class CurveTexture : public Texture2D { GDCLASS(CurveTexture, Texture2D); RES_BASE_EXTENSION("curvetex") diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 6992360df7..84b067d1e2 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -40,7 +40,7 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { if (slash == -1) { return false; } - int id = String::to_int(n.c_str(), slash); + int id = String::to_int(n.get_data(), slash); if (!tile_map.has(id)) { create_tile(id); @@ -216,7 +216,7 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { if (slash == -1) { return false; } - int id = String::to_int(n.c_str(), slash); + int id = String::to_int(n.get_data(), slash); ERR_FAIL_COND_V(!tile_map.has(id), false); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 33de24ad14..803ab265d4 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -172,8 +172,6 @@ void VisualShaderNode::_bind_methods() { } VisualShaderNode::VisualShaderNode() { - port_preview = -1; - simple_decl = true; } ///////////////////////////////////////////////////////// @@ -319,6 +317,14 @@ VisualShaderNodeCustom::VisualShaderNodeCustom() { ///////////////////////////////////////////////////////// +void VisualShader::set_shader_type(Type p_type) { + current_type = p_type; +} + +VisualShader::Type VisualShader::get_shader_type() const { + return current_type; +} + void VisualShader::set_version(const String &p_version) { version = p_version; } @@ -921,8 +927,11 @@ static const char *type_string[VisualShader::TYPE_MAX] = { "vertex", "fragment", "light", - "compute" + "emit", + "process", + "end" }; + bool VisualShader::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (name == "mode") { @@ -1345,6 +1354,19 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui return OK; } +bool VisualShader::has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const { + if (!ShaderTypes::get_singleton()->get_functions(p_mode).has(p_func_name)) { + if (p_mode == RenderingServer::ShaderMode::SHADER_PARTICLES) { + if (p_func_name == "emit" || p_func_name == "process" || p_func_name == "end") { + return true; + } + } + return false; + } + + return true; +} + void VisualShader::_update_shader() const { if (!dirty) { return; @@ -1416,14 +1438,14 @@ void VisualShader::_update_shader() const { global_code += "render_mode " + render_mode + ";\n\n"; } - static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "compute" }; + static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "emit", "process", "end" }; String global_expressions; Set<String> used_uniform_names; List<VisualShaderNodeUniform *> uniforms; for (int i = 0, index = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } @@ -1458,8 +1480,10 @@ void VisualShader::_update_shader() const { } } + Map<int, String> code_map; + for (int i = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } @@ -1467,6 +1491,8 @@ void VisualShader::_update_shader() const { VMap<ConnectionKey, const List<Connection>::Element *> input_connections; VMap<ConnectionKey, const List<Connection>::Element *> output_connections; + StringBuilder func_code; + for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) { ConnectionKey from_key; from_key.node = E->get().from_node; @@ -1480,14 +1506,30 @@ void VisualShader::_update_shader() const { input_connections.insert(to_key, E); } - - code += "\nvoid " + String(func_name[i]) + "() {\n"; + if (shader_mode != Shader::MODE_PARTICLES) { + func_code += "\nvoid " + String(func_name[i]) + "() {\n"; + } + insertion_pos.insert(i, code.get_string_length() + func_code.get_string_length()); Set<int> processed; - Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); + Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes); ERR_FAIL_COND(err != OK); - insertion_pos.insert(i, code.get_string_length()); + if (shader_mode == Shader::MODE_PARTICLES) { + code_map.insert(i, func_code); + } else { + func_code += "}\n"; + code += func_code; + } + } + + if (shader_mode == Shader::MODE_PARTICLES) { + code += "\nvoid compute() {\n"; + code += "\tif (RESTART) {\n"; + code += code_map[TYPE_EMIT]; + code += "\t} else {\n"; + code += code_map[TYPE_PROCESS]; + code += "\t}\n"; code += "}\n"; } @@ -1498,7 +1540,7 @@ void VisualShader::_update_shader() const { final_code += global_expressions; String tcode = code; for (int i = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) { continue; } tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]); @@ -1577,9 +1619,14 @@ void VisualShader::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_graph_offset", "get_graph_offset"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "version", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_version", "get_version"); + ADD_PROPERTY_DEFAULT("code", ""); // Inherited from Shader, prevents showing default code as override in docs. + BIND_ENUM_CONSTANT(TYPE_VERTEX); BIND_ENUM_CONSTANT(TYPE_FRAGMENT); BIND_ENUM_CONSTANT(TYPE_LIGHT); + BIND_ENUM_CONSTANT(TYPE_EMIT); + BIND_ENUM_CONSTANT(TYPE_PROCESS); + BIND_ENUM_CONSTANT(TYPE_END); BIND_ENUM_CONSTANT(TYPE_MAX); BIND_CONSTANT(NODE_ID_INVALID); @@ -1587,8 +1634,6 @@ void VisualShader::_bind_methods() { } VisualShader::VisualShader() { - shader_mode = Shader::MODE_SPATIAL; - for (int i = 0; i < TYPE_MAX; i++) { Ref<VisualShaderNodeOutput> output; output.instance(); @@ -1597,8 +1642,6 @@ VisualShader::VisualShader() { graph[i].nodes[NODE_ID_OUTPUT].node = output; graph[i].nodes[NODE_ID_OUTPUT].position = Vector2(400, 150); } - - dirty = true; } /////////////////////////////////////////////////////////// @@ -1721,20 +1764,50 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" }, - // Particles, Compute - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + // Particles, Emit + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Particles, Process + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, + + // Particles, End + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "restart", "float(RESTART ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "active", "float(ACTIVE ? 1.0 : 0.0)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, // Sky, Fragment { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_cubemap_pass", "AT_CUBEMAP_PASS" }, @@ -2036,10 +2109,6 @@ void VisualShaderNodeInput::_bind_methods() { } VisualShaderNodeInput::VisualShaderNodeInput() { - input_name = "[None]"; - // changed when set - shader_type = VisualShader::TYPE_MAX; - shader_mode = Shader::MODE_MAX; } ////////////// UniformRef @@ -2231,8 +2300,6 @@ Vector<StringName> VisualShaderNodeUniformRef::get_editable_properties() const { } VisualShaderNodeUniformRef::VisualShaderNodeUniformRef() { - uniform_name = "[None]"; - uniform_type = UniformType::UNIFORM_TYPE_FLOAT; } //////////////////////////////////////////// @@ -2291,13 +2358,30 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = { // Canvas Item, Light { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR, "light", "LIGHT.rgb" }, { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" }, - // Particles, Compute - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_COMPUTE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + // Particles, Emit + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_EMIT, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Particles, Process + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, + // Particles, End + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "velocity", "VELOCITY" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_VECTOR, "custom", "CUSTOM.rgb" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_END, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" }, // Sky, Fragment { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR, "color", "COLOR" }, { Shader::MODE_SKY, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" }, @@ -2485,7 +2569,6 @@ Vector<StringName> VisualShaderNodeUniform::get_editable_properties() const { } VisualShaderNodeUniform::VisualShaderNodeUniform() { - qualifier = QUAL_NONE; } ////////////// GroupBase @@ -2959,10 +3042,6 @@ String VisualShaderNodeGroupBase::generate_code(Shader::Mode p_mode, VisualShade } VisualShaderNodeGroupBase::VisualShaderNodeGroupBase() { - size = Size2(0, 0); - inputs = ""; - outputs = ""; - editable = false; simple_decl = false; } @@ -3087,7 +3166,6 @@ void VisualShaderNodeExpression::_bind_methods() { } VisualShaderNodeExpression::VisualShaderNodeExpression() { - expression = ""; set_editable(true); } diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 4ef9db06bc..513a17b024 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -50,7 +50,9 @@ public: TYPE_VERTEX, TYPE_FRAGMENT, TYPE_LIGHT, - TYPE_COMPUTE, + TYPE_EMIT, + TYPE_PROCESS, + TYPE_END, TYPE_MAX }; @@ -67,6 +69,8 @@ public: }; private: + Type current_type; + struct Node { Ref<VisualShaderNode> node; Vector2 position; @@ -78,7 +82,7 @@ private: List<Connection> connections; } graph[TYPE_MAX]; - Shader::Mode shader_mode; + Shader::Mode shader_mode = Shader::MODE_SPATIAL; mutable String previous_code; Array _get_node_connections(Type p_type) const; @@ -95,7 +99,7 @@ private: static RenderModeEnums render_mode_enums[]; - volatile mutable bool dirty; + volatile mutable bool dirty = true; void _queue_update(); union ConnectionKey { @@ -112,6 +116,7 @@ private: Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const; void _input_type_changed(Type p_type, int p_id); + bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const; protected: virtual void _update_shader() const override; @@ -121,6 +126,10 @@ protected: bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; +public: // internal methods + void set_shader_type(Type p_type); + Type get_shader_type() const; + public: void set_version(const String &p_version); String get_version() const; @@ -180,7 +189,7 @@ VARIANT_ENUM_CAST(VisualShader::Type) class VisualShaderNode : public Resource { GDCLASS(VisualShaderNode, Resource); - int port_preview; + int port_preview = -1; Map<int, Variant> default_input_values; Map<int, bool> connected_input_ports; @@ -188,7 +197,7 @@ class VisualShaderNode : public Resource { int connected_output_count = 0; protected: - bool simple_decl; + bool simple_decl = true; static void _bind_methods(); public: @@ -290,8 +299,8 @@ class VisualShaderNodeInput : public VisualShaderNode { GDCLASS(VisualShaderNodeInput, VisualShaderNode); friend class VisualShader; - VisualShader::Type shader_type; - Shader::Mode shader_mode; + VisualShader::Type shader_type = VisualShader::TYPE_MAX; + Shader::Mode shader_mode = Shader::MODE_MAX; struct Port { Shader::Mode mode; @@ -304,7 +313,7 @@ class VisualShaderNodeInput : public VisualShaderNode { static const Port ports[]; static const Port preview_ports[]; - String input_name; + String input_name = "[None]"; protected: static void _bind_methods(); @@ -388,8 +397,8 @@ public: }; private: - String uniform_name; - Qualifier qualifier; + String uniform_name = ""; + Qualifier qualifier = QUAL_NONE; bool global_code_generated = false; protected: @@ -436,8 +445,8 @@ public: }; private: - String uniform_name; - UniformType uniform_type; + String uniform_name = "[None]"; + UniformType uniform_type = UniformType::UNIFORM_TYPE_FLOAT; protected: static void _bind_methods(); @@ -479,10 +488,10 @@ private: void _apply_port_changes(); protected: - Vector2 size; - String inputs; - String outputs; - bool editable; + Vector2 size = Size2(0, 0); + String inputs = ""; + String outputs = ""; + bool editable = false; struct Port { PortType type; @@ -550,7 +559,7 @@ class VisualShaderNodeExpression : public VisualShaderNodeGroupBase { GDCLASS(VisualShaderNodeExpression, VisualShaderNodeGroupBase); protected: - String expression; + String expression = ""; static void _bind_methods(); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b0c871bc71..0e10682daf 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -87,7 +87,6 @@ void VisualShaderNodeFloatConstant::_bind_methods() { } VisualShaderNodeFloatConstant::VisualShaderNodeFloatConstant() { - constant = 0.0; } ////////////// Scalar(Int) @@ -147,7 +146,6 @@ void VisualShaderNodeIntConstant::_bind_methods() { } VisualShaderNodeIntConstant::VisualShaderNodeIntConstant() { - constant = 0; } ////////////// Boolean @@ -207,7 +205,6 @@ void VisualShaderNodeBooleanConstant::_bind_methods() { } VisualShaderNodeBooleanConstant::VisualShaderNodeBooleanConstant() { - constant = false; } ////////////// Color @@ -271,7 +268,6 @@ void VisualShaderNodeColorConstant::_bind_methods() { } VisualShaderNodeColorConstant::VisualShaderNodeColorConstant() { - constant = Color(1, 1, 1, 1); } ////////////// Vector @@ -777,8 +773,6 @@ void VisualShaderNodeTexture::_bind_methods() { } VisualShaderNodeTexture::VisualShaderNodeTexture() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; } ////////////// Sample3D @@ -898,7 +892,6 @@ String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader:: } VisualShaderNodeSample3D::VisualShaderNodeSample3D() { - source = SOURCE_TEXTURE; simple_decl = false; } @@ -958,6 +951,64 @@ void VisualShaderNodeTexture2DArray::_bind_methods() { VisualShaderNodeTexture2DArray::VisualShaderNodeTexture2DArray() { } + +////////////// Texture3D + +String VisualShaderNodeTexture3D::get_caption() const { + return "Texture3D"; +} + +String VisualShaderNodeTexture3D::get_input_port_name(int p_port) const { + if (p_port == 2) { + return "sampler3D"; + } + return VisualShaderNodeSample3D::get_input_port_name(p_port); +} + +Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture3D::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 VisualShaderNodeTexture3D::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + if (source == SOURCE_TEXTURE) { + return "uniform sampler3D " + make_unique_id(p_type, p_id, "tex3d") + ";\n"; + } + return String(); +} + +void VisualShaderNodeTexture3D::set_texture(Ref<Texture3D> p_value) { + texture = p_value; + emit_changed(); +} + +Ref<Texture3D> VisualShaderNodeTexture3D::get_texture() const { + return texture; +} + +Vector<StringName> VisualShaderNodeTexture3D::get_editable_properties() const { + Vector<StringName> props; + props.push_back("source"); + if (source == SOURCE_TEXTURE) { + props.push_back("texture"); + } + return props; +} + +void VisualShaderNodeTexture3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_texture", "value"), &VisualShaderNodeTexture3D::set_texture); + ClassDB::bind_method(D_METHOD("get_texture"), &VisualShaderNodeTexture3D::get_texture); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture3D"), "set_texture", "get_texture"); +} + +VisualShaderNodeTexture3D::VisualShaderNodeTexture3D() { +} + ////////////// Cubemap String VisualShaderNodeCubemap::get_caption() const { @@ -1143,8 +1194,6 @@ void VisualShaderNodeCubemap::_bind_methods() { } VisualShaderNodeCubemap::VisualShaderNodeCubemap() { - texture_type = TYPE_DATA; - source = SOURCE_TEXTURE; simple_decl = false; } @@ -1250,7 +1299,6 @@ void VisualShaderNodeFloatOp::_bind_methods() { } VisualShaderNodeFloatOp::VisualShaderNodeFloatOp() { - op = OP_ADD; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); } @@ -1345,7 +1393,6 @@ void VisualShaderNodeIntOp::_bind_methods() { } VisualShaderNodeIntOp::VisualShaderNodeIntOp() { - op = OP_ADD; set_input_port_default_value(0, 0); set_input_port_default_value(1, 0); } @@ -1460,7 +1507,6 @@ void VisualShaderNodeVectorOp::_bind_methods() { } VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() { - op = OP_ADD; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1628,7 +1674,6 @@ void VisualShaderNodeColorOp::_bind_methods() { } VisualShaderNodeColorOp::VisualShaderNodeColorOp() { - op = OP_SCREEN; set_input_port_default_value(0, Vector3()); set_input_port_default_value(1, Vector3()); } @@ -1703,7 +1748,6 @@ void VisualShaderNodeTransformMult::_bind_methods() { } VisualShaderNodeTransformMult::VisualShaderNodeTransformMult() { - op = OP_AxB; set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Transform()); } @@ -1778,7 +1822,6 @@ void VisualShaderNodeTransformVecMult::_bind_methods() { } VisualShaderNodeTransformVecMult::VisualShaderNodeTransformVecMult() { - op = OP_AxB; set_input_port_default_value(0, Transform()); set_input_port_default_value(1, Vector3()); } @@ -1908,7 +1951,6 @@ void VisualShaderNodeFloatFunc::_bind_methods() { } VisualShaderNodeFloatFunc::VisualShaderNodeFloatFunc() { - func = FUNC_SIGN; set_input_port_default_value(0, 0.0); } @@ -2003,7 +2045,6 @@ void VisualShaderNodeIntFunc::_bind_methods() { } VisualShaderNodeIntFunc::VisualShaderNodeIntFunc() { - func = FUNC_SIGN; set_input_port_default_value(0, 0); } @@ -2169,7 +2210,6 @@ void VisualShaderNodeVectorFunc::_bind_methods() { } VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() { - func = FUNC_NORMALIZE; set_input_port_default_value(0, Vector3()); } @@ -2256,9 +2296,8 @@ void VisualShaderNodeColorFunc::_bind_methods() { } VisualShaderNodeColorFunc::VisualShaderNodeColorFunc() { - func = FUNC_GRAYSCALE; - set_input_port_default_value(0, Vector3()); simple_decl = false; + set_input_port_default_value(0, Vector3()); } ////////////// Transform Func @@ -2328,7 +2367,6 @@ void VisualShaderNodeTransformFunc::_bind_methods() { } VisualShaderNodeTransformFunc::VisualShaderNodeTransformFunc() { - func = FUNC_INVERSE; set_input_port_default_value(0, Transform()); } @@ -2516,7 +2554,6 @@ void VisualShaderNodeScalarDerivativeFunc::_bind_methods() { } VisualShaderNodeScalarDerivativeFunc::VisualShaderNodeScalarDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, 0.0); } @@ -2589,7 +2626,6 @@ void VisualShaderNodeVectorDerivativeFunc::_bind_methods() { } VisualShaderNodeVectorDerivativeFunc::VisualShaderNodeVectorDerivativeFunc() { - func = FUNC_SUM; set_input_port_default_value(0, Vector3()); } @@ -3561,12 +3597,6 @@ Vector<StringName> VisualShaderNodeFloatUniform::get_editable_properties() const } VisualShaderNodeFloatUniform::VisualShaderNodeFloatUniform() { - hint = HINT_NONE; - hint_range_min = 0.0; - hint_range_max = 1.0; - hint_range_step = 0.1; - default_value_enabled = false; - default_value = 0.0; } ////////////// Integer Uniform @@ -3726,12 +3756,6 @@ Vector<StringName> VisualShaderNodeIntUniform::get_editable_properties() const { } VisualShaderNodeIntUniform::VisualShaderNodeIntUniform() { - hint = HINT_NONE; - hint_range_min = 0; - hint_range_max = 100; - hint_range_step = 1; - default_value_enabled = false; - default_value = 0; } ////////////// Boolean Uniform @@ -3824,8 +3848,6 @@ Vector<StringName> VisualShaderNodeBooleanUniform::get_editable_properties() con } VisualShaderNodeBooleanUniform::VisualShaderNodeBooleanUniform() { - default_value_enabled = false; - default_value = false; } ////////////// Color Uniform @@ -3916,8 +3938,6 @@ Vector<StringName> VisualShaderNodeColorUniform::get_editable_properties() const } VisualShaderNodeColorUniform::VisualShaderNodeColorUniform() { - default_value_enabled = false; - default_value = Color(1.0, 1.0, 1.0, 1.0); } ////////////// Vector Uniform @@ -4006,8 +4026,6 @@ Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const } VisualShaderNodeVec3Uniform::VisualShaderNodeVec3Uniform() { - default_value_enabled = false; - default_value = Vector3(0.0, 0.0, 0.0); } ////////////// Transform Uniform @@ -4100,8 +4118,6 @@ Vector<StringName> VisualShaderNodeTransformUniform::get_editable_properties() c } VisualShaderNodeTransformUniform::VisualShaderNodeTransformUniform() { - default_value_enabled = false; - default_value = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); } ////////////// Texture Uniform @@ -4271,8 +4287,6 @@ bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) co } VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() { - texture_type = TYPE_DATA; - color_default = COLOR_DEFAULT_WHITE; simple_decl = false; } @@ -4345,13 +4359,13 @@ String VisualShaderNodeTextureUniformTriplanar::generate_code(Shader::Mode p_mod String code = "\t{\n"; if (p_input_vars[0] == String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal, triplanar_pos );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n"; } else if (p_input_vars[0] != String() && p_input_vars[1] == String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", triplanar_pos );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n"; } else if (p_input_vars[0] == String() && p_input_vars[1] != String()) { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", triplanar_power_normal," + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n"; } else { - code += "\t\tvec4 n_tex_read = triplanar_texture( " + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + " );\n"; + code += "\t\tvec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n"; } code += "\t\t" + p_output_vars[0] + " = n_tex_read.rgb;\n"; @@ -4441,6 +4455,74 @@ String VisualShaderNodeTexture2DArrayUniform::generate_code(Shader::Mode p_mode, VisualShaderNodeTexture2DArrayUniform::VisualShaderNodeTexture2DArrayUniform() { } +////////////// Texture3D Uniform + +String VisualShaderNodeTexture3DUniform::get_caption() const { + return "Texture3DUniform"; +} + +int VisualShaderNodeTexture3DUniform::get_output_port_count() const { + return 1; +} + +VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_output_port_type(int p_port) const { + return PORT_TYPE_SAMPLER; +} + +String VisualShaderNodeTexture3DUniform::get_output_port_name(int p_port) const { + return "sampler3D"; +} + +int VisualShaderNodeTexture3DUniform::get_input_port_count() const { + return 0; +} + +VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture3DUniform::get_input_port_default_hint(int p_port) const { + return ""; +} + +String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { + String code = _get_qual_str() + "uniform sampler3D " + 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 VisualShaderNodeTexture3DUniform::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(); +} + +VisualShaderNodeTexture3DUniform::VisualShaderNodeTexture3DUniform() { +} + ////////////// Cubemap Uniform String VisualShaderNodeCubemapUniform::get_caption() const { @@ -4577,13 +4659,13 @@ String VisualShaderNodeIf::generate_code(Shader::Mode p_mode, VisualShader::Type } VisualShaderNodeIf::VisualShaderNodeIf() { + simple_decl = false; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); set_input_port_default_value(3, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(4, Vector3(0.0, 0.0, 0.0)); set_input_port_default_value(5, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch @@ -4642,10 +4724,10 @@ String VisualShaderNodeSwitch::generate_code(Shader::Mode p_mode, VisualShader:: } VisualShaderNodeSwitch::VisualShaderNodeSwitch() { + simple_decl = false; set_input_port_default_value(0, false); set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0)); set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0)); - simple_decl = false; } ////////////// Switch(scalar) @@ -4836,7 +4918,6 @@ void VisualShaderNodeIs::_bind_methods() { } VisualShaderNodeIs::VisualShaderNodeIs() { - func = FUNC_IS_INF; set_input_port_default_value(0, 0.0); } @@ -5072,9 +5153,6 @@ void VisualShaderNodeCompare::_bind_methods() { } VisualShaderNodeCompare::VisualShaderNodeCompare() { - ctype = CTYPE_SCALAR; - func = FUNC_EQUAL; - condition = COND_ALL; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, CMP_EPSILON); @@ -5167,7 +5245,6 @@ void VisualShaderNodeMultiplyAdd::_bind_methods() { } VisualShaderNodeMultiplyAdd::VisualShaderNodeMultiplyAdd() { - type = TYPE_SCALAR; set_input_port_default_value(0, 0.0); set_input_port_default_value(1, 0.0); set_input_port_default_value(2, 0.0); diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index b9c40d0521..06ad42adf5 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -39,7 +39,7 @@ class VisualShaderNodeFloatConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeFloatConstant, VisualShaderNode); - float constant; + float constant = 0.0f; protected: static void _bind_methods(); @@ -69,7 +69,7 @@ public: class VisualShaderNodeIntConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeIntConstant, VisualShaderNode); - int constant; + int constant = 0; protected: static void _bind_methods(); @@ -99,7 +99,7 @@ public: class VisualShaderNodeBooleanConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeBooleanConstant, VisualShaderNode); - bool constant; + bool constant = false; protected: static void _bind_methods(); @@ -129,7 +129,7 @@ public: class VisualShaderNodeColorConstant : public VisualShaderNode { GDCLASS(VisualShaderNodeColorConstant, VisualShaderNode); - Color constant; + Color constant = Color(1, 1, 1, 1); protected: static void _bind_methods(); @@ -240,8 +240,8 @@ public: }; private: - Source source; - TextureType texture_type; + Source source = SOURCE_TEXTURE; + TextureType texture_type = TYPE_DATA; protected: static void _bind_methods(); @@ -294,7 +294,7 @@ public: }; protected: - Source source; + Source source = SOURCE_TEXTURE; static void _bind_methods(); @@ -343,6 +343,29 @@ public: VisualShaderNodeTexture2DArray(); }; +class VisualShaderNodeTexture3D : public VisualShaderNodeSample3D { + GDCLASS(VisualShaderNodeTexture3D, VisualShaderNodeSample3D); + Ref<Texture3D> texture; + +protected: + static void _bind_methods(); + +public: + virtual String get_caption() const override; + + virtual String get_input_port_name(int p_port) const override; + + virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + + void set_texture(Ref<Texture3D> p_value); + Ref<Texture3D> get_texture() const; + + virtual Vector<StringName> get_editable_properties() const override; + + VisualShaderNodeTexture3D(); +}; + class VisualShaderNodeCubemap : public VisualShaderNode { GDCLASS(VisualShaderNodeCubemap, VisualShaderNode); Ref<Cubemap> cube_map; @@ -360,8 +383,8 @@ public: }; private: - Source source; - TextureType texture_type; + Source source = SOURCE_TEXTURE; + TextureType texture_type = TYPE_DATA; protected: static void _bind_methods(); @@ -421,7 +444,7 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); @@ -463,7 +486,7 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); @@ -510,7 +533,7 @@ public: }; protected: - Operator op; + Operator op = OP_ADD; static void _bind_methods(); @@ -556,7 +579,7 @@ public: }; protected: - Operator op; + Operator op = OP_SCREEN; static void _bind_methods(); @@ -599,7 +622,7 @@ public: }; protected: - Operator op; + Operator op = OP_AxB; static void _bind_methods(); @@ -642,7 +665,7 @@ public: }; protected: - Operator op; + Operator op = OP_AxB; static void _bind_methods(); @@ -713,7 +736,7 @@ public: }; protected: - Function func; + Function func = FUNC_SIGN; static void _bind_methods(); @@ -756,7 +779,7 @@ public: }; protected: - Function func; + Function func = FUNC_SIGN; static void _bind_methods(); @@ -830,7 +853,7 @@ public: }; protected: - Function func; + Function func = FUNC_NORMALIZE; static void _bind_methods(); @@ -871,7 +894,7 @@ public: }; protected: - Function func; + Function func = FUNC_GRAYSCALE; static void _bind_methods(); @@ -912,7 +935,7 @@ public: }; protected: - Function func; + Function func = FUNC_INVERSE; static void _bind_methods(); @@ -1067,7 +1090,7 @@ public: }; protected: - Function func; + Function func = FUNC_SUM; static void _bind_methods(); @@ -1107,7 +1130,7 @@ public: }; protected: - Function func; + Function func = FUNC_SUM; static void _bind_methods(); @@ -1482,12 +1505,12 @@ public: }; private: - Hint hint; - float hint_range_min; - float hint_range_max; - float hint_range_step; - bool default_value_enabled; - float default_value; + Hint hint = HINT_NONE; + float hint_range_min = 0.0f; + float hint_range_max = 1.0f; + float hint_range_step = 0.1f; + bool default_value_enabled = false; + float default_value = 0.0f; protected: static void _bind_methods(); @@ -1544,12 +1567,12 @@ public: }; private: - Hint hint; - int hint_range_min; - int hint_range_max; - int hint_range_step; - bool default_value_enabled; - int default_value; + Hint hint = HINT_NONE; + int hint_range_min = 0; + int hint_range_max = 100; + int hint_range_step = 1; + bool default_value_enabled = false; + int default_value = 0; protected: static void _bind_methods(); @@ -1601,8 +1624,8 @@ class VisualShaderNodeBooleanUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeBooleanUniform, VisualShaderNodeUniform); private: - bool default_value_enabled; - bool default_value; + bool default_value_enabled = false; + bool default_value = false; protected: static void _bind_methods(); @@ -1640,8 +1663,8 @@ class VisualShaderNodeColorUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeColorUniform, VisualShaderNodeUniform); private: - bool default_value_enabled; - Color default_value; + bool default_value_enabled = false; + Color default_value = Color(1.0, 1.0, 1.0, 1.0); protected: static void _bind_methods(); @@ -1679,7 +1702,7 @@ class VisualShaderNodeVec3Uniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeVec3Uniform, VisualShaderNodeUniform); private: - bool default_value_enabled; + bool default_value_enabled = false; Vector3 default_value; protected: @@ -1718,8 +1741,8 @@ class VisualShaderNodeTransformUniform : public VisualShaderNodeUniform { GDCLASS(VisualShaderNodeTransformUniform, VisualShaderNodeUniform); private: - bool default_value_enabled; - Transform default_value; + bool default_value_enabled = false; + Transform default_value = Transform(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); protected: static void _bind_methods(); @@ -1770,8 +1793,8 @@ public: }; protected: - TextureType texture_type; - ColorDefault color_default; + TextureType texture_type = TYPE_DATA; + ColorDefault color_default = COLOR_DEFAULT_WHITE; protected: static void _bind_methods(); @@ -1855,6 +1878,29 @@ public: /////////////////////////////////////// +class VisualShaderNodeTexture3DUniform : public VisualShaderNodeTextureUniform { + GDCLASS(VisualShaderNodeTexture3DUniform, VisualShaderNodeTextureUniform); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String get_input_port_default_hint(int p_port) const override; + virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; + 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 override; //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 + + VisualShaderNodeTexture3DUniform(); +}; + +/////////////////////////////////////// + class VisualShaderNodeCubemapUniform : public VisualShaderNodeTextureUniform { GDCLASS(VisualShaderNodeCubemapUniform, VisualShaderNodeTextureUniform); @@ -1973,7 +2019,7 @@ public: }; protected: - Function func; + Function func = FUNC_IS_INF; protected: static void _bind_methods(); @@ -2032,9 +2078,9 @@ public: }; protected: - ComparisonType ctype; - Function func; - Condition condition; + ComparisonType ctype = CTYPE_SCALAR; + Function func = FUNC_EQUAL; + Condition condition = COND_ALL; protected: static void _bind_methods(); @@ -2082,7 +2128,7 @@ public: }; protected: - Type type; + Type type = TYPE_SCALAR; protected: static void _bind_methods(); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 8f6d6d3b99..356f4b884a 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -194,6 +194,10 @@ void DisplayServer::delete_sub_window(WindowID p_id) { ERR_FAIL_MSG("Sub-windows not supported by this display server."); } +void DisplayServer::window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window) { + ERR_FAIL_MSG("Mouse passthrough not supported by this display server."); +} + void DisplayServer::window_set_ime_active(const bool p_active, WindowID p_window) { WARN_PRINT("IME not supported by this display server."); } @@ -412,6 +416,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window); ClassDB::bind_method(D_METHOD("window_set_title", "title", "window_id"), &DisplayServer::window_set_title, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_set_mouse_passthrough", "region", "window_id"), &DisplayServer::window_set_mouse_passthrough, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_get_current_screen", "window_id"), &DisplayServer::window_get_current_screen, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_set_current_screen", "screen", "window_id"), &DisplayServer::window_set_current_screen, DEFVAL(MAIN_WINDOW_ID)); diff --git a/servers/display_server.h b/servers/display_server.h index b652418244..3ee0da709b 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -247,6 +247,8 @@ public: virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual void window_set_mouse_passthrough(const Vector<Vector2> &p_region, WindowID p_window = MAIN_WINDOW_ID); + virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const = 0; virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) = 0; diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 856bba78f7..75c9a95739 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -468,7 +468,7 @@ void Body2DSW::integrate_forces(real_t p_step) { linear_velocity = motion / p_step; real_t rot = new_transform.get_rotation() - get_transform().get_rotation(); - angular_velocity = rot / p_step; + angular_velocity = remainder(rot, 2.0 * Math_PI) / p_step; do_motion = true; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index e631046524..f609adccf9 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -644,7 +644,7 @@ class PhysicsServer2DManager { name(p_ci.name), create_callback(p_ci.create_callback) {} - ClassInfo operator=(const ClassInfo &p_ci) { + ClassInfo &operator=(const ClassInfo &p_ci) { name = p_ci.name; create_callback = p_ci.create_callback; return *this; diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index dcb183aea4..b779942460 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -785,7 +785,7 @@ class PhysicsServer3DManager { name(p_ci.name), create_callback(p_ci.create_callback) {} - ClassInfo operator=(const ClassInfo &p_ci) { + ClassInfo &operator=(const ClassInfo &p_ci) { name = p_ci.name; create_callback = p_ci.create_callback; return *this; diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index 41dcd387de..a24189bdd7 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -88,7 +88,7 @@ public: virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0; virtual void environment_glow_set_use_high_quality(bool p_enable) = 0; - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_lenght, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0; + virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0; virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0; @@ -331,12 +331,12 @@ public: virtual RID texture_2d_create(const Ref<Image> &p_image) = 0; virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) = 0; - virtual RID texture_3d_create(const Vector<Ref<Image>> &p_slices) = 0; //all slices, then all the mipmaps, must be coherent + virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Ref<Image> &p_image, int p_depth, int p_mipmap) = 0; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; //these two APIs can be used together or in combination with the others. @@ -346,7 +346,7 @@ public: virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Ref<Image> texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const = 0; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; @@ -661,6 +661,8 @@ public: virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; virtual void particles_restart(RID p_particles) = 0; + virtual void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0; + virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0; virtual bool particles_is_inactive(RID p_particles) const = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index efa16628e4..c56c208098 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -2734,6 +2734,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["LIGHT_COLOR"] = "light_color"; actions.renames["LIGHT"] = "light"; actions.renames["ATTENUATION"] = "attenuation"; + actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation"; actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions.renames["SPECULAR_LIGHT"] = "specular_light"; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index eb49233b98..fe31d2f76b 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -1542,7 +1542,7 @@ public: float environment_get_fog_height(RID p_env) const; float environment_get_fog_height_density(RID p_env) const; - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_lenght, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter); + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter); virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth); virtual void environment_set_volumetric_fog_filter_active(bool p_enable); diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index e09926c97e..a13e7d786b 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -715,8 +715,120 @@ RID RasterizerStorageRD::texture_2d_layered_create(const Vector<Ref<Image>> &p_l return texture_owner.make_rid(texture); } -RID RasterizerStorageRD::texture_3d_create(const Vector<Ref<Image>> &p_slices) { - return RID(); +RID RasterizerStorageRD::texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { + ERR_FAIL_COND_V(p_data.size() == 0, RID()); + Image::Image3DValidateError verr = Image::validate_3d_image(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_V_MSG(RID(), Image::get_3d_image_validation_error_text(verr)); + } + + TextureToRDFormat ret_format; + Image::Format validated_format = Image::FORMAT_MAX; + Vector<uint8_t> all_data; + uint32_t mipmap_count = 0; + Vector<Texture::BufferSlice3D> slices; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + TextureToRDFormat f; + images.write[i] = _validate_texture_format(p_data[i], f); + if (i == 0) { + ret_format = f; + validated_format = images[0]->get_format(); + } + + all_data_size += images[i]->get_data().size(); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + Size2i prev_size; + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + + copymem(&all_data.write[offset], images[i]->get_data().ptr(), s); + { + Texture::BufferSlice3D slice; + slice.size.width = images[i]->get_width(); + slice.size.height = images[i]->get_height(); + slice.offset = offset; + slice.buffer_size = s; + slices.push_back(slice); + } + offset += s; + + Size2i img_size(images[i]->get_width(), images[i]->get_height()); + if (img_size != prev_size) { + mipmap_count++; + } + prev_size = img_size; + } + } + + Texture texture; + + texture.type = Texture::TYPE_3D; + texture.width = p_width; + texture.height = p_height; + texture.depth = p_depth; + texture.mipmaps = mipmap_count; + texture.format = p_data[0]->get_format(); + texture.validated_format = validated_format; + + texture.buffer_size_3d = all_data.size(); + texture.buffer_slices_3d = slices; + + texture.rd_type = RD::TEXTURE_TYPE_3D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = texture.depth; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector<Vector<uint8_t>> data_slices; + data_slices.push_back(all_data); //one slice + + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + return texture_owner.make_rid(texture); } RID RasterizerStorageRD::texture_proxy_create(RID p_base) { @@ -772,7 +884,41 @@ void RasterizerStorageRD::texture_2d_update(RID p_texture, const Ref<Image> &p_i _texture_2d_update(p_texture, p_image, p_layer, false); } -void RasterizerStorageRD::texture_3d_update(RID p_texture, const Ref<Image> &p_image, int p_depth, int p_mipmap) { +void RasterizerStorageRD::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_3D); + Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data); + if (verr != Image::VALIDATE_3D_OK) { + ERR_FAIL_MSG(Image::get_3d_image_validation_error_text(verr)); + } + + Vector<uint8_t> all_data; + { + Vector<Ref<Image>> images; + uint32_t all_data_size = 0; + images.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + Ref<Image> image = p_data[i]; + if (image->get_format() != tex->validated_format) { + image = image->duplicate(); + image->convert(tex->validated_format); + } + all_data_size += images[i]->get_data().size(); + images.push_back(image); + } + + all_data.resize(all_data_size); //consolidate all data here + uint32_t offset = 0; + + for (int i = 0; i < p_data.size(); i++) { + uint32_t s = images[i]->get_data().size(); + copymem(&all_data.write[offset], images[i]->get_data().ptr(), s); + offset += s; + } + } + + RD::get_singleton()->texture_update(tex->rd_texture, 0, all_data, true); } void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { @@ -858,7 +1004,25 @@ RID RasterizerStorageRD::texture_2d_layered_placeholder_create(RS::TextureLayere } RID RasterizerStorageRD::texture_3d_placeholder_create() { - return RID(); + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref<Image> image; + image.instance(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + image->set_pixel(i, j, Color(1, 0, 1, 1)); + } + } + + Vector<Ref<Image>> images; + //cube + for (int i = 0; i < 4; i++) { + images.push_back(image); + } + + return texture_3d_create(Image::FORMAT_RGBA8, 4, 4, 4, false, images); } Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const { @@ -890,11 +1054,51 @@ Ref<Image> RasterizerStorageRD::texture_2d_get(RID p_texture) const { } Ref<Image> RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { - return Ref<Image>(); + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!tex, Ref<Image>()); + + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer); + ERR_FAIL_COND_V(data.size() == 0, Ref<Image>()); + Ref<Image> image; + image.instance(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->empty(), Ref<Image>()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + + return image; } -Ref<Image> RasterizerStorageRD::texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const { - return Ref<Image>(); +Vector<Ref<Image>> RasterizerStorageRD::texture_3d_get(RID p_texture) const { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>()); + ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>()); + + Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + + ERR_FAIL_COND_V(all_data.size() != (int)tex->buffer_size_3d, Vector<Ref<Image>>()); + + Vector<Ref<Image>> ret; + + for (int i = 0; i < tex->buffer_slices_3d.size(); i++) { + const Texture::BufferSlice3D &bs = tex->buffer_slices_3d[i]; + ERR_FAIL_COND_V(bs.offset >= (uint32_t)all_data.size(), Vector<Ref<Image>>()); + ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>()); + Vector<uint8_t> sub_region = all_data.subarray(bs.offset, bs.offset + bs.buffer_size - 1); + + Ref<Image> img; + img.instance(); + img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region); + ERR_FAIL_COND_V(img->empty(), Vector<Ref<Image>>()); + if (tex->format != tex->validated_format) { + img->convert(tex->format); + } + + ret.push_back(img); + } + + return ret; } void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { @@ -3004,9 +3208,9 @@ Vector<float> RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const { Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); Vector<float> ret; - ret.resize(multimesh->instances); + ret.resize(multimesh->instances * multimesh->stride_cache); { - float *w = multimesh->data_cache.ptrw(); + float *w = ret.ptrw(); const uint8_t *r = buffer.ptr(); copymem(w, r, buffer.size()); } @@ -3119,24 +3323,40 @@ bool RasterizerStorageRD::particles_get_emitting(RID p_particles) { return particles->emitting; } +void RasterizerStorageRD::_particles_free_data(Particles *particles) { + if (!particles->particle_buffer.is_valid()) { + return; + } + RD::get_singleton()->free(particles->particle_buffer); + RD::get_singleton()->free(particles->frame_params_buffer); + RD::get_singleton()->free(particles->particle_instance_buffer); + particles->particles_transforms_buffer_uniform_set = RID(); + particles->particle_buffer = RID(); + + if (particles->particles_sort_buffer.is_valid()) { + RD::get_singleton()->free(particles->particles_sort_buffer); + particles->particles_sort_buffer = RID(); + } + + if (particles->emission_buffer != nullptr) { + particles->emission_buffer = nullptr; + particles->emission_buffer_data.clear(); + RD::get_singleton()->free(particles->emission_storage_buffer); + particles->emission_storage_buffer = RID(); + } +} + void RasterizerStorageRD::particles_set_amount(RID p_particles, int p_amount) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); - particles->amount = p_amount; + if (particles->amount == p_amount) { + return; + } - if (particles->particle_buffer.is_valid()) { - RD::get_singleton()->free(particles->particle_buffer); - RD::get_singleton()->free(particles->frame_params_buffer); - RD::get_singleton()->free(particles->particle_instance_buffer); - particles->particles_transforms_buffer_uniform_set = RID(); - particles->particle_buffer = RID(); + _particles_free_data(particles); - if (particles->particles_sort_buffer.is_valid()) { - RD::get_singleton()->free(particles->particles_sort_buffer); - particles->particles_sort_buffer = RID(); - } - } + particles->amount = p_amount; if (particles->amount > 0) { particles->particle_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticleData) * p_amount); @@ -3150,27 +3370,6 @@ void RasterizerStorageRD::particles_set_amount(RID p_particles, int p_amount) { { RD::Uniform u; u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.ids.push_back(particles->frame_params_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 1; - u.ids.push_back(particles->particle_buffer); - uniforms.push_back(u); - } - - particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1); - } - - { - Vector<RD::Uniform> uniforms; - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; u.ids.push_back(particles->particle_buffer); uniforms.push_back(u); @@ -3290,6 +3489,79 @@ void RasterizerStorageRD::particles_restart(RID p_particles) { particles->restart_request = true; } +void RasterizerStorageRD::_particles_allocate_emission_buffer(Particles *particles) { + ERR_FAIL_COND(particles->emission_buffer != nullptr); + + particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4); + zeromem(particles->emission_buffer_data.ptrw(), particles->emission_buffer_data.size()); + particles->emission_buffer = (ParticleEmissionBuffer *)particles->emission_buffer_data.ptrw(); + particles->emission_buffer->particle_max = particles->amount; + + particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data); + + if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { + //will need to be re-created + RD::get_singleton()->free(particles->particles_material_uniform_set); + particles->particles_material_uniform_set = RID(); + } +} + +void RasterizerStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) { + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + ERR_FAIL_COND(p_particles == p_subemitter_particles); + + particles->sub_emitter = p_subemitter_particles; + + if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) { + RD::get_singleton()->free(particles->particles_material_uniform_set); + particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting + } +} + +void RasterizerStorageRD::particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + ERR_FAIL_COND(particles->amount == 0); + + if (particles->emitting) { + particles->clear = true; + particles->emitting = false; + } + + if (particles->emission_buffer == nullptr) { + _particles_allocate_emission_buffer(particles); + } + + if (particles->inactive) { + //in case it was inactive, make active again + particles->inactive = false; + particles->inactive_time = 0; + } + + int32_t idx = particles->emission_buffer->particle_count; + if (idx < particles->emission_buffer->particle_max) { + store_transform(p_transform, particles->emission_buffer->data[idx].xform); + + particles->emission_buffer->data[idx].velocity[0] = p_velocity.x; + particles->emission_buffer->data[idx].velocity[1] = p_velocity.y; + particles->emission_buffer->data[idx].velocity[2] = p_velocity.z; + + particles->emission_buffer->data[idx].custom[0] = p_custom.r; + particles->emission_buffer->data[idx].custom[1] = p_custom.g; + particles->emission_buffer->data[idx].custom[2] = p_custom.b; + particles->emission_buffer->data[idx].custom[3] = p_custom.a; + + particles->emission_buffer->data[idx].color[0] = p_color.r; + particles->emission_buffer->data[idx].color[1] = p_color.g; + particles->emission_buffer->data[idx].color[2] = p_color.b; + particles->emission_buffer->data[idx].color[3] = p_color.a; + + particles->emission_buffer->data[idx].flags = p_emit_flags; + particles->emission_buffer->particle_count++; + } +} + void RasterizerStorageRD::particles_request_process(RID p_particles) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); @@ -3375,6 +3647,54 @@ RID RasterizerStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pas } void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_delta) { + if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(p_particles->frame_params_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.ids.push_back(p_particles->particle_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + if (p_particles->emission_storage_buffer.is_valid()) { + u.ids.push_back(p_particles->emission_storage_buffer); + } else { + u.ids.push_back(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 3; + Particles *sub_emitter = particles_owner.getornull(p_particles->sub_emitter); + if (sub_emitter) { + if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer + _particles_allocate_emission_buffer(sub_emitter); + } + u.ids.push_back(sub_emitter->emission_storage_buffer); + } else { + u.ids.push_back(default_rd_storage_buffer); + } + uniforms.push_back(u); + } + + p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1); + } + float new_phase = Math::fmod((float)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, (float)1.0); ParticlesFrameParams &frame_params = p_particles->frame_params; @@ -3416,6 +3736,36 @@ void RasterizerStorageRD::_particles_process(Particles *p_particles, float p_del push_constant.lifetime = p_particles->lifetime; push_constant.trail_size = 1; push_constant.use_fractional_delta = p_particles->fractional_delta; + push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit); + + p_particles->force_sub_emit = false; //reset + + Particles *sub_emitter = particles_owner.getornull(p_particles->sub_emitter); + + if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) { + // print_line("updating subemitter buffer"); + int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 }; + RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero, true); + push_constant.can_emit = true; + + if (sub_emitter->emitting) { + sub_emitter->emitting = false; + sub_emitter->clear = true; //will need to clear if it was emitting, sorry + } + //make sure the sub emitter processes particles too + sub_emitter->inactive = false; + sub_emitter->inactive_time = 0; + + sub_emitter->force_sub_emit = true; + + } else { + push_constant.can_emit = false; + } + + if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) { + RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer, true); + p_particles->emission_buffer->particle_count = 0; + } p_particles->clear = false; @@ -3617,9 +3967,6 @@ void RasterizerStorageRD::update_particles() { RD::get_singleton()->compute_list_end(); } - particle_update_list = particles->update_list; - particles->update_list = nullptr; - particles->instance_dependency.instance_notify_changed(true, false); //make sure shadows are updated } } @@ -6519,6 +6866,11 @@ bool RasterizerStorageRD::free(RID p_rid) { light->instance_dependency.instance_notify_deleted(p_rid); light_owner.free(p_rid); + } else if (particles_owner.owns(p_rid)) { + Particles *particles = particles_owner.getornull(p_rid); + _particles_free_data(particles); + particles->instance_dependency.instance_notify_deleted(p_rid); + particles_owner.free(p_rid); } else if (render_target_owner.owns(p_rid)) { RenderTarget *rt = render_target_owner.getornull(p_rid); @@ -6838,15 +7190,18 @@ RasterizerStorageRD::RasterizerStorageRD() { case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; } break; case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; } break; case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; } break; default: { } @@ -7013,6 +7368,17 @@ RasterizerStorageRD::RasterizerStorageRD() { //actions.renames["GRAVITY"] = "current_gravity"; actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform"; actions.renames["RANDOM_SEED"] = "FRAME.random_seed"; + actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION"; + actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE"; + actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY"; + actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR"; + actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM"; + actions.renames["RESTART_POSITION"] = "restart_position"; + actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale"; + actions.renames["RESTART_VELOCITY"] = "restart_velocity"; + actions.renames["RESTART_COLOR"] = "restart_color"; + actions.renames["RESTART_CUSTOM"] = "restart_custom"; + actions.renames["emit_particle"] = "emit_particle"; actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; @@ -7075,6 +7441,8 @@ RasterizerStorageRD::RasterizerStorageRD() { particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0); } + default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4); + { Vector<String> copy_modes; copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n"); @@ -7115,6 +7483,8 @@ RasterizerStorageRD::~RasterizerStorageRD() { } giprobe_sdf_shader.version_free(giprobe_sdf_shader_version); + RD::get_singleton()->free(default_rd_storage_buffer); + if (decal_atlas.textures.size()) { ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas."); } diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h index e09b4a52eb..e14b9528cf 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -205,6 +205,14 @@ private: int height_2d; int width_2d; + struct BufferSlice3D { + Size2i size; + uint32_t offset = 0; + uint32_t buffer_size = 0; + }; + Vector<BufferSlice3D> buffer_slices_3d; + uint32_t buffer_size_3d = 0; + bool is_render_target; bool is_proxy; @@ -249,6 +257,7 @@ private: RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + RID default_rd_storage_buffer; /* DECAL ATLAS */ @@ -482,6 +491,25 @@ private: float emission_transform[16]; }; + struct ParticleEmissionBufferData { + }; + + struct ParticleEmissionBuffer { + struct Data { + float xform[16]; + float velocity[3]; + uint32_t flags; + float color[4]; + float custom[4]; + }; + + int32_t particle_count; + int32_t particle_max; + uint32_t pad1; + uint32_t pad2; + Data data[1]; //its 2020 and empty arrays are still non standard in C++ + }; + struct Particles { bool inactive; float inactive_time; @@ -515,6 +543,8 @@ private: bool dirty = false; Particles *update_list = nullptr; + RID sub_emitter; + float phase; float prev_phase; uint64_t prev_ticks; @@ -530,8 +560,15 @@ private: bool clear; + bool force_sub_emit = false; + Transform emission_transform; + Vector<uint8_t> emission_buffer_data; + + ParticleEmissionBuffer *emission_buffer = nullptr; + RID emission_storage_buffer; + Particles() : inactive(true), inactive_time(0.0), @@ -562,6 +599,8 @@ private: }; void _particles_process(Particles *p_particles, float p_delta); + void _particles_allocate_emission_buffer(Particles *particles); + void _particles_free_data(Particles *particles); struct ParticlesShader { struct PushConstant { @@ -569,8 +608,11 @@ private: uint32_t clear; uint32_t total_particles; uint32_t trail_size; + uint32_t use_fractional_delta; - uint32_t pad[3]; + uint32_t sub_emitter_mode; + uint32_t can_emit; + uint32_t pad; }; ParticlesShaderRD shader; @@ -946,14 +988,14 @@ public: virtual RID texture_2d_create(const Ref<Image> &p_image); virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type); - virtual RID texture_3d_create(const Vector<Ref<Image>> &p_slices); //all slices, then all the mipmaps, must be coherent + virtual RID texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data); //all slices, then all the mipmaps, must be coherent virtual RID texture_proxy_create(RID p_base); virtual void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer, bool p_immediate); virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); //mostly used for video and streaming virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0); - virtual void texture_3d_update(RID p_texture, const Ref<Image> &p_image, int p_depth, int p_mipmap); + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data); virtual void texture_proxy_update(RID p_texture, RID p_proxy_to); //these two APIs can be used together or in combination with the others. @@ -963,7 +1005,7 @@ public: virtual Ref<Image> texture_2d_get(RID p_texture) const; virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const; - virtual Ref<Image> texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const; virtual void texture_replace(RID p_texture, RID p_by_texture); virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); @@ -1650,6 +1692,8 @@ public: void particles_set_fixed_fps(RID p_particles, int p_fps); void particles_set_fractional_delta(RID p_particles, bool p_enable); void particles_restart(RID p_particles); + void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); + void particles_set_subemitter(RID p_particles, RID p_subemitter_particles); void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order); diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl index e33b3face9..4a40584e16 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl @@ -101,7 +101,7 @@ void main() { offset += 1; } else { instance_color = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); - offser += 4; + offset += 4; } color *= instance_color; diff --git a/servers/rendering/rasterizer_rd/shaders/particles.glsl b/servers/rendering/rasterizer_rd/shaders/particles.glsl index 7cdedfcbfe..a924509771 100644 --- a/servers/rendering/rasterizer_rd/shaders/particles.glsl +++ b/servers/rendering/rasterizer_rd/shaders/particles.glsl @@ -66,6 +66,38 @@ layout(set = 1, binding = 1, std430) restrict buffer Particles { } particles; +#define EMISSION_FLAG_HAS_POSITION 1 +#define EMISSION_FLAG_HAS_ROTATION_SCALE 2 +#define EMISSION_FLAG_HAS_VELOCITY 4 +#define EMISSION_FLAG_HAS_COLOR 8 +#define EMISSION_FLAG_HAS_CUSTOM 16 + +struct ParticleEmission { + mat4 xform; + vec3 velocity; + uint flags; + vec4 color; + vec4 custom; +}; + +layout(set = 1, binding = 2, std430) restrict volatile coherent buffer SourceEmission { + int particle_count; + uint pad0; + uint pad1; + uint pad2; + ParticleEmission data[]; +} +src_particles; + +layout(set = 1, binding = 3, std430) restrict volatile coherent buffer DestEmission { + int particle_count; + int particle_max; + uint pad1; + uint pad2; + ParticleEmission data[]; +} +dst_particles; + /* SET 2: MATERIAL */ #ifdef USE_MATERIAL_UNIFORMS @@ -82,7 +114,9 @@ layout(push_constant, binding = 0, std430) uniform Params { uint total_particles; uint trail_size; bool use_fractional_delta; - uint pad[3]; + bool sub_emitter_mode; + bool can_emit; + uint pad; } params; @@ -93,6 +127,51 @@ uint hash(uint x) { return x; } +bool emit_particle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom, uint p_flags) { + if (!params.can_emit) { + return false; + } + + bool valid = false; + + int dst_index = atomicAdd(dst_particles.particle_count, 1); + + if (dst_index >= dst_particles.particle_max) { + atomicAdd(dst_particles.particle_count, -1); + return false; + } + /* + valid = true; + + int attempts = 256; // never trust compute + while(attempts-- > 0) { + dst_index = dst_particles.particle_count; + if (dst_index == dst_particles.particle_max) { + return false; //can't emit anymore + } + + if (atomicCompSwap(dst_particles.particle_count, dst_index, dst_index +1 ) != dst_index) { + continue; + } + valid=true; + break; + } + + barrier(); + + if (!valid) { + return false; //gave up (attempts exhausted) + } +*/ + dst_particles.data[dst_index].xform = p_xform; + dst_particles.data[dst_index].velocity = p_velocity; + dst_particles.data[dst_index].color = p_color; + dst_particles.data[dst_index].custom = p_custom; + dst_particles.data[dst_index].flags = p_flags; + + return true; +} + /* clang-format off */ COMPUTE_SHADER_GLOBALS @@ -118,76 +197,129 @@ void main() { float mass = 1.0; - float restart_phase = float(index) / float(params.total_particles); + bool restart = false; - if (FRAME.randomness > 0.0) { - uint seed = FRAME.cycle; - if (restart_phase >= FRAME.system_phase) { - seed -= uint(1); - } - seed *= uint(params.total_particles); - seed += uint(index); - float random = float(hash(seed) % uint(65536)) / 65536.0; - restart_phase += FRAME.randomness * random * 1.0 / float(params.total_particles); + bool restart_position = false; + bool restart_rotation_scale = false; + bool restart_velocity = false; + bool restart_color = false; + bool restart_custom = false; + + if (params.clear) { + PARTICLE.color = vec4(1.0); + PARTICLE.custom = vec4(0.0); + PARTICLE.velocity = vec3(0.0); + PARTICLE.is_active = false; + PARTICLE.xform = mat4( + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); } - restart_phase *= (1.0 - FRAME.explosiveness); + if (params.sub_emitter_mode) { + if (!PARTICLE.is_active) { + int src_index = atomicAdd(src_particles.particle_count, -1) - 1; - bool restart = false; + if (src_index >= 0) { + PARTICLE.is_active = true; + restart = true; - if (FRAME.system_phase > FRAME.prev_system_phase) { - // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_POSITION)) { + PARTICLE.xform[3] = src_particles.data[src_index].xform[3]; + } else { + PARTICLE.xform[3] = vec4(0, 0, 0, 1); + restart_position = true; + } + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_ROTATION_SCALE)) { + PARTICLE.xform[0] = src_particles.data[src_index].xform[0]; + PARTICLE.xform[1] = src_particles.data[src_index].xform[1]; + PARTICLE.xform[2] = src_particles.data[src_index].xform[2]; + } else { + PARTICLE.xform[0] = vec4(1, 0, 0, 0); + PARTICLE.xform[1] = vec4(0, 1, 0, 0); + PARTICLE.xform[2] = vec4(0, 0, 1, 0); + restart_rotation_scale = true; + } + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_VELOCITY)) { + PARTICLE.velocity = src_particles.data[src_index].velocity; + } else { + PARTICLE.velocity = vec3(0); + restart_velocity = true; + } + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_COLOR)) { + PARTICLE.color = src_particles.data[src_index].color; + } else { + PARTICLE.color = vec4(1); + restart_color = true; + } - if (restart_phase >= FRAME.prev_system_phase && restart_phase < FRAME.system_phase) { - restart = true; - if (params.use_fractional_delta) { - local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; + if (bool(src_particles.data[src_index].flags & EMISSION_FLAG_HAS_CUSTOM)) { + PARTICLE.custom = src_particles.data[src_index].custom; + } else { + PARTICLE.custom = vec4(0); + restart_custom = true; + } } } - } else if (FRAME.delta > 0.0) { - if (restart_phase >= FRAME.prev_system_phase) { - restart = true; - if (params.use_fractional_delta) { - local_delta = (1.0 - restart_phase + FRAME.system_phase) * params.lifetime; - } + } else if (FRAME.emitting) { + float restart_phase = float(index) / float(params.total_particles); - } else if (restart_phase < FRAME.system_phase) { - restart = true; - if (params.use_fractional_delta) { - local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; + if (FRAME.randomness > 0.0) { + uint seed = FRAME.cycle; + if (restart_phase >= FRAME.system_phase) { + seed -= uint(1); } + seed *= uint(params.total_particles); + seed += uint(index); + float random = float(hash(seed) % uint(65536)) / 65536.0; + restart_phase += FRAME.randomness * random * 1.0 / float(params.total_particles); } - } - uint current_cycle = FRAME.cycle; + restart_phase *= (1.0 - FRAME.explosiveness); - if (FRAME.system_phase < restart_phase) { - current_cycle -= uint(1); - } + if (FRAME.system_phase > FRAME.prev_system_phase) { + // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed - uint particle_number = current_cycle * uint(params.total_particles) + particle; + if (restart_phase >= FRAME.prev_system_phase && restart_phase < FRAME.system_phase) { + restart = true; + if (params.use_fractional_delta) { + local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; + } + } - if (restart) { - PARTICLE.is_active = FRAME.emitting; - } + } else if (FRAME.delta > 0.0) { + if (restart_phase >= FRAME.prev_system_phase) { + restart = true; + if (params.use_fractional_delta) { + local_delta = (1.0 - restart_phase + FRAME.system_phase) * params.lifetime; + } -#ifdef ENABLE_KEEP_DATA - if (params.clear) { -#else - if (params.clear || restart) { -#endif - PARTICLE.color = vec4(1.0); - PARTICLE.custom = vec4(0.0); - PARTICLE.velocity = vec3(0.0); - if (!restart) { - PARTICLE.is_active = false; + } else if (restart_phase < FRAME.system_phase) { + restart = true; + if (params.use_fractional_delta) { + local_delta = (FRAME.system_phase - restart_phase) * params.lifetime; + } + } + } + + uint current_cycle = FRAME.cycle; + + if (FRAME.system_phase < restart_phase) { + current_cycle -= uint(1); + } + + uint particle_number = current_cycle * uint(params.total_particles) + particle; + + if (restart) { + PARTICLE.is_active = FRAME.emitting; + restart_position = true; + restart_rotation_scale = true; + restart_velocity = true; + restart_color = true; + restart_custom = true; } - PARTICLE.xform = mat4( - vec4(1.0, 0.0, 0.0, 0.0), - vec4(0.0, 1.0, 0.0, 0.0), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(0.0, 0.0, 0.0, 1.0)); } if (PARTICLE.is_active) { diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl index 5993e68317..e11f3983c5 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -681,9 +681,13 @@ LIGHT_SHADER_CODE #ifndef USE_NO_SHADOWS -// Produces cheap but low-quality white noise, nothing special +// Produces cheap white noise, optimized for window-space +// Comes from: https://www.shadertoy.com/view/4djSRW +// Copyright: Dave Hoskins, MIT License float quick_hash(vec2 pos) { - return fract(sin(dot(pos * 19.19, vec2(49.5791, 97.413))) * 49831.189237); + vec3 p3 = fract(vec3(pos.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); } float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl index 66bfefbe89..0cc2b90c53 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -252,7 +252,7 @@ layout(set = 1, binding = 0) uniform textureCube radiance_cubemap; #endif -/* Set 2, Reflection and Shadow Atlases (view dependant) */ +/* Set 2, Reflection and Shadow Atlases (view dependent) */ layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl index c4b29216d5..61e4bf5e18 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl @@ -22,7 +22,7 @@ dispatch_data; struct ProcessVoxel { uint position; //xyz 7 bit packed, extra 11 bits for neigbours uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours - uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours //total neighbours: 26 }; diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl index 1ec471d204..d516ab22c3 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl @@ -336,7 +336,7 @@ void main() { #ifdef MODE_STORE - // converting to octahedral in this step is requiered because + // converting to octahedral in this step is required because // octahedral is much faster to read from the screen than spherical harmonics, // despite the very slight quality loss @@ -512,7 +512,7 @@ void main() { imageStore(lightprobe_average_scroll_texture, dst_pos, value); } } else if (params.cascade < params.max_cascades - 1) { - //cant scroll, must look for position in parent cascade + //can't scroll, must look for position in parent cascade //to global coords float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl index dd0ca5c506..916c60ac89 100644 --- a/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl @@ -103,7 +103,7 @@ dispatch_data; struct ProcessVoxel { uint position; //xyz 7 bit packed, extra 11 bits for neigbours uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours - uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours //total neighbours: 26 }; @@ -136,7 +136,7 @@ dispatch_data; struct ProcessVoxel { uint position; //xyz 7 bit packed, extra 11 bits for neigbours uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours - uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours //total neighbours: 26 }; @@ -274,7 +274,7 @@ void main() { #ifdef MODE_JUMPFLOOD - //regular jumpflood, efficent for large steps, inefficient for small steps + //regular jumpflood, efficient for large steps, inefficient for small steps ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); vec3 posf = vec3(pos); diff --git a/servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl b/servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl index cb19fb0b69..13b162f0c9 100644 --- a/servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/rasterizer_rd/shaders/volumetric_fog.glsl @@ -485,7 +485,7 @@ void main() { //get depth at cell pos float z = get_depth_at_pos(fog_cell_size.z, i); - //get distance from previos pos + //get distance from previous pos float d = abs(prev_z - z); //compute exinction based on beer's float extinction = t * exp(-d * fog.a); diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp index 5c0741bb3b..07eabfd430 100644 --- a/servers/rendering/rendering_server_canvas.cpp +++ b/servers/rendering/rendering_server_canvas.cpp @@ -900,13 +900,12 @@ void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skelet void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); - if (bool(canvas_item->copy_back_buffer != nullptr) != p_enable) { - if (p_enable) { - canvas_item->copy_back_buffer = memnew(RasterizerCanvas::Item::CopyBackBuffer); - } else { - memdelete(canvas_item->copy_back_buffer); - canvas_item->copy_back_buffer = nullptr; - } + if (p_enable && (canvas_item->copy_back_buffer == nullptr)) { + canvas_item->copy_back_buffer = memnew(RasterizerCanvas::Item::CopyBackBuffer); + } + if (!p_enable && (canvas_item->copy_back_buffer != nullptr)) { + memdelete(canvas_item->copy_back_buffer); + canvas_item->copy_back_buffer = nullptr; } if (p_enable) { diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 547595f9b0..b554425bef 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -114,6 +114,14 @@ public: m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } #define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } +#define BIND5R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); } +#define BIND5RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); } +#define BIND6R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } +#define BIND6RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } #define BIND0(m_name) \ void m_name() { DISPLAY_CHANGED BINDBASE->m_name(); } @@ -160,14 +168,14 @@ public: //these go pass-through, as they can be called from any thread BIND1R(RID, texture_2d_create, const Ref<Image> &) BIND2R(RID, texture_2d_layered_create, const Vector<Ref<Image>> &, TextureLayeredType) - BIND1R(RID, texture_3d_create, const Vector<Ref<Image>> &) + BIND6R(RID, texture_3d_create, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &) BIND1R(RID, texture_proxy_create, RID) //goes pass-through BIND3(texture_2d_update_immediate, RID, const Ref<Image> &, int) //these go through command queue if they are in another thread BIND3(texture_2d_update, RID, const Ref<Image> &, int) - BIND4(texture_3d_update, RID, const Ref<Image> &, int, int) + BIND2(texture_3d_update, RID, const Vector<Ref<Image>> &) BIND2(texture_proxy_update, RID, RID) //these also go pass-through @@ -177,7 +185,7 @@ public: BIND1RC(Ref<Image>, texture_2d_get, RID) BIND2RC(Ref<Image>, texture_2d_layer_get, RID, int) - BIND3RC(Ref<Image>, texture_3d_slice_get, RID, int, int) + BIND1RC(Vector<Ref<Image>>, texture_3d_get, RID) BIND2(texture_replace, RID, RID) @@ -442,6 +450,8 @@ public: BIND1R(bool, particles_is_inactive, RID) BIND1(particles_request_process, RID) BIND1(particles_restart, RID) + BIND6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t) + BIND2(particles_set_subemitter, RID, RID) BIND2(particles_set_draw_order, RID, RS::ParticlesDrawOrder) diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index 40aff46a3c..372a7269dc 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -79,14 +79,14 @@ public: //these go pass-through, as they can be called from any thread virtual RID texture_2d_create(const Ref<Image> &p_image) { return rendering_server->texture_2d_create(p_image); } virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) { return rendering_server->texture_2d_layered_create(p_layers, p_layered_type); } - virtual RID texture_3d_create(const Vector<Ref<Image>> &p_slices) { return rendering_server->texture_3d_create(p_slices); } + virtual RID texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) { return rendering_server->texture_3d_create(p_format, p_width, p_height, p_depth, p_mipmaps, p_data); } virtual RID texture_proxy_create(RID p_base) { return rendering_server->texture_proxy_create(p_base); } //goes pass-through virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) { rendering_server->texture_2d_update_immediate(p_texture, p_image, p_layer); } //these go through command queue if they are in another thread FUNC3(texture_2d_update, RID, const Ref<Image> &, int) - FUNC4(texture_3d_update, RID, const Ref<Image> &, int, int) + FUNC2(texture_3d_update, RID, const Vector<Ref<Image>> &) FUNC2(texture_proxy_update, RID, RID) //these also go pass-through @@ -96,7 +96,7 @@ public: FUNC1RC(Ref<Image>, texture_2d_get, RID) FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int) - FUNC3RC(Ref<Image>, texture_3d_slice_get, RID, int, int) + FUNC1RC(Vector<Ref<Image>>, texture_3d_get, RID) FUNC2(texture_replace, RID, RID) @@ -360,11 +360,14 @@ public: FUNC1(particles_request_process, RID) FUNC1(particles_restart, RID) + FUNC6(particles_emit, RID, const Transform &, const Vector3 &, const Color &, const Color &, uint32_t) + FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder) FUNC2(particles_set_draw_passes, RID, int) FUNC3(particles_set_draw_pass_mesh, RID, int, RID) FUNC2(particles_set_emission_transform, RID, const Transform &) + FUNC2(particles_set_subemitter, RID, RID) FUNC1R(AABB, particles_get_current_aabb, RID) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index a282f10402..28c41fb2dc 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -33,15 +33,15 @@ #include "core/print_string.h" #include "servers/rendering_server.h" -static bool _is_text_char(CharType c) { +static bool _is_text_char(char32_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; } -static bool _is_number(CharType c) { +static bool _is_number(char32_t c) { return (c >= '0' && c <= '9'); } -static bool _is_hex(CharType c) { +static bool _is_hex(char32_t c) { return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } @@ -334,7 +334,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { }; ShaderLanguage::Token ShaderLanguage::_get_token() { -#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : CharType(0)) +#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : char32_t(0)) while (true) { char_idx++; @@ -582,11 +582,11 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { break; } - str += CharType(GETCHAR(i)); + str += char32_t(GETCHAR(i)); i++; } - CharType last_char = str[str.length() - 1]; + char32_t last_char = str[str.length() - 1]; if (hexa_found) { //integer(hex) @@ -663,7 +663,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { String str; while (_is_text_char(GETCHAR(0))) { - str += CharType(GETCHAR(0)); + str += char32_t(GETCHAR(0)); char_idx++; } @@ -920,13 +920,13 @@ void ShaderLanguage::clear() { } } -bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) { - if (p_builtin_types.has(p_identifier)) { +bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) { + if (p_function_info.built_ins.has(p_identifier)) { if (r_data_type) { - *r_data_type = p_builtin_types[p_identifier].type; + *r_data_type = p_function_info.built_ins[p_identifier].type; } if (r_is_const) { - *r_is_const = p_builtin_types[p_identifier].constant; + *r_is_const = p_function_info.built_ins[p_identifier].constant; } if (r_type) { *r_type = IDENTIFIER_BUILTIN_VAR; @@ -935,6 +935,20 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea return true; } + if (p_function_info.stage_functions.has(p_identifier)) { + if (r_data_type) { + *r_data_type = p_function_info.stage_functions[p_identifier].return_type; + } + if (r_is_const) { + *r_is_const = true; + } + if (r_type) { + *r_type = IDENTIFIER_FUNCTION; + } + + return true; + } + FunctionNode *function = nullptr; while (p_block) { @@ -2152,7 +2166,7 @@ const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] { nullptr, 0 } }; -bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) { +bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) { ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false); Vector<DataType> args; @@ -2169,6 +2183,30 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin int argcount = args.size(); + if (p_function_info.stage_functions.has(name)) { + //stage based function + const StageFunctionInfo &sf = p_function_info.stage_functions[name]; + if (argcount != sf.arguments.size()) { + _set_error(vformat("Invalid number of arguments when calling stage function '%s', which expects %d arguments.", String(name), sf.arguments.size())); + return false; + } + //validate arguments + for (int i = 0; i < argcount; i++) { + if (args[i] != sf.arguments[i].type) { + _set_error(vformat("Invalid argument type when calling stage function '%s', type expected is '%s'.", String(name), String(get_datatype_name(sf.arguments[i].type)))); + return false; + } + } + + if (r_ret_type) { + *r_ret_type = sf.return_type; + } + if (r_ret_type_str) { + *r_ret_type_str = ""; + } + return true; + } + bool failed_builtin = false; bool unsupported_builtin = false; int builtin_idx = 0; @@ -2241,8 +2279,8 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin if (shader->uniforms.has(varname)) { fail = true; } else { - if (p_builtin_types.has(varname)) { - BuiltInInfo info = p_builtin_types[varname]; + if (p_function_info.built_ins.has(varname)) { + BuiltInInfo info = p_function_info.built_ins[varname]; if (info.constant) { fail = true; } @@ -2278,7 +2316,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin const BlockNode *b = p_block; bool valid = false; while (b) { - if (b->variables.has(var_name) || p_builtin_types.has(var_name)) { + if (b->variables.has(var_name) || p_function_info.built_ins.has(var_name)) { valid = true; break; } @@ -2353,10 +2391,13 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin err += ","; } - if (p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && p_func->arguments[i + 1]->get_datatype() == TYPE_INT && static_cast<ConstantNode *>(p_func->arguments[i + 1])->values[0].sint < 0) { - err += "-"; + String arg_name; + if (args[i] == TYPE_STRUCT) { + arg_name = args2[i]; + } else { + arg_name = get_datatype_name(args[i]); } - err += get_datatype_name(args[i]); + err += arg_name; } err += ")"; _set_error(err); @@ -2380,6 +2421,9 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin return false; } + int last_arg_count = 0; + String arg_list = ""; + for (int i = 0; i < shader->functions.size(); i++) { if (name != shader->functions[i].name) { continue; @@ -2391,21 +2435,45 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin } FunctionNode *pfunc = shader->functions[i].function; + if (arg_list == "") { + for (int j = 0; j < pfunc->arguments.size(); j++) { + if (j > 0) { + arg_list += ", "; + } + String func_arg_name; + if (pfunc->arguments[j].type == TYPE_STRUCT) { + func_arg_name = pfunc->arguments[j].type_str; + } else { + func_arg_name = get_datatype_name(pfunc->arguments[j].type); + } + arg_list += func_arg_name; + } + } if (pfunc->arguments.size() != args.size()) { + last_arg_count = pfunc->arguments.size(); continue; } bool fail = false; for (int j = 0; j < args.size(); j++) { - if (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) { - fail = true; - break; - } if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode *>(p_func->arguments[j + 1]), pfunc->arguments[j].type)) { //all good, but it needs implicit conversion later - } else if (args[j] != pfunc->arguments[j].type) { + } else if (args[j] != pfunc->arguments[j].type || (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str)) { + String func_arg_name; + if (pfunc->arguments[j].type == TYPE_STRUCT) { + func_arg_name = pfunc->arguments[j].type_str; + } else { + func_arg_name = get_datatype_name(pfunc->arguments[j].type); + } + String arg_name; + if (args[j] == TYPE_STRUCT) { + arg_name = args2[j]; + } else { + arg_name = get_datatype_name(args[j]); + } + _set_error(vformat("Invalid argument for \"%s(%s)\" function: argument %s should be %s but is %s.", String(name), arg_list, j + 1, func_arg_name, arg_name)); fail = true; break; } @@ -2441,6 +2509,12 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map<Strin } } + if (last_arg_count > args.size()) { + _set_error(vformat("Too few arguments for \"%s(%s)\" call. Expected at least %s but received %s.", String(name), arg_list, last_arg_count, args.size())); + } else if (last_arg_count < args.size()) { + _set_error(vformat("Too many arguments for \"%s(%s)\" call. Expected at most %s but received %s.", String(name), arg_list, last_arg_count, args.size())); + } + return false; } @@ -2456,7 +2530,7 @@ bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const { return true; } -bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) { +bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg) { TkPos pos = _get_tkpos(); Token tk = _get_token(); @@ -2478,7 +2552,7 @@ bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map<Str } } - Node *arg = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *arg = _parse_and_reduce_expression(p_block, p_function_info); if (!arg) { return false; @@ -3017,16 +3091,16 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const { return false; } -bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message) { +bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message) { if (p_node->type == Node::TYPE_OPERATOR) { OperatorNode *op = static_cast<OperatorNode *>(p_node); if (op->op == OP_INDEX) { - return _validate_assign(op->arguments[0], p_builtin_types, r_message); + return _validate_assign(op->arguments[0], p_function_info, r_message); } else if (_is_operator_assign(op->op)) { //chained assignment - return _validate_assign(op->arguments[1], p_builtin_types, r_message); + return _validate_assign(op->arguments[1], p_function_info, r_message); } else if (op->op == OP_CALL) { if (r_message) { @@ -3045,7 +3119,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI return false; } - return _validate_assign(member->owner, p_builtin_types, r_message); + return _validate_assign(member->owner, p_function_info, r_message); } else if (p_node->type == Node::TYPE_VARIABLE) { VariableNode *var = static_cast<VariableNode *>(p_node); @@ -3071,7 +3145,7 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const Map<StringName, BuiltI return false; } - if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) { + if (!(p_function_info.built_ins.has(var->name) && p_function_info.built_ins[var->name].constant)) { return true; } } else if (p_node->type == Node::TYPE_ARRAY) { @@ -3168,7 +3242,7 @@ bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringNa ERR_FAIL_V(false); //bug? function not found } -ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) { +ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info) { Vector<Expression> expression; //Vector<TokenType> operators; @@ -3184,7 +3258,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_PARENTHESIS_OPEN) { //handle subexpression - expr = _parse_and_reduce_expression(p_block, p_builtin_types); + expr = _parse_and_reduce_expression(p_block, p_function_info); if (!expr) { return nullptr; } @@ -3257,7 +3331,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons int carg = -1; - bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); + bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg); if (carg >= 0) { completion_type = COMPLETION_CALL_ARGUMENTS; @@ -3271,7 +3345,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } - if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) { + if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) { _set_error("No matching constructor found for: '" + String(funcname->name) + "'"); return nullptr; } @@ -3347,7 +3421,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else { _set_tkpos(pos2); - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return nullptr; @@ -3408,7 +3482,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { return nullptr; } @@ -3448,7 +3522,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons nexpr = an; } else { - nexpr = _parse_and_reduce_expression(p_block, p_builtin_types); + nexpr = _parse_and_reduce_expression(p_block, p_function_info); if (!nexpr) { return nullptr; } @@ -3490,7 +3564,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons int carg = -1; - bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); + bool ok = _parse_function_arguments(p_block, p_function_info, func, &carg); // Check if block has a variable with the same name as function to prevent shader crash. ShaderLanguage::BlockNode *bnode = p_block; @@ -3532,7 +3606,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } - if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) { + if (!_validate_function_call(p_block, p_function_info, func, &func->return_cache, &func->struct_name)) { _set_error("No matching function found for: '" + String(funcname->name) + "'"); return nullptr; } @@ -3584,8 +3658,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons } else if (shader->uniforms.has(varname)) { error = true; } else { - if (p_builtin_types.has(varname)) { - BuiltInInfo info = p_builtin_types[varname]; + if (p_function_info.built_ins.has(varname)) { + BuiltInInfo info = p_function_info.built_ins[varname]; if (info.constant) { error = true; } @@ -3617,7 +3691,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat)) { return nullptr; } - } else if (p_builtin_types.has(varname)) { + } else if (p_function_info.built_ins.has(varname)) { //a built-in if (!_propagate_function_call_sampler_builtin_reference(name, i, varname)) { return nullptr; @@ -3672,7 +3746,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } } else { - if (!_find_identifier(p_block, false, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { + if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { _set_error("Unknown identifier in expression: " + String(identifier)); return nullptr; } @@ -3697,7 +3771,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (tk.type == TK_PERIOD) { completion_class = TAG_ARRAY; p_block->block_tag = SubClassTag::TAG_ARRAY; - call_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + call_expression = _parse_and_reduce_expression(p_block, p_function_info); p_block->block_tag = SubClassTag::TAG_GLOBAL; if (!call_expression) { return nullptr; @@ -3705,7 +3779,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons data_type = call_expression->get_datatype(); } else { // indexing - index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + index_expression = _parse_and_reduce_expression(p_block, p_function_info); if (!index_expression) { return nullptr; } @@ -3869,7 +3943,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } - const CharType *c = ident.ptr(); + const char32_t *c = ident.ptr(); for (int i = 0; i < l; i++) { switch (c[i]) { case 'r': @@ -3933,7 +4007,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } - const CharType *c = ident.ptr(); + const char32_t *c = ident.ptr(); for (int i = 0; i < l; i++) { switch (c[i]) { case 'r': @@ -4000,7 +4074,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons break; } - const CharType *c = ident.ptr(); + const char32_t *c = ident.ptr(); for (int i = 0; i < l; i++) { switch (c[i]) { case 'r': @@ -4085,7 +4159,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons _set_error("Nested array length() is not yet implemented"); return nullptr; } else if (tk.type == TK_BRACKET_OPEN) { - Node *index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *index_expression = _parse_and_reduce_expression(p_block, p_function_info); if (!index_expression) { return nullptr; } @@ -4134,7 +4208,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons */ } else if (tk.type == TK_BRACKET_OPEN) { - Node *index = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *index = _parse_and_reduce_expression(p_block, p_function_info); if (!index) { return nullptr; } @@ -4276,7 +4350,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons return nullptr; } - if (!_validate_assign(expr, p_builtin_types)) { + if (!_validate_assign(expr, p_function_info)) { _set_error("Invalid use of increment/decrement operator in constant expression."); return nullptr; } @@ -4574,7 +4648,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons for (int i = expr_pos - 1; i >= next_op; i--) { OperatorNode *op = alloc_node<OperatorNode>(); op->op = expression[i].op; - if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) { + if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_function_info)) { _set_error("Can't use increment/decrement operator in constant expression."); return nullptr; } @@ -4648,7 +4722,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons if (_is_operator_assign(op->op)) { String assign_message; - if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) { + if (!_validate_assign(expression[next_op - 1].node, p_function_info, &assign_message)) { _set_error(assign_message); return nullptr; } @@ -4802,8 +4876,8 @@ ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, Sha return p_node; } -ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types) { - ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types); +ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info) { + ShaderLanguage::Node *expr = _parse_expression(p_block, p_function_info); if (!expr) { //errored return nullptr; } @@ -4813,7 +4887,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_ return expr; } -Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) { +Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one, bool p_can_break, bool p_can_continue) { while (true) { TkPos pos = _get_tkpos(); @@ -4897,7 +4971,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui StringName name = tk.text; ShaderLanguage::IdentifierType itype; - if (_find_identifier(p_block, true, p_builtin_types, name, (ShaderLanguage::DataType *)nullptr, &itype)) { + if (_find_identifier(p_block, true, p_function_info, name, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; @@ -5016,7 +5090,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } else { _set_tkpos(pos2); - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return ERR_PARSE_ERROR; @@ -5097,7 +5171,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5169,7 +5243,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui decl.initializer = nullptr; //variable created with assignment! must parse an expression - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5229,7 +5303,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui //a sub block, just because.. BlockNode *block = alloc_node<BlockNode>(); block->parent_block = p_block; - if (_parse_block(block, p_builtin_types, false, p_can_break, p_can_continue) != OK) { + if (_parse_block(block, p_function_info, false, p_can_break, p_can_continue) != OK) { return ERR_PARSE_ERROR; } p_block->statements.push_back(block); @@ -5243,7 +5317,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui ControlFlowNode *cf = alloc_node<ControlFlowNode>(); cf->flow_op = FLOW_OP_IF; - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5265,7 +5339,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); + Error err = _parse_block(block, p_function_info, true, p_can_break, p_can_continue); if (err) { return err; } @@ -5276,7 +5350,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui block = alloc_node<BlockNode>(); block->parent_block = p_block; cf->blocks.push_back(block); - err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); + err = _parse_block(block, p_function_info, true, p_can_break, p_can_continue); } else { _set_tkpos(pos); //rollback @@ -5295,7 +5369,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } ControlFlowNode *cf = alloc_node<ControlFlowNode>(); cf->flow_op = FLOW_OP_SWITCH; - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5323,7 +5397,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui int prev_type = TK_CF_CASE; while (true) { // Go-through multiple cases. - if (_parse_block(switch_block, p_builtin_types, true, true, false) != OK) { + if (_parse_block(switch_block, p_function_info, true, true, false) != OK) { return ERR_PARSE_ERROR; } pos = _get_tkpos(); @@ -5424,7 +5498,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui cf->blocks.push_back(case_block); p_block->statements.push_back(cf); - Error err = _parse_block(case_block, p_builtin_types, false, true, false); + Error err = _parse_block(case_block, p_function_info, false, true, false); if (err) { return err; } @@ -5458,7 +5532,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui cf->blocks.push_back(default_block); p_block->statements.push_back(cf); - Error err = _parse_block(default_block, p_builtin_types, false, true, false); + Error err = _parse_block(default_block, p_function_info, false, true, false); if (err) { return err; } @@ -5475,7 +5549,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui do_block = alloc_node<BlockNode>(); do_block->parent_block = p_block; - Error err = _parse_block(do_block, p_builtin_types, true, true, true); + Error err = _parse_block(do_block, p_function_info, true, true, true); if (err) { return err; } @@ -5499,7 +5573,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } else { cf->flow_op = FLOW_OP_WHILE; } - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(p_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5516,7 +5590,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_builtin_types, true, true, true); + Error err = _parse_block(block, p_function_info, true, true, true); if (err) { return err; } @@ -5547,11 +5621,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui init_block->parent_block = p_block; init_block->single_statement = true; cf->blocks.push_back(init_block); - if (_parse_block(init_block, p_builtin_types, true, false, false) != OK) { + if (_parse_block(init_block, p_function_info, true, false, false) != OK) { return ERR_PARSE_ERROR; } - Node *n = _parse_and_reduce_expression(init_block, p_builtin_types); + Node *n = _parse_and_reduce_expression(init_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5569,7 +5643,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui cf->expressions.push_back(n); - n = _parse_and_reduce_expression(init_block, p_builtin_types); + n = _parse_and_reduce_expression(init_block, p_function_info); if (!n) { return ERR_PARSE_ERROR; } @@ -5587,7 +5661,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui cf->blocks.push_back(block); p_block->statements.push_back(cf); - Error err = _parse_block(block, p_builtin_types, true, true, true); + Error err = _parse_block(block, p_function_info, true, true, true); if (err) { return err; } @@ -5623,7 +5697,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } } else { _set_tkpos(pos); //rollback, wants expression - Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *expr = _parse_and_reduce_expression(p_block, p_function_info); if (!expr) { return ERR_PARSE_ERROR; } @@ -5725,7 +5799,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } else { //nothing else, so expression _set_tkpos(pos); //rollback - Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); + Node *expr = _parse_and_reduce_expression(p_block, p_function_info); if (!expr) { return ERR_PARSE_ERROR; } @@ -6066,7 +6140,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct name = tk.text; - if (_find_identifier(nullptr, false, Map<StringName, BuiltInInfo>(), name)) { + if (_find_identifier(nullptr, false, FunctionInfo(), name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -6315,7 +6389,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct //reset scope for next uniform if (tk.type == TK_OP_ASSIGN) { - Node *expr = _parse_and_reduce_expression(nullptr, Map<StringName, BuiltInInfo>()); + Node *expr = _parse_and_reduce_expression(nullptr, FunctionInfo()); if (!expr) { return ERR_PARSE_ERROR; } @@ -6440,7 +6514,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } - if (_find_identifier(nullptr, false, Map<StringName, BuiltInInfo>(), name)) { + if (_find_identifier(nullptr, false, FunctionInfo(), name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -6553,7 +6627,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } else { _set_tkpos(pos2); - Node *n = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + Node *n = _parse_and_reduce_expression(NULL, FunctionInfo()); if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { _set_error("Expected single integer constant > 0"); return ERR_PARSE_ERROR; @@ -6634,7 +6708,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization while (true) { - Node *n = _parse_and_reduce_expression(NULL, Map<StringName, BuiltInInfo>()); + Node *n = _parse_and_reduce_expression(NULL, FunctionInfo()); if (!n) { return ERR_PARSE_ERROR; } @@ -6689,7 +6763,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct 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>()); + Node *expr = _parse_and_reduce_expression(NULL, FunctionInfo()); if (!expr) return ERR_PARSE_ERROR; if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { @@ -6726,7 +6800,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } name = tk.text; - if (_find_identifier(nullptr, false, Map<StringName, BuiltInInfo>(), name)) { + if (_find_identifier(nullptr, false, FunctionInfo(), name)) { _set_error("Redefinition of '" + String(name) + "'"); return ERR_PARSE_ERROR; } @@ -6749,14 +6823,14 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct break; } - Map<StringName, BuiltInInfo> builtin_types; + FunctionInfo builtins; if (p_functions.has(name)) { - builtin_types = p_functions[name].built_ins; + builtins = p_functions[name]; } if (p_functions.has("global")) { // Adds global variables: 'TIME' for (Map<StringName, BuiltInInfo>::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) { - builtin_types.insert(E->key(), E->value()); + builtins.built_ins.insert(E->key(), E->value()); } } @@ -6879,7 +6953,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct pname = tk.text; ShaderLanguage::IdentifierType itype; - if (_find_identifier(func_node->body, false, builtin_types, pname, (ShaderLanguage::DataType *)nullptr, &itype)) { + if (_find_identifier(func_node->body, false, builtins, pname, (ShaderLanguage::DataType *)nullptr, &itype)) { if (itype != IDENTIFIER_FUNCTION) { _set_error("Redefinition of '" + String(pname) + "'"); return ERR_PARSE_ERROR; @@ -6941,7 +7015,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct current_function = name; - Error err = _parse_block(func_node->body, builtin_types); + Error err = _parse_block(func_node->body, builtins); if (err) { return err; } @@ -7039,7 +7113,7 @@ Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperat static int _get_first_ident_pos(const String &p_code) { int idx = 0; -#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0)) +#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : char32_t(0)) while (true) { if (GETCHAR(0) == '/' && GETCHAR(1) == '/') { @@ -7300,7 +7374,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } if (j == completion_argument) { - calltip += CharType(0xFFFF); + calltip += char32_t(0xFFFF); } if (shader->functions[i].function->arguments[j].is_const) { @@ -7320,7 +7394,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct calltip += shader->functions[i].function->arguments[j].name; if (j == completion_argument) { - calltip += CharType(0xFFFF); + calltip += char32_t(0xFFFF); } } @@ -7383,7 +7457,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct } if (i == completion_argument) { - calltip += CharType(0xFFFF); + calltip += char32_t(0xFFFF); } if (out_arg >= 0 && i == out_arg) { @@ -7393,7 +7467,7 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct calltip += get_datatype_name(builtin_func_defs[idx].args[i]); if (i == completion_argument) { - calltip += CharType(0xFFFF); + calltip += char32_t(0xFFFF); } found_arg = true; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index faf06a9a85..0d044a21c7 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -730,8 +730,25 @@ public: constant(p_constant) {} }; + struct StageFunctionInfo { + struct Argument { + StringName name; + DataType type; + + Argument(const StringName &p_name = StringName(), DataType p_type = TYPE_VOID) { + name = p_name; + type = p_type; + } + }; + + Vector<Argument> arguments; + DataType return_type = TYPE_VOID; + }; + struct FunctionInfo { Map<StringName, BuiltInInfo> built_ins; + Map<StringName, StageFunctionInfo> stage_functions; + bool can_discard; }; static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name); @@ -802,9 +819,9 @@ private: IDENTIFIER_CONSTANT, }; - bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr); + bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type = nullptr, IdentifierType *r_type = nullptr, bool *r_is_const = nullptr, int *r_array_size = nullptr, StringName *r_struct_name = nullptr); bool _is_operator_assign(Operator p_op) const; - bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = nullptr); + bool _validate_assign(Node *p_node, const FunctionInfo &p_function_info, String *r_message = nullptr); bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = nullptr); struct BuiltinFuncDef { @@ -837,16 +854,16 @@ private: Error _validate_datatype(DataType p_type); bool _compare_datatypes_in_nodes(Node *a, Node *b) const; - bool _validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str); - bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = nullptr); + bool _validate_function_call(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str); + bool _parse_function_arguments(BlockNode *p_block, const FunctionInfo &p_function_info, OperatorNode *p_func, int *r_complete_arg = nullptr); bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat); bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); - Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); + Node *_parse_expression(BlockNode *p_block, const FunctionInfo &p_function_info); ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); - Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types); - Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); + Node *_parse_and_reduce_expression(BlockNode *p_block, const FunctionInfo &p_function_info); + Error _parse_block(BlockNode *p_block, const FunctionInfo &p_function_info, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); String _get_shader_type_list(const Set<String> &p_shader_types) const; String _get_qualifier_str(ArgumentQualifier p_qualifier) const; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 9c4f44b928..ad5cbc9e51 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -145,7 +145,8 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SHADOW_ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["BACKLIGHT"] = constt(ShaderLanguage::TYPE_VEC3); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT); @@ -283,8 +284,29 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_VELOCITY"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_COLOR"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["FLAG_EMIT_CUSTOM"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_POSITION"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_ROT_SCALE"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_COLOR"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["compute"].built_ins["RESTART_CUSTOM"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["compute"].can_discard = false; + { + ShaderLanguage::StageFunctionInfo emit_vertex_func; + emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("xform", ShaderLanguage::TYPE_MAT4)); + emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("velocity", ShaderLanguage::TYPE_VEC3)); + emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("color", ShaderLanguage::TYPE_VEC4)); + emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("custom", ShaderLanguage::TYPE_VEC4)); + emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("flags", ShaderLanguage::TYPE_UINT)); + emit_vertex_func.return_type = ShaderLanguage::TYPE_BOOL; //whether it could emit + shader_modes[RS::SHADER_PARTICLES].functions["compute"].stage_functions["emit_particle"] = emit_vertex_func; + } + shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_force"); shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_velocity"); shader_modes[RS::SHADER_PARTICLES].modes.push_back("keep_data"); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 38b4dec658..49f840948f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -97,12 +97,12 @@ public: virtual RID texture_2d_create(const Ref<Image> &p_image) = 0; virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) = 0; - virtual RID texture_3d_create(const Vector<Ref<Image>> &p_slices) = 0; //all slices, then all the mipmaps, must be coherent + virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; //all slices, then all the mipmaps, must be coherent virtual RID texture_proxy_create(RID p_base) = 0; virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; //mostly used for video and streaming virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Ref<Image> &p_image, int p_depth, int p_mipmap) = 0; + virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) = 0; virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0; //these two APIs can be used together or in combination with the others. @@ -112,7 +112,7 @@ public: virtual Ref<Image> texture_2d_get(RID p_texture) const = 0; virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Ref<Image> texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const = 0; + virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0; virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; @@ -563,7 +563,7 @@ public: virtual RID particles_create() = 0; - virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; + virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0; virtual bool particles_get_emitting(RID p_particles) = 0; virtual void particles_set_amount(RID p_particles, int p_amount) = 0; virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; @@ -581,6 +581,18 @@ public: virtual void particles_request_process(RID p_particles) = 0; virtual void particles_restart(RID p_particles) = 0; + virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0; + + enum ParticlesEmitFlags { + PARTICLES_EMIT_FLAG_POSITION = 1, + PARTICLES_EMIT_FLAG_ROTATION_SCALE = 2, + PARTICLES_EMIT_FLAG_VELOCITY = 4, + PARTICLES_EMIT_FLAG_COLOR = 8, + PARTICLES_EMIT_FLAG_CUSTOM = 16 + }; + + virtual void particles_emit(RID p_particles, const Transform &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0; + enum ParticlesDrawOrder { PARTICLES_DRAW_ORDER_INDEX, PARTICLES_DRAW_ORDER_LIFETIME, @@ -872,7 +884,7 @@ public: ENV_VOLUMETRIC_FOG_SHADOW_FILTER_HIGH, }; - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_lenght, float p_detail_spread, float p_gi_inject, EnvVolumetricFogShadowFilter p_shadow_filter) = 0; + virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, EnvVolumetricFogShadowFilter p_shadow_filter) = 0; virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0; virtual void environment_set_volumetric_fog_directional_shadow_shrink_size(int p_shrink_size) = 0; diff --git a/servers/text_server.h b/servers/text_server.h new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/servers/text_server.h diff --git a/tests/SCsub b/tests/SCsub index a2864d805b..7aab28531d 100644 --- a/tests/SCsub +++ b/tests/SCsub @@ -6,6 +6,10 @@ env.tests_sources = [] env_tests = env.Clone() +# Include GDNative headers. +if env["module_gdnative_enabled"]: + env_tests.Append(CPPPATH=["#modules/gdnative/include"]) + # We must disable the THREAD_LOCAL entirely in doctest to prevent crashes on debugging # Since we link with /MT thread_local is always expired when the header is used # So the debugger crashes the engine and it causes weird errors diff --git a/tests/test_expression.h b/tests/test_expression.h index 85d37d1460..a3d4877d52 100644 --- a/tests/test_expression.h +++ b/tests/test_expression.h @@ -66,7 +66,7 @@ TEST_CASE("[Expression] Integer arithmetic") { "Integer / integer division should parse successfully."); CHECK_MESSAGE( int(expression.execute()) == 2, - "Integer / integer divsion should return the expected result."); + "Integer / integer division should return the expected result."); CHECK_MESSAGE( expression.parse("2 * (6 + 14) / 2 - 5") == OK, @@ -98,21 +98,21 @@ TEST_CASE("[Expression] Floating-point arithmetic") { "Float / integer division should parse successfully."); CHECK_MESSAGE( Math::is_equal_approx(float(expression.execute()), 0.3), - "Float / integer divsion should return the expected result."); + "Float / integer division should return the expected result."); CHECK_MESSAGE( expression.parse("3 / 10.0") == OK, "Basic integer / float division should parse successfully."); CHECK_MESSAGE( Math::is_equal_approx(float(expression.execute()), 0.3), - "Basic integer / float divsion should return the expected result."); + "Basic integer / float division should return the expected result."); CHECK_MESSAGE( expression.parse("3.0 / 10.0") == OK, "Float / float division should parse successfully."); CHECK_MESSAGE( Math::is_equal_approx(float(expression.execute()), 0.3), - "Float / float divsion should return the expected result."); + "Float / float division should return the expected result."); CHECK_MESSAGE( expression.parse("2.5 * (6.0 + 14.25) / 2.0 - 5.12345") == OK, @@ -148,6 +148,20 @@ TEST_CASE("[Expression] Scientific notation") { "The expression should return the expected result."); } +TEST_CASE("[Expression] Underscored numeric literals") { + Expression expression; + + CHECK_MESSAGE( + expression.parse("1_000_000") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + expression.parse("1_000.000") == OK, + "The expression should parse successfully."); + CHECK_MESSAGE( + expression.parse("0xff_99_00") == OK, + "The expression should parse successfully."); +} + TEST_CASE("[Expression] Built-in functions") { Expression expression; diff --git a/tests/test_list.h b/tests/test_list.h new file mode 100644 index 0000000000..7412fbc3c8 --- /dev/null +++ b/tests/test_list.h @@ -0,0 +1,279 @@ +/*************************************************************************/ +/* test_list.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 TEST_LIST_H +#define TEST_LIST_H + +#include "core/list.h" + +#include "tests/test_macros.h" + +namespace TestList { + +static void populate_integers(List<int> &p_list, List<int>::Element *r_elements[], int num_elements) { + p_list.clear(); + for (int i = 0; i < num_elements; ++i) { + List<int>::Element *n = p_list.push_back(i); + r_elements[i] = n; + } +} + +TEST_CASE("[List] Swap adjacent front and back") { + List<int> list; + List<int>::Element *n[2]; + populate_integers(list, n, 2); + + list.swap(list.front(), list.back()); + + CHECK(list.front()->prev() == nullptr); + CHECK(list.front() != list.front()->next()); + + CHECK(list.front() == n[1]); + CHECK(list.back() == n[0]); + + CHECK(list.back()->next() == nullptr); + CHECK(list.back() != list.back()->prev()); +} + +TEST_CASE("[List] Swap first adjacent pair") { + List<int> list; + List<int>::Element *n[4]; + populate_integers(list, n, 4); + + list.swap(n[0], n[1]); + + CHECK(list.front()->prev() == nullptr); + CHECK(list.front() != list.front()->next()); + + CHECK(list.front() == n[1]); + CHECK(list.front()->next() == n[0]); + CHECK(list.back()->prev() == n[2]); + CHECK(list.back() == n[3]); + + CHECK(list.back()->next() == nullptr); + CHECK(list.back() != list.back()->prev()); +} + +TEST_CASE("[List] Swap middle adjacent pair") { + List<int> list; + List<int>::Element *n[4]; + populate_integers(list, n, 4); + + list.swap(n[1], n[2]); + + CHECK(list.front()->prev() == nullptr); + + CHECK(list.front() == n[0]); + CHECK(list.front()->next() == n[2]); + CHECK(list.back()->prev() == n[1]); + CHECK(list.back() == n[3]); + + CHECK(list.back()->next() == nullptr); +} + +TEST_CASE("[List] Swap last adjacent pair") { + List<int> list; + List<int>::Element *n[4]; + populate_integers(list, n, 4); + + list.swap(n[2], n[3]); + + CHECK(list.front()->prev() == nullptr); + + CHECK(list.front() == n[0]); + CHECK(list.front()->next() == n[1]); + CHECK(list.back()->prev() == n[3]); + CHECK(list.back() == n[2]); + + CHECK(list.back()->next() == nullptr); +} + +TEST_CASE("[List] Swap first cross pair") { + List<int> list; + List<int>::Element *n[4]; + populate_integers(list, n, 4); + + list.swap(n[0], n[2]); + + CHECK(list.front()->prev() == nullptr); + + CHECK(list.front() == n[2]); + CHECK(list.front()->next() == n[1]); + CHECK(list.back()->prev() == n[0]); + CHECK(list.back() == n[3]); + + CHECK(list.back()->next() == nullptr); +} + +TEST_CASE("[List] Swap last cross pair") { + List<int> list; + List<int>::Element *n[4]; + populate_integers(list, n, 4); + + list.swap(n[1], n[3]); + + CHECK(list.front()->prev() == nullptr); + + CHECK(list.front() == n[0]); + CHECK(list.front()->next() == n[3]); + CHECK(list.back()->prev() == n[2]); + CHECK(list.back() == n[1]); + + CHECK(list.back()->next() == nullptr); +} + +TEST_CASE("[List] Swap edges") { + List<int> list; + List<int>::Element *n[4]; + populate_integers(list, n, 4); + + list.swap(n[1], n[3]); + + CHECK(list.front()->prev() == nullptr); + + CHECK(list.front() == n[0]); + CHECK(list.front()->next() == n[3]); + CHECK(list.back()->prev() == n[2]); + CHECK(list.back() == n[1]); + + CHECK(list.back()->next() == nullptr); +} + +TEST_CASE("[List] Swap middle (values check)") { + List<String> list; + List<String>::Element *n_str1 = list.push_back("Still"); + List<String>::Element *n_str2 = list.push_back("waiting"); + List<String>::Element *n_str3 = list.push_back("for"); + List<String>::Element *n_str4 = list.push_back("Godot."); + + CHECK(n_str1->get() == "Still"); + CHECK(n_str4->get() == "Godot."); + + CHECK(list.front()->get() == "Still"); + CHECK(list.front()->next()->get() == "waiting"); + CHECK(list.back()->prev()->get() == "for"); + CHECK(list.back()->get() == "Godot."); + + list.swap(n_str2, n_str3); + + CHECK(list.front()->next()->get() == "for"); + CHECK(list.back()->prev()->get() == "waiting"); +} + +TEST_CASE("[List] Swap front and back (values check)") { + List<Variant> list; + Variant str = "Godot"; + List<Variant>::Element *n_str = list.push_back(str); + Variant color = Color(0, 0, 1); + List<Variant>::Element *n_color = list.push_back(color); + + CHECK(list.front()->get() == "Godot"); + CHECK(list.back()->get() == Color(0, 0, 1)); + + list.swap(n_str, n_color); + + CHECK(list.front()->get() == Color(0, 0, 1)); + CHECK(list.back()->get() == "Godot"); +} + +TEST_CASE("[List] Swap adjacent back and front (reverse order of elements)") { + List<int> list; + List<int>::Element *n[2]; + populate_integers(list, n, 2); + + list.swap(n[1], n[0]); + + List<int>::Element *it = list.front(); + while (it) { + List<int>::Element *prev_it = it; + it = it->next(); + if (it == prev_it) { + FAIL_CHECK("Infinite loop detected."); + break; + } + } +} + +static void swap_random(List<int> &p_list, List<int>::Element *r_elements[], size_t p_size, size_t p_iterations) { + Math::seed(0); + + for (size_t test_i = 0; test_i < p_iterations; ++test_i) { + // A and B elements have corresponding indices as values. + const int a_idx = static_cast<int>(Math::rand() % p_size); + const int b_idx = static_cast<int>(Math::rand() % p_size); + List<int>::Element *a = p_list.find(a_idx); // via find. + List<int>::Element *b = r_elements[b_idx]; // via pointer. + + int va = a->get(); + int vb = b->get(); + + p_list.swap(a, b); + + CHECK(va == a->get()); + CHECK(vb == b->get()); + + size_t element_count = 0; + + // Fully traversable after swap? + List<int>::Element *it = p_list.front(); + while (it) { + element_count += 1; + List<int>::Element *prev_it = it; + it = it->next(); + if (it == prev_it) { + FAIL_CHECK("Infinite loop detected."); + break; + } + } + // We should not lose anything in the process. + if (element_count != p_size) { + FAIL_CHECK("Element count mismatch."); + break; + } + } +} + +TEST_CASE("[Stress][List] Swap random 100 elements, 500 iterations.") { + List<int> list; + List<int>::Element *n[100]; + populate_integers(list, n, 100); + swap_random(list, n, 100, 500); +} + +TEST_CASE("[Stress][List] Swap random 10 elements, 1000 iterations.") { + List<int> list; + List<int>::Element *n[10]; + populate_integers(list, n, 10); + swap_random(list, n, 10, 1000); +} + +} // namespace TestList + +#endif // TEST_LIST_H diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 4e172caadb..f0dec22738 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -39,6 +39,7 @@ #include "test_expression.h" #include "test_gradient.h" #include "test_gui.h" +#include "test_list.h" #include "test_math.h" #include "test_oa_hash_map.h" #include "test_ordered_hash_map.h" diff --git a/tests/test_math.cpp b/tests/test_math.cpp index 84a85be2f6..862535b57e 100644 --- a/tests/test_math.cpp +++ b/tests/test_math.cpp @@ -162,7 +162,7 @@ class GetClassAndNamespace { } break; case '\'': case '"': { - CharType begin_str = code[idx]; + char32_t begin_str = code[idx]; idx++; String tk_string = String(); while (true) { @@ -176,13 +176,13 @@ class GetClassAndNamespace { } else if (code[idx] == '\\') { //escaped characters... idx++; - CharType next = code[idx]; + char32_t next = code[idx]; if (next == 0) { error_str = "Unterminated String"; error = true; return TK_ERROR; } - CharType res = 0; + char32_t res = 0; switch (next) { case 'b': @@ -241,7 +241,7 @@ class GetClassAndNamespace { if (code[idx] == '-' || (code[idx] >= '0' && code[idx] <= '9')) { //a number - const CharType *rptr; + const char32_t *rptr; double number = String::to_float(&code[idx], &rptr); idx += (rptr - &code[idx]); value = number; diff --git a/tests/test_shader_lang.cpp b/tests/test_shader_lang.cpp index 34ee3e3210..d363ee22b5 100644 --- a/tests/test_shader_lang.cpp +++ b/tests/test_shader_lang.cpp @@ -325,7 +325,7 @@ MainLoop *test() { String code; while (true) { - CharType c = fa->get_8(); + char32_t c = fa->get_8(); if (fa->eof_reached()) { break; } diff --git a/tests/test_string.h b/tests/test_string.h index 22019a64c6..b041cb2f49 100644 --- a/tests/test_string.h +++ b/tests/test_string.h @@ -48,36 +48,159 @@ namespace TestString { -TEST_CASE("[String] Assign from cstr") { +int u32scmp(const char32_t *l, const char32_t *r) { + for (; *l == *r && *l && *r; l++, r++) + ; + return *l - *r; +} + +TEST_CASE("[String] Assign Latin-1 char string") { String s = "Hello"; - CHECK(wcscmp(s.c_str(), L"Hello") == 0); + CHECK(u32scmp(s.get_data(), U"Hello") == 0); } -TEST_CASE("[String] Assign from string (operator=)") { +TEST_CASE("[String] Assign from Latin-1 char string (operator=)") { String s = "Dolly"; const String &t = s; - CHECK(wcscmp(t.c_str(), L"Dolly") == 0); + CHECK(u32scmp(t.get_data(), U"Dolly") == 0); } -TEST_CASE("[String] Assign from c-string (copycon)") { +TEST_CASE("[String] Assign from Latin-1 char string (copycon)") { String s("Sheep"); - const String &t(s); - CHECK(wcscmp(t.c_str(), L"Sheep") == 0); + const String &t1(s); + CHECK(u32scmp(t1.get_data(), U"Sheep") == 0); + + String t2 = String("Sheep", 3); + CHECK(u32scmp(t2.get_data(), U"She") == 0); } -TEST_CASE("[String] Assign from c-widechar (operator=)") { - String s(L"Give me"); - CHECK(wcscmp(s.c_str(), L"Give me") == 0); +TEST_CASE("[String] Assign from wchar_t string (operator=)") { + String s = L"Give me"; + CHECK(u32scmp(s.get_data(), U"Give me") == 0); } -TEST_CASE("[String] Assign from c-widechar (copycon)") { +TEST_CASE("[String] Assign from wchar_t string (copycon)") { String s(L"Wool"); - CHECK(wcscmp(s.c_str(), L"Wool") == 0); + CHECK(u32scmp(s.get_data(), U"Wool") == 0); +} + +TEST_CASE("[String] Assign from char32_t string (operator=)") { + String s = U"Give me"; + CHECK(u32scmp(s.get_data(), U"Give me") == 0); +} + +TEST_CASE("[String] Assign from char32_t string (copycon)") { + String s(U"Wool"); + CHECK(u32scmp(s.get_data(), U"Wool") == 0); +} + +TEST_CASE("[String] UTF8") { + /* how can i embed UTF in here? */ + static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const uint8_t u8str[] = { 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; + String s = u32str; + bool err = s.parse_utf8(s.utf8().get_data()); + CHECK(!err); + CHECK(s == u32str); + + err = s.parse_utf8((const char *)u8str); + CHECK(!err); + CHECK(s == u32str); + + CharString cs = (const char *)u8str; + CHECK(String::utf8(cs) == s); +} + +TEST_CASE("[String] UTF16") { + /* how can i embed UTF in here? */ + static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const char16_t u16str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 }; + String s = u32str; + bool err = s.parse_utf16(s.utf16().get_data()); + CHECK(!err); + CHECK(s == u32str); + + err = s.parse_utf16(u16str); + CHECK(!err); + CHECK(s == u32str); + + Char16String cs = u16str; + CHECK(String::utf16(cs) == s); +} + +TEST_CASE("[String] UTF8 with BOM") { + /* how can i embed UTF in here? */ + static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const uint8_t u8str[] = { 0xEF, 0xBB, 0xBF, 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; + String s; + bool err = s.parse_utf8((const char *)u8str); + CHECK(!err); + CHECK(s == u32str); + + CharString cs = (const char *)u8str; + CHECK(String::utf8(cs) == s); +} + +TEST_CASE("[String] UTF16 with BOM") { + /* how can i embed UTF in here? */ + static const char32_t u32str[] = { 0x0020, 0x0045, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 }; + static const char16_t u16str[] = { 0xFEFF, 0x0020, 0x0045, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 }; + static const char16_t u16str_swap[] = { 0xFFFE, 0x2000, 0x4500, 0x4A30, 0x0F36, 0x8830, 0x4630, 0x3CD8, 0xA4DF, 0 }; + String s; + bool err = s.parse_utf16(u16str); + CHECK(!err); + CHECK(s == u32str); + + err = s.parse_utf16(u16str_swap); + CHECK(!err); + CHECK(s == u32str); + + Char16String cs = u16str; + CHECK(String::utf16(cs) == s); + + cs = u16str_swap; + CHECK(String::utf16(cs) == s); +} + +TEST_CASE("[String] Invalid UTF8") { + ERR_PRINT_OFF + static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 }; + String s; + bool err = s.parse_utf8((const char *)u8str); + CHECK(err); + CHECK(s == String()); + + CharString cs = (const char *)u8str; + CHECK(String::utf8(cs) == String()); + ERR_PRINT_ON +} + +TEST_CASE("[String] Invalid UTF16") { + ERR_PRINT_OFF + static const char16_t u16str[] = { 0x0045, 0x304A, 0x3088, 0x3046, 0xDFA4, 0 }; + String s; + bool err = s.parse_utf16(u16str); + CHECK(err); + CHECK(s == String()); + + Char16String cs = u16str; + CHECK(String::utf16(cs) == String()); + ERR_PRINT_ON +} + +TEST_CASE("[String] ASCII") { + String s = U"Primero Leche"; + String t = s.ascii(false).get_data(); + CHECK(s == t); + + t = s.ascii(true).get_data(); + CHECK(s == t); } TEST_CASE("[String] Comparisons (equal)") { String s = "Test Compare"; CHECK(s == "Test Compare"); + CHECK(s == U"Test Compare"); CHECK(s == L"Test Compare"); CHECK(s == String("Test Compare")); } @@ -85,6 +208,7 @@ TEST_CASE("[String] Comparisons (equal)") { TEST_CASE("[String] Comparisons (not equal)") { String s = "Test Compare"; CHECK(s != "Peanut"); + CHECK(s != U"Coconut"); CHECK(s != L"Coconut"); CHECK(s != String("Butter")); } @@ -92,6 +216,7 @@ TEST_CASE("[String] Comparisons (not equal)") { TEST_CASE("[String] Comparisons (operator <)") { String s = "Bees"; CHECK(s < "Elephant"); + CHECK(!(s < U"Amber")); CHECK(!(s < L"Amber")); CHECK(!(s < String("Beatrix"))); } @@ -103,7 +228,7 @@ TEST_CASE("[String] Concatenation") { s += ' '; s += 'a'; s += String(" "); - s = s + L"Nice"; + s = s + U"Nice"; s = s + " "; s = s + String("Day"); @@ -130,34 +255,49 @@ TEST_CASE("[String] Testing for empty string") { CHECK(String("").empty()); } +TEST_CASE("[String] Test chr") { + CHECK(String::chr('H') == "H"); + CHECK(String::chr(0x3012)[0] == 0x3012); + ERR_PRINT_OFF + CHECK(String::chr(0xd812)[0] == 0xfffd); // Unpaired UTF-16 surrogate + CHECK(String::chr(0x20d812)[0] == 0xfffd); // Outside UTF-32 range + ERR_PRINT_ON +} + TEST_CASE("[String] Operator []") { String a = "Kugar Sane"; a[0] = 'S'; a[6] = 'C'; CHECK(a == "Sugar Cane"); CHECK(a[1] == 'u'); + CHECK(a.ord_at(1) == 'u'); } TEST_CASE("[String] Case function test") { String a = "MoMoNgA"; CHECK(a.to_upper() == "MOMONGA"); + CHECK(a.to_lower() == "momonga"); +} + +TEST_CASE("[String] Case compare function test") { + String a = "MoMoNgA"; + + CHECK(a.casecmp_to("momonga") != 0); CHECK(a.nocasecmp_to("momonga") == 0); } -TEST_CASE("[String] UTF8") { - /* how can i embed UTF in here? */ - static const CharType ustr[] = { 0x304A, 0x360F, 0x3088, 0x3046, 0 }; - //static const wchar_t ustr[] = { 'P', 0xCE, 'p',0xD3, 0 }; - String s = ustr; - s.parse_utf8(s.utf8().get_data()); - CHECK(s == ustr); +TEST_CASE("[String] Natural compare function test") { + String a = "img2.png"; + + CHECK(a.nocasecmp_to("img10.png") > 0); + CHECK(a.naturalnocasecmp_to("img10.png") < 0); } -TEST_CASE("[String] ASCII") { - String s = L"Primero Leche"; - String t = s.ascii().get_data(); - CHECK(s == t); +TEST_CASE("[String] hex_encode_buffer") { + static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3 }; + String s = String::hex_encode_buffer(u8str, 6); + CHECK(s == U"45e3818a8fe3"); } TEST_CASE("[String] Substr") { @@ -165,24 +305,45 @@ TEST_CASE("[String] Substr") { CHECK(s.substr(3, 4) == "ler "); } -TEST_CASE("[string] Find") { - String s = "Pretty Woman"; - s.find("Revenge of the Monster Truck"); - +TEST_CASE("[String] Find") { + String s = "Pretty Woman Woman"; CHECK(s.find("tty") == 3); + CHECK(s.find("Wo", 9) == 13); CHECK(s.find("Revenge of the Monster Truck") == -1); + CHECK(s.rfind("man") == 15); } -TEST_CASE("[String] find no case") { - String s = "Pretty Whale"; +TEST_CASE("[String] Find no case") { + String s = "Pretty Whale Whale"; CHECK(s.findn("WHA") == 7); + CHECK(s.findn("WHA", 9) == 13); CHECK(s.findn("Revenge of the Monster SawFish") == -1); + CHECK(s.rfindn("WHA") == 13); +} + +TEST_CASE("[String] Find MK") { + Vector<String> keys; + keys.push_back("sty"); + keys.push_back("tty"); + keys.push_back("man"); + + String s = "Pretty Woman"; + int key = 0; + + CHECK(s.findmk(keys, 0, &key) == 3); + CHECK(key == 1); + + CHECK(s.findmk(keys, 5, &key) == 9); + CHECK(key == 2); } TEST_CASE("[String] Find and replace") { String s = "Happy Birthday, Anna!"; s = s.replace("Birthday", "Halloween"); CHECK(s == "Happy Halloween, Anna!"); + + s = s.replace_first("H", "W"); + CHECK(s == "Wappy Halloween, Anna!"); } TEST_CASE("[String] Insertion") { @@ -193,6 +354,12 @@ TEST_CASE("[String] Insertion") { TEST_CASE("[String] Number to string") { CHECK(String::num(3.141593) == "3.141593"); + CHECK(String::num(3.141593, 3) == "3.142"); + CHECK(String::num_real(3.141593) == "3.141593"); + CHECK(String::num_scientific(30000000) == "3e+07"); + CHECK(String::num_int64(3141593) == "3141593"); + CHECK(String::num_int64(0xA141593, 16) == "a141593"); + CHECK(String::num_int64(0xA141593, 16, true) == "A141593"); } TEST_CASE("[String] String to integer") { @@ -204,6 +371,18 @@ TEST_CASE("[String] String to integer") { } } +TEST_CASE("[String] Hex to integer") { + static const char *nums[4] = { "0xFFAE", "22", "0", "AADDAD" }; + static const int64_t num[4] = { 0xFFAE, 0x22, 0, 0xAADDAD }; + static const bool wo_prefix[4] = { false, true, true, true }; + static const bool w_prefix[4] = { true, false, true, false }; + + for (int i = 0; i < 4; i++) { + CHECK((String(nums[i]).hex_to_int(true) == num[i]) == w_prefix[i]); + CHECK((String(nums[i]).hex_to_int(false) == num[i]) == wo_prefix[i]); + } +} + TEST_CASE("[String] String to float") { static const char *nums[4] = { "-12348298412.2", "0.05", "2.0002", " -0.0001" }; static const double num[4] = { -12348298412.2, 0.05, 2.0002, -0.0001 }; @@ -213,6 +392,11 @@ TEST_CASE("[String] String to float") { } } +TEST_CASE("[String] CamelCase to underscore") { + CHECK(String("TestTestStringGD").camelcase_to_underscore(false) == String("Test_Test_String_GD")); + CHECK(String("TestTestStringGD").camelcase_to_underscore(true) == String("test_test_string_gd")); +} + TEST_CASE("[String] Slicing") { String s = "Mars,Jupiter,Saturn,Uranus"; @@ -222,6 +406,69 @@ TEST_CASE("[String] Slicing") { } } +TEST_CASE("[String] Splitting") { + String s = "Mars,Jupiter,Saturn,Uranus"; + Vector<String> l; + + const char *slices_l[3] = { "Mars", "Jupiter", "Saturn,Uranus" }; + const char *slices_r[3] = { "Mars,Jupiter", "Saturn", "Uranus" }; + + l = s.split(",", true, 2); + CHECK(l.size() == 3); + for (int i = 0; i < l.size(); i++) { + CHECK(l[i] == slices_l[i]); + } + + l = s.rsplit(",", true, 2); + CHECK(l.size() == 3); + for (int i = 0; i < l.size(); i++) { + CHECK(l[i] == slices_r[i]); + } + + s = "Mars Jupiter Saturn Uranus"; + const char *slices_s[4] = { "Mars", "Jupiter", "Saturn", "Uranus" }; + l = s.split_spaces(); + for (int i = 0; i < l.size(); i++) { + CHECK(l[i] == slices_s[i]); + } + + s = "1.2;2.3 4.5"; + const double slices_d[3] = { 1.2, 2.3, 4.5 }; + + Vector<float> f; + f = s.split_floats(";"); + CHECK(f.size() == 2); + for (int i = 0; i < f.size(); i++) { + CHECK(ABS(f[i] - slices_d[i]) <= 0.00001); + } + + Vector<String> keys; + keys.push_back(";"); + keys.push_back(" "); + + f = s.split_floats_mk(keys); + CHECK(f.size() == 3); + for (int i = 0; i < f.size(); i++) { + CHECK(ABS(f[i] - slices_d[i]) <= 0.00001); + } + + s = "1;2 4"; + const int slices_i[3] = { 1, 2, 4 }; + + Vector<int> ii; + ii = s.split_ints(";"); + CHECK(ii.size() == 2); + for (int i = 0; i < ii.size(); i++) { + CHECK(ii[i] == slices_i[i]); + } + + ii = s.split_ints_mk(keys); + CHECK(ii.size() == 3); + for (int i = 0; i < ii.size(); i++) { + CHECK(ii[i] == slices_i[i]); + } +} + TEST_CASE("[String] Erasing") { String s = "Josephine is such a cute girl!"; s.erase(s.find("cute "), String("cute ").length()); @@ -239,7 +486,7 @@ TEST_CASE("[String] Regex substitution") { struct test_27_data { char const *data; - char const *begin; + char const *part; bool expected; }; @@ -253,9 +500,9 @@ TEST_CASE("[String] Begins with") { bool state = true; for (size_t i = 0; state && i < count; ++i) { String s = tc[i].data; - state = s.begins_with(tc[i].begin) == tc[i].expected; + state = s.begins_with(tc[i].part) == tc[i].expected; if (state) { - String sb = tc[i].begin; + String sb = tc[i].part; state = s.begins_with(sb) == tc[i].expected; } CHECK(state); @@ -266,6 +513,42 @@ TEST_CASE("[String] Begins with") { CHECK(state); } +TEST_CASE("[String] Ends with") { + test_27_data tc[] = { + { "res://foobar", "foobar", true }, + { "res", "res://", false }, + { "abc", "abc", true } + }; + size_t count = sizeof(tc) / sizeof(tc[0]); + bool state = true; + for (size_t i = 0; state && i < count; ++i) { + String s = tc[i].data; + state = s.ends_with(tc[i].part) == tc[i].expected; + if (state) { + String sb = tc[i].part; + state = s.ends_with(sb) == tc[i].expected; + } + CHECK(state); + if (!state) { + break; + } + }; + CHECK(state); +} + +TEST_CASE("[String] format") { + const String value_format = "red=\"$red\" green=\"$green\" blue=\"$blue\" alpha=\"$alpha\""; + + Dictionary value_dictionary; + value_dictionary["red"] = 10; + value_dictionary["green"] = 20; + value_dictionary["blue"] = "bla"; + value_dictionary["alpha"] = 0.4; + String value = value_format.format(value_dictionary, "$_"); + + CHECK(value == "red=\"10\" green=\"20\" blue=\"bla\" alpha=\"0.4\""); +} + TEST_CASE("[String] sprintf") { String format, output; Array args; @@ -560,6 +843,38 @@ TEST_CASE("[String] sprintf") { CHECK(output == "%c requires number or single-character string"); } +TEST_CASE("[String] is_numeric") { + CHECK(String("12").is_numeric()); + CHECK(String("1.2").is_numeric()); + CHECK(!String("AF").is_numeric()); + CHECK(String("-12").is_numeric()); + CHECK(String("-1.2").is_numeric()); +} + +TEST_CASE("[String] pad") { + String s = String("test"); + CHECK(s.lpad(10, "x") == U"xxxxxxtest"); + CHECK(s.rpad(10, "x") == U"testxxxxxx"); + + s = String("10.10"); + CHECK(s.pad_decimals(4) == U"10.1000"); + CHECK(s.pad_zeros(4) == U"0010.10"); +} + +TEST_CASE("[String] is_subsequence_of") { + String a = "is subsequence of"; + CHECK(String("sub").is_subsequence_of(a)); + CHECK(!String("Sub").is_subsequence_of(a)); + CHECK(String("Sub").is_subsequence_ofi(a)); +} + +TEST_CASE("[String] match") { + CHECK(String("img1.png").match("*.png")); + CHECK(!String("img1.jpeg").match("*.png")); + CHECK(!String("img1.Png").match("*.png")); + CHECK(String("img1.Png").matchn("*.png")); +} + TEST_CASE("[String] IPVX address to string") { IP_Address ip0("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); IP_Address ip(0x0123, 0x4567, 0x89ab, 0xcdef, true); @@ -792,7 +1107,196 @@ TEST_CASE("[String] Count and countn functionality") { COUNT_TEST(String("testTest-TeStatest").countn("tEsT", 4, 16) == 2); CHECK(state); + +#undef COUNT_TEST +} + +TEST_CASE("[String] Bigrams") { + String s = "abcd"; + Vector<String> bigr = s.bigrams(); + + CHECK(bigr.size() == 3); + CHECK(bigr[0] == "ab"); + CHECK(bigr[1] == "bc"); + CHECK(bigr[2] == "cd"); +} + +TEST_CASE("[String] c-escape/unescape") { + String s = "\\1\a2\b\f3\n45\r6\t7\v8\'9\?0\""; + CHECK(s.c_escape().c_unescape() == s); +} + +TEST_CASE("[String] dedent") { + String s = " aaa\n bbb"; + String t = "aaa\nbbb"; + CHECK(s.dedent() == t); +} + +TEST_CASE("[String] Path functions") { + static const char *path[4] = { "C:\\Godot\\project\\test.tscn", "/Godot/project/test.xscn", "../Godot/project/test.scn", "Godot\\test.doc" }; + static const char *base_dir[4] = { "C:\\Godot\\project", "/Godot/project", "../Godot/project", "Godot" }; + static const char *base_name[4] = { "C:\\Godot\\project\\test", "/Godot/project/test", "../Godot/project/test", "Godot\\test" }; + static const char *ext[4] = { "tscn", "xscn", "scn", "doc" }; + static const char *file[4] = { "test.tscn", "test.xscn", "test.scn", "test.doc" }; + static const bool abs[4] = { true, true, false, false }; + + for (int i = 0; i < 4; i++) { + CHECK(String(path[i]).get_base_dir() == base_dir[i]); + CHECK(String(path[i]).get_basename() == base_name[i]); + CHECK(String(path[i]).get_extension() == ext[i]); + CHECK(String(path[i]).get_file() == file[i]); + CHECK(String(path[i]).is_abs_path() == abs[i]); + CHECK(String(path[i]).is_rel_path() != abs[i]); + CHECK(String(path[i]).simplify_path().get_base_dir().plus_file(file[i]) == String(path[i]).simplify_path()); + } + + static const char *file_name[3] = { "test.tscn", "test://.xscn", "?tes*t.scn" }; + static const bool valid[3] = { true, false, false }; + for (int i = 0; i < 3; i++) { + CHECK(String(file_name[i]).is_valid_filename() == valid[i]); + } +} + +TEST_CASE("[String] hash") { + String a = "Test"; + String b = "Test"; + String c = "West"; + CHECK(a.hash() == b.hash()); + CHECK(a.hash() != c.hash()); + + CHECK(a.hash64() == b.hash64()); + CHECK(a.hash64() != c.hash64()); +} + +TEST_CASE("[String] http_escape/unescape") { + String s = "Godot Engine:'docs'"; + String t = "Godot%20Engine%3A%27docs%27"; + + CHECK(s.http_escape() == t); + CHECK(t.http_unescape() == s); +} + +TEST_CASE("[String] percent_encode/decode") { // Note: is it redundant? Seems to be same as http_escape/unescape but in lower case. + String s = "Godot Engine:'docs'"; + String t = "Godot%20Engine%3a%27docs%27"; + + CHECK(s.percent_encode() == t); + CHECK(t.percent_decode() == s); +} + +TEST_CASE("[String] xml_escape/unescape") { + String s = "\"Test\" <test@test&'test'>"; + CHECK(s.xml_escape(true).xml_unescape() == s); + CHECK(s.xml_escape(false).xml_unescape() == s); +} + +TEST_CASE("[String] Strip escapes") { + String s = "\t\tTest Test\r\n Test"; + CHECK(s.strip_escapes() == "Test Test Test"); } + +TEST_CASE("[String] Similarity") { + String a = "Test"; + String b = "West"; + String c = "Toad"; + CHECK(a.similarity(b) > a.similarity(c)); +} + +TEST_CASE("[String] Strip edges") { + String s = "\t Test Test "; + CHECK(s.strip_edges(true, false) == "Test Test "); + CHECK(s.strip_edges(false, true) == "\t Test Test"); + CHECK(s.strip_edges(true, true) == "Test Test"); +} + +TEST_CASE("[String] Trim") { + String s = "aaaTestbbb"; + CHECK(s.trim_prefix("aaa") == "Testbbb"); + CHECK(s.trim_suffix("bbb") == "aaaTest"); + CHECK(s.trim_suffix("Test") == s); +} + +TEST_CASE("[String] Right/Left") { + String s = "aaaTestbbb"; + // ^ + CHECK(s.right(6) == "tbbb"); + CHECK(s.left(6) == "aaaTes"); +} + +TEST_CASE("[String] Repeat") { + String s = "abababab"; + String x = "ab"; + String t = x.repeat(4); + CHECK(t == s); +} + +TEST_CASE("[String] SHA1/SHA256/MD5") { + String s = "Godot"; + String sha1 = "a1e91f39b9fce6a9998b14bdbe2aa2b39dc2d201"; + static uint8_t sha1_buf[20] = { + 0xA1, 0xE9, 0x1F, 0x39, 0xB9, 0xFC, 0xE6, 0xA9, 0x99, 0x8B, 0x14, 0xBD, 0xBE, 0x2A, 0xA2, 0xB3, + 0x9D, 0xC2, 0xD2, 0x01 + }; + String sha256 = "2a02b2443f7985d89d09001086ae3dcfa6eb0f55c6ef170715d42328e16e6cb8"; + static uint8_t sha256_buf[32] = { + 0x2A, 0x02, 0xB2, 0x44, 0x3F, 0x79, 0x85, 0xD8, 0x9D, 0x09, 0x00, 0x10, 0x86, 0xAE, 0x3D, 0xCF, + 0xA6, 0xEB, 0x0F, 0x55, 0xC6, 0xEF, 0x17, 0x07, 0x15, 0xD4, 0x23, 0x28, 0xE1, 0x6E, 0x6C, 0xB8 + }; + String md5 = "4a336d087aeb0390da10ee2ea7cb87f8"; + static uint8_t md5_buf[16] = { + 0x4A, 0x33, 0x6D, 0x08, 0x7A, 0xEB, 0x03, 0x90, 0xDA, 0x10, 0xEE, 0x2E, 0xA7, 0xCB, 0x87, 0xF8 + }; + + PackedByteArray buf = s.sha1_buffer(); + CHECK(memcmp(sha1_buf, buf.ptr(), 20) == 0); + CHECK(s.sha1_text() == sha1); + + buf = s.sha256_buffer(); + CHECK(memcmp(sha256_buf, buf.ptr(), 32) == 0); + CHECK(s.sha256_text() == sha256); + + buf = s.md5_buffer(); + CHECK(memcmp(md5_buf, buf.ptr(), 16) == 0); + CHECK(s.md5_text() == md5); +} + +TEST_CASE("[String] Join") { + String s = ", "; + Vector<String> parts; + parts.push_back("One"); + parts.push_back("B"); + parts.push_back("C"); + String t = s.join(parts); + CHECK(t == "One, B, C"); +} + +TEST_CASE("[String] Is_*") { + static const char *data[12] = { "-30", "100", "10.1", "10,1", "1e2", "1e-2", "1e2e3", "0xAB", "AB", "Test1", "1Test", "Test*1" }; + static bool isnum[12] = { true, true, true, false, false, false, false, false, false, false, false, false }; + static bool isint[12] = { true, true, false, false, false, false, false, false, false, false, false, false }; + static bool ishex[12] = { true, true, false, false, true, false, true, false, true, false, false, false }; + static bool ishex_p[12] = { false, false, false, false, false, false, false, true, false, false, false, false }; + static bool isflt[12] = { true, true, true, false, true, true, false, false, false, false, false, false }; + static bool isid[12] = { false, false, false, false, false, false, false, false, true, true, false, false }; + for (int i = 0; i < 12; i++) { + String s = String(data[i]); + CHECK(s.is_numeric() == isnum[i]); + CHECK(s.is_valid_integer() == isint[i]); + CHECK(s.is_valid_hex_number(false) == ishex[i]); + CHECK(s.is_valid_hex_number(true) == ishex_p[i]); + CHECK(s.is_valid_float() == isflt[i]); + CHECK(s.is_valid_identifier() == isid[i]); + } +} + +TEST_CASE("[String] humanize_size") { + CHECK(String::humanize_size(1000) == "1000 B"); + CHECK(String::humanize_size(1025) == "1.00 KiB"); + CHECK(String::humanize_size(1025300) == "1001.2 KiB"); + CHECK(String::humanize_size(100523550) == "95.86 MiB"); + CHECK(String::humanize_size(5345555000) == "4.97 GiB"); +} + } // namespace TestString #endif // TEST_STRING_H diff --git a/thirdparty/README.md b/thirdparty/README.md index a63eca2a2a..58bdafa850 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -304,7 +304,7 @@ changes are marked with `// -- GODOT --` comments. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.16.7 (2020) +- Version: 2.16.8 (2020) - License: Apache 2.0 File extracted from upstream release tarball: @@ -564,7 +564,7 @@ comments and a patch is provided in the squish/ folder. ## tinyexr - Upstream: https://github.com/syoyo/tinyexr -- Version: git (4dbd05a22f51a2d7462311569b8b0cba0bbe2ac5, 2020) +- Version: 1.0.0 (e4b7840d9448b7d57a88384ce26143004f3c0c71, 2020) - License: BSD-3-Clause Files extracted from upstream source: diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h index d20cdbd6da..4468b6623a 100644 --- a/thirdparty/mbedtls/include/mbedtls/aes.h +++ b/thirdparty/mbedtls/include/mbedtls/aes.h @@ -21,7 +21,7 @@ */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -62,8 +62,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_AES_H diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h index 91a4e0f116..9b63a0010a 100644 --- a/thirdparty/mbedtls/include/mbedtls/aesni.h +++ b/thirdparty/mbedtls/include/mbedtls/aesni.h @@ -7,7 +7,7 @@ * functions; you must not call them directly. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -48,8 +48,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_AESNI_H #define MBEDTLS_AESNI_H diff --git a/thirdparty/mbedtls/include/mbedtls/arc4.h b/thirdparty/mbedtls/include/mbedtls/arc4.h index ecaf310122..6334a9cc1e 100644 --- a/thirdparty/mbedtls/include/mbedtls/arc4.h +++ b/thirdparty/mbedtls/include/mbedtls/arc4.h @@ -7,7 +7,7 @@ * security risk. We recommend considering stronger ciphers instead. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * * ********** * - * This file is part of mbed TLS (https://tls.mbed.org) - * */ #ifndef MBEDTLS_ARC4_H #define MBEDTLS_ARC4_H diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h index 66f2668bf3..13763d4200 100644 --- a/thirdparty/mbedtls/include/mbedtls/aria.h +++ b/thirdparty/mbedtls/include/mbedtls/aria.h @@ -10,7 +10,7 @@ * and also described by the IETF in <em>RFC 5794</em>. */ /* - * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -51,8 +51,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ARIA_H diff --git a/thirdparty/mbedtls/include/mbedtls/asn1.h b/thirdparty/mbedtls/include/mbedtls/asn1.h index c64038cdb5..0e596bca2c 100644 --- a/thirdparty/mbedtls/include/mbedtls/asn1.h +++ b/thirdparty/mbedtls/include/mbedtls/asn1.h @@ -4,7 +4,7 @@ * \brief Generic ASN.1 parsing */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ASN1_H #define MBEDTLS_ASN1_H diff --git a/thirdparty/mbedtls/include/mbedtls/asn1write.h b/thirdparty/mbedtls/include/mbedtls/asn1write.h index 4fed59371c..3c7cdd6b46 100644 --- a/thirdparty/mbedtls/include/mbedtls/asn1write.h +++ b/thirdparty/mbedtls/include/mbedtls/asn1write.h @@ -4,7 +4,7 @@ * \brief ASN.1 buffer writing functionality */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H diff --git a/thirdparty/mbedtls/include/mbedtls/base64.h b/thirdparty/mbedtls/include/mbedtls/base64.h index 215255e628..cbed6887ee 100644 --- a/thirdparty/mbedtls/include/mbedtls/base64.h +++ b/thirdparty/mbedtls/include/mbedtls/base64.h @@ -4,7 +4,7 @@ * \brief RFC 1521 base64 encoding/decoding */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h index 590cde58da..4bb9fa3d43 100644 --- a/thirdparty/mbedtls/include/mbedtls/bignum.h +++ b/thirdparty/mbedtls/include/mbedtls/bignum.h @@ -4,7 +4,7 @@ * \brief Multi-precision integer library */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_BIGNUM_H #define MBEDTLS_BIGNUM_H diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h index d2a1ebdbf4..945bd426a9 100644 --- a/thirdparty/mbedtls/include/mbedtls/blowfish.h +++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h @@ -4,7 +4,7 @@ * \brief Blowfish block cipher */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_BLOWFISH_H #define MBEDTLS_BLOWFISH_H diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h index 42339b7b71..9615090f91 100644 --- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h +++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h @@ -4,7 +4,7 @@ * \brief Multi-precision integer library */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * Multiply source vector [s] with b, add result diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h index 41d6f955ba..38871288e4 100644 --- a/thirdparty/mbedtls/include/mbedtls/camellia.h +++ b/thirdparty/mbedtls/include/mbedtls/camellia.h @@ -4,7 +4,7 @@ * \brief Camellia block cipher */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CAMELLIA_H #define MBEDTLS_CAMELLIA_H diff --git a/thirdparty/mbedtls/include/mbedtls/ccm.h b/thirdparty/mbedtls/include/mbedtls/ccm.h index 3647d5094f..3dcdc91894 100644 --- a/thirdparty/mbedtls/include/mbedtls/ccm.h +++ b/thirdparty/mbedtls/include/mbedtls/ccm.h @@ -28,7 +28,7 @@ * consistent with RFC 3610. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -69,8 +69,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CCM_H diff --git a/thirdparty/mbedtls/include/mbedtls/certs.h b/thirdparty/mbedtls/include/mbedtls/certs.h index 2a645ad0d0..8472a6f38c 100644 --- a/thirdparty/mbedtls/include/mbedtls/certs.h +++ b/thirdparty/mbedtls/include/mbedtls/certs.h @@ -4,7 +4,7 @@ * \brief Sample certificates and DHM parameters for testing */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CERTS_H #define MBEDTLS_CERTS_H diff --git a/thirdparty/mbedtls/include/mbedtls/chacha20.h b/thirdparty/mbedtls/include/mbedtls/chacha20.h index e2950e1a01..8c9c2af6ff 100644 --- a/thirdparty/mbedtls/include/mbedtls/chacha20.h +++ b/thirdparty/mbedtls/include/mbedtls/chacha20.h @@ -13,7 +13,7 @@ */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -54,8 +54,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CHACHA20_H diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h index bee5a3ab03..5f6cb6e030 100644 --- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h +++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h @@ -13,7 +13,7 @@ */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -54,8 +54,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CHACHAPOLY_H diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h index 8ce73ceff1..2bbd7a80ff 100644 --- a/thirdparty/mbedtls/include/mbedtls/check_config.h +++ b/thirdparty/mbedtls/include/mbedtls/check_config.h @@ -4,7 +4,7 @@ * \brief Consistency checks for configuration options */ /* - * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* @@ -199,6 +197,16 @@ #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #endif +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + #if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) #error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" diff --git a/thirdparty/mbedtls/include/mbedtls/cipher.h b/thirdparty/mbedtls/include/mbedtls/cipher.h index 8672dd2b98..1f41b528c4 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher.h @@ -8,7 +8,7 @@ * \author Adriaan de Jong <dejong@fox-it.com> */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CIPHER_H diff --git a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h index 558be52a7e..88282ec9d2 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h @@ -6,7 +6,7 @@ * \author Adriaan de Jong <dejong@fox-it.com> */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -47,8 +47,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CIPHER_WRAP_H #define MBEDTLS_CIPHER_WRAP_H diff --git a/thirdparty/mbedtls/include/mbedtls/cmac.h b/thirdparty/mbedtls/include/mbedtls/cmac.h index 2074747567..5a7c9b246f 100644 --- a/thirdparty/mbedtls/include/mbedtls/cmac.h +++ b/thirdparty/mbedtls/include/mbedtls/cmac.h @@ -7,7 +7,7 @@ * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>. */ /* - * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -48,8 +48,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CMAC_H diff --git a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h index 71cc4f4d97..45e5a1cf77 100644 --- a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h +++ b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h @@ -7,7 +7,7 @@ * \deprecated Use the new names directly instead */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -48,8 +48,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index 28b405ebca..217998a5eb 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -8,7 +8,7 @@ * memory footprint. */ /* - * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CONFIG_H @@ -552,6 +550,42 @@ //#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT /** + * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** * \def MBEDTLS_TEST_NULL_ENTROPY * * Enables testing and use of mbed TLS without any configured entropy sources. diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index 894fa17130..7e5f2e5769 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -38,7 +38,7 @@ * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time. */ /* - * Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -79,8 +79,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CTR_DRBG_H diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h index 11928e9818..abc2d4f07c 100644 --- a/thirdparty/mbedtls/include/mbedtls/debug.h +++ b/thirdparty/mbedtls/include/mbedtls/debug.h @@ -4,7 +4,7 @@ * \brief Functions for controlling and providing debug output from the library. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_DEBUG_H #define MBEDTLS_DEBUG_H diff --git a/thirdparty/mbedtls/include/mbedtls/des.h b/thirdparty/mbedtls/include/mbedtls/des.h index 4c6441d7d9..ee24f65945 100644 --- a/thirdparty/mbedtls/include/mbedtls/des.h +++ b/thirdparty/mbedtls/include/mbedtls/des.h @@ -8,7 +8,7 @@ * instead. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -50,8 +50,6 @@ * * ********** * - * This file is part of mbed TLS (https://tls.mbed.org) - * */ #ifndef MBEDTLS_DES_H #define MBEDTLS_DES_H diff --git a/thirdparty/mbedtls/include/mbedtls/dhm.h b/thirdparty/mbedtls/include/mbedtls/dhm.h index 5c04ed19fb..11042efb55 100644 --- a/thirdparty/mbedtls/include/mbedtls/dhm.h +++ b/thirdparty/mbedtls/include/mbedtls/dhm.h @@ -44,7 +44,7 @@ * */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -85,8 +85,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_DHM_H diff --git a/thirdparty/mbedtls/include/mbedtls/ecdh.h b/thirdparty/mbedtls/include/mbedtls/ecdh.h index a0052df471..b9324bc496 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdh.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdh.h @@ -13,7 +13,7 @@ * Cryptography</em>. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -54,8 +54,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ECDH_H diff --git a/thirdparty/mbedtls/include/mbedtls/ecdsa.h b/thirdparty/mbedtls/include/mbedtls/ecdsa.h index bc219dcad7..da02b27864 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdsa.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdsa.h @@ -11,7 +11,7 @@ * */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -52,8 +52,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ECDSA_H diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h index 1b6c6ac244..a9b68d00c6 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h +++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h @@ -4,7 +4,7 @@ * \brief Elliptic curve J-PAKE */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ECJPAKE_H #define MBEDTLS_ECJPAKE_H diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h index 8db206060b..bdc750eb24 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp.h @@ -15,7 +15,7 @@ */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -56,8 +56,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ECP_H diff --git a/thirdparty/mbedtls/include/mbedtls/ecp_internal.h b/thirdparty/mbedtls/include/mbedtls/ecp_internal.h index 4e9445ae44..0047bd4ef9 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp_internal.h @@ -5,7 +5,7 @@ * point arithmetic. */ /* - * Copyright (C) 2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index fd70cd7e9e..1e1d3f56ec 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -4,7 +4,7 @@ * \brief Entropy accumulator implementation */ /* - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ENTROPY_H #define MBEDTLS_ENTROPY_H diff --git a/thirdparty/mbedtls/include/mbedtls/entropy_poll.h b/thirdparty/mbedtls/include/mbedtls/entropy_poll.h index 9843a9e460..c348fe52d4 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy_poll.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy_poll.h @@ -4,7 +4,7 @@ * \brief Platform-specific and custom entropy polling functions */ /* - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ENTROPY_POLL_H #define MBEDTLS_ENTROPY_POLL_H diff --git a/thirdparty/mbedtls/include/mbedtls/error.h b/thirdparty/mbedtls/include/mbedtls/error.h index 3ee7bbba89..fa8582a391 100644 --- a/thirdparty/mbedtls/include/mbedtls/error.h +++ b/thirdparty/mbedtls/include/mbedtls/error.h @@ -4,7 +4,7 @@ * \brief Error to string translation */ /* - * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H diff --git a/thirdparty/mbedtls/include/mbedtls/gcm.h b/thirdparty/mbedtls/include/mbedtls/gcm.h index 52d03b0ce8..4e4434ed4d 100644 --- a/thirdparty/mbedtls/include/mbedtls/gcm.h +++ b/thirdparty/mbedtls/include/mbedtls/gcm.h @@ -12,7 +12,7 @@ * */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -53,8 +53,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_GCM_H diff --git a/thirdparty/mbedtls/include/mbedtls/havege.h b/thirdparty/mbedtls/include/mbedtls/havege.h index 75ab3cb963..e90839ddeb 100644 --- a/thirdparty/mbedtls/include/mbedtls/havege.h +++ b/thirdparty/mbedtls/include/mbedtls/havege.h @@ -4,7 +4,7 @@ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_HAVEGE_H #define MBEDTLS_HAVEGE_H diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h index a8db554d9f..07ffe83b23 100644 --- a/thirdparty/mbedtls/include/mbedtls/hkdf.h +++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h @@ -7,7 +7,7 @@ * specified by RFC 5869. */ /* - * Copyright (C) 2016-2019, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -48,8 +48,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_HKDF_H #define MBEDTLS_HKDF_H diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index 231fb459bc..6883678204 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -8,7 +8,7 @@ * Deterministic Random Bit Generators</em>. */ /* - * Copyright (C) 2006-2019, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_HMAC_DRBG_H #define MBEDTLS_HMAC_DRBG_H diff --git a/thirdparty/mbedtls/include/mbedtls/md.h b/thirdparty/mbedtls/include/mbedtls/md.h index 6a21f05908..2ba8d9e7a9 100644 --- a/thirdparty/mbedtls/include/mbedtls/md.h +++ b/thirdparty/mbedtls/include/mbedtls/md.h @@ -6,7 +6,7 @@ * \author Adriaan de Jong <dejong@fox-it.com> */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -47,8 +47,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MD_H diff --git a/thirdparty/mbedtls/include/mbedtls/md2.h b/thirdparty/mbedtls/include/mbedtls/md2.h index 6d563b41be..9607df66ba 100644 --- a/thirdparty/mbedtls/include/mbedtls/md2.h +++ b/thirdparty/mbedtls/include/mbedtls/md2.h @@ -8,7 +8,7 @@ * instead. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -50,8 +50,6 @@ * * ********** * - * This file is part of mbed TLS (https://tls.mbed.org) - * */ #ifndef MBEDTLS_MD2_H #define MBEDTLS_MD2_H diff --git a/thirdparty/mbedtls/include/mbedtls/md4.h b/thirdparty/mbedtls/include/mbedtls/md4.h index 3f4bcdc607..6ceaf7a2f6 100644 --- a/thirdparty/mbedtls/include/mbedtls/md4.h +++ b/thirdparty/mbedtls/include/mbedtls/md4.h @@ -8,7 +8,7 @@ * instead. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -50,8 +50,6 @@ * * ********** * - * This file is part of mbed TLS (https://tls.mbed.org) - * */ #ifndef MBEDTLS_MD4_H #define MBEDTLS_MD4_H diff --git a/thirdparty/mbedtls/include/mbedtls/md5.h b/thirdparty/mbedtls/include/mbedtls/md5.h index 34279c7212..b9d0ca929a 100644 --- a/thirdparty/mbedtls/include/mbedtls/md5.h +++ b/thirdparty/mbedtls/include/mbedtls/md5.h @@ -8,7 +8,7 @@ * digests instead. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MD5_H #define MBEDTLS_MD5_H diff --git a/thirdparty/mbedtls/include/mbedtls/md_internal.h b/thirdparty/mbedtls/include/mbedtls/md_internal.h index 154b8bbc27..847f50aa0a 100644 --- a/thirdparty/mbedtls/include/mbedtls/md_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/md_internal.h @@ -8,7 +8,7 @@ * \author Adriaan de Jong <dejong@fox-it.com> */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MD_WRAP_H #define MBEDTLS_MD_WRAP_H diff --git a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h index c1e0926b13..89c0617495 100644 --- a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h +++ b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -4,7 +4,7 @@ * \brief Buffer-based memory allocator */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H #define MBEDTLS_MEMORY_BUFFER_ALLOC_H diff --git a/thirdparty/mbedtls/include/mbedtls/net.h b/thirdparty/mbedtls/include/mbedtls/net.h index bba4a35940..6c7a49d3bd 100644 --- a/thirdparty/mbedtls/include/mbedtls/net.h +++ b/thirdparty/mbedtls/include/mbedtls/net.h @@ -6,7 +6,7 @@ * \deprecated Superseded by mbedtls/net_sockets.h */ /* - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -47,8 +47,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #include "config.h" diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index d4d23fe9d8..00fea7db19 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -20,7 +20,7 @@ * */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -61,8 +61,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_NET_SOCKETS_H #define MBEDTLS_NET_SOCKETS_H diff --git a/thirdparty/mbedtls/include/mbedtls/nist_kw.h b/thirdparty/mbedtls/include/mbedtls/nist_kw.h index f2b9cebf9c..9435656994 100644 --- a/thirdparty/mbedtls/include/mbedtls/nist_kw.h +++ b/thirdparty/mbedtls/include/mbedtls/nist_kw.h @@ -16,7 +16,7 @@ * */ /* - * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -57,8 +57,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_NIST_KW_H diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h index 7fe4b38621..4a7e3b4b3f 100644 --- a/thirdparty/mbedtls/include/mbedtls/oid.h +++ b/thirdparty/mbedtls/include/mbedtls/oid.h @@ -4,7 +4,7 @@ * \brief Object Identifier (OID) database */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_OID_H #define MBEDTLS_OID_H diff --git a/thirdparty/mbedtls/include/mbedtls/padlock.h b/thirdparty/mbedtls/include/mbedtls/padlock.h index bd476f5f38..d8246e2cd0 100644 --- a/thirdparty/mbedtls/include/mbedtls/padlock.h +++ b/thirdparty/mbedtls/include/mbedtls/padlock.h @@ -8,7 +8,7 @@ * functions; you must not call them directly. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -49,8 +49,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PADLOCK_H #define MBEDTLS_PADLOCK_H diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h index 16b6101415..c9df7ca6e8 100644 --- a/thirdparty/mbedtls/include/mbedtls/pem.h +++ b/thirdparty/mbedtls/include/mbedtls/pem.h @@ -4,7 +4,7 @@ * \brief Privacy Enhanced Mail (PEM) decoding */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H @@ -139,17 +137,27 @@ void mbedtls_pem_free( mbedtls_pem_context *ctx ); * \brief Write a buffer of PEM information from a DER encoded * buffer. * - * \param header header string to write - * \param footer footer string to write - * \param der_data DER data to write - * \param der_len length of the DER data - * \param buf buffer to write to - * \param buf_len length of output buffer - * \param olen total length written / required (if buf_len is not enough) - * - * \return 0 on success, or a specific PEM or BASE64 error code. On - * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required - * size. + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. */ int mbedtls_pem_write_buffer( const char *header, const char *footer, const unsigned char *der_data, size_t der_len, diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h index 408f7baee7..20d51d4f38 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk.h +++ b/thirdparty/mbedtls/include/mbedtls/pk.h @@ -4,7 +4,7 @@ * \brief Public Key abstraction layer */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PK_H diff --git a/thirdparty/mbedtls/include/mbedtls/pk_internal.h b/thirdparty/mbedtls/include/mbedtls/pk_internal.h index 1cd05943ba..3f84cdf748 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/pk_internal.h @@ -4,7 +4,7 @@ * \brief Public Key abstraction layer: wrapper functions */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PK_WRAP_H diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs11.h b/thirdparty/mbedtls/include/mbedtls/pkcs11.h index e1446120c8..3874d4a05e 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs11.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs11.h @@ -6,7 +6,7 @@ * \author Adriaan de Jong <dejong@fox-it.com> */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -47,8 +47,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PKCS11_H #define MBEDTLS_PKCS11_H diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs12.h b/thirdparty/mbedtls/include/mbedtls/pkcs12.h index c418e8f243..9cbcb17305 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs12.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs12.h @@ -4,7 +4,7 @@ * \brief PKCS#12 Personal Information Exchange Syntax */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PKCS12_H #define MBEDTLS_PKCS12_H diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs5.h b/thirdparty/mbedtls/include/mbedtls/pkcs5.h index c3f645aff1..328633c492 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs5.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs5.h @@ -6,7 +6,7 @@ * \author Mathias Olsson <mathias@kompetensum.com> */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -47,8 +47,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PKCS5_H #define MBEDTLS_PKCS5_H diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h index dcb5a88eeb..689cfc6ec7 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform.h +++ b/thirdparty/mbedtls/include/mbedtls/platform.h @@ -13,7 +13,7 @@ * dynamically configured at runtime. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -54,8 +54,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_H #define MBEDTLS_PLATFORM_H diff --git a/thirdparty/mbedtls/include/mbedtls/platform_time.h b/thirdparty/mbedtls/include/mbedtls/platform_time.h index a45870c3a6..e132f6a688 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_time.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_time.h @@ -4,7 +4,7 @@ * \brief mbed TLS Platform time abstraction */ /* - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_TIME_H #define MBEDTLS_PLATFORM_TIME_H diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h index f10574afe6..426afaf040 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_util.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h @@ -5,7 +5,7 @@ * library. */ /* - * Copyright (C) 2018, Arm Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_UTIL_H #define MBEDTLS_PLATFORM_UTIL_H diff --git a/thirdparty/mbedtls/include/mbedtls/poly1305.h b/thirdparty/mbedtls/include/mbedtls/poly1305.h index 6e45b2c2ba..b337aa841c 100644 --- a/thirdparty/mbedtls/include/mbedtls/poly1305.h +++ b/thirdparty/mbedtls/include/mbedtls/poly1305.h @@ -13,7 +13,7 @@ */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -54,8 +54,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_POLY1305_H diff --git a/thirdparty/mbedtls/include/mbedtls/ripemd160.h b/thirdparty/mbedtls/include/mbedtls/ripemd160.h index 505c39252e..31c6637d6d 100644 --- a/thirdparty/mbedtls/include/mbedtls/ripemd160.h +++ b/thirdparty/mbedtls/include/mbedtls/ripemd160.h @@ -4,7 +4,7 @@ * \brief RIPE MD-160 message digest */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_RIPEMD160_H #define MBEDTLS_RIPEMD160_H diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index cd22fc4c1f..188c37cf3a 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -10,7 +10,7 @@ * */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -51,8 +51,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_RSA_H #define MBEDTLS_RSA_H diff --git a/thirdparty/mbedtls/include/mbedtls/rsa_internal.h b/thirdparty/mbedtls/include/mbedtls/rsa_internal.h index 2464e6b082..953cb7b81d 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa_internal.h @@ -35,7 +35,7 @@ * */ /* - * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -77,8 +77,6 @@ * * ********** * - * This file is part of mbed TLS (https://tls.mbed.org) - * */ #ifndef MBEDTLS_RSA_INTERNAL_H diff --git a/thirdparty/mbedtls/include/mbedtls/sha1.h b/thirdparty/mbedtls/include/mbedtls/sha1.h index e69db8a15a..60c514a49e 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha1.h +++ b/thirdparty/mbedtls/include/mbedtls/sha1.h @@ -11,7 +11,7 @@ * digests instead. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -52,8 +52,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H diff --git a/thirdparty/mbedtls/include/mbedtls/sha256.h b/thirdparty/mbedtls/include/mbedtls/sha256.h index 5b03bc31dc..b1881e183c 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha256.h +++ b/thirdparty/mbedtls/include/mbedtls/sha256.h @@ -7,7 +7,7 @@ * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -48,8 +48,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H diff --git a/thirdparty/mbedtls/include/mbedtls/sha512.h b/thirdparty/mbedtls/include/mbedtls/sha512.h index 2fbc69f80e..9ff78ecf41 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha512.h +++ b/thirdparty/mbedtls/include/mbedtls/sha512.h @@ -6,7 +6,7 @@ * hash functions are defined in <em>FIPS 180-4: Secure Hash Standard (SHS)</em>. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -47,8 +47,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA512_H #define MBEDTLS_SHA512_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h index 6f56983562..d3ee3c4e6f 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl.h @@ -4,7 +4,7 @@ * \brief SSL/TLS functions. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_H #define MBEDTLS_SSL_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h index e987c29e11..612d81776e 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h @@ -4,7 +4,7 @@ * \brief SSL session cache implementation */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_CACHE_H #define MBEDTLS_SSL_CACHE_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h index 8969141165..ab8e601db7 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -4,7 +4,7 @@ * \brief SSL Ciphersuites for mbed TLS */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h index 71e056781c..9c2d5b62a4 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h @@ -4,7 +4,7 @@ * \brief DTLS cookie callbacks implementation */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h index b371094f1e..6ba6c2af09 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h @@ -4,7 +4,7 @@ * \brief Internal functions shared by the SSL modules */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_INTERNAL_H #define MBEDTLS_SSL_INTERNAL_H @@ -152,6 +150,24 @@ #define MBEDTLS_SSL_RETRANS_WAITING 2 #define MBEDTLS_SSL_RETRANS_FINISHED 3 +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_CAMELLIA_C) || \ + defined(MBEDTLS_ARIA_C) || \ + defined(MBEDTLS_DES_C) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether the CBC construct used in TLS 1.0-1.2 (as + * opposed to the very different CBC construct used in SSLv3) is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + /* * Allow extra bytes for record, authentication and encryption overhead: * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) @@ -843,6 +859,73 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/** \brief Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The additional data prepended to \p data. This + * must point to a readable buffer of \p add_data_len + * bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The data appended to \p add_data. This must point + * to a readable buffer of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of \p data in bytes. + * \param max_data_len The maximal length of \p data in bytes. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 + * Success. + * \retval MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ); + +/** \brief Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * + * \param dst The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src_base The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. + * \param offset_secret The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset_secret. + * \param offset_max The maximal value of \p offset_secret. + * \param len The number of bytes to copy. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + #ifdef __cplusplus } #endif diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h index ac3be04337..a10a434138 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h @@ -4,7 +4,7 @@ * \brief TLS server ticket callbacks implementation */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_TICKET_H #define MBEDTLS_SSL_TICKET_H diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index b6ec4df8e9..a8183a6ef4 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -4,7 +4,7 @@ * \brief Threading abstraction layer */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_THREADING_H #define MBEDTLS_THREADING_H diff --git a/thirdparty/mbedtls/include/mbedtls/timing.h b/thirdparty/mbedtls/include/mbedtls/timing.h index 149ccfb666..8611ba9a4e 100644 --- a/thirdparty/mbedtls/include/mbedtls/timing.h +++ b/thirdparty/mbedtls/include/mbedtls/timing.h @@ -4,7 +4,7 @@ * \brief Portable interface to timeouts and to the CPU cycle counter */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_TIMING_H #define MBEDTLS_TIMING_H diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index 2bff31d51f..d09b45002d 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -4,7 +4,7 @@ * \brief Run-time version information */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * This set of compile-time defines and run-time variables can be used to @@ -67,16 +65,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 16 -#define MBEDTLS_VERSION_PATCH 7 +#define MBEDTLS_VERSION_PATCH 8 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02100700 -#define MBEDTLS_VERSION_STRING "2.16.7" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.7" +#define MBEDTLS_VERSION_NUMBER 0x02100800 +#define MBEDTLS_VERSION_STRING "2.16.8" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.8" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/include/mbedtls/x509.h b/thirdparty/mbedtls/include/mbedtls/x509.h index e9f2fc6024..5bb9b00292 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509.h +++ b/thirdparty/mbedtls/include/mbedtls/x509.h @@ -4,7 +4,7 @@ * \brief X.509 generic defines and structures */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_H #define MBEDTLS_X509_H diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crl.h b/thirdparty/mbedtls/include/mbedtls/x509_crl.h index 0e37f65e8f..2ade47c89d 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crl.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crl.h @@ -4,7 +4,7 @@ * \brief X.509 certificate revocation list parsing */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_CRL_H #define MBEDTLS_X509_CRL_H diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h index 4aae923ea0..c38e0c0556 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h @@ -4,7 +4,7 @@ * \brief X.509 certificate parsing and writing */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_CRT_H #define MBEDTLS_X509_CRT_H diff --git a/thirdparty/mbedtls/include/mbedtls/x509_csr.h b/thirdparty/mbedtls/include/mbedtls/x509_csr.h index 8ba2cda0dc..5dfb4213e8 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_csr.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_csr.h @@ -4,7 +4,7 @@ * \brief X.509 certificate signing request parsing and writing */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_CSR_H #define MBEDTLS_X509_CSR_H diff --git a/thirdparty/mbedtls/include/mbedtls/xtea.h b/thirdparty/mbedtls/include/mbedtls/xtea.h index d372110215..cd6d3753d1 100644 --- a/thirdparty/mbedtls/include/mbedtls/xtea.h +++ b/thirdparty/mbedtls/include/mbedtls/xtea.h @@ -4,7 +4,7 @@ * \brief XTEA block cipher (32-bit) */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -45,8 +45,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_XTEA_H #define MBEDTLS_XTEA_H diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index 9ec28690b2..9b337505fd 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -1,7 +1,7 @@ /* * FIPS-197 compliant AES implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. diff --git a/thirdparty/mbedtls/library/aesni.c b/thirdparty/mbedtls/library/aesni.c index 44bd89cba9..358d4ad860 100644 --- a/thirdparty/mbedtls/library/aesni.c +++ b/thirdparty/mbedtls/library/aesni.c @@ -1,7 +1,7 @@ /* * AES-NI support functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/arc4.c b/thirdparty/mbedtls/library/arc4.c index c30facb671..6729bab002 100644 --- a/thirdparty/mbedtls/library/arc4.c +++ b/thirdparty/mbedtls/library/arc4.c @@ -1,7 +1,7 @@ /* * An implementation of the ARCFOUR algorithm * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The ARCFOUR algorithm was publicly disclosed on 94/09. diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c index 0c9dd76f07..ef0392f658 100644 --- a/thirdparty/mbedtls/library/aria.c +++ b/thirdparty/mbedtls/library/aria.c @@ -1,7 +1,7 @@ /* * ARIA implementation * - * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/asn1parse.c b/thirdparty/mbedtls/library/asn1parse.c index 8d59119ae0..10239fdd15 100644 --- a/thirdparty/mbedtls/library/asn1parse.c +++ b/thirdparty/mbedtls/library/asn1parse.c @@ -1,7 +1,7 @@ /* * Generic ASN.1 parsing * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c index bd0d6af4d8..d94d0a7605 100644 --- a/thirdparty/mbedtls/library/asn1write.c +++ b/thirdparty/mbedtls/library/asn1write.c @@ -1,7 +1,7 @@ /* * ASN.1 buffer writing functionality * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c index 75849d1214..bfafb05353 100644 --- a/thirdparty/mbedtls/library/base64.c +++ b/thirdparty/mbedtls/library/base64.c @@ -1,7 +1,7 @@ /* * RFC 1521 base64 encoding/decoding * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index f42b97650f..dfe976d648 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -1,7 +1,7 @@ /* * Multi-precision integer library * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/blowfish.c b/thirdparty/mbedtls/library/blowfish.c index f11a9d6395..a3f9be959f 100644 --- a/thirdparty/mbedtls/library/blowfish.c +++ b/thirdparty/mbedtls/library/blowfish.c @@ -1,7 +1,7 @@ /* * Blowfish implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The Blowfish block cipher was designed by Bruce Schneier in 1993. diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c index 9f5724917b..40d62121bf 100644 --- a/thirdparty/mbedtls/library/camellia.c +++ b/thirdparty/mbedtls/library/camellia.c @@ -1,7 +1,7 @@ /* * Camellia implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The Camellia block cipher was designed by NTT and Mitsubishi Electric diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c index 18a2343ac5..b2e5a4763d 100644 --- a/thirdparty/mbedtls/library/ccm.c +++ b/thirdparty/mbedtls/library/ccm.c @@ -1,7 +1,7 @@ /* * NIST SP800-38C compliant CCM implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/certs.c b/thirdparty/mbedtls/library/certs.c index 7423168b25..cb43f53368 100644 --- a/thirdparty/mbedtls/library/certs.c +++ b/thirdparty/mbedtls/library/certs.c @@ -1,7 +1,7 @@ /* * X.509 test certificates * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c index d851a25bd6..80fe50cc67 100644 --- a/thirdparty/mbedtls/library/chacha20.c +++ b/thirdparty/mbedtls/library/chacha20.c @@ -5,7 +5,7 @@ * * \author Daniel King <damaki.gh@gmail.com> * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c index f232190dfc..c8b5bba4b2 100644 --- a/thirdparty/mbedtls/library/chachapoly.c +++ b/thirdparty/mbedtls/library/chachapoly.c @@ -3,7 +3,7 @@ * * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -44,8 +44,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c index 896ec8ec66..57da0b9c44 100644 --- a/thirdparty/mbedtls/library/cipher.c +++ b/thirdparty/mbedtls/library/cipher.c @@ -5,7 +5,7 @@ * * \author Adriaan de Jong <dejong@fox-it.com> * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c index 09296c7f9b..1dcac21be1 100644 --- a/thirdparty/mbedtls/library/cipher_wrap.c +++ b/thirdparty/mbedtls/library/cipher_wrap.c @@ -5,7 +5,7 @@ * * \author Adriaan de Jong <dejong@fox-it.com> * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/cmac.c b/thirdparty/mbedtls/library/cmac.c index ce0cd4b055..1a1200b52b 100644 --- a/thirdparty/mbedtls/library/cmac.c +++ b/thirdparty/mbedtls/library/cmac.c @@ -3,7 +3,7 @@ * * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -44,8 +44,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index e1900afc45..b98df29a9b 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -1,7 +1,7 @@ /* * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The NIST SP 800-90 DRBGs are described in the following publication. diff --git a/thirdparty/mbedtls/library/debug.c b/thirdparty/mbedtls/library/debug.c index 3604cfb253..5f06d0da13 100644 --- a/thirdparty/mbedtls/library/debug.c +++ b/thirdparty/mbedtls/library/debug.c @@ -1,7 +1,7 @@ /* * Debugging routines * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/des.c b/thirdparty/mbedtls/library/des.c index a5f73330b0..623165d391 100644 --- a/thirdparty/mbedtls/library/des.c +++ b/thirdparty/mbedtls/library/des.c @@ -1,7 +1,7 @@ /* * FIPS-46-3 compliant Triple-DES implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * DES, on which TDES is based, was originally designed by Horst Feistel diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c index f8d367ee89..d652cf0ac9 100644 --- a/thirdparty/mbedtls/library/dhm.c +++ b/thirdparty/mbedtls/library/dhm.c @@ -1,7 +1,7 @@ /* * Diffie-Hellman-Merkle key exchange * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The following sources were referenced in the design of this implementation @@ -351,6 +349,32 @@ cleanup: } /* + * Pick a random R in the range [2, M) for blinding purposes + */ +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + count = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 ); + +cleanup: + return( ret ); +} + + +/* * Use the blinding method and optimisation suggested in section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer @@ -359,7 +383,10 @@ cleanup: static int dhm_update_blinding( mbedtls_dhm_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret, count; + int ret; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); /* * Don't use any blinding the first time a particular X is used, @@ -394,24 +421,23 @@ static int dhm_update_blinding( mbedtls_dhm_context *ctx, */ /* Vi = random( 2, P-1 ) */ - count = 0; - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); + + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); - /* Vf = Vi^-X mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); cleanup: + mbedtls_mpi_free( &R ); + return( ret ); } diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c index 5ef205f36d..8c27e4e196 100644 --- a/thirdparty/mbedtls/library/ecdh.c +++ b/thirdparty/mbedtls/library/ecdh.c @@ -1,7 +1,7 @@ /* * Elliptic curve Diffie-Hellman * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c index 08fda3fa9b..da8df9cde2 100644 --- a/thirdparty/mbedtls/library/ecdsa.c +++ b/thirdparty/mbedtls/library/ecdsa.c @@ -1,7 +1,7 @@ /* * Elliptic curve DSA * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index c89163c68a..f6e24580c7 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -1,7 +1,7 @@ /* * Elliptic curve J-PAKE * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c index 7ea8b1676a..fe41b4128a 100644 --- a/thirdparty/mbedtls/library/ecp.c +++ b/thirdparty/mbedtls/library/ecp.c @@ -1,7 +1,7 @@ /* * Elliptic curves over GF(p): generic functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c index 796e0d1250..cc4c5b71c0 100644 --- a/thirdparty/mbedtls/library/ecp_curves.c +++ b/thirdparty/mbedtls/library/ecp_curves.c @@ -1,7 +1,7 @@ /* * Elliptic curves over GF(p): curve-specific data and functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c index 1bd6ce54ee..666c55654c 100644 --- a/thirdparty/mbedtls/library/entropy.c +++ b/thirdparty/mbedtls/library/entropy.c @@ -1,7 +1,7 @@ /* * Entropy accumulator implementation * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index a5996a198d..26b7e4e2b9 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -1,7 +1,7 @@ /* * Platform-specific and custom entropy polling functions * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if defined(__linux__) diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c index 4ab8733e0c..eb52052b51 100644 --- a/thirdparty/mbedtls/library/error.c +++ b/thirdparty/mbedtls/library/error.c @@ -1,7 +1,7 @@ /* * Error message information * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c index 7edc6da366..2afe5025a0 100644 --- a/thirdparty/mbedtls/library/gcm.c +++ b/thirdparty/mbedtls/library/gcm.c @@ -1,7 +1,7 @@ /* * NIST SP800-38D compliant GCM implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/havege.c b/thirdparty/mbedtls/library/havege.c index 800a518a66..5e91f40d84 100644 --- a/thirdparty/mbedtls/library/havege.c +++ b/thirdparty/mbedtls/library/havege.c @@ -1,7 +1,7 @@ /** * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The HAVEGE RNG was designed by Andre Seznec in 2002. diff --git a/thirdparty/mbedtls/library/hkdf.c b/thirdparty/mbedtls/library/hkdf.c index 0dd4d05645..4a8bdfbe18 100644 --- a/thirdparty/mbedtls/library/hkdf.c +++ b/thirdparty/mbedtls/library/hkdf.c @@ -1,7 +1,7 @@ /* * HKDF implementation -- RFC 5869 * - * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c index 2cb108c406..9fbfc30660 100644 --- a/thirdparty/mbedtls/library/hmac_drbg.c +++ b/thirdparty/mbedtls/library/hmac_drbg.c @@ -1,7 +1,7 @@ /* * HMAC_DRBG implementation (NIST SP 800-90) * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/md.c b/thirdparty/mbedtls/library/md.c index bfada3c058..867b91462d 100644 --- a/thirdparty/mbedtls/library/md.c +++ b/thirdparty/mbedtls/library/md.c @@ -5,7 +5,7 @@ * * \author Adriaan de Jong <dejong@fox-it.com> * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/md2.c b/thirdparty/mbedtls/library/md2.c index d772039b79..cbdaaabdc7 100644 --- a/thirdparty/mbedtls/library/md2.c +++ b/thirdparty/mbedtls/library/md2.c @@ -1,7 +1,7 @@ /* * RFC 1115/1319 compliant MD2 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The MD2 algorithm was designed by Ron Rivest in 1989. diff --git a/thirdparty/mbedtls/library/md4.c b/thirdparty/mbedtls/library/md4.c index 56b359ce34..cb16dce54a 100644 --- a/thirdparty/mbedtls/library/md4.c +++ b/thirdparty/mbedtls/library/md4.c @@ -1,7 +1,7 @@ /* * RFC 1186/1320 compliant MD4 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The MD4 algorithm was designed by Ron Rivest in 1990. diff --git a/thirdparty/mbedtls/library/md5.c b/thirdparty/mbedtls/library/md5.c index 31879a9b14..fe25925214 100644 --- a/thirdparty/mbedtls/library/md5.c +++ b/thirdparty/mbedtls/library/md5.c @@ -1,7 +1,7 @@ /* * RFC 1321 compliant MD5 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The MD5 algorithm was designed by Ron Rivest in 1991. diff --git a/thirdparty/mbedtls/library/md_wrap.c b/thirdparty/mbedtls/library/md_wrap.c index 7c737d87e9..7459db2faf 100644 --- a/thirdparty/mbedtls/library/md_wrap.c +++ b/thirdparty/mbedtls/library/md_wrap.c @@ -5,7 +5,7 @@ * * \author Adriaan de Jong <dejong@fox-it.com> * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c index e854eea8ee..915ec3ae9d 100644 --- a/thirdparty/mbedtls/library/memory_buffer_alloc.c +++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c @@ -1,7 +1,7 @@ /* * Buffer-based memory allocator * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 9489576aae..1130408263 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -1,7 +1,7 @@ /* * TCP/IP or UDP/IP networking functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must @@ -51,6 +49,10 @@ * Harmless on other platforms. */ #define _POSIX_C_SOURCE 200112L +#if defined(__NetBSD__) +#define _XOPEN_SOURCE 600 /* sockaddr_storage */ +#endif + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -345,8 +347,9 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, struct sockaddr_storage client_addr; -#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ - defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ + ( defined(__NetBSD__) && defined(socklen_t) ) socklen_t n = (socklen_t) sizeof( client_addr ); socklen_t type_len = (socklen_t) sizeof( type ); #else diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c index 35be530957..8341ff1303 100644 --- a/thirdparty/mbedtls/library/nist_kw.c +++ b/thirdparty/mbedtls/library/nist_kw.c @@ -2,7 +2,7 @@ * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes * only * - * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -43,8 +43,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ /* * Definition of Key Wrapping: diff --git a/thirdparty/mbedtls/library/oid.c b/thirdparty/mbedtls/library/oid.c index 0a1658f821..2414083f0c 100644 --- a/thirdparty/mbedtls/library/oid.c +++ b/thirdparty/mbedtls/library/oid.c @@ -3,7 +3,7 @@ * * \brief Object Identifier (OID) database * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -44,8 +44,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/padlock.c b/thirdparty/mbedtls/library/padlock.c index fe6e7f9cf3..afb7e0ad42 100644 --- a/thirdparty/mbedtls/library/padlock.c +++ b/thirdparty/mbedtls/library/padlock.c @@ -1,7 +1,7 @@ /* * VIA PadLock support functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * This implementation is based on the VIA PadLock Programming Guide: diff --git a/thirdparty/mbedtls/library/pem.c b/thirdparty/mbedtls/library/pem.c index 3bf4ca5b8c..a7a2f7f5cf 100644 --- a/thirdparty/mbedtls/library/pem.c +++ b/thirdparty/mbedtls/library/pem.c @@ -1,7 +1,7 @@ /* * Privacy Enhanced Mail (PEM) decoding * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/pk.c b/thirdparty/mbedtls/library/pk.c index e9e56c029b..81cfdbfe80 100644 --- a/thirdparty/mbedtls/library/pk.c +++ b/thirdparty/mbedtls/library/pk.c @@ -1,7 +1,7 @@ /* * Public Key abstraction layer * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c index 21a7a33d82..2c27552d9b 100644 --- a/thirdparty/mbedtls/library/pk_wrap.c +++ b/thirdparty/mbedtls/library/pk_wrap.c @@ -1,7 +1,7 @@ /* * Public Key abstraction layer: wrapper functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/pkcs11.c b/thirdparty/mbedtls/library/pkcs11.c index 30d045bf18..cf484b86eb 100644 --- a/thirdparty/mbedtls/library/pkcs11.c +++ b/thirdparty/mbedtls/library/pkcs11.c @@ -5,7 +5,7 @@ * * \author Adriaan de Jong <dejong@fox-it.com> * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #include "mbedtls/pkcs11.h" diff --git a/thirdparty/mbedtls/library/pkcs12.c b/thirdparty/mbedtls/library/pkcs12.c index 3c34128682..3d23d5e354 100644 --- a/thirdparty/mbedtls/library/pkcs12.c +++ b/thirdparty/mbedtls/library/pkcs12.c @@ -1,7 +1,7 @@ /* * PKCS#12 Personal Information Exchange Syntax * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c index 7ac67093c0..8a80aa5d05 100644 --- a/thirdparty/mbedtls/library/pkcs5.c +++ b/thirdparty/mbedtls/library/pkcs5.c @@ -5,7 +5,7 @@ * * \author Mathias Olsson <mathias@kompetensum.com> * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -46,8 +46,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * PKCS#5 includes PBKDF2 and more diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c index 624ca4c671..086807d836 100644 --- a/thirdparty/mbedtls/library/pkparse.c +++ b/thirdparty/mbedtls/library/pkparse.c @@ -1,7 +1,7 @@ /* * Public Key layer for parsing key files and structures * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c index 76159e5a80..150626c147 100644 --- a/thirdparty/mbedtls/library/pkwrite.c +++ b/thirdparty/mbedtls/library/pkwrite.c @@ -1,7 +1,7 @@ /* * Public Key layer for writing key files and structures * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/platform.c b/thirdparty/mbedtls/library/platform.c index 7fe5e56b71..c4c3fd332d 100644 --- a/thirdparty/mbedtls/library/platform.c +++ b/thirdparty/mbedtls/library/platform.c @@ -1,7 +1,7 @@ /* * Platform abstraction layer * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/platform_util.c b/thirdparty/mbedtls/library/platform_util.c index c31c173c89..3ba2aead12 100644 --- a/thirdparty/mbedtls/library/platform_util.c +++ b/thirdparty/mbedtls/library/platform_util.c @@ -2,7 +2,7 @@ * Common and shared functions used by multiple modules in the Mbed TLS * library. * - * Copyright (C) 2018, Arm Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -43,8 +43,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of Mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c index 295997f2bc..5b023f04e4 100644 --- a/thirdparty/mbedtls/library/poly1305.c +++ b/thirdparty/mbedtls/library/poly1305.c @@ -3,7 +3,7 @@ * * \brief Poly1305 authentication algorithm. * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -44,8 +44,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" diff --git a/thirdparty/mbedtls/library/ripemd160.c b/thirdparty/mbedtls/library/ripemd160.c index 721db1efe4..0b6efcb574 100644 --- a/thirdparty/mbedtls/library/ripemd160.c +++ b/thirdparty/mbedtls/library/ripemd160.c @@ -1,7 +1,7 @@ /* * RIPE MD-160 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index af1cef6515..42becbf17b 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -1,7 +1,7 @@ /* * The RSA public-key cryptosystem * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* @@ -83,7 +81,7 @@ #include "mbedtls/md.h" #endif -#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include <stdlib.h> #endif @@ -808,6 +806,9 @@ static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret, count = 0; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); if( ctx->Vf.p != NULL ) { @@ -823,18 +824,41 @@ static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, /* Unblinding value: Vf = random number, invertible mod N */ do { if( count++ > 10 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED ); + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); - } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); - /* Blinding value: Vi = Vf^(-e) mod N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + continue; + if( ret != 0 ) + goto cleanup; + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + } while( 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); cleanup: + mbedtls_mpi_free( &R ); + return( ret ); } @@ -2590,7 +2614,7 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) #if defined(MBEDTLS_PKCS1_V15) static int myrand( void *rng_state, unsigned char *output, size_t len ) { -#if !defined(__OpenBSD__) +#if !defined(__OpenBSD__) && !defined(__NetBSD__) size_t i; if( rng_state != NULL ) @@ -2603,7 +2627,7 @@ static int myrand( void *rng_state, unsigned char *output, size_t len ) rng_state = NULL; arc4random_buf( output, len ); -#endif /* !OpenBSD */ +#endif /* !OpenBSD && !NetBSD */ return( 0 ); } diff --git a/thirdparty/mbedtls/library/rsa_internal.c b/thirdparty/mbedtls/library/rsa_internal.c index 4db49aa578..4d94ca685a 100644 --- a/thirdparty/mbedtls/library/rsa_internal.c +++ b/thirdparty/mbedtls/library/rsa_internal.c @@ -1,7 +1,7 @@ /* * Helper functions for the RSA module * - * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -43,8 +43,6 @@ * * ********** * - * This file is part of mbed TLS (https://tls.mbed.org) - * */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c index 1cffc75f8c..8682abd740 100644 --- a/thirdparty/mbedtls/library/sha1.c +++ b/thirdparty/mbedtls/library/sha1.c @@ -1,7 +1,7 @@ /* * FIPS-180-1 compliant SHA-1 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-1 standard was published by NIST in 1993. diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c index d4dd4859a6..5169584b68 100644 --- a/thirdparty/mbedtls/library/sha256.c +++ b/thirdparty/mbedtls/library/sha256.c @@ -1,7 +1,7 @@ /* * FIPS-180-2 compliant SHA-256 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c index fdcf360d3f..36d5d96146 100644 --- a/thirdparty/mbedtls/library/sha512.c +++ b/thirdparty/mbedtls/library/sha512.c @@ -1,7 +1,7 @@ /* * FIPS-180-2 compliant SHA-384/512 implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-512 Secure Hash Standard was published by NIST in 2002. diff --git a/thirdparty/mbedtls/library/ssl_cache.c b/thirdparty/mbedtls/library/ssl_cache.c index 3cbfeb740a..1d2558a189 100644 --- a/thirdparty/mbedtls/library/ssl_cache.c +++ b/thirdparty/mbedtls/library/ssl_cache.c @@ -1,7 +1,7 @@ /* * SSL session cache implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * These session callbacks use a simple chained list diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c index de566ebca9..090040e9ab 100644 --- a/thirdparty/mbedtls/library/ssl_ciphersuites.c +++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c @@ -3,7 +3,7 @@ * * \brief SSL ciphersuites for mbed TLS * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -44,8 +44,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c index 9fb2eceb22..bd7f28134d 100644 --- a/thirdparty/mbedtls/library/ssl_cli.c +++ b/thirdparty/mbedtls/library/ssl_cli.c @@ -1,7 +1,7 @@ /* * SSLv3/TLSv1 client-side functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c index 15a3173773..04565e0b79 100644 --- a/thirdparty/mbedtls/library/ssl_cookie.c +++ b/thirdparty/mbedtls/library/ssl_cookie.c @@ -1,7 +1,7 @@ /* * DTLS cookie callbacks implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * These session callbacks use a simple chained list diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c index 2c31a8ac54..97b778452c 100644 --- a/thirdparty/mbedtls/library/ssl_srv.c +++ b/thirdparty/mbedtls/library/ssl_srv.c @@ -1,7 +1,7 @@ /* * SSLv3/TLSv1 server-side functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c index 4a091bb640..bbde8e4ceb 100644 --- a/thirdparty/mbedtls/library/ssl_ticket.c +++ b/thirdparty/mbedtls/library/ssl_ticket.c @@ -1,7 +1,7 @@ /* * TLS server tickets callbacks implementation * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index a40b46a1c0..2471600c9a 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -1,7 +1,7 @@ /* * SSLv3/TLSv1 shared functions * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SSL 3.0 specification was drafted by Netscape in 1996, @@ -1433,32 +1431,10 @@ static void ssl_mac( mbedtls_md_context_t *md_ctx, #endif /* MBEDTLS_SSL_PROTO_SSL3 */ #if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ - ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C)) ) + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) #define SSL_SOME_MODES_USE_MAC #endif -/* The function below is only used in the Lucky 13 counter-measure in - * ssl_decrypt_buf(). These are the defines that guard the call site. */ -#if defined(SSL_SOME_MODES_USE_MAC) && \ - ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) ) -/* This function makes sure every byte in the memory region is accessed - * (in ascending addresses order) */ -static void ssl_read_memory( unsigned char *p, size_t len ) -{ - unsigned char acc = 0; - volatile unsigned char force; - - for( ; len != 0; p++, len-- ) - acc ^= *p; - - force = acc; - (void) force; -} -#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */ - /* * Encryption/decryption functions */ @@ -1669,8 +1645,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) if( mode == MBEDTLS_MODE_CBC ) { int ret; @@ -1789,8 +1764,7 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ } else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); @@ -1808,6 +1782,156 @@ static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) return( 0 ); } +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/* + * Constant-flow conditional memcpy: + * - if c1 == c2, equivalent to memcpy(dst, src, len), + * - otherwise, a no-op, + * but with execution flow independent of the values of c1 and c2. + * + * Use only bit operations to avoid branches that could be used by some + * compilers on some platforms to translate comparison operators. + */ +static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ) +{ + /* diff = 0 if c1 == c2, non-zero otherwise */ + const size_t diff = c1 ^ c2; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* diff_msb's most significant bit is equal to c1 != c2 */ + const size_t diff_msb = ( diff | -diff ); + + /* diff1 = c1 != c2 */ + const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); + + /* mask = c1 != c2 ? 0xff : 0x00 */ + const unsigned char mask = (unsigned char) -diff1; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* dst[i] = c1 != c2 ? dst[i] : src[i] */ + size_t i; + for( i = 0; i < len; i++ ) + dst[i] = ( dst[i] & mask ) | ( src[i] & ~mask ); +} + +/* + * Compute HMAC of variable-length data with constant flow. + * + * Only works with MD-5, SHA-1, SHA-256 and SHA-384. + * (Otherwise, computation of block_size needs to be adapted.) + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ssl_cf_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); + + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); + +#undef MD_CHK + +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} + +/* + * Constant-flow memcpy from variable position in buffer. + * - functionally equivalent to memcpy(dst, src + offset_secret, len) + * - but with execution flow independent from the value of offset_secret. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ) +{ + size_t offset; + + for( offset = offset_min; offset <= offset_max; offset++ ) + { + mbedtls_ssl_cf_memcpy_if_eq( dst, src_base + offset, len, + offset, offset_secret ); + } +} +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) { mbedtls_cipher_mode_t mode; @@ -1962,8 +2086,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) } else #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) ) +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) if( mode == MBEDTLS_MODE_CBC ) { /* @@ -2176,8 +2299,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) ssl->in_msglen -= padlen; } else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */ +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ { MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); @@ -2196,6 +2318,7 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) if( auth_done == 0 ) { unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD]; ssl->in_msglen -= ssl->transform_in->maclen; @@ -2210,6 +2333,8 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) ssl->in_msg, ssl->in_msglen, ssl->in_ctr, ssl->in_msgtype, mac_expect ); + memcpy( mac_peer, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); } else #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -2217,34 +2342,8 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) { - /* - * Process MAC and always update for padlen afterwards to make - * total time independent of padlen. - * - * Known timing attacks: - * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) - * - * To compensate for different timings for the MAC calculation - * depending on how much padding was removed (which is determined - * by padlen), process extra_run more blocks through the hash - * function. - * - * The formula in the paper is - * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 ) - * where L1 is the size of the header plus the decrypted message - * plus CBC padding and L2 is the size of the header plus the - * decrypted message. This is for an underlying hash function - * with 64-byte blocks. - * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values - * correctly. We round down instead of up, so -56 is the correct - * value for our calculations instead of -55. - * - * Repeat the formula rather than defining a block_size variable. - * This avoids requiring division by a variable at runtime - * (which would be marginally less efficient and would require - * linking an extra division function in some builds). - */ - size_t j, extra_run = 0; + int ret; + unsigned char add_data[13]; /* * The next two sizes are the minimum and maximum values of @@ -2259,66 +2358,25 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) const size_t max_len = ssl->in_msglen + padlen; const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; - switch( ssl->transform_in->ciphersuite_info->mac ) - { -#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \ - defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_MD5: - case MBEDTLS_MD_SHA1: - case MBEDTLS_MD_SHA256: - /* 8 bytes of message size, 64-byte compression blocks */ - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - - ( 13 + ssl->in_msglen + 8 ) / 64; - break; -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - /* 16 bytes of message size, 128-byte compression blocks */ - extra_run = ( 13 + ssl->in_msglen + padlen + 16 ) / 128 - - ( 13 + ssl->in_msglen + 16 ) / 128; - break; -#endif - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - extra_run &= correct * 0xFF; - - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, - ssl->in_msglen ); - /* Make sure we access everything even when padlen > 0. This - * makes the synchronisation requirements for just-in-time - * Prime+Probe attacks much tighter and hopefully impractical. */ - ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); + memcpy( add_data + 0, ssl->in_ctr, 8 ); + memcpy( add_data + 8, ssl->in_hdr, 3 ); + memcpy( add_data + 11, ssl->in_len, 2 ); - /* Dummy calls to compression function. - * Call mbedtls_md_process at least once due to cache attacks - * that observe whether md_process() was called of not. - * Respect the usual start-(process|update)-finish sequence for - * the sake of hardware accelerators that might require it. */ - mbedtls_md_starts( &ssl->transform_in->md_ctx_dec ); - for( j = 0; j < extra_run + 1; j++ ) - mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + ret = mbedtls_ssl_cf_hmac( &ssl->transform_in->md_ctx_dec, + add_data, sizeof( add_data ), + ssl->in_msg, ssl->in_msglen, + min_len, max_len, + mac_expect ); + if( ret != 0 ) { - /* The switch statement above already checks that we're using - * one of MD-5, SHA-1, SHA-256 or SHA-384. */ - unsigned char tmp[384 / 8]; - mbedtls_md_finish( &ssl->transform_in->md_ctx_dec, tmp ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cf_hmac", ret ); + return( ret ); } - mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); - - /* Make sure we access all the memory that could contain the MAC, - * before we check it in the next code block. This makes the - * synchronisation requirements for just-in-time Prime+Probe - * attacks much tighter and hopefully impractical. */ - ssl_read_memory( ssl->in_msg + min_len, - max_len - min_len + ssl->transform_in->maclen ); + mbedtls_ssl_cf_memcpy_offset( mac_peer, ssl->in_msg, + ssl->in_msglen, + min_len, max_len, + ssl->transform_in->maclen ); } else #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -2330,11 +2388,10 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", mac_peer, ssl->transform_in->maclen ); #endif - if( mbedtls_ssl_safer_memcmp( ssl->in_msg + ssl->in_msglen, mac_expect, + if( mbedtls_ssl_safer_memcmp( mac_peer, mac_expect, ssl->transform_in->maclen ) != 0 ) { #if defined(MBEDTLS_SSL_DEBUG_ALL) @@ -2762,7 +2819,7 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) if( ret < 0 ) return( ret ); - if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "f_recv returned %d bytes but only %lu were requested", @@ -2816,7 +2873,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) if( ret <= 0 ) return( ret ); - if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) ) + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "f_send returned %d bytes but only %lu bytes were sent", @@ -8596,6 +8653,10 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) memcpy( buf, ssl->in_offt, n ); ssl->in_msglen -= n; + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_platform_zeroize( ssl->in_offt, n ); + if( ssl->in_msglen == 0 ) { /* all bytes consumed */ diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index 144fe5d46c..61c4b94041 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -1,7 +1,7 @@ /* * Threading abstraction layer * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index a4beff35a9..50a22165a6 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -1,7 +1,7 @@ /* * Portable interface to the CPU cycle counter * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/version.c b/thirdparty/mbedtls/library/version.c index bdba12f613..5733288f62 100644 --- a/thirdparty/mbedtls/library/version.c +++ b/thirdparty/mbedtls/library/version.c @@ -1,7 +1,7 @@ /* * Version information * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index 51662bfd21..cbf38dc2c2 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -1,7 +1,7 @@ /* * Version feature information * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) @@ -279,6 +277,12 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) + "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) + "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ #if defined(MBEDTLS_TEST_NULL_ENTROPY) "MBEDTLS_TEST_NULL_ENTROPY", #endif /* MBEDTLS_TEST_NULL_ENTROPY */ diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c index 63ceaf9f4d..0c820eca90 100644 --- a/thirdparty/mbedtls/library/x509.c +++ b/thirdparty/mbedtls/library/x509.c @@ -1,7 +1,7 @@ /* * X.509 common functions for parsing and verification * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The ITU-T X.509 standard defines a certificate format for PKI. diff --git a/thirdparty/mbedtls/library/x509_create.c b/thirdparty/mbedtls/library/x509_create.c index 75de91f6c8..0dbd679a93 100644 --- a/thirdparty/mbedtls/library/x509_create.c +++ b/thirdparty/mbedtls/library/x509_create.c @@ -1,7 +1,7 @@ /* * X.509 base functions for creating certificates / CSRs * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c index 94c0c01afe..dba71fad58 100644 --- a/thirdparty/mbedtls/library/x509_crl.c +++ b/thirdparty/mbedtls/library/x509_crl.c @@ -1,7 +1,7 @@ /* * X.509 Certidicate Revocation List (CRL) parsing * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The ITU-T X.509 standard defines a certificate format for PKI. @@ -285,13 +283,13 @@ static int x509_get_entries( unsigned char **p, size_t len2; const unsigned char *end2; + cur_entry->raw.tag = **p; if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) { return( ret ); } - cur_entry->raw.tag = **p; cur_entry->raw.p = *p; cur_entry->raw.len = len2; end2 = *p + len2; diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index 7d01585472..de40eaaf58 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -1,7 +1,7 @@ /* * X.509 certificate parsing and verification * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The ITU-T X.509 standard defines a certificate format for PKI. @@ -1846,8 +1844,7 @@ int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509 if( crt->serial.len == cur->serial.len && memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) { - if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) - return( 1 ); + return( 1 ); } cur = cur->next; diff --git a/thirdparty/mbedtls/library/x509_csr.c b/thirdparty/mbedtls/library/x509_csr.c index 5045c10830..663047d516 100644 --- a/thirdparty/mbedtls/library/x509_csr.c +++ b/thirdparty/mbedtls/library/x509_csr.c @@ -1,7 +1,7 @@ /* * X.509 Certificate Signing Request (CSR) parsing * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The ITU-T X.509 standard defines a certificate format for PKI. diff --git a/thirdparty/mbedtls/library/x509write_crt.c b/thirdparty/mbedtls/library/x509write_crt.c index 0fc94fed2e..5462e83fe0 100644 --- a/thirdparty/mbedtls/library/x509write_crt.c +++ b/thirdparty/mbedtls/library/x509write_crt.c @@ -1,7 +1,7 @@ /* * X.509 certificate writing * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * References: @@ -101,39 +99,44 @@ void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); } -void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, + int version ) { ctx->version = version; } -void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, + mbedtls_md_type_t md_alg ) { ctx->md_alg = md_alg; } -void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) { ctx->subject_key = key; } -void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) { ctx->issuer_key = key; } int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, - const char *subject_name ) + const char *subject_name ) { return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); } int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, - const char *issuer_name ) + const char *issuer_name ) { return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); } -int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, + const mbedtls_mpi *serial ) { int ret; @@ -143,8 +146,9 @@ int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls return( 0 ); } -int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, - const char *not_after ) +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, + const char *not_before, + const char *not_after ) { if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) @@ -164,12 +168,12 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, int critical, const unsigned char *val, size_t val_len ) { - return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, - critical, val, val_len ); + return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ) ); } int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, - int is_ca, int max_pathlen ) + int is_ca, int max_pathlen ) { int ret; unsigned char buf[9]; @@ -185,18 +189,21 @@ int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, { if( max_pathlen >= 0 ) { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, + max_pathlen ) ); } MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); } MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, - MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), - 0, buf + sizeof(buf) - len, len ); + return( + mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + 0, buf + sizeof(buf) - len, len ) ); } #if defined(MBEDTLS_SHA1_C) @@ -208,7 +215,8 @@ int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ct size_t len = 0; memset( buf, 0, sizeof(buf) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, buf + sizeof( buf ) - 20 ); @@ -218,11 +226,13 @@ int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ct len = 20; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), - 0, buf + sizeof(buf) - len, len ); + return mbedtls_x509write_crt_set_extension( ctx, + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); } int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) @@ -233,7 +243,8 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert * size_t len = 0; memset( buf, 0, sizeof(buf) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, buf + sizeof( buf ) - 20 ); @@ -243,15 +254,19 @@ int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert * len = 20; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), - 0, buf + sizeof( buf ) - len, len ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( + ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); } #endif /* MBEDTLS_SHA1_C */ @@ -298,8 +313,8 @@ int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, return( MBEDTLS_ERR_X509_INVALID_FORMAT ); ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - 1, c, (size_t)ret ); + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, c, (size_t)ret ); if( ret != 0 ) return( ret ); @@ -325,8 +340,8 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, return( ret ); ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - 0, c, (size_t)ret ); + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); if( ret != 0 ) return( ret ); @@ -348,7 +363,8 @@ static int x509_write_time( unsigned char **p, unsigned char *start, (const unsigned char *) t + 2, size - 2 ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_UTC_TIME ) ); } else { @@ -356,15 +372,17 @@ static int x509_write_time( unsigned char **p, unsigned char *start, (const unsigned char *) t, size ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_GENERALIZED_TIME ) ); } return( (int) len ); } -int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; const char *sig_oid; @@ -372,15 +390,14 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[SIGNATURE_MAX_SIZE]; - unsigned char tmp_buf[2048]; size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; /* - * Prepare data to be signed in tmp_buf + * Prepare data to be signed at the end of the target buffer */ - c = tmp_buf + sizeof( tmp_buf ); + c = buf + size; /* Signature algorithm needed in TBS, and later for actual signature */ @@ -406,27 +423,36 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, /* Only for v3 */ if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_extensions( &c, + buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); } /* * SubjectPublicKeyInfo */ - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, - tmp_buf, c - tmp_buf ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, + mbedtls_pk_write_pubkey_der( ctx->subject_key, + buf, c - buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); /* * Validity ::= SEQUENCE { @@ -435,32 +461,39 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, */ sub_len = 0; - MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, - MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); - MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, - MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); /* * Issuer ::= Name */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->issuer ) ); /* * Signature ::= AlgorithmIdentifier */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, - sig_oid, strlen( sig_oid ), 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_algorithm_identifier( &c, buf, + sig_oid, strlen( sig_oid ), 0 ) ); /* * Serial ::= INTEGER */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, + &ctx->serial ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } @@ -470,48 +503,67 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) { sub_len = 0; - MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); + MBEDTLS_ASN1_CHK_ADD( sub_len, + mbedtls_asn1_write_int( &c, buf, ctx->version ) ); len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); } - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); /* * Make signature */ + + /* Compute hash of CRT. */ if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ) ) != 0 ) { return( ret ); } - if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng ) ) != 0 ) + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, + hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) { return( ret ); } - /* - * Write data to output buffer - */ + /* Move CRT to the front of the buffer to have space + * for the signature. */ + memmove( buf, c, len ); + c = buf + len; + + /* Add signature at the end of the buffer, + * making sure that it doesn't underflow + * into the CRT buffer. */ c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c, sig_oid, sig_oid_len, sig, sig_len ) ); - if( len > (size_t)( c2 - buf ) ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + /* + * Memory layout after this step: + * + * buf c=buf+len c2 buf+size + * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] + */ - c2 -= len; - memcpy( c2, c, len ); + /* Move raw CRT to just before the signature. */ + c = c2 - len; + memmove( c, buf, len ); len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); return( (int) len ); @@ -521,23 +573,23 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, #define PEM_END_CRT "-----END CERTIFICATE-----\n" #if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; - unsigned char output_buf[4096]; - size_t olen = 0; + size_t olen; - if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), + if( ( ret = mbedtls_x509write_crt_der( crt, buf, size, f_rng, p_rng ) ) < 0 ) { return( ret ); } if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) + buf + size - ret, ret, + buf, size, &olen ) ) != 0 ) { return( ret ); } diff --git a/thirdparty/mbedtls/library/x509write_csr.c b/thirdparty/mbedtls/library/x509write_csr.c index d1b0716c96..60cf12379f 100644 --- a/thirdparty/mbedtls/library/x509write_csr.c +++ b/thirdparty/mbedtls/library/x509write_csr.c @@ -1,7 +1,7 @@ /* * X.509 Certificate Signing Request writing * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ /* * References: @@ -81,6 +79,14 @@ #define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdlib.h> +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) { memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); @@ -187,71 +193,85 @@ int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, return( 0 ); } -int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) +static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx, + unsigned char *buf, + size_t size, + unsigned char *sig, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; - unsigned char sig[SIGNATURE_MAX_SIZE]; - unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; - /* - * Prepare data to be signed in tmp_buf - */ - c = tmp_buf + sizeof( tmp_buf ); + /* Write the CSR backwards starting from the end of buf */ + c = buf + size; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf, + ctx->extensions ) ); if( len ) { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SET ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, - MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_oid( + &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); } - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, - tmp_buf, c - tmp_buf ) ); + buf, c - buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); /* - * Prepare signature + * Sign the written CSR data into the sig buffer + * Note: hash errors can happen only after an internal error */ ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); if( ret != 0 ) @@ -271,32 +291,68 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s return( MBEDTLS_ERR_X509_INVALID_ALG ); if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) + &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* - * Write data to output buffer + * Move the written CSR data to the start of buf to create space for + * writing the signature into buf. */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, - sig_oid, sig_oid_len, sig, sig_len ) ); + memmove( buf, c, len ); - if( len > (size_t)( c2 - buf ) ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + /* + * Write sig and its OID into buf backwards from the end of buf. + * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len + * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, + mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len, + sig, sig_len ) ); + /* + * Compact the space between the CSR data and signature by moving the + * CSR data to the start of the signature. + */ c2 -= len; - memcpy( c2, c, len ); + memmove( c2, buf, len ); + /* ASN encode the total size and tag the CSR data with it. */ len += sig_and_oid_len; MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c2, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* Zero the unused bytes at the start of buf */ + memset( buf, 0, c2 - buf); return( (int) len ); } +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, + size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *sig; + + if( ( sig = mbedtls_calloc( 1, SIGNATURE_MAX_SIZE ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + ret = x509write_csr_der_internal( ctx, buf, size, sig, f_rng, p_rng ); + + mbedtls_free( sig ); + + return( ret ); +} + #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" diff --git a/thirdparty/mbedtls/library/xtea.c b/thirdparty/mbedtls/library/xtea.c index 26ec5de5a9..4e62817579 100644 --- a/thirdparty/mbedtls/library/xtea.c +++ b/thirdparty/mbedtls/library/xtea.c @@ -1,7 +1,7 @@ /* * An 32-bit implementation of the XTEA algorithm * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * * This file is provided under the Apache License 2.0, or the @@ -42,8 +42,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * ********** - * - * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/tinyexr/tinyexr.cc b/thirdparty/tinyexr/tinyexr.cc index 969a6d505d..fef8f66c98 100644 --- a/thirdparty/tinyexr/tinyexr.cc +++ b/thirdparty/tinyexr/tinyexr.cc @@ -1,2 +1,8 @@ +#if defined(_WIN32) +#ifndef NOMINMAX +#define NOMINMAX +#endif +#endif + #define TINYEXR_IMPLEMENTATION #include "tinyexr.h" diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h index 7e8956f7d3..a3e7b23161 100644 --- a/thirdparty/tinyexr/tinyexr.h +++ b/thirdparty/tinyexr/tinyexr.h @@ -1,5 +1,7 @@ +#ifndef TINYEXR_H_ +#define TINYEXR_H_ /* -Copyright (c) 2014 - 2019, Syoyo Fujita and many contributors. +Copyright (c) 2014 - 2020, Syoyo Fujita and many contributors. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -63,9 +65,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // End of OpenEXR license ------------------------------------------------- -#ifndef TINYEXR_H_ -#define TINYEXR_H_ - // // // Do this: @@ -198,11 +197,18 @@ typedef struct _EXRTile { unsigned char **images; // image[channels][pixels] } EXRTile; +typedef struct _EXRBox2i { + int min_x; + int min_y; + int max_x; + int max_y; +} EXRBox2i; + typedef struct _EXRHeader { float pixel_aspect_ratio; int line_order; - int data_window[4]; - int display_window[4]; + EXRBox2i data_window; + EXRBox2i display_window; float screen_window_center[2]; float screen_window_width; @@ -287,26 +293,29 @@ typedef struct _DeepImage { extern int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, const char **err); -// Loads single-frame OpenEXR image by specifing layer name. Assume EXR image contains A(single channel -// alpha) or RGB(A) channels. -// Application must free image data as returned by `out_rgba` -// Result image format is: float x RGBA x width x hight -// Returns negative value and may set error string in `err` when there's an -// error -// When the specified layer name is not found in the EXR file, the function will return `TINYEXR_ERROR_LAYER_NOT_FOUND`. +// Loads single-frame OpenEXR image by specifying layer name. Assume EXR image +// contains A(single channel alpha) or RGB(A) channels. Application must free +// image data as returned by `out_rgba` Result image format is: float x RGBA x +// width x hight Returns negative value and may set error string in `err` when +// there's an error When the specified layer name is not found in the EXR file, +// the function will return `TINYEXR_ERROR_LAYER_NOT_FOUND`. extern int LoadEXRWithLayer(float **out_rgba, int *width, int *height, - const char *filename, const char *layer_name, const char **err); + const char *filename, const char *layer_name, + const char **err); // // Get layer infos from EXR file. // -// @param[out] layer_names List of layer names. Application must free memory after using this. +// @param[out] layer_names List of layer names. Application must free memory +// after using this. // @param[out] num_layers The number of layers -// @param[out] err Error string(wll be filled when the function returns error code). Free it using FreeEXRErrorMessage after using this value. +// @param[out] err Error string(will be filled when the function returns error +// code). Free it using FreeEXRErrorMessage after using this value. // // @return TINYEXR_SUCCEES upon success. // -extern int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, const char **err); +extern int EXRLayers(const char *filename, const char **layer_names[], + int *num_layers, const char **err); // @deprecated { to be removed. } // Simple wrapper API for ParseEXRHeaderFromFile. @@ -336,13 +345,13 @@ extern void InitEXRHeader(EXRHeader *exr_header); // Initialize EXRImage struct extern void InitEXRImage(EXRImage *exr_image); -// Free's internal data of EXRHeader struct +// Frees internal data of EXRHeader struct extern int FreeEXRHeader(EXRHeader *exr_header); -// Free's internal data of EXRImage struct +// Frees internal data of EXRImage struct extern int FreeEXRImage(EXRImage *exr_image); -// Free's error message +// Frees error message extern void FreeEXRErrorMessage(const char *msg); // Parse EXR version header of a file. @@ -497,8 +506,17 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, #endif // TINYEXR_H_ #ifdef TINYEXR_IMPLEMENTATION -#ifndef TINYEXR_IMPLEMENTATION_DEIFNED -#define TINYEXR_IMPLEMENTATION_DEIFNED +#ifndef TINYEXR_IMPLEMENTATION_DEFINED +#define TINYEXR_IMPLEMENTATION_DEFINED + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> // for UTF-8 + +#endif #include <algorithm> #include <cassert> @@ -536,7 +554,18 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, #endif #if TINYEXR_USE_ZFP + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Weverything" +#endif + #include "zfp.h" + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + #endif namespace tinyexr { @@ -619,7 +648,7 @@ namespace miniz { - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug - would only have occured in earlier versions if you explicitly used this + would only have occurred in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place() (which used this flag). If you can't switch to v1.15 but want to fix @@ -7002,6 +7031,13 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, // Reuse MINIZ_LITTE_ENDIAN macro +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || \ + defined(__i386) || defined(__i486__) || defined(__i486) || \ + defined(i386) || defined(__ia64__) || defined(__x86_64__) +// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. +#define MINIZ_X86_OR_X64_CPU 1 +#endif + #if defined(__sparcv9) // Big endian #else @@ -7116,6 +7152,36 @@ static void swap4(unsigned int *val) { #endif } +static void swap4(int *val) { +#ifdef MINIZ_LITTLE_ENDIAN + (void)val; +#else + int tmp = *val; + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +#endif +} + +static void swap4(float *val) { +#ifdef MINIZ_LITTLE_ENDIAN + (void)val; +#else + float tmp = *val; + unsigned char *dst = reinterpret_cast<unsigned char *>(val); + unsigned char *src = reinterpret_cast<unsigned char *>(&tmp); + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; +#endif +} + #if 0 static void cpy8(tinyexr::tinyexr_uint64 *dst_val, const tinyexr::tinyexr_uint64 *src_val) { unsigned char *dst = reinterpret_cast<unsigned char *>(dst_val); @@ -7363,7 +7429,7 @@ static void WriteAttributeToMemory(std::vector<unsigned char> *out, out->insert(out->end(), type, type + strlen(type) + 1); int outLen = len; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&outLen)); + tinyexr::swap4(&outLen); out->insert(out->end(), reinterpret_cast<unsigned char *>(&outLen), reinterpret_cast<unsigned char *>(&outLen) + sizeof(int)); out->insert(out->end(), data, data + len); @@ -7379,12 +7445,19 @@ typedef struct { } ChannelInfo; typedef struct { + int min_x; + int min_y; + int max_x; + int max_y; +} Box2iInfo; + +struct HeaderInfo { std::vector<tinyexr::ChannelInfo> channels; std::vector<EXRAttribute> attributes; - int data_window[4]; + Box2iInfo data_window; int line_order; - int display_window[4]; + Box2iInfo display_window; float screen_window_center[2]; float screen_window_width; float pixel_aspect_ratio; @@ -7405,15 +7478,15 @@ typedef struct { channels.clear(); attributes.clear(); - data_window[0] = 0; - data_window[1] = 0; - data_window[2] = 0; - data_window[3] = 0; + data_window.min_x = 0; + data_window.min_y = 0; + data_window.max_x = 0; + data_window.max_y = 0; line_order = 0; - display_window[0] = 0; - display_window[1] = 0; - display_window[2] = 0; - display_window[3] = 0; + display_window.min_x = 0; + display_window.min_y = 0; + display_window.max_x = 0; + display_window.max_y = 0; screen_window_center[0] = 0.0f; screen_window_center[1] = 0.0f; screen_window_width = 0.0f; @@ -7430,7 +7503,7 @@ typedef struct { header_len = 0; compression_type = 0; } -} HeaderInfo; +}; static bool ReadChannelInfo(std::vector<ChannelInfo> &channels, const std::vector<unsigned char> &data) { @@ -7469,9 +7542,9 @@ static bool ReadChannelInfo(std::vector<ChannelInfo> &channels, memcpy(&info.y_sampling, p, sizeof(int)); // int p += 4; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.pixel_type)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.x_sampling)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info.y_sampling)); + tinyexr::swap4(&info.pixel_type); + tinyexr::swap4(&info.x_sampling); + tinyexr::swap4(&info.y_sampling); channels.push_back(info); } @@ -7501,9 +7574,9 @@ static void WriteChannelInfo(std::vector<unsigned char> &data, int pixel_type = channels[c].pixel_type; int x_sampling = channels[c].x_sampling; int y_sampling = channels[c].y_sampling; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&pixel_type)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&x_sampling)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&y_sampling)); + tinyexr::swap4(&pixel_type); + tinyexr::swap4(&x_sampling); + tinyexr::swap4(&y_sampling); memcpy(p, &pixel_type, sizeof(int)); p += sizeof(int); @@ -7712,7 +7785,7 @@ static int rleCompress(int inLength, const char in[], signed char out[]) { if (runEnd - runStart >= MIN_RUN_LENGTH) { // - // Compressable run + // Compressible run // *outWrite++ = static_cast<char>(runEnd - runStart) - 1; @@ -8056,7 +8129,7 @@ static void wav2Encode( int p2 = 2; // == 1 << (level+1) // - // Hierachical loop on smaller dimension n + // Hierarchical loop on smaller dimension n // while (p2 <= n) { @@ -8287,9 +8360,9 @@ const int HUF_DECMASK = HUF_DECSIZE - 1; struct HufDec { // short code long code //------------------------------- - int len : 8; // code length 0 - int lit : 24; // lit p size - int *p; // 0 lits + unsigned int len : 8; // code length 0 + unsigned int lit : 24; // lit p size + unsigned int *p; // 0 lits }; inline long long hufLength(long long code) { return code & 63; } @@ -8745,14 +8818,14 @@ static bool hufBuildDecTable(const long long *hcode, // i : encoding table pl->lit++; if (pl->p) { - int *p = pl->p; - pl->p = new int[pl->lit]; + unsigned int *p = pl->p; + pl->p = new unsigned int[pl->lit]; for (int i = 0; i < pl->lit - 1; ++i) pl->p[i] = p[i]; delete[] p; } else { - pl->p = new int[1]; + pl->p = new unsigned int[1]; } pl->p[pl->lit - 1] = im; @@ -9491,35 +9564,48 @@ static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr, #endif // TINYEXR_USE_PIZ #if TINYEXR_USE_ZFP + struct ZFPCompressionParam { double rate; - int precision; + unsigned int precision; + unsigned int __pad0; double tolerance; int type; // TINYEXR_ZFP_COMPRESSIONTYPE_* + unsigned int __pad1; ZFPCompressionParam() { type = TINYEXR_ZFP_COMPRESSIONTYPE_RATE; rate = 2.0; precision = 0; - tolerance = 0.0f; + tolerance = 0.0; } }; -bool FindZFPCompressionParam(ZFPCompressionParam *param, - const EXRAttribute *attributes, - int num_attributes) { +static bool FindZFPCompressionParam(ZFPCompressionParam *param, + const EXRAttribute *attributes, + int num_attributes, std::string *err) { bool foundType = false; for (int i = 0; i < num_attributes; i++) { - if ((strcmp(attributes[i].name, "zfpCompressionType") == 0) && - (attributes[i].size == 1)) { - param->type = static_cast<int>(attributes[i].value[0]); - - foundType = true; + if ((strcmp(attributes[i].name, "zfpCompressionType") == 0)) { + if (attributes[i].size == 1) { + param->type = static_cast<int>(attributes[i].value[0]); + foundType = true; + break; + } else { + if (err) { + (*err) += + "zfpCompressionType attribute must be uchar(1 byte) type.\n"; + } + return false; + } } } if (!foundType) { + if (err) { + (*err) += "`zfpCompressionType` attribute not found.\n"; + } return false; } @@ -9531,6 +9617,11 @@ bool FindZFPCompressionParam(ZFPCompressionParam *param, return true; } } + + if (err) { + (*err) += "`zfpCompressionRate` attribute not found.\n"; + } + } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) { for (int i = 0; i < num_attributes; i++) { if ((strcmp(attributes[i].name, "zfpCompressionPrecision") == 0) && @@ -9539,6 +9630,11 @@ bool FindZFPCompressionParam(ZFPCompressionParam *param, return true; } } + + if (err) { + (*err) += "`zfpCompressionPrecision` attribute not found.\n"; + } + } else if (param->type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) { for (int i = 0; i < num_attributes; i++) { if ((strcmp(attributes[i].name, "zfpCompressionTolerance") == 0) && @@ -9547,8 +9643,14 @@ bool FindZFPCompressionParam(ZFPCompressionParam *param, return true; } } + + if (err) { + (*err) += "`zfpCompressionTolerance` attribute not found.\n"; + } } else { - assert(0); + if (err) { + (*err) += "Unknown value specified for `zfpCompressionType`.\n"; + } } return false; @@ -9556,10 +9658,11 @@ bool FindZFPCompressionParam(ZFPCompressionParam *param, // Assume pixel format is FLOAT for all channels. static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines, - int num_channels, const unsigned char *src, + size_t num_channels, const unsigned char *src, unsigned long src_size, const ZFPCompressionParam ¶m) { - size_t uncompressed_size = dst_width * dst_num_lines * num_channels; + size_t uncompressed_size = + size_t(dst_width) * size_t(dst_num_lines) * num_channels; if (uncompressed_size == src_size) { // Data is not compressed(Issue 40). @@ -9572,22 +9675,24 @@ static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines, assert((dst_width % 4) == 0); assert((dst_num_lines % 4) == 0); - if ((dst_width & 3U) || (dst_num_lines & 3U)) { + if ((size_t(dst_width) & 3U) || (size_t(dst_num_lines) & 3U)) { return false; } field = zfp_field_2d(reinterpret_cast<void *>(const_cast<unsigned char *>(src)), - zfp_type_float, dst_width, dst_num_lines * num_channels); + zfp_type_float, static_cast<unsigned int>(dst_width), + static_cast<unsigned int>(dst_num_lines) * + static_cast<unsigned int>(num_channels)); zfp = zfp_stream_open(NULL); if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) { - zfp_stream_set_rate(zfp, param.rate, zfp_type_float, /* dimention */ 2, + zfp_stream_set_rate(zfp, param.rate, zfp_type_float, /* dimension */ 2, /* write random access */ 0); } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) { - zfp_stream_set_precision(zfp, param.precision, zfp_type_float); + zfp_stream_set_precision(zfp, param.precision); } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) { - zfp_stream_set_accuracy(zfp, param.tolerance, zfp_type_float); + zfp_stream_set_accuracy(zfp, param.tolerance); } else { assert(0); } @@ -9600,17 +9705,17 @@ static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines, zfp_stream_set_bit_stream(zfp, stream); zfp_stream_rewind(zfp); - size_t image_size = dst_width * dst_num_lines; + size_t image_size = size_t(dst_width) * size_t(dst_num_lines); - for (int c = 0; c < num_channels; c++) { + for (size_t c = 0; c < size_t(num_channels); c++) { // decompress 4x4 pixel block. - for (int y = 0; y < dst_num_lines; y += 4) { - for (int x = 0; x < dst_width; x += 4) { + for (size_t y = 0; y < size_t(dst_num_lines); y += 4) { + for (size_t x = 0; x < size_t(dst_width); x += 4) { float fblock[16]; zfp_decode_block_float_2(zfp, fblock); - for (int j = 0; j < 4; j++) { - for (int i = 0; i < 4; i++) { - dst[c * image_size + ((y + j) * dst_width + (x + i))] = + for (size_t j = 0; j < 4; j++) { + for (size_t i = 0; i < 4; i++) { + dst[c * image_size + ((y + j) * size_t(dst_width) + (x + i))] = fblock[j * 4 + i]; } } @@ -9626,31 +9731,33 @@ static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines, } // Assume pixel format is FLOAT for all channels. -bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize, - const float *inPtr, int width, int num_lines, int num_channels, - const ZFPCompressionParam ¶m) { +static bool CompressZfp(std::vector<unsigned char> *outBuf, + unsigned int *outSize, const float *inPtr, int width, + int num_lines, int num_channels, + const ZFPCompressionParam ¶m) { zfp_stream *zfp = NULL; zfp_field *field = NULL; assert((width % 4) == 0); assert((num_lines % 4) == 0); - if ((width & 3U) || (num_lines & 3U)) { + if ((size_t(width) & 3U) || (size_t(num_lines) & 3U)) { return false; } // create input array. field = zfp_field_2d(reinterpret_cast<void *>(const_cast<float *>(inPtr)), - zfp_type_float, width, num_lines * num_channels); + zfp_type_float, static_cast<unsigned int>(width), + static_cast<unsigned int>(num_lines * num_channels)); zfp = zfp_stream_open(NULL); if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_RATE) { zfp_stream_set_rate(zfp, param.rate, zfp_type_float, 2, 0); } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_PRECISION) { - zfp_stream_set_precision(zfp, param.precision, zfp_type_float); + zfp_stream_set_precision(zfp, param.precision); } else if (param.type == TINYEXR_ZFP_COMPRESSIONTYPE_ACCURACY) { - zfp_stream_set_accuracy(zfp, param.tolerance, zfp_type_float); + zfp_stream_set_accuracy(zfp, param.tolerance); } else { assert(0); } @@ -9663,17 +9770,17 @@ bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize, zfp_stream_set_bit_stream(zfp, stream); zfp_field_free(field); - size_t image_size = width * num_lines; + size_t image_size = size_t(width) * size_t(num_lines); - for (int c = 0; c < num_channels; c++) { + for (size_t c = 0; c < size_t(num_channels); c++) { // compress 4x4 pixel block. - for (int y = 0; y < num_lines; y += 4) { - for (int x = 0; x < width; x += 4) { + for (size_t y = 0; y < size_t(num_lines); y += 4) { + for (size_t x = 0; x < size_t(width); x += 4) { float fblock[16]; - for (int j = 0; j < 4; j++) { - for (int i = 0; i < 4; i++) { + for (size_t j = 0; j < 4; j++) { + for (size_t i = 0; i < 4; i++) { fblock[j * 4 + i] = - inPtr[c * image_size + ((y + j) * width + (x + i))]; + inPtr[c * image_size + ((y + j) * size_t(width) + (x + i))]; } } zfp_encode_block_float_2(zfp, fblock); @@ -9682,7 +9789,7 @@ bool CompressZfp(std::vector<unsigned char> *outBuf, unsigned int *outSize, } zfp_stream_flush(zfp); - (*outSize) = zfp_stream_compressed_size(zfp); + (*outSize) = static_cast<unsigned int>(zfp_stream_compressed_size(zfp)); zfp_stream_close(zfp); @@ -10122,8 +10229,10 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, } else if (compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { #if TINYEXR_USE_ZFP tinyexr::ZFPCompressionParam zfp_compression_param; - if (!FindZFPCompressionParam(&zfp_compression_param, attributes, - num_attributes)) { + std::string e; + if (!tinyexr::FindZFPCompressionParam(&zfp_compression_param, attributes, + int(num_attributes), &e)) { + // This code path should not be reachable. assert(0); return false; } @@ -10323,8 +10432,11 @@ static bool DecodeTiledPixelData( const EXRAttribute *attributes, size_t num_channels, const EXRChannelInfo *channels, const std::vector<size_t> &channel_offset_list) { - assert(tile_offset_x * tile_size_x < data_width); - assert(tile_offset_y * tile_size_y < data_height); + if (tile_size_x > data_width || tile_size_y > data_height || + tile_size_x * tile_offset_x > data_width || + tile_size_y * tile_offset_y > data_height) { + return false; + } // Compute actual image size in a tile. if ((tile_offset_x + 1) * tile_size_x >= data_width) { @@ -10418,6 +10530,17 @@ static unsigned char **AllocateImage(int num_channels, return images; } +#ifdef _WIN32 +static inline std::wstring UTF8ToWchar(const std::string &str) { + int wstr_size = + MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), NULL, 0); + std::wstring wstr(wstr_size, 0); + MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), &wstr[0], + (int)wstr.size()); + return wstr; +} +#endif + static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, const EXRVersion *version, std::string *err, const unsigned char *buf, size_t size) { @@ -10457,15 +10580,15 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, bool has_screen_window_center = false; bool has_screen_window_width = false; - info->data_window[0] = 0; - info->data_window[1] = 0; - info->data_window[2] = 0; - info->data_window[3] = 0; + info->data_window.min_x = 0; + info->data_window.min_y = 0; + info->data_window.max_x = 0; + info->data_window.max_y = 0; info->line_order = 0; // @fixme - info->display_window[0] = 0; - info->display_window[1] = 0; - info->display_window[2] = 0; - info->display_window[3] = 0; + info->display_window.min_x = 0; + info->display_window.min_y = 0; + info->display_window.max_x = 0; + info->display_window.max_y = 0; info->screen_window_center[0] = 0.0f; info->screen_window_center[1] = 0.0f; info->screen_window_width = -1.0f; @@ -10515,6 +10638,14 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, tinyexr::swap4(&x_size); tinyexr::swap4(&y_size); + if (x_size > static_cast<unsigned int>(std::numeric_limits<int>::max()) || + y_size > static_cast<unsigned int>(std::numeric_limits<int>::max())) { + if (err) { + (*err) = "Tile sizes were invalid."; + } + return TINYEXR_ERROR_UNSUPPORTED_FORMAT; + } + info->tile_size_x = static_cast<int>(x_size); info->tile_size_y = static_cast<int>(y_size); @@ -10586,30 +10717,26 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, } else if (attr_name.compare("dataWindow") == 0) { if (data.size() >= 16) { - memcpy(&info->data_window[0], &data.at(0), sizeof(int)); - memcpy(&info->data_window[1], &data.at(4), sizeof(int)); - memcpy(&info->data_window[2], &data.at(8), sizeof(int)); - memcpy(&info->data_window[3], &data.at(12), sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[0])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[1])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[2])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->data_window[3])); + memcpy(&info->data_window.min_x, &data.at(0), sizeof(int)); + memcpy(&info->data_window.min_y, &data.at(4), sizeof(int)); + memcpy(&info->data_window.max_x, &data.at(8), sizeof(int)); + memcpy(&info->data_window.max_y, &data.at(12), sizeof(int)); + tinyexr::swap4(&info->data_window.min_x); + tinyexr::swap4(&info->data_window.min_y); + tinyexr::swap4(&info->data_window.max_x); + tinyexr::swap4(&info->data_window.max_y); has_data_window = true; } } else if (attr_name.compare("displayWindow") == 0) { if (data.size() >= 16) { - memcpy(&info->display_window[0], &data.at(0), sizeof(int)); - memcpy(&info->display_window[1], &data.at(4), sizeof(int)); - memcpy(&info->display_window[2], &data.at(8), sizeof(int)); - memcpy(&info->display_window[3], &data.at(12), sizeof(int)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[0])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[1])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[2])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->display_window[3])); + memcpy(&info->display_window.min_x, &data.at(0), sizeof(int)); + memcpy(&info->display_window.min_y, &data.at(4), sizeof(int)); + memcpy(&info->display_window.max_x, &data.at(8), sizeof(int)); + memcpy(&info->display_window.max_y, &data.at(12), sizeof(int)); + tinyexr::swap4(&info->display_window.min_x); + tinyexr::swap4(&info->display_window.min_y); + tinyexr::swap4(&info->display_window.max_x); + tinyexr::swap4(&info->display_window.max_y); has_display_window = true; } @@ -10621,32 +10748,28 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, } else if (attr_name.compare("pixelAspectRatio") == 0) { if (data.size() >= sizeof(float)) { memcpy(&info->pixel_aspect_ratio, &data.at(0), sizeof(float)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->pixel_aspect_ratio)); + tinyexr::swap4(&info->pixel_aspect_ratio); has_pixel_aspect_ratio = true; } } else if (attr_name.compare("screenWindowCenter") == 0) { if (data.size() >= 8) { memcpy(&info->screen_window_center[0], &data.at(0), sizeof(float)); memcpy(&info->screen_window_center[1], &data.at(4), sizeof(float)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->screen_window_center[0])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->screen_window_center[1])); + tinyexr::swap4(&info->screen_window_center[0]); + tinyexr::swap4(&info->screen_window_center[1]); has_screen_window_center = true; } } else if (attr_name.compare("screenWindowWidth") == 0) { if (data.size() >= sizeof(float)) { memcpy(&info->screen_window_width, &data.at(0), sizeof(float)); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&info->screen_window_width)); + tinyexr::swap4(&info->screen_window_width); has_screen_window_width = true; } } else if (attr_name.compare("chunkCount") == 0) { if (data.size() >= sizeof(int)) { memcpy(&info->chunk_count, &data.at(0), sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&info->chunk_count)); + tinyexr::swap4(&info->chunk_count); } } else { // Custom attribute(up to TINYEXR_MAX_CUSTOM_ATTRIBUTES) @@ -10732,14 +10855,14 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) { exr_header->screen_window_center[1] = info.screen_window_center[1]; exr_header->screen_window_width = info.screen_window_width; exr_header->chunk_count = info.chunk_count; - exr_header->display_window[0] = info.display_window[0]; - exr_header->display_window[1] = info.display_window[1]; - exr_header->display_window[2] = info.display_window[2]; - exr_header->display_window[3] = info.display_window[3]; - exr_header->data_window[0] = info.data_window[0]; - exr_header->data_window[1] = info.data_window[1]; - exr_header->data_window[2] = info.data_window[2]; - exr_header->data_window[3] = info.data_window[3]; + exr_header->display_window.min_x = info.display_window.min_x; + exr_header->display_window.min_y = info.display_window.min_y; + exr_header->display_window.max_x = info.display_window.max_x; + exr_header->display_window.max_y = info.display_window.max_y; + exr_header->data_window.min_x = info.data_window.min_x; + exr_header->data_window.min_y = info.data_window.min_y; + exr_header->data_window.max_x = info.data_window.max_x; + exr_header->data_window.max_y = info.data_window.max_y; exr_header->line_order = info.line_order; exr_header->compression_type = info.compression_type; @@ -10798,7 +10921,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) { memcpy(exr_header->custom_attributes[i].type, info.attributes[i].type, 256); exr_header->custom_attributes[i].size = info.attributes[i].size; - // Just copy poiner + // Just copy pointer exr_header->custom_attributes[i].value = info.attributes[i].value; } @@ -10822,21 +10945,30 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, num_scanline_blocks = 32; } else if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { num_scanline_blocks = 16; - } - int data_width = exr_header->data_window[2] - exr_header->data_window[0] + 1; - int data_height = exr_header->data_window[3] - exr_header->data_window[1] + 1; +#if TINYEXR_USE_ZFP + tinyexr::ZFPCompressionParam zfp_compression_param; + if (!FindZFPCompressionParam(&zfp_compression_param, + exr_header->custom_attributes, + int(exr_header->num_custom_attributes), err)) { + return TINYEXR_ERROR_INVALID_HEADER; + } +#endif + } - if ((data_width < 0) || (data_height < 0)) { + if (exr_header->data_window.max_x < exr_header->data_window.min_x || + exr_header->data_window.max_y < exr_header->data_window.min_y) { if (err) { - std::stringstream ss; - ss << "Invalid data width or data height: " << data_width << ", " - << data_height << std::endl; - (*err) += ss.str(); + (*err) += "Invalid data window.\n"; } return TINYEXR_ERROR_INVALID_DATA; } + int data_width = + exr_header->data_window.max_x - exr_header->data_window.min_x + 1; + int data_height = + exr_header->data_window.max_y - exr_header->data_window.min_y + 1; + // Do not allow too large data_width and data_height. header invalid? { const int threshold = 1024 * 8192; // heuristics @@ -10938,14 +11070,10 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, int tile_coordinates[4]; memcpy(tile_coordinates, data_ptr, sizeof(int) * 4); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&tile_coordinates[0])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&tile_coordinates[1])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&tile_coordinates[2])); - tinyexr::swap4( - reinterpret_cast<unsigned int *>(&tile_coordinates[3])); + tinyexr::swap4(&tile_coordinates[0]); + tinyexr::swap4(&tile_coordinates[1]); + tinyexr::swap4(&tile_coordinates[2]); + tinyexr::swap4(&tile_coordinates[3]); // @todo{ LoD } if (tile_coordinates[2] != 0) { @@ -10960,7 +11088,7 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, int data_len; memcpy(&data_len, data_ptr + 16, sizeof(int)); // 16 = sizeof(tile_coordinates) - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); + tinyexr::swap4(&data_len); if (data_len < 4 || size_t(data_len) > data_size) { // TODO(LTE): atomic @@ -11081,8 +11209,8 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, memcpy(&line_no, data_ptr, sizeof(int)); int data_len; memcpy(&data_len, data_ptr + 4, sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); + tinyexr::swap4(&line_no); + tinyexr::swap4(&data_len); if (size_t(data_len) > data_size) { invalid_data = true; @@ -11098,7 +11226,7 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, } else { // line_no may be negative. int end_line_no = (std::min)(line_no + num_scanline_blocks, - (exr_header->data_window[3] + 1)); + (exr_header->data_window.max_y + 1)); int num_lines = end_line_no - line_no; @@ -11113,13 +11241,13 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, // overflow check tinyexr_int64 lno = static_cast<tinyexr_int64>(line_no) - - static_cast<tinyexr_int64>(exr_header->data_window[1]); + static_cast<tinyexr_int64>(exr_header->data_window.min_y); if (lno > std::numeric_limits<int>::max()) { line_no = -1; // invalid } else if (lno < -std::numeric_limits<int>::max()) { line_no = -1; // invalid } else { - line_no -= exr_header->data_window[1]; + line_no -= exr_header->data_window.min_y; } if (line_no < 0) { @@ -11204,8 +11332,8 @@ static bool ReconstructLineOffsets( return false; } - tinyexr::swap4(reinterpret_cast<unsigned int *>(&y)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); + tinyexr::swap4(&y); + tinyexr::swap4(&data_len); (*offsets)[i] = offset; @@ -11234,25 +11362,24 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, num_scanline_blocks = 16; } - int data_width = exr_header->data_window[2] - exr_header->data_window[0]; - if (data_width >= std::numeric_limits<int>::max()) { + if (exr_header->data_window.max_x < exr_header->data_window.min_x || + exr_header->data_window.max_x - exr_header->data_window.min_x == + std::numeric_limits<int>::max()) { // Issue 63 tinyexr::SetErrorMessage("Invalid data width value", err); return TINYEXR_ERROR_INVALID_DATA; } - data_width++; + int data_width = + exr_header->data_window.max_x - exr_header->data_window.min_x + 1; - int data_height = exr_header->data_window[3] - exr_header->data_window[1]; - if (data_height >= std::numeric_limits<int>::max()) { + if (exr_header->data_window.max_y < exr_header->data_window.min_y || + exr_header->data_window.max_y - exr_header->data_window.min_y == + std::numeric_limits<int>::max()) { tinyexr::SetErrorMessage("Invalid data height value", err); return TINYEXR_ERROR_INVALID_DATA; } - data_height++; - - if ((data_width < 0) || (data_height < 0)) { - tinyexr::SetErrorMessage("data width or data height is negative.", err); - return TINYEXR_ERROR_INVALID_DATA; - } + int data_height = + exr_header->data_window.max_y - exr_header->data_window.min_y + 1; // Do not allow too large data_width and data_height. header invalid? { @@ -11275,6 +11402,12 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, num_blocks = static_cast<size_t>(exr_header->chunk_count); } else if (exr_header->tiled) { // @todo { LoD } + if (exr_header->tile_size_x > data_width || exr_header->tile_size_x < 1 || + exr_header->tile_size_y > data_height || exr_header->tile_size_y < 1) { + tinyexr::SetErrorMessage("tile sizes are invalid.", err); + return TINYEXR_ERROR_INVALID_DATA; + } + size_t num_x_tiles = static_cast<size_t>(data_width) / static_cast<size_t>(exr_header->tile_size_x); if (num_x_tiles * static_cast<size_t>(exr_header->tile_size_x) < @@ -11371,7 +11504,8 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, } } -static void GetLayers(const EXRHeader& exr_header, std::vector<std::string>& layer_names) { +static void GetLayers(const EXRHeader &exr_header, + std::vector<std::string> &layer_names) { // Naive implementation // Group channels by layers // go over all channel names, split by periods @@ -11382,22 +11516,22 @@ static void GetLayers(const EXRHeader& exr_header, std::vector<std::string>& lay const size_t pos = full_name.find_last_of('.'); if (pos != std::string::npos && pos != 0 && pos + 1 < full_name.size()) { full_name.erase(pos); - if (std::find(layer_names.begin(), layer_names.end(), full_name) == layer_names.end()) + if (std::find(layer_names.begin(), layer_names.end(), full_name) == + layer_names.end()) layer_names.push_back(full_name); } } } struct LayerChannel { - explicit LayerChannel (size_t i, std::string n) - : index(i) - , name(n) - {} + explicit LayerChannel(size_t i, std::string n) : index(i), name(n) {} size_t index; std::string name; }; -static void ChannelsInLayer(const EXRHeader& exr_header, const std::string layer_name, std::vector<LayerChannel>& channels) { +static void ChannelsInLayer(const EXRHeader &exr_header, + const std::string layer_name, + std::vector<LayerChannel> &channels) { channels.clear(); for (int c = 0; c < exr_header.num_channels; c++) { std::string ch_name(exr_header.channels[c].name); @@ -11408,8 +11542,7 @@ static void ChannelsInLayer(const EXRHeader& exr_header, const std::string layer } } else { const size_t pos = ch_name.find(layer_name + '.'); - if (pos == std::string::npos) - continue; + if (pos == std::string::npos) continue; if (pos == 0) { ch_name = ch_name.substr(layer_name.size() + 1); } @@ -11421,7 +11554,8 @@ static void ChannelsInLayer(const EXRHeader& exr_header, const std::string layer } // namespace tinyexr -int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, const char **err) { +int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, + const char **err) { EXRVersion exr_version; EXRHeader exr_header; InitEXRHeader(&exr_header); @@ -11435,8 +11569,8 @@ int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, if (exr_version.multipart || exr_version.non_image) { tinyexr::SetErrorMessage( - "Loading multipart or DeepImage is not supported in LoadEXR() API", - err); + "Loading multipart or DeepImage is not supported in LoadEXR() API", + err); return TINYEXR_ERROR_INVALID_DATA; // @fixme. } } @@ -11452,7 +11586,7 @@ int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, (*num_layers) = int(layer_vec.size()); (*layer_names) = static_cast<const char **>( - malloc(sizeof(const char *) * static_cast<size_t>(layer_vec.size()))); + malloc(sizeof(const char *) * static_cast<size_t>(layer_vec.size()))); for (size_t c = 0; c < static_cast<size_t>(layer_vec.size()); c++) { #ifdef _MSC_VER (*layer_names)[c] = _strdup(layer_vec[c].c_str()); @@ -11467,11 +11601,13 @@ int EXRLayers(const char *filename, const char **layer_names[], int *num_layers, int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, const char **err) { - return LoadEXRWithLayer(out_rgba, width, height, filename, /* layername */NULL, err); + return LoadEXRWithLayer(out_rgba, width, height, filename, + /* layername */ NULL, err); } -int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *filename, const char *layername, - const char **err) { +int LoadEXRWithLayer(float **out_rgba, int *width, int *height, + const char *filename, const char *layername, + const char **err) { if (out_rgba == NULL) { tinyexr::SetErrorMessage("Invalid argument for LoadEXR()", err); return TINYEXR_ERROR_INVALID_ARGUMENT; @@ -11487,7 +11623,8 @@ int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *file int ret = ParseEXRVersionFromFile(&exr_version, filename); if (ret != TINYEXR_SUCCESS) { std::stringstream ss; - ss << "Failed to open EXR file or read version info from EXR file. code(" << ret << ")"; + ss << "Failed to open EXR file or read version info from EXR file. code(" + << ret << ")"; tinyexr::SetErrorMessage(ss.str(), err); return ret; } @@ -11534,7 +11671,8 @@ int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *file tinyexr::GetLayers(exr_header, layer_names); std::vector<tinyexr::LayerChannel> channels; - tinyexr::ChannelsInLayer(exr_header, layername == NULL ? "" : std::string(layername), channels); + tinyexr::ChannelsInLayer( + exr_header, layername == NULL ? "" : std::string(layername), channels); if (channels.size() < 1) { tinyexr::SetErrorMessage("Layer Not Found", err); @@ -11549,14 +11687,11 @@ int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *file if (ch.name == "R") { idxR = int(ch.index); - } - else if (ch.name == "G") { + } else if (ch.name == "G") { idxG = int(ch.index); - } - else if (ch.name == "B") { + } else if (ch.name == "B") { idxB = int(ch.index); - } - else if (ch.name == "A") { + } else if (ch.name == "A") { idxA = int(ch.index); } } @@ -11573,11 +11708,13 @@ int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *file for (int it = 0; it < exr_image.num_tiles; it++) { for (int j = 0; j < exr_header.tile_size_y; j++) { for (int i = 0; i < exr_header.tile_size_x; i++) { - const int ii = - exr_image.tiles[it].offset_x * exr_header.tile_size_x + i; - const int jj = - exr_image.tiles[it].offset_y * exr_header.tile_size_y + j; - const int idx = ii + jj * exr_image.width; + const int ii = exr_image.tiles[it].offset_x * + static_cast<int>(exr_header.tile_size_x) + + i; + const int jj = exr_image.tiles[it].offset_y * + static_cast<int>(exr_header.tile_size_y) + + j; + const int idx = ii + jj * static_cast<int>(exr_image.width); // out of region check. if (ii >= exr_image.width) { @@ -11601,7 +11738,8 @@ int LoadEXRWithLayer(float **out_rgba, int *width, int *height, const char *file } } else { for (int i = 0; i < exr_image.width * exr_image.height; i++) { - const float val = reinterpret_cast<float **>(exr_image.images)[chIdx][i]; + const float val = + reinterpret_cast<float **>(exr_image.images)[chIdx][i]; (*out_rgba)[4 * i + 0] = val; (*out_rgba)[4 * i + 1] = val; (*out_rgba)[4 * i + 2] = val; @@ -11947,11 +12085,22 @@ int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header, return TINYEXR_ERROR_INVALID_ARGUMENT; } -#ifdef _WIN32 FILE *fp = NULL; - fopen_s(&fp, filename, "rb"); +#ifdef _WIN32 +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + // TODO(syoyo): return wfopen_s erro code + return TINYEXR_ERROR_CANT_OPEN_FILE; + } #else - FILE *fp = fopen(filename, "rb"); + // Unknown compiler + fp = fopen(filename, "rb"); +#endif +#else + fp = fopen(filename, "rb"); #endif if (!fp) { tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); @@ -12101,7 +12250,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, { int comp = exr_header->compression_type; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&comp)); + tinyexr::swap4(&comp); tinyexr::WriteAttributeToMemory( &memory, "compression", "compression", reinterpret_cast<const unsigned char *>(&comp), 1); @@ -12109,10 +12258,10 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, { int data[4] = {0, 0, exr_image->width - 1, exr_image->height - 1}; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[0])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[1])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[2])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&data[3])); + tinyexr::swap4(&data[0]); + tinyexr::swap4(&data[1]); + tinyexr::swap4(&data[2]); + tinyexr::swap4(&data[3]); tinyexr::WriteAttributeToMemory( &memory, "dataWindow", "box2i", reinterpret_cast<const unsigned char *>(data), sizeof(int) * 4); @@ -12129,7 +12278,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, { float aspectRatio = 1.0f; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&aspectRatio)); + tinyexr::swap4(&aspectRatio); tinyexr::WriteAttributeToMemory( &memory, "pixelAspectRatio", "float", reinterpret_cast<const unsigned char *>(&aspectRatio), sizeof(float)); @@ -12137,8 +12286,8 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, { float center[2] = {0.0f, 0.0f}; - tinyexr::swap4(reinterpret_cast<unsigned int *>(¢er[0])); - tinyexr::swap4(reinterpret_cast<unsigned int *>(¢er[1])); + tinyexr::swap4(¢er[0]); + tinyexr::swap4(¢er[1]); tinyexr::WriteAttributeToMemory( &memory, "screenWindowCenter", "v2f", reinterpret_cast<const unsigned char *>(center), 2 * sizeof(float)); @@ -12146,7 +12295,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, { float w = static_cast<float>(exr_image->width); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&w)); + tinyexr::swap4(&w); tinyexr::WriteAttributeToMemory(&memory, "screenWindowWidth", "float", reinterpret_cast<const unsigned char *>(&w), sizeof(float)); @@ -12213,9 +12362,10 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, // Use ZFP compression parameter from custom attributes(if such a parameter // exists) { + std::string e; bool ret = tinyexr::FindZFPCompressionParam( &zfp_compression_param, exr_header->custom_attributes, - exr_header->num_custom_attributes); + exr_header->num_custom_attributes, &e); if (!ret) { // Use predefined compression parameter. @@ -12225,7 +12375,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, } #endif - // TOOD(LTE): C++11 thread + // TODO(LTE): C++11 thread // Use signed int since some OpenMP compiler doesn't allow unsigned type for // `parallel for` @@ -12257,7 +12407,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, tinyexr::FP32 f32 = half_to_float(h16); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&f32.f)); + tinyexr::swap4(&f32.f); // line_ptr[x] = f32.f; tinyexr::cpy4(line_ptr + x, &(f32.f)); @@ -12321,7 +12471,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, float val = reinterpret_cast<float **>( exr_image->images)[c][(y + start_y) * exr_image->width + x]; - tinyexr::swap4(reinterpret_cast<unsigned int *>(&val)); + tinyexr::swap4(&val); // line_ptr[x] = val; tinyexr::cpy4(line_ptr + x, &val); @@ -12538,14 +12688,26 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header, } #endif -#ifdef _WIN32 FILE *fp = NULL; - fopen_s(&fp, filename, "wb"); +#ifdef _WIN32 +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"wb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename), + err); + return TINYEXR_ERROR_CANT_WRITE_FILE; + } +#else + // Unknown compiler + fp = fopen(filename, "wb"); +#endif #else - FILE *fp = fopen(filename, "wb"); + fp = fopen(filename, "wb"); #endif if (!fp) { - tinyexr::SetErrorMessage("Cannot write a file", err); + tinyexr::SetErrorMessage("Cannot write a file: " + std::string(filename), + err); return TINYEXR_ERROR_CANT_WRITE_FILE; } @@ -12577,10 +12739,21 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { return TINYEXR_ERROR_INVALID_ARGUMENT; } -#ifdef _MSC_VER +#ifdef _WIN32 FILE *fp = NULL; - errno_t errcode = fopen_s(&fp, filename, "rb"); - if ((0 != errcode) || (!fp)) { +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), + err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } +#else + // Unknown compiler + fp = fopen(filename, "rb"); +#endif + if (!fp) { tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), err); return TINYEXR_ERROR_CANT_OPEN_FILE; @@ -12714,10 +12887,10 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { memcpy(&dy, &data.at(4), sizeof(int)); memcpy(&dw, &data.at(8), sizeof(int)); memcpy(&dh, &data.at(12), sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&dx)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&dy)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&dw)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&dh)); + tinyexr::swap4(&dx); + tinyexr::swap4(&dy); + tinyexr::swap4(&dw); + tinyexr::swap4(&dh); } else if (attr_name.compare("displayWindow") == 0) { int x; @@ -12728,10 +12901,10 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { memcpy(&y, &data.at(4), sizeof(int)); memcpy(&w, &data.at(8), sizeof(int)); memcpy(&h, &data.at(12), sizeof(int)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&x)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&y)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&w)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&h)); + tinyexr::swap4(&x); + tinyexr::swap4(&y); + tinyexr::swap4(&w); + tinyexr::swap4(&h); } } @@ -12819,7 +12992,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { memcpy(&unpackedSampleDataSize, data_ptr + 20, sizeof(tinyexr::tinyexr_int64)); - tinyexr::swap4(reinterpret_cast<unsigned int *>(&line_no)); + tinyexr::swap4(&line_no); tinyexr::swap8( reinterpret_cast<tinyexr::tinyexr_uint64 *>(&packedOffsetTableSize)); tinyexr::swap8( @@ -13054,11 +13227,21 @@ int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, return TINYEXR_ERROR_INVALID_ARGUMENT; } -#ifdef _WIN32 FILE *fp = NULL; - fopen_s(&fp, filename, "rb"); +#ifdef _WIN32 +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_INVALID_FILE; + } #else - FILE *fp = fopen(filename, "rb"); + // Unknown compiler + fp = fopen(filename, "rb"); +#endif +#else + fp = fopen(filename, "rb"); #endif if (!fp) { tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); @@ -13174,11 +13357,21 @@ int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers, return TINYEXR_ERROR_INVALID_ARGUMENT; } -#ifdef _WIN32 FILE *fp = NULL; - fopen_s(&fp, filename, "rb"); +#ifdef _WIN32 +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_INVALID_FILE; + } #else - FILE *fp = fopen(filename, "rb"); + // Unknown compiler + fp = fopen(filename, "rb"); +#endif +#else + fp = fopen(filename, "rb"); #endif if (!fp) { tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); @@ -13270,11 +13463,20 @@ int ParseEXRVersionFromFile(EXRVersion *version, const char *filename) { return TINYEXR_ERROR_INVALID_ARGUMENT; } -#ifdef _WIN32 FILE *fp = NULL; - fopen_s(&fp, filename, "rb"); +#ifdef _WIN32 +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t err = _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (err != 0) { + // TODO(syoyo): return wfopen_s erro code + return TINYEXR_ERROR_CANT_OPEN_FILE; + } #else - FILE *fp = fopen(filename, "rb"); + // Unknown compiler + fp = fopen(filename, "rb"); +#endif +#else + fp = fopen(filename, "rb"); #endif if (!fp) { return TINYEXR_ERROR_CANT_OPEN_FILE; @@ -13408,11 +13610,21 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images, return TINYEXR_ERROR_INVALID_ARGUMENT; } -#ifdef _WIN32 FILE *fp = NULL; - fopen_s(&fp, filename, "rb"); +#ifdef _WIN32 +#if defined(_MSC_VER) || defined(__MINGW32__) // MSVC, MinGW gcc or clang + errno_t errcode = + _wfopen_s(&fp, tinyexr::UTF8ToWchar(filename).c_str(), L"rb"); + if (errcode != 0) { + tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); + return TINYEXR_ERROR_CANT_OPEN_FILE; + } #else - FILE *fp = fopen(filename, "rb"); + // Unknown compiler + fp = fopen(filename, "rb"); +#endif +#else + fp = fopen(filename, "rb"); #endif if (!fp) { tinyexr::SetErrorMessage("Cannot read file " + std::string(filename), err); @@ -13582,5 +13794,5 @@ int SaveEXR(const float *data, int width, int height, int components, #pragma clang diagnostic pop #endif -#endif // TINYEXR_IMPLEMENTATION_DEIFNED +#endif // TINYEXR_IMPLEMENTATION_DEFINED #endif // TINYEXR_IMPLEMENTATION |